@xiaozhi-client/mcp-core
MCP 协议核心实现库,提供服务连接和管理功能

简介
@xiaozhi-client/mcp-core 是一个完全独立的 MCP(Model Context Protocol)核心实现库,提供:
- 零业务耦合 - 纯粹的 MCP 协议实现,无任何业务逻辑依赖
- 多传输协议支持 - 支持 STDIO、SSE、HTTP 三种传输方式
- 灵活的事件系统 - 基于回调的事件机制,易于集成
- 完整的类型定义 - TypeScript 严格模式,提供完整的类型支持
- 生产就绪 - 经过充分测试,可直接用于生产环境
特性
核心功能
- MCP 服务连接管理 - 自动连接、重连、断开处理
- 工具发现与管理 - 自动发现和管理 MCP 工具
- 工具调用 - 简单易用的工具调用接口
- 参数验证 - 内置参数验证和类型检查
- 事件通知 - 连接状态变化、工具更新的实时通知
传输协议
| STDIO | 标准输入输出通信 | 本地进程通信 |
| SSE | Server-Sent Events | 单向服务器推送 |
| HTTP | HTTP 通信 | 现代 HTTP 场景 |
安装
npm install @xiaozhi-client/mcp-core
pnpm add @xiaozhi-client/mcp-core
yarn add @xiaozhi-client/mcp-core
依赖要求
{
"peerDependencies": {
"@modelcontextprotocol/sdk": "^1.24.0"
}
}
请确保项目中安装了 @modelcontextprotocol/sdk:
npm install @modelcontextprotocol/sdk
快速开始
使用 MCPManager(推荐)
MCPManager 提供了简洁的 API 来管理多个 MCP 服务:
import { MCPManager } from '@xiaozhi-client/mcp-core';
const manager = new MCPManager();
manager.addServer('datetime', {
type: 'stdio',
command: 'node',
args: ['datetime.js']
});
manager.addServer('web-search', {
type: 'http',
url: 'https://api.example.com/mcp',
headers: {
Authorization: 'Bearer your-api-key'
}
});
manager.addServer('sse-server', {
type: 'sse',
url: 'https://api.example.com/sse'
});
manager.addServer('custom-server', {
type: 'stdio',
command: 'npx',
args: ['-y', '@example/mcp-server'],
env: {
API_KEY: 'your-api-key',
MODE: 'production'
}
});
await manager.connect();
const result = await manager.callTool('datetime', 'get_current_time', {
format: 'YYYY-MM-DD HH:mm:ss'
});
const tools = manager.listTools();
console.log('可用工具:', tools.map(t => `${t.serverName}/${t.name}`));
const status = manager.getServerStatus('datetime');
console.log('datetime 服务状态:', status);
await manager.disconnect();
事件监听
manager.on('connect', () => {
console.log('开始连接所有服务');
});
manager.on('connected', ({ serverName, tools }) => {
console.log(`服务 ${serverName} 已连接,发现 ${tools.length} 个工具`);
});
manager.on('disconnected', ({ serverName, reason }) => {
console.log(`服务 ${serverName} 已断开: ${reason}`);
});
manager.on('error', ({ serverName, error }) => {
console.error(`服务 ${serverName} 出错:`, error.message);
});
manager.on('disconnect', () => {
console.log('所有服务已断开');
});
MCPManager API 方法
addServer(name, config) | 添加服务器配置 | void |
removeServer(name) | 移除服务器配置 | boolean |
connect() | 连接所有服务 | Promise<void> |
disconnect() | 断开所有服务 | Promise<void> |
callTool(serverName, toolName, args) | 调用指定服务的工具 | Promise<ToolCallResult> |
listTools() | 列出所有可用工具 | ToolInfo[] |
getServerStatus(name) | 获取服务状态 | ServiceStatus | null |
getAllServerStatus() | 获取所有服务状态 | Record<string, ServiceStatus> |
isConnected(name) | 检查服务是否已连接 | boolean |
getServerNames() | 获取已配置的服务名列表 | string[] |
getConnectedServerNames() | 获取已连接的服务名列表 | string[] |
使用 MCPConnection(底层 API)
如果你需要更细粒度的控制,可以直接使用 MCPConnection:
基础用法
import { MCPConnection, MCPTransportType } from '@xiaozhi-client/mcp-core';
const config = {
name: 'my-mcp-service',
type: MCPTransportType.HTTP,
url: 'https://api.example.com/mcp',
apiKey: 'your-api-key'
};
const callbacks = {
onConnected: (data) => {
console.log(`服务 ${data.serviceName} 已连接,发现 ${data.tools.length} 个工具`);
},
onDisconnected: (data) => {
console.log(`服务 ${data.serviceName} 已断开: ${data.reason}`);
},
onConnectionFailed: (data) => {
console.error(`连接失败: ${data.error.message}`);
}
};
const connection = new MCPConnection(config, callbacks);
await connection.connect();
const result = await connection.callTool('my_tool', {
param1: 'value1',
param2: 'value2'
});
const tools = connection.getTools();
console.log('可用工具:', tools.map(t => t.name));
await connection.disconnect();
STDIO 连接示例
import { MCPConnection, MCPTransportType } from '@xiaozhi-client/mcp-core';
const config = {
name: 'local-mcp-server',
type: MCPTransportType.STDIO,
command: 'node',
args: ['path/to/server.js'],
env: {
NODE_ENV: 'production'
}
};
const connection = new MCPConnection(config);
await connection.connect();
SSE 连接示例
import { MCPConnection, MCPTransportType } from '@xiaozhi-client/mcp-core';
const config = {
name: 'sse-server',
type: MCPTransportType.SSE,
url: 'https://api.example.com/sse',
headers: {
'X-Custom-Header': 'value'
}
};
const connection = new MCPConnection(config);
await connection.connect();
核心概念
MCPConnection
MCPConnection 是核心连接类,负责单个 MCP 服务的完整生命周期管理。
主要方法
connect() | 建立连接 | Promise<void> |
disconnect() | 断开连接 | Promise<void> |
callTool(name, args) | 调用工具 | Promise<ToolCallResult> |
getTools() | 获取工具列表 | Tool[] |
getConfig() | 获取配置 | MCPServiceConfig |
getStatus() | 获取状态 | MCPServiceStatus |
isConnected() | 检查连接状态 | boolean |
连接状态
enum ConnectionState {
DISCONNECTED = 'disconnected',
CONNECTING = 'connecting',
CONNECTED = 'connected',
RECONNECTING = 'reconnecting',
FAILED = 'failed',
ERROR = 'error'
}
事件回调
使用回调函数模式处理连接事件:
interface MCPServiceEventCallbacks {
onConnected?: (data: {
serviceName: string;
tools: Tool[];
connectionTime: Date;
}) => void;
onDisconnected?: (data: {
serviceName: string;
reason?: string;
disconnectionTime: Date;
}) => void;
onConnectionFailed?: (data: {
serviceName: string;
error: Error;
attempt: number;
}) => void;
}
配置选项
MCPServiceConfig
interface MCPServiceConfig {
name: string;
type?: MCPTransportType;
command?: string;
args?: string[];
env?: Record<string, string>;
url?: string;
apiKey?: string;
headers?: Record<string, string>;
}
传输类型推断
如果不指定 type,库会自动根据配置推断:
- 有
command 字段 → MCPTransportType.STDIO
- 有
url 字段 → MCPTransportType.HTTP 或 MCPTransportType.SSE
工具调用
基础调用
const result = await connection.callTool('tool_name', {
parameter1: 'value1',
parameter2: 123
});
interface ToolCallResult {
content: Array<{
type: string;
text: string;
}>;
isError?: boolean;
}
参数验证
使用内置验证器确保参数正确:
import { validateToolCallParams, ToolCallValidationOptions } from '@xiaozhi-client/mcp-core';
const options: ToolCallValidationOptions = {
validateName: true,
validateArguments: true,
allowEmptyArguments: false
};
const validated = validateToolCallParams(params, options);
错误处理
import { ToolCallError, ToolCallErrorCode } from '@xiaozhi-client/mcp-core';
try {
await connection.callTool('tool_name', params);
} catch (error) {
if (error instanceof ToolCallError) {
switch (error.code) {
case ToolCallErrorCode.INVALID_PARAMS:
console.error('参数无效');
break;
case ToolCallErrorCode.TOOL_NOT_FOUND:
console.error('工具不存在');
break;
case ToolCallErrorCode.SERVICE_UNAVAILABLE:
console.error('服务不可用');
break;
}
}
}
工具函数
TypeFieldNormalizer
标准化类型字段格式:
import { normalizeTypeField } from '@xiaozhi-client/mcp-core';
normalizeTypeField({ type: 'streamableHttp' });
normalizeTypeField({ type: 'S_SE' });
TransportFactory
直接创建传输层:
import { TransportFactory } from '@xiaozhi-client/mcp-core';
const transport = TransportFactory.create(config);
完整示例
带完整错误处理的 MCP 客户端
import {
MCPConnection,
MCPTransportType,
ToolCallError,
ToolCallErrorCode
} from '@xiaozhi-client/mcp-core';
class MyMCPClient {
private connection: MCPConnection;
constructor(url: string, apiKey: string) {
const config = {
name: 'my-service',
type: MCPTransportType.HTTP,
url,
apiKey
};
const callbacks = {
onConnected: (data) => {
console.log(`✅ 已连接,发现 ${data.tools.length} 个工具`);
},
onDisconnected: (data) => {
console.log(`❌ 已断开: ${data.reason}`);
},
onConnectionFailed: (data) => {
console.error(`⚠️ 连接失败: ${data.error.message}`);
}
};
this.connection = new MCPConnection(config, callbacks);
}
async connect() {
try {
await this.connection.connect();
} catch (error) {
console.error('连接错误:', error);
throw error;
}
}
async callTool(name: string, params: Record<string, unknown>) {
try {
const result = await this.connection.callTool(name, params);
if (result.isError) {
throw new Error(`工具调用失败: ${result.content[0]?.text}`);
}
return result.content[0]?.text;
} catch (error) {
if (error instanceof ToolCallError) {
this.handleToolCallError(error);
}
throw error;
}
}
private handleToolCallError(error: ToolCallError) {
switch (error.code) {
case ToolCallErrorCode.INVALID_PARAMS:
console.error('❌ 参数错误:', error.message);
break;
case ToolCallErrorCode.TOOL_NOT_FOUND:
console.error('❌ 工具不存在:', error.message);
break;
case ToolCallErrorCode.TIMEOUT:
console.error('⏱️ 调用超时:', error.message);
break;
default:
console.error('❌ 未知错误:', error.message);
}
}
async disconnect() {
await this.connection.disconnect();
}
}
const client = new MyMCPClient(
'https://api.example.com/mcp',
'your-api-key'
);
await client.connect();
const result = await client.callTool('calculate', {
expression: '2 + 2'
});
console.log('结果:', result);
await client.disconnect();
API 参考
导出的类
export { MCPConnection } from './connection.js';
export { MCPManager, MCPServiceManager } from './manager.js';
export { ToolCallError } from './types.js';
export { TransportFactory } from './transport-factory.js';
导出的类型
export type {
MCPServiceConfig,
ModelScopeSSEOptions,
UnifiedServerConfig,
MCPServiceStatus,
MCPServiceConnectionStatus,
ManagerStatus,
UnifiedServerStatus,
ToolInfo,
EnhancedToolInfo,
ToolCallResult,
ToolCallParams,
ValidatedToolCallParams,
ToolCallValidationOptions,
CustomMCPTool,
JSONSchema,
MCPServerTransport,
MCPServiceEventCallbacks,
} from './types.js';
导出的枚举
export {
MCPTransportType,
ConnectionState,
ToolCallErrorCode,
} from './types.js';
导出的工具函数
export {
TypeFieldNormalizer,
normalizeTypeField,
validateToolCallParams,
inferTransportTypeFromUrl,
inferTransportTypeFromConfig,
} from './utils/index.js';
export {
isValidToolJSONSchema,
ensureToolJSONSchema,
} from './types.js';
开发指南
本地开发
git clone https://github.com/shenjingnan/xiaozhi-client.git
cd xiaozhi-client/packages/mcp-core
pnpm install
pnpm dev
pnpm build
pnpm test
pnpm type-check
构建产物
dist/
├── index.js
├── index.d.ts
└── index.js.map
最佳实践
1. 连接管理
try {
await connection.connect();
} finally {
await connection.disconnect();
}
await connection.connect();
2. 错误处理
try {
await connection.callTool(name, params);
} catch (error) {
if (error instanceof ToolCallError) {
}
}
await connection.callTool(name, params);
3. 配置验证
const config = {
name: 'service',
url: 'https://api.example.com'
};
const config = {
name: 'service',
type: MCPTransportType.SSE,
url: 'https://api.example.com'
};
常见问题
Q: 如何选择传输协议?
A:
- 本地进程 → 使用
STDIO
- 单向推送 → 使用
SSE
- 现代 HTTP → 使用
HTTP(推荐)
Q: 如何处理连接失败?
A: 使用 onConnectionFailed 回调:
const callbacks = {
onConnectionFailed: (data) => {
console.error(`第 ${data.attempt} 次尝试失败`);
}
};
Q: 工具调用支持流式响应吗?
A: 这取决于具体的 MCP 服务实现。@xiaozhi-client/mcp-core 支持所有 MCP SDK 定义的功能,包括流式响应。
许可证
MIT
相关资源
作者: xiaozhi-client
版本: 1.9.7-beta.3