JSON-RPC协议转换工具

Legatus是一个协议边界处理工具,通过STDIO与HTTP/WebSocket之间的JSON-RPC消息转发,实现客户端无需嵌入传输逻辑即可与远程服务通信。

  • by sovetnik
  • Elixir
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 sovetnik/legatus

使用说明

准备就绪

JSON-RPC边界:STDIO↔ HTTP/WebSocket

Legatus 是一个协议边界过程。
它从STDIN读取JSON-RPC,并通过以下两种模式之一中继消息:

  • :http --向上游HTTP端点的请求/响应传输
  • :websocket --持久WebSocket上的双向中继

Legatus为什么存在

Legatus解决了一个具体问题: 使STDIO JSON-RPC客户端与远程传输通信,而无需在客户端中嵌入传输逻辑。

快速开始

# Build the escript
mix escript.install hex legatus

# or
git clone git@github.com:sovetnik/legatus.git
mix escript.build

# Start your JSON-RPC HTTP server (example on port 4000)
# Then send a request:
echo '{"jsonrpc":"2.0","method":"add","params":[2,3],"id":1}' | \
  ./legatus http://localhost:4000/rpc

mix escript.build 收集 legatus 本地,和 mix escript.install 将其设置为可用的命令 PATH.

预期产量:

{"jsonrpc":"2.0","result":5,"id":1}

就是这样,一行进去,一行出去。STDIO变成HTTP,HTTP变成STDIO。

架构(当前)

图层

  • Legatus.Paramount
    流程编排和运行时生命周期。
  • Legatus.Canalis.*
    混凝土渠道/运输(Stdio, Http, Ws).
  • Legatus.Umwelt.*
    解释管道: Merkwelt.distinctio -> Verstand.descriptio -> Wirkwelt.portare.
  • Legatus.Aussenwelt
    边界解析/格式(receptio / profanatio).

使用模式

作为Escript(推荐用于生产)

mix escript.build
./legatus http://localhost:4000/rpc

使用承载令牌身份验证

当您的上游服务器需要身份验证时,通过环境变量传递令牌:

# Using escript
token=your_secret_token ./legatus http://localhost:4000/rpc

# Using escript
token=your_secret_token ./legatus http://localhost:4000/rpc

Legatus将自动添加 Authorization: Bearer <token> 所有HTTP请求的头部。

编辑器集成示例(Zed、Claude Code等):

{
  "context_servers": {
    "my_server": {
      "source": "custom",
      "enabled": true,
      "command": "legatus",
      "args": ["http://localhost:4000/rpc"],
      "env": {"token": "your_secret_token"}
    }
  }
}

流动

HTTP模式:

STDIN -> Aussenwelt.receptio -> Umwelt.percipere -> Canalis.Http.Client -> Aussenwelt.profanatio -> STDOUT

Websocket模式:

STDIN (uplink) -> Aussenwelt.receptio -> Umwelt.percipere -> Canalis.Ws.send_request
Canalis.Ws.receive_message (downlink) -> Aussenwelt.receptio -> Umwelt.percipere -> STDOUT

建筑

数据流

管道使用标记的元组来跟踪数据状态:

  1. 接待处 (Aussenwelt):解析JSON
    {:phaenomenon, map} | {:fiasco, json_error}

  2. 感知 (Merkwelt):验证请求
    {:actio, map} | {:fiasco, error_map}

  3. 携带 (操作世界):HTTP传输
    {:gloria, map} | {:fiasco, error_map} | {:silentium, map}

  4. Profanatio (Aussenwelt):格式化输出
    {:gloria, json} | {:fiasco, json} | {:silentium, "Nullius in verba"}

  5. 发射 (Geist):写信给STDOUT或跳过

关键模块

  • Legatus --入口点(invoke/2, invoke/3)
  • Legatus.Paramount.Http --HTTP运行时进程
  • Legatus.Paramount.Ws --WebSocket运行时进程
  • Legatus.Canalis.Stdio --STDIN/STDOUT边界
  • Legatus.Canalis.Http.Client --HTTP POST传输
  • Legatus.Canalis.Ws --有状态的WS客户端进程
  • Legatus.Paramount.Memento --WS-close语义的待定请求ID
  • Legatus.Chronica --测井

执行期语意学

  • 在 :http 模式下,当STDIN达到EOF时,运行时终止。
  • 在 :websocket 模式下,运行时在WS关闭/关闭时终止,并发出JSON-RPC错误 -32001 带信息 "connection_closed" 对于未决请求。

错误处理

所有错误均符合JSON-RPC标准:

  • -32700 解析错误(JSON无效)
  • -32600 无效请求(缺少方法)
  • -32000 HTTP错误(4xx/5xx)
  • -32001 传输错误(连接被拒绝)

配置

Legatus是通过命令行参数配置的:

./legatus http://localhost:4000/rpc

模式选择:

./legatus http://localhost:4000/rpc
./legatus ws://localhost:4000/ws --ws

测试

  • 流程生命周期断言: ExUnitEx (assert_processes_started/stopped)
  • WS通道内存的队列/等待语义: test/legatus/canalis/ws/memento_test.exs
  • 边界解析/格式语义: Aussenwelt 测试
  • 集成运行时测试:
    • test/legatus/paramount/http_test.exs
    • test/legatus/paramount_test.exs

JSON-RPC支持

请求:

  • ✅ 标准请求 id
  • ✅ 通知(否 id)
  • ❌ 不支持批处理(请求数组)

回复

  • ✅ 成功响应(result)
  • ✅ 错误响应(error)
  • ✅ HTTP 204处理(通知)

局限性

  • 每个进程调用一个运行时
  • 没有内置重试/回退策略
  • 没有业务逻辑;仅限运输/翻译
  • 不支持JSON-RPC批处理请求/响应

许可证

请参阅许可证文件。

词源

  • 准备就绪 (拉丁语)-特使、信使
  • 澳大利亚 --外部世界
  • Merkwelt --知觉区别
  • 理解 --解释/描述
  • 工作世界 --动作世界
  • 至高无上的 --运行时进程现实的挂载点