MCP服务器库
对 模型上下文协议 (MCP)。
适用于 Node.js 和 裸运行时 (梨/Holepunch)。
特性
- 工具 --注册AI客户端可以调用的函数
- 资源 --公开客户端可以读取的数据(静态或动态)
- 资源模板 --带参数的URI模式(
user://{id}) - 注释 --工具和内容的元数据提示(MCP 2025-11-25)
- 通知 --向连接的客户端推送更新
- 订阅 --客户端可以订阅资源更改
- 多个传输 --HTTP、websocket、SSE、Stdio
快速开始
import { createMCPServer } from 'bare-mcp'
import { createHttpTransport } from 'bare-mcp/http'
// Create server
const mcp = createMCPServer({
name: 'my-server',
version: '1.0.0'
})
// Register a tool
mcp.addTool({
name: 'greet',
description: 'Say hello to someone',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Name to greet' }
},
required: ['name']
},
execute: async ({ name }) => `Hello, ${name}!`
})
// Start HTTP server (works on both Node.js and Bare)
await createHttpTransport(mcp, { port: 3000 })工具
工具是AI客户端可以调用的功能。
mcp.addTool({
name: 'calculate',
description: 'Perform arithmetic',
inputSchema: {
type: 'object',
properties: {
a: { type: 'number' },
b: { type: 'number' },
op: { type: 'string', enum: ['add', 'subtract', 'multiply', 'divide'] }
},
required: ['a', 'b', 'op']
},
execute: async ({ a, b, op }) => {
const ops = { add: a + b, subtract: a - b, multiply: a * b, divide: a / b }
return JSON.stringify({ result: ops[op] })
}
})
// Register multiple tools
mcp.addTools([tool1, tool2, tool3])工具注释
工具可以包括描述其行为的注释:
mcp.addTool({
name: 'search',
description: 'Search the web',
inputSchema: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query']
},
execute: async ({ query }) => `Results for: ${query}`,
annotations: {
title: 'Web Search', // Human-readable title
readOnlyHint: true, // Doesn't modify environment (default: false)
openWorldHint: true // Interacts with external systems (default: true)
}
})
// Destructive tool example
mcp.addTool({
name: 'delete_file',
description: 'Delete a file',
inputSchema: {
type: 'object',
properties: { path: { type: 'string' } },
required: ['path']
},
execute: async ({ path }) => { /* ... */ },
annotations: {
title: 'Delete File',
readOnlyHint: false, // Modifies environment
destructiveHint: true, // May destroy data (default: true)
idempotentHint: true, // Repeated calls have same effect (default: false)
openWorldHint: false // Only affects local system
}
})| 注释 | 默认值 | 说明 |
|---|---|---|
title | -- | 人类可读的显示名称 |
readOnlyHint | false | 如果为真,则工具不会修改其环境 |
destructiveHint | true | 如果为真,工具可能会销毁数据(仅当readOnlyHint=false时) |
idempotentHint | false | 如果为true,重复调用没有额外效果(仅当readOnlyHint=false时) |
openWorldHint | true | 如果为真,则与外部系统交互 |
带注释的工具结果
工具可以返回带有注释的丰富内容:
mcp.addTool({
name: 'analyze',
execute: async () => [{
type: 'text',
text: 'Analysis results...',
annotations: {
audience: ['user'], // Who content is for: 'user', 'assistant', or both
priority: 0.9 // Importance: 0.0 (optional) to 1.0 (required)
}
}]
})
// Return error with content
mcp.addTool({
name: 'fetch',
execute: async () => ({
content: [{ type: 'text', text: 'Connection timeout' }],
isError: true
})
})错误处理
工具可以投掷 MCPError 带有特定错误代码:
import { MCPError, ErrorCode } from 'bare-mcp'
mcp.addTool({
name: 'get_user',
inputSchema: {
type: 'object',
properties: { id: { type: 'string' } },
required: ['id']
},
execute: async ({ id }) => {
const user = await db.findUser(id)
if (!user) {
throw new MCPError(
ErrorCode.INVALID_PARAMS,
`User not found: ${id}`,
{ userId: id } // Optional data field
)
}
return JSON.stringify(user)
}
})
// Custom error codes (use values > -32000)
mcp.addTool({
name: 'rate_limited_api',
execute: async () => {
throw new MCPError(-32001, 'Rate limit exceeded', { retryAfter: 60 })
}
})标准错误代码:
| 代码 | 名称 | 描述 |
|---|---|---|
| -32700 | PARSE_ERROR | JSON无效 |
| -32600 | INVALID_REQUEST | 不是有效的JSON-RPC请求 |
| -32601 | METHOD_NOT_FOUND | 方法不存在 |
| -32602 | INVALID_PARAMS | 无效参数(验证,缺少参数) |
| -32603 | INTERNAL_ERROR | 内部服务器错误 |
| -32002 | RESOURCE_NOT_FOUND | 未找到资源 |
错误响应遵循JSON-RPC 2.0规范:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "User not found: abc123",
"data": { "userId": "abc123" }
}
}资源
资源公开了客户端可以读取的数据。
静态资源
mcp.addResource({
uri: 'config://app',
name: 'App Configuration',
description: 'Application settings',
mimeType: 'application/json',
text: JSON.stringify({ theme: 'dark', version: '1.0' })
})动态资源
mcp.addResource({
uri: 'stats://live',
name: 'Live Statistics',
mimeType: 'application/json',
read: async () => JSON.stringify({
uptime: process.uptime(),
memory: process.memoryUsage()
})
})资源注释
资源支持显示提示和内容元数据的注释:
mcp.addResource({
uri: 'doc://readme',
name: 'README',
title: 'Project Documentation', // Human-readable title
mimeType: 'text/markdown',
text: '# My Project',
annotations: {
audience: ['user'], // Who content is for
priority: 0.9, // Importance (0.0 to 1.0)
lastModified: '2025-01-15T10:00:00Z'
}
})动态资源每次读取都可以返回注释:
mcp.addResource({
uri: 'cache://data',
name: 'Cached Data',
read: async () => ({
text: JSON.stringify(getCachedData()),
annotations: {
lastModified: new Date().toISOString(),
audience: ['assistant']
}
})
})| 注释 | 类型 | 描述 |
|---|---|---|
audience | string[] | 内容针对谁: ["user"], ["assistant"],或 ["user", "assistant"] |
priority | number | 重要性:0.0(可选)到1.0(必需) |
lastModified | string | ISO 8601上次修改时间戳 |
资源模板
提取参数的URI模式:
mcp.addResourceTemplate({
uriTemplate: 'user://{id}',
name: 'User by ID',
description: 'Fetch user details',
mimeType: 'application/json',
read: async ({ id }) => {
const user = await db.getUser(id)
return JSON.stringify(user)
}
})
// Client can read: user://alice, user://bob, etc.通知
向连接的客户端推送更新。
// Resource was modified
mcp.notifyResourceUpdated('stats://live')
// Resource list changed (added/removed)
mcp.notifyResourceListChanged()
// Tool list changed
mcp.notifyToolListChanged()
// Progress update for long operations
mcp.notifyProgress('upload-token', 50, 100)
// Custom notification
mcp.notify('notifications/custom', { data: 'anything' })运输
运行时检测是自动的-- bare-mcp/http 和 bare-mcp/stdio 使用 which-runtime 在导入时选择正确的实现(Node.js或Bare)。下游包装永远不需要担心。
HTTP传输
HTTP传输支持三种连接模式,所有连接模式都由同一服务器提供服务:
| 模式 | 端点 | 协议 | 方向 |
|---|---|---|---|
| 流式HTTP | POST /mcp | 基于HTTP的JSON-RPC | 请求→ 答复 |
| 上海证券交易所 | GET /sse + POST /message | 基于SSE的JSON-RPC | 双向 |
| 双向通信 | ws://host:port | 基于WS的JSON-RPC | 双向 |
启动服务器
import { createMCPServer } from 'bare-mcp'
import { createHttpTransport } from 'bare-mcp/http'
const mcp = createMCPServer({ name: 'my-server', version: '1.0.0' })
mcp.addTool({
name: 'greet',
description: 'Say hello',
inputSchema: {
type: 'object',
properties: { name: { type: 'string' } },
required: ['name']
},
execute: async ({ name }) => `Hello, ${name}!`
})
const transport = await createHttpTransport(mcp, {
port: 3000,
host: '0.0.0.0',
websocket: true, // Enable WebSocket (default: true, Node.js only)
verbose: false, // Log requests/notifications to stderr (default: false)
onActivity: (entry) => console.log('Tool called:', entry.tool)
})HTTP端点
| 方法 | 路径 | 描述 |
|---|---|---|
POST | /mcp 或 / | JSON-RPC端点(可流式HTTP) |
GET | /sse | SSE流(双向MCP传输) |
POST | /message?sessionId=... | SSE消息端点(与配对 /sse) |
GET | /health | 健康检查({ status, server, version, requestCount }) |
GET | /activity | 最近的工具调用活动日志 |
POST | /activity/clear | 清除活动日志 |
WS | ws://host:port | WebSocket(仅限Node.js) |
流式HTTP(推荐)
最简单的模式。客户端通过POST发送JSON-RPC请求,并在HTTP正文中接收响应。这是Cursor、Claude Code和大多数现代MCP客户端使用的传输方式。
// Client sends a request
const res = await fetch('http://localhost:3000/mcp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'initialize',
params: {
protocolVersion: '2025-03-26',
capabilities: {},
clientInfo: { name: 'my-client', version: '1.0.0' }
},
id: 1
})
})
const { result } = await res.json()
// result.serverInfo, result.capabilities, etc.
// Call a tool
const toolRes = await fetch('http://localhost:3000/mcp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: { name: 'greet', arguments: { name: 'World' } },
id: 2
})
})
const { result: toolResult } = await toolRes.json()
// toolResult.content[0].text === 'Hello, World!'通知(否 id 字段)接收a 204 No Content 响应:
await fetch('http://localhost:3000/mcp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'notifications/initialized'
})
})
// 204 No Content苏格兰和南方能源公司运输(传统)
MCP SSE传输是双向的。客户端打开SSE流,接收 POST 端点URL,然后向该URL发送JSON-RPC请求。响应和服务器通知到达SSE流。
// 1. Open SSE connection
const events = new EventSource('http://localhost:3000/sse')
let messageEndpoint = null
// 2. Wait for the endpoint event (sent immediately on connect)
events.addEventListener('endpoint', (e) => {
messageEndpoint = e.data
// e.g. "http://localhost:3000/message?sessionId=client-1-1234567890"
})
// 3. Listen for responses and notifications on the SSE stream
events.addEventListener('message', (e) => {
const msg = JSON.parse(e.data)
if (msg.id) {
// Response to a request you sent
console.log('Response:', msg.result)
} else if (msg.method) {
// Server-initiated notification
console.log('Notification:', msg.method, msg.params)
}
})
// 4. Send JSON-RPC requests by POSTing to the endpoint
await fetch(messageEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: { name: 'greet', arguments: { name: 'World' } },
id: 1
})
})
// HTTP response is 202 Accepted — the actual result arrives on the SSE streamWebSocket(仅限Node.js)
基于WebSocket的全双向JSON-RPC。支持订阅和实时通知。
const ws = new WebSocket('ws://localhost:3000')
ws.onopen = () => {
// Initialize
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'initialize',
params: {
protocolVersion: '2025-03-26',
capabilities: {},
clientInfo: { name: 'ws-client', version: '1.0.0' }
},
id: 1
}))
// Call a tool
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: { name: 'greet', arguments: { name: 'World' } },
id: 2
}))
// Subscribe to resource updates
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'resources/subscribe',
params: { uri: 'stats://live' },
id: 3
}))
}
ws.onmessage = (e) => {
const msg = JSON.parse(e.data)
if (msg.type === 'connected') {
// Initial connection status
console.log('Connected as:', msg.clientId)
} else if (msg.id) {
// Response to a request
console.log('Response:', msg.result)
} else if (msg.method) {
// Server notification (resource updates, progress, etc.)
console.log('Notification:', msg.method, msg.params)
}
}运输退货对象
createHttpTransport() 返回:
| 属性 | 类型 | 描述 | |
|---|---|---|---|
port | number | 绑定端口 | |
host | string | 绑定主机 | |
httpServer | http.Server | 底层HTTP服务器 | |
wss | `WebSocketServer \ | null` | WebSocket服务器(Node.js,如果启用) |
wsClients | Map | 已连接的WebSocket客户端 | |
sseClients | Map | 连接的SSE客户端 | |
activityLog | Array | 最近的工具调用活动 | |
requestCount() | function | 返回请求总数 | |
broadcast(msg) | function | 发送给所有客户端(WS+SSE) | |
close() | async function | 优雅的关机 |
stdio运输
对于Claude Desktop和通过stdin/stdout通信的类似客户端:
import { createMCPServer } from 'bare-mcp'
import { createStdioTransport } from 'bare-mcp/stdio'
const mcp = createMCPServer({ name: 'my-server', version: '1.0.0' })
mcp.addTool({ /* ... */ })
await createStdioTransport(mcp, {
onActivity: (entry) => console.error('Tool:', entry.tool),
onClose: () => process.exit(0)
})配置MCP客户端
克劳德桌面(stdio)
~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/server.js"]
}
}
}克劳德桌面(HTTP)
{
"mcpServers": {
"my-server": {
"url": "http://localhost:3000/mcp"
}
}
}游标(HTTP)
在光标设置中→ MCP,添加服务器URL:
http://localhost:3000/mcpCursor使用流式HTTP传输(POST /mcp).
通用MCP客户端(HTTP)
任何支持Streamable HTTP的MCP客户端都可以通过指向 /mcp 端点:
http://your-host:3000/mcp使用传统SSE传输的客户端应连接到:
http://your-host:3000/sseMCP方法
| 方法 | 说明 |
|---|---|
initialize | 初始化连接,获取功能 |
tools/list | 列出可用工具 |
tools/call | 执行工具 |
resources/list | 列出可用资源 |
resources/templates/list | 列出资源模板 |
resources/read | 按URI读取资源 |
resources/subscribe | 订阅资源更新 |
resources/unsubscribe | 取消订阅更新 |
ping | 健康检查 |
通知类型
| 方法 | 说明 |
|---|---|
notifications/resources/updated | 资源的内容已更改 |
notifications/resources/list_changed | 添加/删除资源 |
notifications/tools/list_changed | 添加/删除工具 |
notifications/progress | 进度更新 |
API 参考
createMCPServer(options)
创建MCP服务器实例。
const mcp = createMCPServer({
name: 'my-server', // Server name
version: '1.0.0', // Server version
protocolVersion: '2025-11-25' // MCP protocol version
})返回一个具有以下属性的对象:
addTool(tool)/addTools(tools[])--注册工具addResource(resource)/addResources(resources[])--注册资源addResourceTemplate(template)--注册URI模板readResource(uri)--阅读资源notify(method, params)--发送通知notifyResourceUpdated(uri)--通知资源已更改notifyResourceListChanged()--通知添加/删除的资源notifyToolListChanged()--通知添加/删除的工具notifyProgress(token, progress, total?)--发送进度handleRequest(method, params)--处理JSON-RPC请求
createHttpTransport(mcp, options)
启动支持WebSocket和SSE的HTTP服务器。
const transport = await createHttpTransport(mcp, {
port: 3000,
host: '0.0.0.0',
websocket: true,
onActivity: (entry) => {}
})退货:
port,host--绑定地址httpServer--Node.js HTTP服务器wss--WebSocket服务器broadcast(message)--发送给所有客户close()--关闭服务器
createStdioTransport(mcp, options)
启动stdio传输以供CLI使用。
const transport = await createStdioTransport(mcp, {
onActivity: (entry) => {},
onClose: () => {}
})裸运行时(Pear)
这个图书馆使用 which-runtime 自动检测您是使用Node.js还是Bare,并加载正确的传输实现。无论哪种方式,你的代码都是一样的:
import { createMCPServer } from 'bare-mcp'
import { createHttpTransport } from 'bare-mcp/http' // Auto-detects runtime
import { createStdioTransport } from 'bare-mcp/stdio' // Auto-detects runtime
const mcp = createMCPServer({ name: 'my-app' })
mcp.addTool({ /* ... */ })
await createHttpTransport(mcp, { port: 3000 })显式导入
如果需要绕过运行时检测并针对特定实现:
| 传输 | Node.js | 裸 |
|---|---|---|
| HTTP | bare-mcp/http-node | bare-mcp/http-bare |
| 站立 | bare-mcp/stdio-node | bare-mcp/stdio-bare |
运输差异
| Node.js | 裸 | |
|---|---|---|
| 超文本传输协议 | node:http + ws --流式HTTP、SSE、WebSocket | bare-http1 --流式HTTP、SSE(无WebSocket) |
| 标准 | node:readline | 生的 process.stdin/stdout |
依赖项
对于Node.js:
npm install bare-mcp ws对于裸/梨:
npm install bare-mcp bare-http1许可证
麻省理工学院
