MCP and Capabilities

External agents reach Xema through the Model Context Protocol (MCP). External tool servers (GitHub MCP, Slack MCP, third-party MCP servers an org installs) also speak MCP. Xema unifies both directions under one surface: every external MCP tool becomes a Xema capability, and every agent — whether it lives inside Xema or talks to Xema over MCP — sees the same six meta-tools.

This is the bridge between the agent ecosystem's wire protocol and Xema's typed, policy-mediated capability plane.


The agent's view: six meta-tools, no proliferation

An agent connected to Xema does not see N separate MCP servers, one per integration. It sees exactly six tools:

Meta-toolPurpose
xema_capabilities_searchFind capabilities the agent is armed and allowed to invoke right now
xema_capabilities_describeGet the input/output schema, examples, and side effects for one or more refs
xema_capabilities_invokeInvoke a capability by ref
xema_capabilities_planDerive the shortest runnable sequence of capabilities to reach a goal
xema_capabilities_preflightReport what blocks an invocation — before the call fails
xema_capabilities_explainTurn a denial into the grant that would unlock it

This collapses the agent's surface from "one tool per provider verb across every installed integration" (dozens to hundreds) to six tools, always — and, crucially, keeps it constant as the capability catalogue grows. The results returned by search are the agent's working set: filtered by Subject, Space, Environment, and Policy, so the agent never sees what it cannot invoke.

Finds the capabilities the agent may invoke under the current ExecutionContext.

Search is anchored, not exhaustive. Naming a resource type — explicitly, or as a noun in query — enters the capability graph at that type and returns its neighbourhood: the actions that act on it, plus those one containment hop below. That is what keeps discovery a constant-cost operation whether the org has installed forty capabilities or forty thousand. Without an anchor, search returns a bounded, ranked page of the catalogue.

There is no full-catalogue listing. Page through results with cursor.

jsonc
1// Input — every field optional
2{ "query": "open a pull request", "domain": "connector", "limit": 20 }
3
4// Output
5{
6  "capabilities": [
7    {
8      "ref":      "connector:scm.create-pull-request@1",
9      "biome":    { "id": "software-dev", "version": "1.4.0" },
10      "title":    "Open a pull request",
11      "summary":  "Creates a PR on the project's bound SCM provider.",
12      "riskTier": "high",
13      "requiresApproval": true,
14      "mutation": "mutating",
15      "relation": "acts_on",
16      "distance": 0
17    },
18    { "ref": "connector:tracker.issue.create@1", "...": "..." }
19  ],
20  "anchor":          { "resourceType": "scm", "source": "derived-from-query" },
21  "consideredCount": 34,
22  "nextCursor":      "eyJ2IjoxLCJvIjoyMH0"
23}

Filtering happens server-side, and a capability the agent may not invoke is absent — not returned with a denial marker. An agent in the public environment never sees connector:bank.transfer@1 even if some other subject can invoke it. Compare consideredCount with the number of results to see how much authorization removed.

xema_capabilities_describe

Returns full schemas, examples, side-effect labels, and approval requirements:

jsonc
1// Input
2{ "refs": ["connector:scm.create-pull-request@1"] }
3
4// Output
5{
6  "items": [
7    {
8      "ref":            "connector:scm.create-pull-request@1",
9      "inputSchema":    { /* JSON Schema */ },
10      "outputSchema":   { /* JSON Schema */ },
11      "examples":       [ { "input": {...}, "output": {...} } ],
12      "sideEffects":    ["writes-external-system"],
13      "requiresApproval": true,
14      "biome":          { "id": "software-dev", "version": "2.4.1" }
15    }
16  ]
17}

Describe accepts arrays so an agent fetching context can batch-resolve every capability it plans to use in one call.

xema_capabilities_invoke

Generic invocation:

jsonc
1// Input — `sourceBranch`, `targetBranch` and `title` are required, `description` is optional.
2// The repository is the one bound to the calling session's project; it is not an input.
3{
4  "ref": "connector:scm.create-pull-request@1",
5  "input": { "sourceBranch": "feature/x", "targetBranch": "main", "title": "Add user authentication" }
6}
7
8// Output — the change-request record
9{
10  "output": {
11    "id": "cr-1", "externalId": "123",
12    "sourceBranch": "feature/x", "targetBranch": "main",
13    "title": "Add user authentication", "status": "open",
14    "createdAt": "2026-01-15T10:00:00Z", "updatedAt": "2026-01-15T10:00:00Z"
15  },
16  "auditId":     "inv_abc",
17  "obligations": [],
18  "decision":    "allow"
19}

Validation runs at invoke-time against the same schema describe returns. Bad input is rejected at the router boundary before any runner touches it.


External MCP servers — federation as capability providers

When an org admin registers an external MCP server (a GitHub MCP, a Slack MCP, a third-party domain MCP), the platform's MCP bridge:

  1. Calls tools/list on the external server at registration time.
  2. Translates each tool to a Xema capability ref using the closed grammar <provider-id>:<tool-name>@1 (e.g. github-mcp:create-issue@1).
  3. Registers each capability through the Service Registry with runner kind mcp-external and the external server as its endpoint.
  4. Lints the manifest so policy authors and admins can attach permission digests and obligations exactly as they would for a first-party capability.

From that point forward, the external tool is indistinguishable from a native Xema capability:

  • Every invocation routes through the capability router.
  • Every call is authorized against the org's grants by the same policy decision every capability call gets.
  • Every input/output is validated against the schema the external server published.
  • Every result lands in the audit log with the full ExecutionContext.

The agent never sees the external MCP server as a separate tool list. It sees one result in xema_capabilities_search, with the same shape as every other capability.


Why one surface

Three forces converge here:

  • Agent UX — a tool list that grows linearly with installed integrations becomes unusable. Six meta-tools stay constant, and anchored search keeps the cost of finding the right one constant too.
  • Authorization — every invocation crosses the same trust boundary, so it must read the same ExecutionContext. A direct-MCP escape hatch would bypass policy.
  • Auditability — one capability invocation = one audit row, regardless of whether the implementation is a first-party connector or an external MCP server.

The federation bridge handles the wire-protocol translation. The Xema-native capability surface handles policy, audit, and dispatch. Agents see the unified result.


Discovery, not memorization

Agents are taught — in their system skill — to discover capabilities at the start of each turn, not to hardcode tool names from training data. The recommended pattern:

text
1On each new task:
21. Call `xema_capabilities_search`, naming the resource you are acting on
3   (e.g. resourceType: "project") or describing the goal in `query`.
42. Pick the capability whose summary matches the goal.
53. Call `xema_capabilities_describe` to see the schema.
64. Call `xema_capabilities_invoke` with valid input.
7
8For work that takes several dependent steps, call `xema_capabilities_plan`
9with the goal ref instead of guessing the order. Before an action that
10needs a connection or a grant, call `xema_capabilities_preflight`. If an
11invocation is refused, call `xema_capabilities_explain` with the denial
12code rather than retrying unchanged.

This means a freshly installed biome's new capabilities appear to the agent immediately — no agent prompt redeployment, no skill bundle refresh, no training cycle.


What this replaces

Before unification:

  • Agents saw a separate MCP "server" entry per integration (GitHub-MCP, Slack-MCP, Linear-MCP…).
  • Each MCP tool was a distinct OpenAI/Anthropic-style tool definition in the agent's context window.
  • Capability boundaries between providers were enforced only at the runner layer, never in the agent's view of "what exists".
  • Adding a new integration meant updating agent skill bundles and rotating prompts.

After unification:

  • One tool list, always six entries.
  • The capability list updates in real time as biomes install/uninstall.
  • Policy is the only thing that decides what an agent can see.
  • No prompt rotations on integration change.

  • Capabilities — the underlying invocation surface.
  • Execution contexts — what each meta-tool reads to filter.
  • Policy — what the capability router consults at invoke time.
  • Service registry — where external MCP servers register as capability providers.
  • Skills — agents learn discovery patterns via system skills.

Previous: ← Governed web access Next: Developer Annotations →