MCP(1) -- STDIO

通信方式 stdio
stdio:每个在操作系统上执行中的进程都有几个接口 stdout stdin stderr 标准输入/输出/错误。
stdio,是在一台机器上不同进程间通信的一种方式。
js
// in node.js
console.log("hello console")
process.stdout.write("hello stdout")我们在 node 中去跑一个 console.log,内部就是调用的 stdout.
js
console.log("PID:",process.pid)process 对象上也可以拿到当前进程 ID,正如任务管理器里看到的一样。
bash
node server.js当启用终端,然后输入 node xxx.js,那么终端进程就创建了一个 node 进程,然后把这个 xxx.js 作为参数,把参数发送给在 node 进程,代码在 node 进程中执行。
当我们xxx.js中还执行了一个 process.stdout.write("hello stdout") 时,会打印到终端。这背后其实就是终端进程监听了 node 进程的标准输出接口。
js
process.stdin.on('data', data=>{
const resp = `哈哈,${data}`
process.stdout.write(resp)
})
运行上面的脚本,会得到一个永不结束的进程,在终端输入并回车,可以给进程发消息,这背后就是终端进程,把用户输入,通过 node 进程的标准输入接口传入数据。
上面的实践中,终端相当于 Client,node 进程相当于 Server,已经有了一个交互的雏形,自然,这个 Client 我们也能自己写。
js
import { spawn } from 'child_process'
const serverProcess = spawn('node', ['server.js'])
// 监听 server 进程的标准输出
serverProcess.stdout.on('data', (data) => {
console.log(data.toString())
})
// 利用标准输入接口,向 server 进程写入数据
serverProcess.stdin.write("hello server")特点:适用于本地,stdio 通信高效、简介。
通信格式 JSON-RPC
Request
json
{
"jsonrpc":"2.0",
"method": "myMethod",
"params": {
"a": 5,
"b": 6,
...
},
"id": 1
}Response
json
{
"jsonrpc":"2.0",
"result": 11,
"id": 1
}基于上面一种格式,我们可以在 node 中,基于标准输入接口做如下实现
js
import tools from './tool.js'
process.stdin.on('data', data => {
const req = JSON.parse(data)
const { method, params } = req
const result = tools[method](params)
const res = {
jsonrpc: "2.0",
result,
id: req.id
}
process.stdout.write(JSON.stringify(res))
})用这种方式,我们就可以实现规范的进程间通信交互和功能调用。A 进程没有执行某功能的能力,B 进程有,那么我们就可以用上边的实现,让 A 进程去找 B 进程执行后拿到结果。