使用说明
Nochen jsonrpc
基于stdio(子进程通信)的干净、开发人员友好的JSON-RPC 2.0客户端
建在上面 @gnana997/node-jsonrpc 具有stdio传输层,用于使用行分隔的JSON与子进程通信。
非常适合为以下客户建立客户:
- 模型上下文协议(MCP) 服务器
- 语言服务器(LSP)
- 自定义基于stdio的JSON-RPC服务
- 具有JSON-RPC接口的CLI工具
特性
✨ 清洁API -用于stdio JSON-RPC通信的简单直观的界面 🚀 TypeScript优先 -具有泛型的完全类型安全 📦 双包装 -ESM和CommonJS支持 🔄 事件驱动 -基于EventEmitter构建,用于通知和日志 🛡️ 健壮 -全面的错误处理和流程生命周期管理 🧪 测试良好 -47项测试,覆盖率超过81% 📝 有据可查 -示例和包含的TypeScript类型
安装
npm install node-stdio-jsonrpc
快速开始
import { StdioClient } from 'node-stdio-jsonrpc';
// Create a client that spawns a child process
const client = new StdioClient({
command: 'node',
args: ['./your-jsonrpc-server.js'],
debug: true, // Optional: enable debug logging
});
// Connect to the server
await client.connect();
// Make a request
const result = await client.request('yourMethod', { param: 'value' });
console.log('Result:', result);
// Send a notification (no response expected)
client.notify('log', { level: 'info', message: 'Hello' });
// Listen for server notifications
client.on('notification', (method, params) => {
console.log(`Server notification: ${method}`, params);
});
// Disconnect when done
await client.disconnect();
API 参考
StdioClient
通过stdio创建JSON-RPC客户端的主类。
构造函数
new StdioClient(config: StdioClientConfig)
配置选项:
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
command |
string |
必需的 | 生成命令(例如。, 'node', 'python') |
args |
string[] |
[] |
传递给命令的参数 |
cwd |
string |
process.cwd() |
子进程的工作目录 |
env |
NodeJS.ProcessEnv |
process.env |
环境变量 |
connectionTimeout |
number |
10000 |
连接超时(毫秒) |
requestTimeout |
number |
30000 |
请求超时(毫秒) |
debug |
boolean |
false |
启用调试日志记录 |
方法
connect(): Promise<void>
生成子进程并建立连接。
await client.connect();
disconnect(): Promise<void>
终止子进程并清理资源。
await client.disconnect();
request<TResult>(method: string, params?: unknown): Promise<TResult>
发送JSON-RPC请求并等待响应。
interface CalculateResult {
sum: number;
}
const result = await client.request<CalculateResult>('calculate', {
operation: 'add',
a: 5,
b: 3,
});
console.log(result.sum); // 8
notify(method: string, params?: unknown): void
发送JSON-RPC通知(预期无响应)。
client.notify('log', { level: 'info', message: 'Task completed' });
isConnected(): boolean
检查客户端当前是否已连接。
if (client.isConnected()) {
console.log('Connected!');
}
事件
客户端扩展 EventEmitter 并发出以下事件:
| 事件 | 参数 | 描述 |
|---|---|---|
connected |
() |
连接建立时发出 |
disconnected |
() |
与服务器断开连接时发出 |
notification |
(method: string, params?: unknown) |
服务器发送了通知 |
error |
(error: Error) |
发生错误 |
log |
(message: string) |
服务器已写入stderr |
client.on('connected', () => {
console.log('Connected to server!');
});
client.on('disconnected', () => {
console.log('Disconnected from server');
});
client.on('notification', (method, params) => {
console.log(`Notification: ${method}`, params);
});
client.on('error', (error) => {
console.error('Error:', error);
});
client.on('log', (message) => {
console.log(`Server log: ${message}`);
});
StdioTransport
较低级别的运输实施。通常你会使用 StdioClient但是 StdioTransport 如果您需要直接控制,则可以使用。
import { StdioTransport } from 'node-stdio-jsonrpc/transport';
import { JSONRPCClient } from '@gnana997/node-jsonrpc';
const transport = new StdioTransport({
command: 'node',
args: ['./server.js'],
});
const client = new JSONRPCClient({ transport });
await client.connect();
例子
基础示例
import { StdioClient } from 'node-stdio-jsonrpc';
const client = new StdioClient({
command: 'node',
args: ['./echo-server.js'],
});
await client.connect();
const response = await client.request('echo', { message: 'Hello, World!' });
console.log(response); // { message: 'Hello, World!' }
await client.disconnect();
MCP客户端示例
非常适合连接到模型上下文协议服务器:
import { StdioClient } from 'node-stdio-jsonrpc';
const client = new StdioClient({
command: 'npx',
args: ['@modelcontextprotocol/server-filesystem', '~/Documents'],
debug: true,
});
await client.connect();
// Initialize MCP session
const initResult = await client.request('initialize', {
protocolVersion: '2024-11-05',
capabilities: { roots: { listChanged: true } },
clientInfo: { name: 'my-client', version: '1.0.0' },
});
client.notify('notifications/initialized');
// List available tools
const { tools } = await client.request('tools/list');
console.log('Available tools:', tools);
await client.disconnect();
看 MCP客户端示例 为了完整实施。
错误处理
import { StdioClient, JSONRPCError } from 'node-stdio-jsonrpc';
const client = new StdioClient({
command: 'node',
args: ['./server.js'],
});
try {
await client.connect();
const result = await client.request('someMethod', { param: 'value' });
console.log('Success:', result);
} catch (error) {
if (error instanceof JSONRPCError) {
console.error('JSON-RPC Error:', error.code, error.message);
} else {
console.error('Connection/Transport Error:', error);
}
} finally {
if (client.isConnected()) {
await client.disconnect();
}
}
使用TypeScript
import { StdioClient } from 'node-stdio-jsonrpc';
// Define your request/response types
interface CalculateParams {
operation: 'add' | 'subtract' | 'multiply' | 'divide';
a: number;
b: number;
}
interface CalculateResult {
result: number;
}
const client = new StdioClient({
command: 'node',
args: ['./calculator-server.js'],
});
await client.connect();
// Type-safe requests
const result = await client.request<CalculateResult>('calculate', {
operation: 'add',
a: 10,
b: 5,
} satisfies CalculateParams);
console.log(result.result); // TypeScript knows this is a number
await client.disconnect();
协议
此库实现 JSON-RPC 2.0 超过 标准 (标准输入/输出)使用 行分隔JSON 框架:
- 每条JSON消息都在自己的行上
- 消息以以下方式终止
\n - stdin:客户端→ 服务器
- stdout:服务器→ 客户端(JSON-RPC消息)
- stderr:服务器日志(不是JSON-RPC)
消息格式
请求:
{"jsonrpc":"2.0","id":1,"method":"methodName","params":{"key":"value"}}
成功响应:
{"jsonrpc":"2.0","id":1,"result":{"data":"value"}}
错误响应:
{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"Error message"}}
通知(无id):
{"jsonrpc":"2.0","method":"notifyMethod","params":{"key":"value"}}
需求
- Node.js 18或更高版本
- TypeScript 5.x(如果使用TypeScript)
相关包
@gnana997/node-jsonrpc-核心JSON-RPC 2.0实现node-ipc-jsonrpc-基于IPC的JSON-RPC(Unix套接字/Windows命名管道)
贡献
欢迎投稿!请看 贡献.md 作为指导方针。
许可证
MIT© 格纳997
更新日志
看 更改日志.md 版本历史。
内置❤️ 使用TypeScript和 @gnana997/节点jsonrpc
