AI MCP
约 1251 字大约 4 分钟
2026-01-17
MCP(Model Context Protocol)是一种用于定义和管理模型上下文的协议,是一个用于增强AI大模型能力的标准工具箱,让AI不仅能“说”话,还能“做”事。
标准化执行环境:MCP让AI系统能够执行实际操作(如控制设备、进行计算、调动外部API等),不仅仅停留在输出文本的阶段。
跨系统协同:MCP让AI与外部系统或工具协作无缝衔接。它能够调用外部资源或服务,执行任务,提升AI的功能。
MCP 就是给 AI 一个“工具箱”。
要自己做一个(Node / TypeScript),最常见、也最适合接入 OpenCode 的方式是:做一个本地(local)MCP server,用 stdio 传输,然后在 opencode.jsonc 里用 command 启动它。OpenCode 的 MCP 配置就是这么设计的。
从 0 到可用的最小模板:
mkdir my-mcp
cd my-mcp
npm init -y
npm i @modelcontextprotocol/sdk zod
npm i -D typescript tsx @types/node@modelcontextprotocol/sdk 是官方 TS SDK,支持 stdio(本地进程)以及 HTTP 等传输。
创建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true
}
}写一个最小 MCP Server(stdio)
新建 src/index.ts:
import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new McpServer({
name: "my-mcp",
version: "0.1.0",
});
// 一个最简单的工具:add
server.tool(
"add",
{ a: z.number(), b: z.number() },
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }],
})
);
// 再来一个:hello
server.tool(
"say_hello",
{ name: z.string() },
async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name}!` }],
})
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});这段写法就是官方 TS SDK 的典型姿势:McpServer + StdioServerTransport + zod 定义入参。
改 package.json(加上 type/module + scripts):
{
"name": "my-mcp",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"scripts": {
"dev": "tsx src/index.ts",
"build": "tsc -p tsconfig.json"
}
}编译:
npm run build接入你的 OpenCode(opencode.jsonc)
OpenCode 文档里说:在配置里 mcp 下给每个 server 一个名字,type: "local",再用 command 指定启动命令。
例如(把路径换成自己的):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my_mcp": {
"type": "local",
"command": ["node", "/absolute/path/to/my-mcp/dist/index.js"],
"enabled": true,
"environment": {
"MY_ENV_VAR": "optional"
},
"timeout": 5000
}
}
}文档里也给了 command: ["npx","-y", "..."] 这种写法;你如果把项目发布成 npm 包,也能用 npx 启动。
在对话里,在 prompt 里直接说 “use the <name> tool”(上述示例的名字就是 my_mcp)。
比如你可以对 opencode 说:use the my_mcp tool to add 3 and 4
command: ["npx","-y","..."] 本质上就是“不安装到项目里,也能直接跑一个 npm 包的可执行入口”。
npx = npm 自带的“临时执行器/包运行器”(现在很多场景里它其实已经集成进 npm exec 了)。
它帮你做两件事:
- 找到并运行一个命令(优先用本地
node_modules/.bin里的) - 如果本地没有,就临时下载对应 npm 包,跑完就结束(通常会缓存一下,下次更快)
所以它不只是“快捷启动”,更准确是:“无需预装也能运行(或优先运行本地已装的)npm 包命令”
-y 通常是让 npx 自动回答 yes(避免它提示你“要不要安装/运行这个包?”然后卡住)。
在 MCP 里很常见,因为 MCP server 是 opencode 启动的子进程,你肯定不希望它弹交互式确认。
MCP 配置里经常用 npx,因为只想启动这个 MCP server,不想把它写进我的项目依赖,希望随用随跑,跨机器配置简单
用 npx 的优点
- 零安装、配置简单
- 不污染项目依赖
- 适合“工具型/一次性/外部组件”
- 可以在配置里直接 pin 版本:
pkg@1.2.3
用 npm i(本地装)优点
- 更可控、更可复现(锁到 lockfile)
- 启动更快、更稳定(离线也行)
- 更安全(供应链风险更低)
- 团队协作更规范(版本统一)
MCP 的消息格式是 JSON-RPC 2.0,常见的标准传输包括:
STDIO(最常见)
- 本地进程通信:client 启动 server 子进程
- 通过 stdin/stdout 传 JSON-RPC
- 特别适合:CLI、桌面、本地工具链(上述的示例在 opencode + node 就是这个套路)
Streamable HTTP(更“服务化”)
- server 是独立服务,可多客户端连接
- 通过 HTTP POST/GET 交互
- 可选启用 SSE 来把 server->client 的多条消息“流式推送”出去
用 STDIO 的典型场景
- opencode / cline 这种本地集成
- 你希望安装简单、权限少、网络无关
- 单用户、单机为主
优点:简单、稳定、延迟低
缺点:不适合“多用户共享同一套服务”
用 Streamable HTTP + SSE 的典型场景
- 你要把 MCP 变成一个“常驻服务”
- 多个客户端/多台机器要连同一个 MCP
- 需要更标准的网络部署(容器、k8s、网关)
优点:服务化、可复用、可扩展
缺点:部署复杂度更高(鉴权、CORS、反向代理等也会跟着来)
远程 MCP(部署在服务器上、多个客户端连接),现在更推荐用 Streamable HTTP。
Streamable HTTP 才是 MCP 规范里“远程传输”的主推荐方案;而老的 HTTP + SSE 在很多实现/SDK 里已经变成“兼容用”。