Liking cljdoc? Tell your friends :D

im.ttalk.agent.mcp.transport

客户端传输:Streamable HTTP 与 stdio。

一个协议、两个实现,外加「传输就是一个函数」这条后门:

(send! t msg)   ;; 请求 → 响应 map;通知 → nil
(close! t)      ;; 释放(stdio 杀子进程;HTTP 无状态,无操作)

(fn [msg] resp) 也是合法传输(send! 对 IFn 有实现)——测试因此不用起 服务、不用起进程,一个纯函数就能把整条客户端逻辑跑完。这条不是给测试开的 特例,它就是这层的最小契约。

Streamable HTTP(2026-07-28)

POST 一条 JSON-RPC,Accept: application/json, text/event-stream,响应可能是 两种之一。三个头是必填且不能与信封不一致:

头值不对会怎样
MCP-Protocol-Version与 _meta 里的版本同一个值-32020 HeaderMismatch
Mcp-Method与 body 的 method 同一个值同上
Mcp-Name只对 tools/call / prompts/get(取 name)与 resources/read(取 uri)同上

版本是从信封里反读的(protocol/protocol-version-of),不是传输自己记一份 ——两处各记一份就是 -32020 的来源。

没有会话:modern 不再有 Mcp-Session-Id。但双时代客户端要连老 server, 所以这里仍然会收下并回传 server 给的 session id;modern 路径上 server 不会 给,这段代码就是死的。

stdio

一行一条 JSON(消息内不得有裸换行)。读端是一条后台线程:响应按 id 交给 等待中的 promise,其余(通知、日志)交给 :on-notification。

为什么不能「写一行、读一行」了事:协议允许 server 在响应之前先推通知 (进度、日志、订阅事件),同步读会把它们当成响应。而且 2026-07-28 明说 「一条 stdio 连接不是一个会话」,客户端可以在同一个进程上交错发无关请求。

客户端传输:Streamable HTTP 与 stdio。

一个协议、两个实现,外加「传输就是一个函数」这条后门:

```clojure
(send! t msg)   ;; 请求 → 响应 map;通知 → nil
(close! t)      ;; 释放(stdio 杀子进程;HTTP 无状态,无操作)
```

**`(fn [msg] resp)` 也是合法传输**(`send!` 对 `IFn` 有实现)——测试因此不用起
服务、不用起进程,一个纯函数就能把整条客户端逻辑跑完。这条不是给测试开的
特例,它就是这层的最小契约。

## Streamable HTTP(2026-07-28)

POST 一条 JSON-RPC,`Accept: application/json, text/event-stream`,响应可能是
两种之一。三个头是**必填**且**不能与信封不一致**:

| 头 | 值 | 不对会怎样 |
|---|---|---|
| `MCP-Protocol-Version` | 与 `_meta` 里的版本**同一个值** | `-32020 HeaderMismatch` |
| `Mcp-Method` | 与 body 的 `method` 同一个值 | 同上 |
| `Mcp-Name` | 只对 `tools/call` / `prompts/get`(取 `name`)与 `resources/read`(取 `uri`) | 同上 |

版本是从**信封里反读**的(`protocol/protocol-version-of`),不是传输自己记一份
——两处各记一份就是 `-32020` 的来源。

**没有会话**:modern 不再有 `Mcp-Session-Id`。但双时代客户端要连老 server,
所以这里仍然会**收下并回传** server 给的 session id;modern 路径上 server 不会
给,这段代码就是死的。

## stdio

一行一条 JSON(消息内不得有裸换行)。读端是一条**后台线程**:响应按 id 交给
等待中的 promise,其余(通知、日志)交给 `:on-notification`。

为什么不能「写一行、读一行」了事:协议允许 server 在响应之前先推通知
(进度、日志、订阅事件),同步读会把它们当成响应。而且 2026-07-28 明说
「一条 stdio 连接不是一个会话」,客户端可以在同一个进程上交错发无关请求。
raw docstring

http-transportclj

(http-transport {:keys [url headers timeout-ms client proxy]
                 :or {timeout-ms 30000}})

Streamable HTTP 传输(传输层是 im.ttalk.http)。

  • :url 必填
  • :headers 额外头(鉴权走这里;MCP 的 auth 框架只管 HTTP)
  • :timeout-ms 单次请求上限(缺省 30s)
  • :client 自带 java.net.http.HttpClient;缺省共享的 im.ttalk.http/default-client (HTTP/1.1、虚拟线程、connect 30s——designs/http-module.md §6)
  • :proxy 没给 :client 时用::env(读 https_proxy / no_proxy …)、代理地址串,或 ProxySelector
Streamable HTTP 传输(传输层是 `im.ttalk.http`)。

- `:url`        必填
- `:headers`    额外头(鉴权走这里;MCP 的 auth 框架只管 HTTP)
- `:timeout-ms` 单次请求上限(缺省 30s)
- `:client`     自带 `java.net.http.HttpClient`;缺省共享的 `im.ttalk.http/default-client`
                (HTTP/1.1、虚拟线程、connect 30s——designs/http-module.md §6)
- `:proxy`      没给 `:client` 时用:`:env`(读 https_proxy / no_proxy …)、代理地址串,或 ProxySelector
sourceraw docstring

stdio-transportclj

(stdio-transport {:keys [command env dir timeout-ms on-notification]
                  :or {timeout-ms 30000}})

起一个子进程当 MCP server,用它的 stdin/stdout 说话。

  • :command ["npx" "-y" "@modelcontextprotocol/server-everything"](必填)
  • :env 追加的环境变量 map
  • :dir 工作目录
  • :timeout-ms 单次请求上限(缺省 30s)
  • :on-notification (fn [msg])——通知与「没人等的响应」都走这里

stderr 直接继承父进程:server 的诊断信息本来就该看得见,吞掉它等于把 「为什么连不上」变成猜谜。

起一个子进程当 MCP server,用它的 stdin/stdout 说话。

- `:command`  `["npx" "-y" "@modelcontextprotocol/server-everything"]`(必填)
- `:env`      追加的环境变量 map
- `:dir`      工作目录
- `:timeout-ms` 单次请求上限(缺省 30s)
- `:on-notification` `(fn [msg])`——通知与「没人等的响应」都走这里

**stderr 直接继承父进程**:server 的诊断信息本来就该看得见,吞掉它等于把
「为什么连不上」变成猜谜。
sourceraw docstring

Transportcljprotocol

close!clj

(close! t)

释放资源。

释放资源。

send!clj

(send! t msg)

发一条消息。请求返回响应 map;通知返回 nil。

发一条消息。请求返回响应 map;通知返回 nil。
source

transport-errorclj

(transport-error msg data)

传输层失败。带上足够让客户端判时代的证据:HTTP 状态码与响应体里可能有的 JSON-RPC 错误——双时代回退正是看这两样(见 mcp.client)。

传输层失败。**带上足够让客户端判时代的证据**:HTTP 状态码与响应体里可能有的
JSON-RPC 错误——双时代回退正是看这两样(见 `mcp.client`)。
sourceraw docstring

transport-error?clj

(transport-error? t)
source

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close