For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /reference/contracts/mcp/README.md.

MCP contract

The experimental MCP gateway exposes every x-owner business operation in the assembled Go API OpenAPI specification. The reviewed manifest gives each operation one stable tool name, scope and effect classification. It currently contains 54 operations, including writes, deletions and the two operator-only Support routes.

The manifest is deliberately explicit. Generation fails when an API operation is added or removed without a parity decision, a scope crosses its owner, a write is classified as a read, or an input admits an authentication header. Authentication/session endpoints, internal relays, diagnostics and realtime connections do not become tools.

Run pnpm generate:contracts after editing sources or generators. pnpm check:http checks the bundled specification, generated tool schemas, Go DTOs, HTTP client and closed typed dispatcher. Generated files live in services/api/adaptors/{mcpcontract,mcpclient}/generated.

Inputs and outcomes

Inputs retain the OpenAPI names in three optional groups:

{
  "path": {"id": "11111111-1111-4111-8111-111111111111"},
  "parameters": {
    "Idempotency-Key": "22222222-2222-4222-8222-222222222222",
    "If-Match": "0"
  },
  "body": {"title": "A support request", "body": "Please investigate."}
}

This is the input to create_support_ticket. Tools retain required command headers, canonical identifiers, expected revisions, filters and pagination. Path values are encoded by the generated client; they cannot select an arbitrary origin or operation. Read-only annotations include SSH key validation, which the HTTP API models as a POST.

Each result has operation_id, HTTP status, and either the generated result or a bounded error containing code, message and optional outcome_unknown. Structured and text results contain the same envelope. The HPC projection keeps its Protobuf representation as {media_type, base64}.

Declared, schema-valid shared, Run and Pipeline command outcomes retain their aggregateId, version, status and rejection in result, including HTTP 404, 409 and 422 where that operation declares the corresponding outcome schema. These non-success replies set the MCP error flag while preserving the recorded outcome for recovery. Ordinary and unrecognised error bodies keep the sanitised error envelope.

Arguments are limited to 64 KiB. API replies are read with a 1 MiB bound; the gateway also bounds the duplicated MCP envelope. Large results require narrower queries or the ordinary API. Unknown provider error details are omitted. Malformed successful replies fail contract validation.

The gateway makes one HTTP attempt, refuses redirects and never manufactures idempotency keys or revisions. After an uncertain write, preserve the exact input and command identity for a user-authorised replay or current-state query. Tool annotations and instructions ask clients to obtain approval before writes. The platform enforces identity, scopes and owner permissions; the client owns per-action human approval.

Authority

Scopes use <owner-with-hyphens>:read, :write or :admin. Tokens contain only resource scopes actually granted through OAuth. Discovery is scoped to each request. The API rechecks permissions for each invocation.

An ordinary Party can request member scopes and use the operations allowed by the existing API and owners. The two Support administration operations also require API-side operator enrolment, checked at each call. The broker captures that enrolment at login and checks it on refresh; an old grant cannot silently gain newly enrolled operator rights.

The protocol uses three distinct JWT families:

FamilySignerAudienceLifetime
at+jwtOAuth brokerExact MCP_RESOURCE_URLAt most 600 seconds
pharos-mcp-login+jwtOAuth brokerpharos-api-mcp-login:v1At most 30 seconds
pharos-mcp-assertion+jwtGatewaypharos-api-mcp:v1At most 30 seconds, bounded by the access token

All carry exact iss, aud, sub, iat, exp, jti, identity_issuer, identity_subject and identity_voperson_id. Access tokens additionally require client_id, party_id, auth_version and scope. Gateway assertions retain Party authority and scopes, replace client_id with an exact operation_id, and receive a fresh identity and expiry. Login assertions contain neither a Party nor an operation or scope.

The private POST /internal/mcp/identity endpoint accepts only a broker login assertion. Its response contains party_id, auth_version and operator. It resolves an existing exact identity through Party Governance, checks current AUP through its established binding and rechecks the Party generation. Missing registration, pending setup or required AUP asks the user to complete ordinary platform login. No account is created by the MCP login query.

JWT parsing rejects duplicates, unknown fields, incorrect casing, nulls, missing identity, wrong token families, wrong audiences and invalid lifetimes. Broker and gateway verification keys are explicitly enrolled and must be different. The API's ordinary browser and CLI paths retain their existing credentials. A failed delegated bearer never falls back to a browser cookie.

See ADR 0071 and the runtime guide.

Page source

Source snapshot ยท Revision f928834c8.