本地 MCP Server
解释由 AI Host 在本机拉起的 MCP Server 如何通过 stdio 交换 JSON-RPC、暴露工具并保持权限边界。
[!abstract] 一句话定义 本地 MCP Server 是由 AI Host 启动的受控子进程:它不等于 Web 服务,而是通过 stdin/stdout 与 Host 建立一条 JSON-RPC 会话,把特定本地能力包装成 tools、resources 或 prompts。
[!info] related notes
- 所属 MOC: MCP MOC
- 前置概念: MCP 协议, Function Calling
- 配置操作: MCP 客户端配置指南
- 示例: CodeGraph, Nx MCP, Docker MCP Gateway
本地 MCP Server
它是什么,为什么需要它
模型本身不能直接安全地读取仓库、查询本机数据库或运行项目工具。把每种能力都为每个 AI 产品单独适配,会造成重复集成和不一致的权限模型。
本地 MCP Server 把一个边界清晰的能力(例如代码图查询、浏览器自动化、文件读取)封装为标准接口。Host 负责模型、会话、用户授权和工具选择;Server 只负责自己声明的工具、资源或提示模板。它不是 Agent,也不是模型,更不是“让模型拥有整个终端”。
stdio 启动后发生了什么
sequenceDiagram
participant H as Host(Codex / Claude / IDE)
participant C as MCP client
participant S as 本地 Server 子进程
participant L as 本地能力(CLI / DB / 项目)
H->>C: 读取配置并请求连接
C->>S: 启动 command + args
C->>S: stdin: initialize(JSON-RPC)
S-->>C: stdout: capabilities(JSON-RPC)
C-->>H: 注册可用 tools/resources/prompts
H->>C: 选择并调用 tool
C->>S: stdin: tools/call(JSON-RPC)
S->>L: 执行受限能力
S-->>C: stdout: 结果(JSON-RPC)
C-->>H: 将结果加入模型上下文
标准 stdio 传输的关键不变量:
- Host 启动子进程;不是用户先在某个端口“开服务”等待连接。
- Server 从
stdin读取、向stdout写入逐行 UTF-8 JSON-RPC。 stdout只能出现协议消息;调试与普通日志应写入stderr,否则会污染协议。- 一个 Host 可为不同 Server 建立隔离连接;Server 不天然拥有完整对话历史或其他 Server 的能力。
因此,codegraph serve --mcp 的 serve 指“提供 MCP 能力”,不意味着它一定监听 TCP 端口。它通常被配置为由 Host 在会话开始时拉起、在会话结束时停止。
初始化、发现与调用是三件事
- 配置发现:Host 从自己的配置文件读取 Server 名称、命令、参数和环境变量。
- 能力协商:连接建立后,客户端与 Server 在初始化中声明支持什么;Server 可能只提供 tools,也可能提供 resources 或 prompts。
- 模型调用:Host 把可用工具及其 schema 放入模型工作流,在模型请求并通过权限策略后,才将调用转给 Server。
“装好了 Server”不等于“模型已经会用”。配置错误会导致根本没有连接;权限策略会阻止调用;Server 或其依赖异常则会让工具调用失败。这三个层次要分开排查。
与远程 MCP 的区别
| 维度 | 本地 stdio Server | 远程 Streamable HTTP Server |
|---|---|---|
| 谁启动 | Host 启动子进程 | 远端独立服务已运行 |
| 通信 | stdin/stdout 的 JSON-RPC | HTTP endpoint,可选 SSE 流 |
| 典型能力 | 本机仓库、CLI、浏览器、数据库 | 托管文档、云服务、团队数据 |
| 主要风险 | 本地命令权限、工作目录、stdout 污染 | 认证、网络、Origin、数据外传 |
| 示例 | CodeGraph、Nx MCP | Context7 |
远程 HTTP Server 仍是 MCP Server,但它不是由 Host 以子进程方式启动;它需要正确的认证和网络边界。MCP 规范建议本地 HTTP 服务仅绑定 localhost 并验证 Origin,避免被网页跨域滥用。
最小配置和安全边界
[mcp_servers.example]
type = "stdio"
command = "example-mcp"
args = ["--read-only"]
配置应遵循最小权限:只提供任务需要的目录、命令和凭据;密钥通过安全环境变量或 Host 的密钥管理注入;不要把 token 写进可提交的 JSON/TOML。安装陌生 MCP Server 前应检查其源码来源、所需权限和网络行为——MCP 统一的是接入协议,不会自动让第三方工具变得可信。
常见误解
- “MCP Server 就是 REST API。” 不一定;本地 stdio 根本不需要 HTTP 端口。
- “Server 直接和模型聊天。” 不对;Host 才维护模型和会话,Server 只处理协议请求。
- “启动命令能手动跑通,就代表客户端可用。” 不充分;还要验证 Host 的配置、能力协商和实际 tool call。
- “stdio 可以随意打印日志。” 不可以;stdout 中的非协议文本会使通信失败。