AttestoMCP.Server.Test (attesto_mcp_server v2.8.0)

Copy Markdown View Source

Helpers for exercising a registered catalog in host test suites.

Each helper builds a JSON-RPC request, encodes and decodes it as JSON, dispatches it through the supervised server, and returns the complete JSON-RPC response map. Requests take the same operation-scope, definition-scope, definition authorize, schema, handler, cache-hint, and final wire-output path as transport dispatch. Handlers are never called directly.

response =
  AttestoMCP.Server.Test.call_tool(
    MyApp.MCP,
    "get_item",
    %{"id" => "item-7"},
    principal: principal,
    scopes: ["items.read"],
    host_context: %{account_id: "acct-1"}
  )

assert %{"result" => %{"structuredContent" => %{"id" => "item-7"}}} = response

The same request path is available for the other primitives:

AttestoMCP.Server.Test.read_resource(MyApp.MCP, "file:///docs/item-7")
AttestoMCP.Server.Test.get_prompt(MyApp.MCP, "summarize", %{"topic" => "release"})
AttestoMCP.Server.Test.complete(MyApp.MCP, %{"type" => "ref/prompt", "name" => "summarize"},
  %{"name" => "topic", "value" => "rel"})
AttestoMCP.Server.Test.discover(MyApp.MCP)
AttestoMCP.Server.Test.list_tools(MyApp.MCP, cursor: next_cursor)

request/4 sends any other method through the same builder.

Boundaries

The helpers start after transport authentication. :principal, :tenant, :scopes, and :host_context represent an already authenticated request. They do not verify a token, DPoP proof, mTLS certificate, HTTP header, or Plug parser order, and they do not establish HTTP header/body mirroring, legacy session negotiation, stdio framing, or disconnect behaviour. Keep separate Plug and stdio tests for those boundaries.

Options

Every helper accepts:

  • :principal (default "test-principal"), :tenant, :scopes (default []), and :host_context: the authenticated handler context. These are never copied into protocol parameters.
  • :request_id: a stable response ID.
  • :protocol_version: the request revision, default "2026-07-28".
  • :client_capabilities: the modern request's declared capabilities.
  • :meta: application metadata for params["_meta"], which handlers see as context.request_meta. The helper generates the protocol version and client capability keys; supplying either in :meta raises.
  • :request_state and :input_responses: modern multi-round retry fields for call_tool/4, read_resource/3, get_prompt/4, and request/4.
  • :timeout: a positive request timeout in milliseconds, still capped by the server's :max_request_timeout.

List helpers also accept :cursor, and complete/4 accepts :completion_context (the request's context member).

Protocol failures, including denied definitions, invalid schemas, missing prompt arguments, invalid completion references, invalid cursors, handler failures, and invalid outputs, are returned as the server's "error" or "result" members. Malformed helper options and values that cannot be represented as JSON raise ArgumentError because they are test setup errors.

Summary

Functions

Calls one registered tool and returns its complete JSON-RPC response map.

Requests completions for a prompt or resource-template reference.

Sends modern server/discover.

Retrieves a prompt with string arguments.

Lists one page of prompts.

Lists one page of resource templates.

Lists one page of static resources.

Lists one page of tools. Pass :cursor for a continuation.

Reads a static or templated resource through the production resolver.

Sends any request method through the shared builder.

Types

option()

@type option() ::
  {:principal, term()}
  | {:tenant, term()}
  | {:scopes, [String.t()]}
  | {:host_context, map()}
  | {:request_id, String.t() | integer()}
  | {:protocol_version, String.t()}
  | {:client_capabilities, map()}
  | {:meta, map()}
  | {:request_state, String.t()}
  | {:input_responses, map()}
  | {:cursor, String.t()}
  | {:completion_context, map()}
  | {:timeout, pos_integer()}

Functions

call_tool(server, name, arguments, opts \\ [])

@spec call_tool(AttestoMCP.Server.API.server(), String.t(), map(), [option()]) ::
  map()

Calls one registered tool and returns its complete JSON-RPC response map.

The default protocol revision is 2026-07-28, the default principal is "test-principal", and the default scope list is empty. Use :request_id when a stable response ID is useful in an assertion. :client_capabilities supplies the modern request's declared capabilities, including capabilities needed by a tool that returns an interactive request.

complete(server, ref, argument, opts \\ [])

@spec complete(AttestoMCP.Server.API.server(), map(), map(), [option()]) :: map()

Requests completions for a prompt or resource-template reference.

ref is the wire reference, for example %{"type" => "ref/prompt", "name" => "summarize"}, and argument is %{"name" => name, "value" => partial_value}.

discover(server, opts \\ [])

@spec discover(AttestoMCP.Server.API.server(), [option()]) :: map()

Sends modern server/discover.

get_prompt(server, name, arguments, opts \\ [])

@spec get_prompt(AttestoMCP.Server.API.server(), String.t(), map(), [option()]) ::
  map()

Retrieves a prompt with string arguments.

list_prompts(server, opts \\ [])

@spec list_prompts(AttestoMCP.Server.API.server(), [option()]) :: map()

Lists one page of prompts.

list_resource_templates(server, opts \\ [])

@spec list_resource_templates(AttestoMCP.Server.API.server(), [option()]) :: map()

Lists one page of resource templates.

list_resources(server, opts \\ [])

@spec list_resources(AttestoMCP.Server.API.server(), [option()]) :: map()

Lists one page of static resources.

list_tools(server, opts \\ [])

@spec list_tools(AttestoMCP.Server.API.server(), [option()]) :: map()

Lists one page of tools. Pass :cursor for a continuation.

read_resource(server, uri, opts \\ [])

@spec read_resource(AttestoMCP.Server.API.server(), String.t(), [option()]) :: map()

Reads a static or templated resource through the production resolver.

request(server, method, params \\ %{}, opts \\ [])

@spec request(AttestoMCP.Server.API.server(), String.t(), map(), [option()]) :: map()

Sends any request method through the shared builder.

params must not contain _meta, requestState, or inputResponses; use the :meta, :request_state, and :input_responses options so the helper can keep protocol fields separate from application metadata.