archwall 把架构画全Every architecture, drawn in full

MCP:AI 应用怎么接上外部工具和数据MCP: how AI apps plug into tools and data

protocolagentstoolsclient-server

MCP overview: 1 the host is the AI app (such as Claude Code or VS Code); it keeps the model and the conversation and makes one MCP client per server; 2 each connection has two layers, the transport outside is the pipe (stdio locally, Streamable HTTP remotely) and the data layer inside is the messages (JSON-RPC 2.0), the same on either pipe; 3 servers give context: tools the model calls, resources the app reads, prompts the user picks, local (a filesystem) or remote (Sentry); 4 the host merges every tool into one list for the model, routes each call to the right client and adds the result to the conversation

AI 应用想读文件、查数据库、看 Sentry。MCP 是统一插口,不用每个工具单独接。本文按 2026-07-28 版协议。

谁参与。宿主是 AI 应用,如 Claude Code、VS Code。它给每个服务端配一个客户端,管着对话,工具运行前问用户。服务端只见所需。

Participants: 1 the host makes one client per server, keeps the conversation history, asks the user before a tool runs and merges context from all clients, and the user agrees before their data goes to any server; 2 each client keeps a dedicated connection: client 1 to a local filesystem, client 2 to a local database, clients 3 and 4 both to remote Sentry; 3 a server is local (stdio, usually one client) or remote (Streamable HTTP, usually many); 4 walls between servers: each gets only the context it needs, none sees into another, the host controls anything across servers and keeps the full conversation
谁参与:宿主管全局,每个服务端一个客户端,服务端彼此隔开

两层。内层数据层是消息:JSON-RPC 2.0,客户端发请求,服务端答。外层传输层是管子。

Two layers: 1 the data layer defines what is said: discovery (versions and capabilities), server features (tools, resources, prompts), client features (asking the user), utilities (change notices, progress); 2 written as JSON-RPC 2.0 messages: the client sends requests and notifications, the server sends a result or error for each request and notifications, servers never send requests, notifications get no reply; 3 the transport layer defines how they travel: connection setup, message framing, authorization, over stdio or Streamable HTTP; 4 the data layer sits inside the transport layer: swap the pipe and the messages stay the same
两层:数据层是说什么,传输层是怎么送

一个请求。每个请求都带协议版本和客户端能力,服务端不记会话。server/discover 查它支持什么,然后 tools/list、tools/call。

One request: 1 every request carries the protocol version (e.g. 2026-07-28) and the client's capabilities, and should carry the client's name, so the server keeps no session; 2 discover, optional: server/discover returns supported versions, capabilities and the server's name, every server must answer it, and a wrong version gets an error listing the good ones; 3 tools/list returns each tool's name, title, description and input schema, with a cache hint of 5 minutes in the docs' example; 4 tools/call with the tool name and arguments returns text, images or other content, which the host hands to the model
一个请求:每次都自带版本和能力,先发现,再列出,再调用

服务端提供。模型调用的工具、应用读取的资源、用户选用的提示词。

What servers offer: 1 tools, the model decides: functions that act, such as file operations, API calls, database queries, via tools/list and tools/call; the host asks the user before a tool runs and a person should be able to say no; 2 resources, the app decides: data for context, such as file contents, records, API replies, each with a URI, via resources/list and resources/read; 3 prompts, the user decides: reusable templates such as few-shot examples, often shown as slash commands or menus, via prompts/list and prompts/get; 4 the docs' example: one database server offers a query tool, a schema resource and a few-shot prompt; optional extensions such as Tasks need both sides to opt in
服务端提供三样:工具归模型,资源归应用,提示词归用户

问用户。服务端不发请求,只回"需要输入";客户端问过用户后带答案重发。密码走网页,不走表单。

When the server needs the user: 1 the client declares elicitation in its capabilities and sends tools/call as request 1; only tools/call, resources/read and prompts/get can be asked back; 2 the server answers 'input required' with elicitation/create inside and optional requestState, its own notes; it sends no request and needs no stored state; 3 the client asks the user: form mode for names and choices, URL mode (the client opts in) for passwords and keys, which sends the user to a web page; the user accepts, declines or cancels; 4 the client tries again as request 2 with the same parameters plus the answers and requestState unchanged, and gets the final result, or is asked again; sampling and roots use the same path but are deprecated in 2026-07-28
问用户:服务端不发请求,只回“需要输入”,客户端问完重发

获知变化。客户端用 subscriptions/listen 选想听的,如"工具列表变了"。需订阅,尽力送达。

Hearing about changes: 1 the client opens a long-lived stream with subscriptions/listen and picks what to hear: tool list changed, prompt list changed, resource list changed, one resource updated; nothing comes unless asked; 2 the server confirms what it will send, leaves out what it can't do, sends list changes only if it declared them, and keeps the stream open; 3 notices such as notifications/tools/list_changed and notifications/resources/updated arrive, each tagged with the stream's id; best effort, so clients poll as well; 4 the client refreshes with tools/list and the new tools reach the model; if the stream is lost the client sends listen again; progress notices travel on the reply of their own request
获知变化:主动订阅,服务端确认,有变就推,客户端再刷新

传输。本地走 stdio,客户端把它当子进程启动。远程走 Streamable HTTP:每条消息一个 POST,回 JSON 或 SSE 流。

Transports: 1 stdio for a local server: the client starts the server as a child process, they talk over stdin and stdout with one JSON message per line, and to stop the client closes stdin, waits, then forces it; logs go to stderr, keys come from the environment, usually one client; 2 Streamable HTTP for a remote server: one endpoint such as /mcp, each message its own HTTP POST, the reply one JSON object or an SSE stream, usually many clients; 3 HTTP safety: check the Origin header against DNS rebinding, bind to 127.0.0.1 when local, headers copy the method, name and version and must match the body, sign-in optional with OAuth; 4 the same on every transport: the same JSON-RPC messages, no sessions, cancelling on both (a notice on stdio, closing the stream on HTTP), and custom transports keep the same format; the old HTTP+SSE transport is deprecated
传输:本地走 stdio,远程走 Streamable HTTP,消息都一样

登录可选,只用于 HTTP。服务端指明授权服务器,用户在浏览器同意,之后每个请求带令牌。

Signing in to a remote server (optional, HTTP only; stdio takes keys from the environment): 1 no token yet: the client calls the server and gets 401 with a link to its metadata; 2 find the auth server: the server's resource metadata names its auth server, which can be a separate service, and the auth server's metadata gives its addresses; 3 get a client ID (pre-registered or a metadata URL; old-style DCR registration is deprecated), the user approves in the browser, and the client gets a token for this server only; 4 use the token: Authorization: Bearer on every HTTP request, the server checks it was issued for it and never passes tokens on, and if more access is needed it answers 403 and the client asks for more; based on OAuth 2.1
登录(可选):找到授权服务器,用户同意,令牌只给这个服务端用

MCP 只管传上下文,怎么用归应用。

An AI app wants to read your files, query a database or check Sentry. MCP is one plug for all of them, so each tool doesn't need its own integration. This is protocol version 2026-07-28.

Who takes part. The host is the AI app, like Claude Code or VS Code. It makes one client per server, keeps the conversation and asks the user before a tool runs. Servers see only what they need.

Participants: 1 the host makes one client per server, keeps the conversation history, asks the user before a tool runs and merges context from all clients, and the user agrees before their data goes to any server; 2 each client keeps a dedicated connection: client 1 to a local filesystem, client 2 to a local database, clients 3 and 4 both to remote Sentry; 3 a server is local (stdio, usually one client) or remote (Streamable HTTP, usually many); 4 walls between servers: each gets only the context it needs, none sees into another, the host controls anything across servers and keeps the full conversation
Who takes part: the host runs things, one client per server, servers kept apart

Two layers. Inside, the data layer is the messages: JSON-RPC 2.0. The client sends requests, the server answers. Outside, the transport layer is the pipe.

Two layers: 1 the data layer defines what is said: discovery (versions and capabilities), server features (tools, resources, prompts), client features (asking the user), utilities (change notices, progress); 2 written as JSON-RPC 2.0 messages: the client sends requests and notifications, the server sends a result or error for each request and notifications, servers never send requests, notifications get no reply; 3 the transport layer defines how they travel: connection setup, message framing, authorization, over stdio or Streamable HTTP; 4 the data layer sits inside the transport layer: swap the pipe and the messages stay the same
Two layers: the data layer is what is said, the transport layer is how it travels

One request. Every request carries the protocol version and the client's capabilities, so the server keeps no session. server/discover says what a server supports. Then tools/list and tools/call.

One request: 1 every request carries the protocol version (e.g. 2026-07-28) and the client's capabilities, and should carry the client's name, so the server keeps no session; 2 discover, optional: server/discover returns supported versions, capabilities and the server's name, every server must answer it, and a wrong version gets an error listing the good ones; 3 tools/list returns each tool's name, title, description and input schema, with a cache hint of 5 minutes in the docs' example; 4 tools/call with the tool name and arguments returns text, images or other content, which the host hands to the model
One request: each one carries its version and capabilities; discover, list, then call

What servers offer. Tools the model calls, resources the app reads, prompts the user picks.

What servers offer: 1 tools, the model decides: functions that act, such as file operations, API calls, database queries, via tools/list and tools/call; the host asks the user before a tool runs and a person should be able to say no; 2 resources, the app decides: data for context, such as file contents, records, API replies, each with a URI, via resources/list and resources/read; 3 prompts, the user decides: reusable templates such as few-shot examples, often shown as slash commands or menus, via prompts/list and prompts/get; 4 the docs' example: one database server offers a query tool, a schema resource and a few-shot prompt; optional extensions such as Tasks need both sides to opt in
Three things servers offer: tools for the model, resources for the app, prompts for the user

Asking the user. A server sends no requests. It answers "input required", the client asks the user, then sends the call again with the answers. Passwords go through a web page, never a form.

When the server needs the user: 1 the client declares elicitation in its capabilities and sends tools/call as request 1; only tools/call, resources/read and prompts/get can be asked back; 2 the server answers 'input required' with elicitation/create inside and optional requestState, its own notes; it sends no request and needs no stored state; 3 the client asks the user: form mode for names and choices, URL mode (the client opts in) for passwords and keys, which sends the user to a web page; the user accepts, declines or cancels; 4 the client tries again as request 2 with the same parameters plus the answers and requestState unchanged, and gets the final result, or is asked again; sampling and roots use the same path but are deprecated in 2026-07-28
Asking the user: the server sends no request, it answers 'input required' and the client retries

Hearing about changes. The client opens subscriptions/listen and picks what to hear, such as "the tool list changed". It's opt-in and best effort.

Hearing about changes: 1 the client opens a long-lived stream with subscriptions/listen and picks what to hear: tool list changed, prompt list changed, resource list changed, one resource updated; nothing comes unless asked; 2 the server confirms what it will send, leaves out what it can't do, sends list changes only if it declared them, and keeps the stream open; 3 notices such as notifications/tools/list_changed and notifications/resources/updated arrive, each tagged with the stream's id; best effort, so clients poll as well; 4 the client refreshes with tools/list and the new tools reach the model; if the stream is lost the client sends listen again; progress notices travel on the reply of their own request
Hearing about changes: subscribe, the server confirms, notices arrive, the client refreshes

Transports. Local servers use stdio: the client starts them as child processes. Remote ones use Streamable HTTP: each message is a POST, the reply is JSON or an SSE stream.

Transports: 1 stdio for a local server: the client starts the server as a child process, they talk over stdin and stdout with one JSON message per line, and to stop the client closes stdin, waits, then forces it; logs go to stderr, keys come from the environment, usually one client; 2 Streamable HTTP for a remote server: one endpoint such as /mcp, each message its own HTTP POST, the reply one JSON object or an SSE stream, usually many clients; 3 HTTP safety: check the Origin header against DNS rebinding, bind to 127.0.0.1 when local, headers copy the method, name and version and must match the body, sign-in optional with OAuth; 4 the same on every transport: the same JSON-RPC messages, no sessions, cancelling on both (a notice on stdio, closing the stream on HTTP), and custom transports keep the same format; the old HTTP+SSE transport is deprecated
Transports: stdio for local, Streamable HTTP for remote, the same messages on both

Signing in is optional and only for HTTP. The server points to its auth server, the user approves in the browser, then every request carries the token.

Signing in to a remote server (optional, HTTP only; stdio takes keys from the environment): 1 no token yet: the client calls the server and gets 401 with a link to its metadata; 2 find the auth server: the server's resource metadata names its auth server, which can be a separate service, and the auth server's metadata gives its addresses; 3 get a client ID (pre-registered or a metadata URL; old-style DCR registration is deprecated), the user approves in the browser, and the client gets a token for this server only; 4 use the token: Authorization: Bearer on every HTTP request, the server checks it was issued for it and never passes tokens on, and if more access is needed it answers 403 and the client asks for more; based on OAuth 2.1
Signing in (optional): find the auth server, the user approves, the token works for this server only

MCP only moves context. How to use it is up to the app.

来源Source: modelcontextprotocol.io

← 全部架构← All architectures