MCP server

MCP (Model Context Protocol) servers expose tools to agents over a standard protocol. The Fuze MCP host (@fuze-ai/agent-mcp) intercepts the transport so every MCP tool call flows through the same evidence pipeline as a native tool.

What you'll build: a filesystem MCP server attached to your agent with fingerprint pinning, tool allowlist, and audit spans. Prerequisites: Cerbos policies, MCP admission re-uses the same engine. Next: verify the audit chain end to end.

Install

bash
npm install @fuze-ai/agent-mcp @modelcontextprotocol/sdk

Wire the filesystem MCP server

ts
import { MCPHost } from '@fuze-ai/agent-mcp'
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'

const host = new MCPHost({
  servers: [
    {
      name: 'filesystem',
      transport: new StdioClientTransport({
        command: 'npx',
        args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp/agent-workspace'],
      }),
      fingerprint: 'sha256:<expected-server-fingerprint>',
      allowedTools: ['read_file', 'write_file', 'list_directory'],
    },
  ],
})

await host.connect()

const tools = await host.listTools()

Admission policy

The MCP host enforces an admission policy via Cerbos (mcp.admission.yaml). Servers not on the fingerprint allowlist are rejected at connect time. Tools not on the per-server allowlist are rejected at dispatch.

yaml
# policies/mcp.admission.yaml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: default
  resource: mcp.server
  rules:
    - actions: ['connect']
      effect: EFFECT_ALLOW
      roles: ['operator']
      condition:
        match:
          all:
            of:
              - expr: request.resource.attr.fingerprint in request.principal.attr.allowed_fingerprints
              - expr: request.resource.attr.sandbox_tier == "isolated"

A non-isolated sandbox tier on an MCP server is refused.

Use MCP tools in your agent

The host exposes MCP tools as FuzeTool instances; pass them directly to defineAgent:

ts
const agent = defineAgent({
  // ...
  tools: [...host.toFuzeTools(), greet],
})

Each MCP-backed tool's threat boundary is derived from the server's declared capabilities and the host's policy.

Cap the tool-list token budget

Cap the size of tools/list results to keep prompt tokens predictable:

ts
const host = new MCPHost({
  servers: [/* ... */],
  toolListBudget: { maxTokens: 4000, softWarnAtPercent: 80 },
})

When the budget is exceeded, the host emits a fuze.mcp.budget warning span and returns a truncated tool list. A hard cap fails closed.

Evidence

Every MCP dispatch emits both fuze.tool (as for native tools) and fuze.mcp spans:

json
{
  "span": "fuze.mcp",
  "attributes": {
    "fuze.mcp.server": "filesystem",
    "fuze.mcp.fingerprint": "sha256:...",
    "fuze.mcp.tool": "read_file"
  }
}

Next: verify the audit chain end to end.