使用说明
简单mcp
Node.js的小型、流媒体优先、无状态模型上下文协议服务器。没有打字稿,完全用JsDoc打字。
状态
早期预览(v0.0.1)。API可能会发生变化。
为什么不是主流的TypeScript SDK?
- SSE耦合使多节点部署复杂化:标准SDK维护一个内存映射,将POST与SSE流相匹配,SSE流在没有粘性会话的情况下中断。
- 以服务器为中心的客户端状态:工具列表和其他特定于客户端的设置在服务器实例上,除非每个连接运行一个服务器,否则每个客户端的变化会很尴尬。
- Base64响应需要完全缓冲:返回base64强制在响应之前在内存中构建整个有效载荷。
- 不必要的大表面积:当你只需要一个紧凑的流媒体管道时,代码太多,移动部件太多。
这个图书馆是什么
- 先流媒体:单身
Transform您可以将JSON-RPC请求写入并从中读取响应。适用于stdio和HTTP。 - 设计无状态:没有交通地图。每个请求都是自包含的。推送通知在协商或交给SSE时通过SSE发送
notify钩子你可以用pub/sub回来。 - 可更换编解码器:NDJSON、JSON和SSE编码器/解码器,无需更改服务器逻辑。
- 无大缓冲区:响应可以嵌入节点
Readable溪流;文本流以JSON字符串的形式流动,二进制流实时进行base64编码。
安装
npm i @zjonsson/simple-mcp
快速品尝
import { SimpleMCP, StdioTransport } from '@zjonsson/simple-mcp'
const server = new SimpleMCP({
tools: [{
name: 'echo',
description: 'Echo text',
inputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
fn: async ({ text }) => ({ content: [{ type: 'text', text }] })
}]
});
await new StdioTransport(server).connect();
HTTP也可以工作。如果客户端请求SSE,则响应对服务器发起的通知保持开放;否则,你会得到一个 notify 挂钩发布乐队外。
快速示例
import express from 'express'
import { SimpleMCP, HttpTransport } from '@zjonsson/simple-mcp'
const app = express()
// Important: do not attach JSON body parsers to the MCP route.
// The transport reads the raw request stream.
const server = new SimpleMCP({
tools: [{ name: 'ping', description: 'Ping', inputSchema: { type: 'object', properties: {} }, fn: async () => ({}) }]
})
// Regular MCP endpoint (request/response)
app.post('/mcp', (req, res) => {
const transport = new HttpTransport(server)
transport.connect(req, res)
})
app.listen(3000)
SSE流(客户端包括 mcp-session-id 绑定到会话)。默认值 notify 发射 HttpTransport.events 使用 sessionId 作为事件名称。此路由订阅该通道并将SSE帧写入客户端。对于分布式系统,覆盖 notify 发布到您的中央发布/订阅,并让订阅者重新发布到 HttpTransport.events 使用 sessionId 作为事件名称。(服务器还将设置 mcp-session-id 初始化时的响应标头。)
app.get('/mcp/sse', (req, res) => {
const sessionId = String(req.headers['mcp-session-id'] || '')
if (!sessionId) return res.status(400).send('Missing mcp-session-id header')
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache, no-transform',
Connection: 'keep-alive'
})
let id = 0
const listener = (message) => {
res.write(`id: ${id++}\nevent: message\ndata: ${JSON.stringify(message)}\n\n`)
}
HttpTransport.events.on(sessionId, listener)
req.once('close', () => HttpTransport.events.removeListener(sessionId, listener))
})
核心理念
- 一个抽象:
Transport扩展节点Transform在对象模式下。通过背压输入请求,获取响应。 - 通过HTTP协商:
Content-Type/Accept选择JSON、NDJSON或SSE。Stdio默认为NDJSON。 - 通知:
- 传入
notification/*从客户那里不会产生尸体。 - 发送的通知在可用时发送给SSE,或发送给您的
notify酒吧/酒吧扇出的钩子。
- 传入
何时使用此
- 你想要一个小型的、可组合的MCP服务器,它可以水平扩展,没有粘性会话。
- 您需要在不缓冲整个响应的情况下流式传输大输出。
- 您更喜欢标准节点流和最小表面积。
