AIP-32: MCP.md — agentmcp/v1 (MCP driver specialisation)
A markdown + frontmatter format for declaring a Model Context Protocol driver — its server reference, transport (stdio / SSE / HTTP), per-tool MCP tool-name binding, prompts/resources composition, and lifecycle. Specialises AIP-30 DRIVER for the `kind: mcp` case. Wraps Anthropic-spec MCP servers (filesystem, github, postgres, …) as agent tools.
| Field | Value |
|---|---|
| AIP | 32 |
| Title | MCP.md — agentmcp/v1 (MCP driver specialisation) |
| Status | Draft |
| Type | Schema |
| Family | Driver |
| Driver kind | mcp |
| Specialises | AIP-30 DRIVER.md |
| Requires | AIP-14 (TOOL), AIP-16 (IO), AIP-19 (SECRETS), AIP-30 (DRIVER) |
| Resources | ./resources/aip-32 — MCP.schema.json, ADAPTER.md, EXAMPLES.md, SKILL.md |
Abstract
MCP.md is the kind: mcp specialisation of
AIP-30 DRIVER. It packages a
Model Context Protocol server
integration — its server reference (binary, container, or remote
URL), transport (stdio / SSE / HTTP), and per-tool mapping from
abstract TOOL contracts to MCP tool names.
MCP is Anthropic's open protocol for connecting LLMs to data sources, tools, and prompts via a JSON-RPC-like interface. Reference servers exist for filesystems, git, GitHub, postgres, sqlite, Brave search, etc. This AIP wraps those servers as conformant drivers in the AIP-30 supertype.
The frontmatter inherits everything from DRIVER and adds MCP-
specific fields: server, transport, mcp_tools mapping, plus
optional prompts and resources composition. The format pairs
with defineDriver({ kind: "mcp", ... }).
Motivation
MCP is rapidly becoming the de-facto protocol for "give an LLM access to a tool". Anthropic ships ~15 reference servers; community servers proliferate. Without a shared MCP-driver format:
-
Each MCP server has its own setup story. "Run via npx", "build from source", "docker pull then expose stdio" — five flavours of install, no shared declaration.
-
MCP tools don't carry contracts. An MCP server exposes
tools/listreturning JSON-Schema-validated tool definitions, but those don't naturally map to AIP-14 abstract contracts. Two different MCP servers may both exposeread_filewith subtly different schemas; a contract-bound layer normalises. -
Auth state is per-server. GitHub MCP server needs OAuth; filesystem MCP server needs no auth; postgres MCP server needs a connection string. The DRIVER auth shape covers all three; without it, callers handle each separately.
-
Routing across same-purpose servers. Multiple MCP servers may serve
fs.read(Anthropic's reference filesystem-mcp, alternative implementations, custom server). The resolver picks; without the AIP-30 layering, "MCP" is a bypass that hides alternatives. -
Lifecycle. MCP servers spawn, connect, list tools, get torn down. Without a driver format, every host re-implements the lifecycle.
Design principles
-
Inherit, don't repeat. Identity, auth, install, sandbox, policy_tags, region all come from DRIVER. MCP only adds what's MCP-specific: server location, transport, tool-name mapping.
-
Server is data, not code.
serverdeclares "where the MCP server lives" (binary path, npm package + args, docker image, or remote URL). The host's MCP runtime spawns / connects per the declaration; driver authors write zero connection code in the common case. -
mcp_toolsis the binding. Each entry inimplements[]includesmetadata.mcp.tool_namedeclaring which MCP tool name serves the contract. The host callsmcp.tools/call({ name, arguments })with the validated input. -
Transport-agnostic at the contract layer. stdio, SSE, and HTTP transports all conform to the same MCP semantics; driver declares transport, host's MCP client handles dispatch.
-
Prompts and resources are first-class. MCP exposes prompts and resources alongside tools. v1 references them via optional
prompts/resourcesblocks; full integration with AIP-3 SKILL and AIP-27 REF is a follow-up. -
Local stdio for self-hosted, HTTP for remote. Default-recommend stdio when the MCP server runs locally (filesystem, sqlite, localhost postgres). Use HTTP/SSE for remote managed services or shared-network deployments.
Specification
File location
MCP drivers live in a single folder:
.drivers/
filesystem-mcp/
DRIVER.md ← this AIP, kind: mcp
driver.ts ← optional entry (custom resource handler)
server.json ← MCP server config (sometimes inlined into DRIVER.md)
SECRETS.md ← AIP-19 inventory (when auth is needed)Convention: id ends with -mcp. The folder name SHOULD match id.
Frontmatter
Inherits all fields from AIP-30 DRIVER.md plus the MCP-specific fields below.
Required MCP-specific fields
| Field | Type | Description |
|---|---|---|
kind | const "mcp" | Per AIP-30. |
server | object | Where the MCP server lives. See The server block. |
transport | enum | "stdio" | "sse" | "http". How the host connects to the server. |
Optional MCP-specific fields
| Field | Type | Default | Description |
|---|---|---|---|
protocol_version | string | latest known | MCP protocol version this driver targets. v1 default tracks the latest stable MCP release. |
prompts | object[] | [] | MCP prompts the server exposes. Each { name, description, integrate_as }. v1 supports integrate_as: "skill_block" (composes into AIP-3 SKILL.md) or "raw" (exposed verbatim). |
resources | object[] | [] | MCP resources the server exposes. Each { uri_template, description, integrate_as }. v1 integrate_as: "ref_kind" registers a new AIP-27 REF kind. |
connection_options | object | {} | Transport-specific connection params: timeout_ms, max_retries, keepalive. |
Per-tool metadata.mcp (in implements[N].metadata.mcp)
Every entry in implements[] adds:
| Field | Type | Description |
|---|---|---|
tool_name | string | The MCP tool name to call (tools/call({ name: <here> })). MUST be a tool exposed by the server's tools/list. |
argument_mapping | object | Optional rename: contract-input key → MCP-tool argument name. Default: identity (contract input keys passed verbatim). |
result_extract | string | JSONPath-lite to extract the contract's outputs shape from the MCP tools/call response. Default: identity ($). |
The server block
Declares where the MCP server lives. Four shapes:
1. Local binary (stdio)
server:
kind: binary
path: /usr/local/bin/mcp-filesystem
args: ["/workspace"]
transport: stdioThe host spawns the binary as a subprocess with stdio piped.
2. npm package (stdio, most common pattern)
server:
kind: npm
package: "@modelcontextprotocol/server-filesystem"
args: ["/workspace"]
transport: stdio
install:
- { method: npm, package: "@modelcontextprotocol/server-filesystem", global: false }Host runs npx <package> <args> (or installs and runs).
3. Docker image (stdio or http)
server:
kind: docker
image: "modelcontextprotocol/server-postgres:latest"
env:
DATABASE_URL: "${secrets.POSTGRES_URL}"
transport: stdioHost pulls + runs the image, connecting via stdio (with -i flag) or
exposed port.
4. Remote HTTP / SSE endpoint
server:
kind: remote
url: "https://mcp.example.com/v1"
transport: sse # or "http"Host connects directly; no spawn, no install.
Transport semantics
| Transport | Use when | Lifecycle |
|---|---|---|
stdio | MCP server is a local subprocess (binary, npm, docker -i). | Spawn-on-first-use, keep alive across calls, terminate on host shutdown or idle timeout. |
sse | MCP server is remote, supports server-sent-events for bidirectional streaming. | HTTP connection upgrade; one connection per driver, multiplexed across calls. |
http | MCP server is remote, request-response per call. | One HTTP request per tools/call. |
Drivers SHOULD prefer stdio for local servers and sse for remote managed services with bidirectional needs.
MCP tool mapping
Each implements[] entry binds an abstract TOOL.md to an MCP tool
exposed by the server:
implements:
- tool: ./tools/fs-read/TOOL.md
version: "^1.0.0"
metadata:
mcp:
tool_name: read_file # the MCP tool's name from tools/list
argument_mapping:
path: path # contract input → MCP arg
result_extract: "$.contents" # MCP returns { contents, mime_type }
- tool: ./tools/fs-write/TOOL.md
version: "^1.0.0"
metadata:
mcp:
tool_name: write_file
argument_mapping:
path: path
content: contentThe host's MCP runtime:
- Spawns/connects the server (per
serverandtransport). - Calls
tools/listto validate the declaredtool_names exist. - Per call: applies
argument_mappingto the validated contract input, callstools/call, appliesresult_extractto the response.
Prompts integration (preview)
When the MCP server exposes prompts (via prompts/list), the
DRIVER MAY declare integration:
prompts:
- name: summarize-document
description: "Generate a structured summary of a document."
integrate_as: skill_block
skill_ref: ./skills/summarize/SKILL.mdintegrate_as: "skill_block" registers the prompt as a callable
sub-skill within the named SKILL.md. v1 implementation is preview
quality; full integration with AIP-3 is on the roadmap.
Resources integration (preview)
When the MCP server exposes resources (via resources/list), the
DRIVER MAY declare integration:
resources:
- uri_template: "file:///{path}"
description: "Filesystem resource."
integrate_as: ref_kind
ref_kind_id: mcp_filesystemintegrate_as: "ref_kind" registers a new AIP-27 REF kind
(mcp_filesystem:file:///path/to/file) so other AIPs can reference
MCP-server-backed resources via the unified REF format. v1 preview.
Stable identity
Per AIP-30. Bumping the MCP protocol version, the server source (npm package version major), or the transport is a major change.
The defineDriver({ kind: "mcp", ... }) signature
interface DriverDefinition<"mcp"> extends DriverDefinition {
kind: "mcp"
server: McpServer
transport: "stdio" | "sse" | "http"
protocolVersion?: string
prompts?: McpPrompt[]
resources?: McpResource[]
connectionOptions?: { timeout_ms?: number; max_retries?: number; keepalive?: boolean }
// Optional behavioural adapters.
buildArguments?: (args: BuildArgumentsArgs) => Record<string, unknown>
parseToolResult?: (args: ParseToolResultArgs) => DriverResult<unknown>
}
type McpServer =
| { kind: "binary"; path: string; args?: string[]; env?: Record<string, string> }
| { kind: "npm"; package: string; args?: string[]; env?: Record<string, string> }
| { kind: "docker"; image: string; args?: string[]; env?: Record<string, string> }
| { kind: "remote"; url: string; auth?: McpRemoteAuth }A frontmatter-only MCP driver is valid when argument_mapping +
result_extract cover the dispatch shape — most reference MCP servers
fit this pattern.
Authoring with SKILL.md
The canonical way to generate an MCP DRIVER.md is via the paired
author-mcp skill.
The skill walks the agent through:
- Identify the MCP server (npm package / docker image / remote URL).
- Identify the transport (stdio for local, sse for remote).
- Connect once and list MCP tools (
tools/list). - Map each MCP tool to a TOOL.md contract (existing or new).
- Author
argument_mappingandresult_extractper tool. - Validate against
./resources/aip-32/draft/MCP.schema.json.
Example
---
name: Filesystem MCP
id: filesystem-mcp
description:
Anthropic's reference filesystem MCP server. Stdio transport. Exposes
read_file, write_file, list_directory as the contracts fs-read,
fs-write, fs-list.
version: 1.0.0
kind: mcp
server:
kind: npm
package: "@modelcontextprotocol/server-filesystem"
args: ["/workspace"]
transport: stdio
protocol_version: "2025-03"
install:
- { method: npm, package: "@modelcontextprotocol/server-filesystem", global: false }
version_check:
cmd: "npx @modelcontextprotocol/server-filesystem --version"
parse: 'v(\S+)'
range: ">=0.5"
network:
egress: [] # local stdio, no network
region: ["self-hosted"]
policy_tags: ["self-hosted", "pii-safe"]
implements:
- tool: ./tools/fs-read/TOOL.md
version: "^1.0.0"
metadata:
mcp:
tool_name: read_file
argument_mapping: { path: path }
result_extract: "$.contents"
- tool: ./tools/fs-write/TOOL.md
version: "^1.0.0"
metadata:
mcp:
tool_name: write_file
argument_mapping: { path: path, content: content }
result_extract: "$"
- tool: ./tools/fs-list/TOOL.md
version: "^1.0.0"
metadata:
mcp:
tool_name: list_directory
argument_mapping: { path: path }
result_extract: "$.entries"
resources:
- uri_template: "file:///{path}"
description: "Filesystem resources accessible via this MCP server."
integrate_as: ref_kind
ref_kind_id: mcp_filesystem
tags: [mcp, filesystem, anthropic-reference, pii-safe]
---See ./resources/aip-32/draft/EXAMPLES.md
for additional patterns: postgres MCP, GitHub MCP with OAuth, custom
remote MCP server.
Compatibility
With AIP-30 DRIVER.md
Strict specialisation. Universal fields validate against AIP-30's schema; MCP-specific fields validate against AIP-32's. Hosts run both in sequence.
With AIP-14 TOOL.md
MCP drivers reference TOOL.md contracts. The contract's
inputSchema is what the runtime validates; argument_mapping
renames keys for the MCP server. The contract's outputSchema is
what result_extract produces.
With AIP-3 SKILL.md (preview)
prompts[].integrate_as: "skill_block" lets MCP-server prompts plug
into named skills. Full integration is on the roadmap; v1 wires the
prompt as a callable block within the named skill.
With AIP-27 REF.md (preview)
resources[].integrate_as: "ref_kind" registers MCP-resource URIs
as new REF kinds. Other AIPs can then reference MCP resources via
mcp_<kind_id>:<uri> strings.
With Anthropic MCP reference servers
The reference-server registry at
github.com/modelcontextprotocol/servers
provides ~15 servers. Each can be wrapped as a kind: mcp driver
following the patterns in EXAMPLES.md. The author-mcp skill
templates the wrapping.
Security considerations
- Spawned subprocess sandbox. Stdio MCP servers spawn a
subprocess per driver. The DRIVER's
network.egressand (for CLI-style) sandbox apply to the subprocess. Hosts MUST NOT allow the MCP subprocess to escape the declared sandbox. - MCP tool definitions are server-supplied. A malicious MCP
server could expose a tool whose schema doesn't match the contract.
Hosts MUST validate
tools/listresponses against the registered contract; mismatches fail at registration, not at first call. - Resource URIs may be user-controlled. When a tool input is a
resource URI (
file:///user/path), hosts MUST sanitise against the MCP server's declared sandbox before forwarding. - Connection state across users. A stdio MCP server is a
long-lived subprocess; per-call user context (auth, tenant) MUST
be passed in
tools/call.arguments, never bound at spawn time. Otherwise users share state. - Remote MCP servers expose the same risks as third-party HTTP APIs (per AIP-31's security considerations). TLS verification, policy_tags, region — all apply.
Open questions
- Prompts and resources integration depth. v1 marks both as preview. Full integration with AIP-3 SKILL.md and AIP-27 REF.md needs more concrete server examples to settle.
- MCP protocol versioning. Anthropic ships breaking changes via protocol version. v1 doesn't yet codify how drivers express "supports both v1 and v2"; defer to v2 with field experience.
- Multi-tenant stdio servers. Stdio servers are subprocess- per-driver; multi-tenant routing today means subprocess-per- tenant. Scaling needs a connection-pool model — v2.
- Streaming on stdio. MCP supports streaming via newline- delimited JSON-RPC notifications; the AIP-31 streaming pattern doesn't quite fit. Defer to a v2 streaming integration.
See also
- Model Context Protocol — upstream protocol
- AIP-14 — TOOL.md — abstract contracts MCP drivers implement
- AIP-19 — SECRETS.md — auth-surface inventory
- AIP-29 — CLI.md — sibling specialisation,
kind: cli - AIP-30 — DRIVER.md — abstract supertype
- AIP-31 — HTTP.md — sibling specialisation,
kind: http - AIP-33 — SDK.md — sibling specialisation,
kind: sdk - Driver family — index of related AIPs
./MCP.schema.json— JSON Schema validator./ADAPTER.md— implementer's guide./EXAMPLES.md— additional patterns
Resources
Supporting artifacts for AIP-32. Links open the file on GitHub — markdown and JSON render natively in GitHub's viewer. Browse the full resource tree →
AIP-31: HTTP.md — agenthttp/v1 (HTTP driver specialisation)
A markdown + frontmatter format for declaring an HTTP-API driver — its base URL, per-tool endpoint/method/body templates, header bindings, response extraction, and (when needed) streaming hints. Specialises AIP-30 DRIVER for the `kind: http` case. Most third-party APIs (OpenAI, Stripe, Replicate, Anthropic) wrap as HTTP drivers.
AIP-33: SDK.md — agentsdk/v1 (in-process SDK driver specialisation)
A markdown + frontmatter format for declaring an in-process SDK driver — an npm/pip/cargo/go package that exposes named functions implementing one or more abstract TOOL contracts directly in the host runtime, without subprocess spawn or network hop. Specialises AIP-30 DRIVER for the `kind: sdk` case.