基于 MCP 最新规范 2025-11-25(https://modelcontextprotocol.io/specification/2025-11-25)对当前仓库的 MCP 实现进行了审查。
结论:当前实现仍主要停留在 2024-11-05 协议语义与旧版 HTTP+SSE 传输模型上,基础能力可用,但与 2025-11-25 规范存在较明确的兼容性缺口。 若目标是兼容更多新 MCP Server、对齐最新 SDK/规范、减少互操作问题,建议分阶段升级。
重点审查了以下实现:
src/mcp/client.tssrc/mcp/manager.tssrc/mcp/types.tssrc/core/config.tssrc/mcp/app/host.tssrc/mcp/app/types.ts
当前 MCP 实现的主要特点:
- 初始化时固定发送
protocolVersion: "2024-11-05" - 远端 HTTP 连接使用旧版 HTTP+SSE 模型
- 已实现的 server feature 较少,主要只有:
tools/listtools/callresources/read
- 未覆盖或未处理的能力较多,包括:
resources/listresources/templates/listresources/subscribeprompts/listprompts/getcompletion/completelogging/setLevelnotifications/messagenotifications/*/list_changednotifications/progressnotifications/cancelledroots/list- sampling / elicitation / tasks
当前实现不是完全不兼容,但它是按较早期 MCP 规范设计的;对于只支持旧版协议或愿意向后兼容的 server,通常还能工作;但对于按 2025-11-25 新规范实现、尤其依赖 Streamable HTTP、通知语义、分页、日志、进度与取消机制的 server,存在较高概率的兼容问题。
- 协议版本过旧:客户端固定声明
2024-11-05 - HTTP 传输模型过时:仍以旧版 HTTP+SSE 为主,而不是
Streamable HTTP - 未实现若干关键 utilities:取消、进度、日志、list changed
- 未完整消费 Tool 结果语义:未正确处理
isError - feature 覆盖不足:缺少 prompts/resources discovery/completion/roots 等能力
位置:src/mcp/client.ts:9
const MCP_PROTOCOL_VERSION = "2024-11-05";根据 2025-11-25 lifecycle 规范,客户端初始化时应发送自己支持的协议版本,且通常应优先发送最新支持版本。当前固定发送旧版本,意味着:
- 新 server 可能只能退回兼容模式
- 也可能直接按新规范工作,导致行为不一致
- 后续 HTTP 请求中要求的
MCP-Protocol-Versionheader 也没有实现
- 将首选协议版本升级为
2025-11-25 - 如需兼容旧 server,增加版本协商/fallback 逻辑
P0 / 高
位置:
src/mcp/types.ts:28src/core/config.ts:159src/mcp/client.ts:214
当前 transport 类型:
transport: "stdio" | "sse";2025-11-25 标准传输为:
stdioStreamable HTTP
旧的 HTTP+SSE 已被新规范替代,仅建议作为向后兼容保留。
当前 connectSSE() 的逻辑是:
- 先
GET建立 SSE - 等待
endpoint事件 - 再向该 endpoint 发 POST
这是典型 2024-11-05 HTTP+SSE 模型,不是 2025-11-25 的 Streamable HTTP。
新版 Streamable HTTP 的关键点:
- 单一 MCP endpoint
- client -> server 消息一律走
POST POST必须带Accept: application/json, text/event-stream- server 可返回:
- 单个
application/json - 或
text/event-stream
- 单个
- client 可额外
GET同一 endpoint 建立 server -> client SSE 流 - 支持:
MCP-Protocol-VersionMCP-Session-IdLast-Event-ID- 404/405/202 等语义
目前未实现:
- Streamable HTTP 的
POST initialize - 单 endpoint 模式
MCP-Protocol-VersionheaderMCP-Session-Id的保存和复用- session 失效后的重建
Last-Event-ID恢复能力- GET stream / POST stream 的规范区分
- 将 transport 抽象升级为:
"stdio""streamable-http"- 可选
"sse"(legacy fallback)
- 优先尝试
Streamable HTTP - 当遇到兼容性失败时,再回退到 legacy HTTP+SSE
- 不再将
url默认推断为sse
P0 / 最高
位置:
src/mcp/client.ts:223src/mcp/client.ts:347
当前 GET 请求只发:
headers: { Accept: "text/event-stream" }当前 POST 请求只发:
headers: { "Content-Type": "application/json" }Streamable HTTP 下,规范要求:
- POST 必须包含
Accept: application/json, text/event-stream - 初始化后后续 HTTP 请求必须带
MCP-Protocol-Version - 若 server 返回
MCP-Session-Id,后续请求必须回带该 header
- 未发送
Accept: application/json, text/event-stream - 未发送
MCP-Protocol-Version - 未处理
MCP-Session-Id
P0 / 高
位置:
src/mcp/client.ts:85src/mcp/client.ts:279
当前 stdio 关闭时直接 kill:
this.killProcessTree();2025-11-25 lifecycle 对 stdio shutdown 的建议为:
- 先关闭 server stdin
- 等待 server 自行退出
- 超时再发
SIGTERM - 仍不退出再发
SIGKILL
将当前 stdio close() 改为更平滑的 graceful shutdown。
P1 / 中高
位置:src/mcp/client.ts:331
当前超时只做本地 reject,没有向 server 发取消通知。
超时场景下,发送方 SHOULD 发送:
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": 123,
"reason": "Request timeout"
}
}- server 侧任务可能继续执行
- 资源浪费
- 长任务 server 兼容性较差
- 对所有非
initialize请求记录 request id - 超时或用户中止时发送
notifications/cancelled - 取消后忽略迟到响应
P1 / 高
位置:src/mcp/client.ts:315
当前所有 notification 基本都被忽略:
if (msg.id === undefined && msg.method) {
return;
}若客户端希望接收进度,应在请求参数中通过 _meta.progressToken 传入 token;server 可回:
notifications/progress
- 请求未带
progressToken - 未处理
notifications/progress - 超时管理不会因 progress 更新而调整
- 长时间 tool 调用体验较差
- server 的进度通知全部丢失
最低限度可先实现:
- 对长请求附加
_meta.progressToken - 在
handleMessage()中识别notifications/progress - 用于 TUI 展示或延长超时窗口
P1 / 中高
位置:src/mcp/client.ts:315
server 若声明 logging capability,可发送:
notifications/message
client 可发送:
logging/setLevel
- 完全忽略
notifications/message - 没有
logging/setLevel
- server 诊断日志不可见
- 初始化前允许发送的 logging 也没有被消费
- 先实现
notifications/message接收和本地展示 - 之后再补
logging/setLevel
P1 / 中
位置:
src/mcp/client.ts:315src/mcp/manager.ts:189
当前未处理这些通知:
notifications/tools/list_changednotifications/resources/list_changednotifications/prompts/list_changednotifications/roots/list_changed
- server 端能力变更后,客户端不会刷新
- MCP browser 只能看到初始化快照
优先补:
tools/list_changed-> 重新拉取tools/list
如后续支持 resources/prompts,再补其余通知。
P1 / 中
位置:
src/mcp/types.ts:43src/mcp/manager.ts:230
当前 MCPToolDefinition 只识别:
namedescriptioninputSchemaalwaysLoad_meta.ui
2025-11-25 中 Tool 还包含:
titleiconsoutputSchemaannotationsexecution.taskSupport
- UI 元信息缺失
- 不能使用
outputSchema校验structuredContent - 无法识别 tool 的 task 支持情况
位置:src/mcp/manager.ts:252
当前调用工具后只提取文本和 structuredContent,没有消费 isError。
这意味着如果 server 返回:
{
"content": [...],
"isError": true
}当前逻辑仍倾向于把它当正常结果处理,而不是工具执行错误。
- 扩展
MCPToolDefinition类型 - 保留
title/icons/outputSchema/annotations/execution - 在工具返回值中识别并传递
isError - 在 UI / tool bridge 层面将其映射为真正的错误状态
P0 / 高
位置:src/mcp/client.ts:59
当前只发一次 tools/list,没有处理 cursor / nextCursor。
工具很多的 server 可能只能拿到第一页工具。
循环调用 tools/list,直到没有 nextCursor。
P1 / 中
位置:
src/mcp/client.ts:81src/mcp/manager.ts:129
resources/listresources/templates/listresources/subscriberesources/unsubscribenotifications/resources/updatednotifications/resources/list_changed
- 只能在“已知 URI”前提下直接读资源
- 不能发现资源
- 不能发现 resource template
- 不能跟踪资源变化
若产品后续要更完整消费资源体系,建议补齐 list/templates/subscription。
P2 / 中高
仓库中未发现:
prompts/listprompts/get
- 无法消费 server 暴露的 prompt 模板
- 无法把 prompt 映射成 slash command 或 UI 入口
P2 / 中
仓库中未发现:
completion/complete
- prompt 参数补全无法使用
- resource template 参数补全无法使用
P2 / 中
位置:src/mcp/client.ts:39
当前初始化 capabilities 只有 UI extension:
capabilities: {
extensions: {
"io.modelcontextprotocol/ui": {
mimeTypes: ["text/html;profile=mcp-app"],
},
},
}未声明:
rootssamplingelicitationtasks
server 无法和客户端协商这些能力:
roots:文件系统边界暴露sampling:server 发起模型采样elicitation:server 请求用户补充信息tasks:耐久请求/轮询式任务
若产品定位包含 IDE/CLI 宿主能力,roots 是最值得优先评估补上的 client feature。
P2 / 中
位置:
src/mcp/types.ts:25src/core/config.ts:156
当前:
transport: "stdio" | "sse";建议调整为:
transport: "stdio" | "streamable-http" | "sse";同时:
url默认优先按streamable-http处理sse作为 legacy 模式保留
位置:src/mcp/manager.ts:48
当前 convertJsonSchema() 只做了粗粒度类型映射,忽略了:
requiredenum$schema- nested object
oneOf/anyOf- array item schema
2025-11-25 明确使用 JSON Schema 2020-12 作为默认 dialect。
复杂 tool schema 在当前宿主里的参数表达并不准确。
P2 / 中
位置:src/mcp/manager.ts:27
当前主要处理:
textimageresource
audioresource_link- 带 annotations 的 content block
这些类型会被弱化处理,甚至降级成字符串化 JSON。
P3 / 中
位置:src/mcp/client.ts:46
当前只发送:
clientInfo: { name: "dscode", version: "0.2.0" }titledescriptioniconswebsiteUrl
不是阻塞项,但可作为完善项补充。
P3 / 低
相关文件:
src/mcp/client.tssrc/mcp/app/types.tssrc/mcp/app/host.ts
仓库当前实现了 io.modelcontextprotocol/ui 扩展,用于 mcp-app 类 UI 资源的承载。这个扩展本身不构成与主协议的明显冲突。
问题的重点不在 UI extension 本身,而在于:
- 底层 MCP client 仍基于旧版协议/旧版 HTTP 传输模型
- 因此即使内部 UI 方案可工作,也不代表对第三方新 MCP server 兼容良好
- 将协议版本升级到
2025-11-25 - 实现
streamable-http传输 - 为 HTTP 请求补齐必要 headers:
Accept: application/json, text/event-streamMCP-Protocol-VersionMCP-Session-Id
- 保留 legacy HTTP+SSE fallback
- 正确处理 tool result 中的
isError
- 支持
notifications/cancelled - 支持
notifications/progress - 支持
notifications/message - 支持
tools/list分页 - 支持
tools/list_changed - 改善 stdio graceful shutdown
resources/listresources/templates/listresources/subscribeprompts/list/prompts/getcompletion/completeroots- 更完整的 JSON Schema 适配
- 更完整的 content type 支持
icons/title/outputSchema/annotations/execution的完整消费- 更完整的 initialize implementation info
- tasks / sampling / elicitation 等较新能力
如果短期目标只是“让当前内置或自控 MCP server 继续可用”,以下项可以先不作为第一批改造目标:
- OAuth / Authorization 全量支持
- OIDC discovery
- incremental scope consent
- tasks experimental
- elicitation URL mode
- sampling 中的 tool calling 扩展
- icons 的完整 UI 消费
这些是 2025-11-25 的重要新增,但不是当前仓库最先暴露兼容问题的点。
当前仓库的 MCP 实现有必要更新。
最核心的不是零散小修,而是:
- 把远端 HTTP MCP 客户端从旧版 HTTP+SSE 迁移到新版 Streamable HTTP
- 补上取消、进度、日志、list changed 等基础协议 utilities
- 完善 tool result 与 schema 的语义消费,尤其是
isError与更完整的 JSON Schema 支持
如果只优先改最关键的代码,建议先聚焦:
src/mcp/client.tssrc/mcp/types.tssrc/core/config.tssrc/mcp/manager.ts
- MCP Specification 2025-11-25: https://modelcontextprotocol.io/specification/2025-11-25
- Lifecycle: https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle
- Transports: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
- Tools: https://modelcontextprotocol.io/specification/2025-11-25/server/tools
- Resources: https://modelcontextprotocol.io/specification/2025-11-25/server/resources
- Prompts: https://modelcontextprotocol.io/specification/2025-11-25/server/prompts
- Completion: https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/completion
- Logging: https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/logging
- Progress: https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/progress
- Cancellation: https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/cancellation
- Changelog: https://modelcontextprotocol.io/specification/2025-11-25/changelog
下面给出一份可执行的分批改造计划,目标是把当前实现升级为:
- 2025-11-25 优先
- Streamable HTTP 优先
- legacy HTTP+SSE 可回退
- 保持现有 stdio 与 MCP App UI bridge 主链路稳定
目标:先让类型系统、配置解析和初始化协商具备承载 2025-11-25 的能力。
src/mcp/types.tssrc/core/config.tssrc/mcp/client.tssrc/mcp/manager.ts
- 增加协议版本相关类型,至少覆盖:
2024-11-052025-11-25
- 扩展 transport 类型:
transport: "stdio" | "streamable-http" | "sse"- 补充 initialize、tool result、notification 的更明确类型
- 明确 tool result 结构,包含:
contentstructuredContentisError_meta
- 为 client/server capabilities 预留更清晰的结构
- 调整 transport 推断逻辑:
- 有
command时优先stdio - 有
url但未显式指定 transport 时,默认streamable-http sse仅作为 legacy 显式配置或回退路径
- 有
- 为运行时配置补充承载位:
- preferred protocol version
- fallback 开关
- HTTP headers
- timeout
- 保持对旧配置格式的兼容
- 将固定
2024-11-05升级为首选2025-11-25 - 记录服务端返回的协商版本
- 区分:
- 初始化响应无效
- 协议版本不兼容
- 为后续 transport 拆分做准备,避免继续把“非 stdio”统一看成
sse
- 扩展 server state,记录:
- negotiated protocol version
- transport kind
- compatibility / fallback mode
目标:把远端 MCP 客户端从旧版 HTTP+SSE 主路径迁移到新版 Streamable HTTP 主路径,同时保留旧 SSE 兼容回退。
src/mcp/client.tssrc/mcp/types.tssrc/core/config.ts
- 拆分 transport 责任:
connectStdio()connectStreamableHttp()connectLegacySSE()
- 将 request / notification 的发送逻辑按 transport 分离
- 将消息接收与 JSON-RPC 解析统一收敛到单一入口
- Streamable HTTP 中补齐:
Accept: application/json, text/event-streamMCP-Protocol-VersionMCP-Session-Id
- 处理:
- 非 2xx 响应
- 非 JSON 响应
- 提前断流
- 空响应
- 保留旧 SSE 的 endpoint 发现逻辑,但仅在以下场景启用:
- 配置显式指定
sse - Streamable HTTP 失败且允许 fallback
- 配置显式指定
- 将 stdio 关闭流程改为:
- 关闭 stdin
- 等待退出
- 超时后
SIGTERM - 必要时
SIGKILL
- 为 HTTP transport 补充运行时状态类型:
- session id
- negotiated version
- fallback mode
- 确保配置层能表达:
- 显式
streamable-http - 显式
sse - 是否允许自动 fallback
- 显式
目标:补齐 2025-11-25 下最关键但当前缺失的协议 utilities 与动态刷新逻辑。
src/mcp/client.tssrc/mcp/manager.tssrc/core/harness.tssrc/ui/mcp-browser.tssrc/mcp/app/host.ts
- 增加 notification 分发与订阅机制,至少支持:
notifications/cancellednotifications/progressnotifications/messagenotifications/tools/list_changednotifications/resources/list_changed
- 对超时或显式取消的请求,发送
notifications/cancelled(非initialize) - 将 progress / message / list changed 作为 client event 往上抛
- 消费 client 事件:
- 收到
tools/list_changed后重新拉取工具列表 - 收到
resources/list_changed后做缓存失效或变更标记
- 收到
- 在
buildAgentTool()中正确处理isError:- 不再只用抛异常判断失败
- tool-level error 需要透传给 agent / UI
- 保留原始正文与
structuredContent
- 若 driver registry 动态替换能力不足,先实现“刷新提示 + 保守更新”策略,避免重复注册导致状态错乱
- 将 progress / message / list changed 接入运行期展示
- 建议展示策略:
- progress 用状态更新,不刷屏
- message 按级别映射 info / warn / error
- list changed 提示刷新成功或失败
- 扩展 server 面板显示:
- transport
- negotiated version
- compatibility mode
- refresh 状态
- refresh error
- 校验 app bridge 下工具调用的结果语义:
- JSON-RPC 成功不等于工具执行成功
- app 端也需要看到
isError/structuredContent
- 为后续 app 内接收 progress / message 留好桥接空间
目标:把当前 convertJsonSchema() 的粗糙映射升级为可用的兼容转换层。
src/mcp/manager.tssrc/mcp/types.ts
- 重构
convertJsonSchema(),支持更多结构:requiredenumarray.items- 嵌套
object.properties additionalPropertiesdefault
- 对复杂或暂不支持的 schema,采取“宽松降级”而不是直接失败:
- 优先降级到
Type.Any - 或宽松对象
- 优先降级到
- 为 JSON Schema 输入定义更清晰的支持子集类型
- 为后续
outputSchema的消费预留结构
目标:确保新旧 server 共存时行为稳定,并提升诊断能力。
src/ui/mcp-browser.tssrc/core/harness.tssrc/mcp/manager.tssrc/mcp/app/host.ts
- 增强状态文案:
connectedconnected (legacy sse)connected (protocol downgraded)refreshingrefresh failed
- 对 progress / message 做节流与分类展示
- 在初始化后提示:
- 哪些 server 走的是 legacy 模式
- 哪些 server 发生了协议降级
- 记录最近一次刷新时间、最近 warning/error
- 对 fallback / downgrade / schema downgrade 做低噪声提示
- 检查 app 模式下的 tool result、message、progress 语义与主 MCP 通道保持一致
建议新增或补强以下测试:
src/mcp/client.ts- initialize 协商
- Streamable HTTP 请求/响应
- legacy SSE fallback
- notification 分发
src/mcp/manager.tsisError处理tools/list_changed刷新- schema 转换
src/core/config.ts- transport 推断
- 新旧配置兼容
src/ui/mcp-browser.ts- server 状态展示
可执行命令:
npm run typechecknpm test
至少准备三类 MCP server 做联调:
- stdio server
- 2025-11-25 Streamable HTTP server
- 旧版 HTTP+SSE server
重点验证:
- initialize 版本协商
- 成功工具调用与
isError: true的差异化处理 - progress 展示
- message 展示
tools/list_changed后的工具刷新- 关闭会话时资源释放
- MCP Browser 中可看到:
- transport
- negotiated version
- compatibility mode
- refresh / error 状态
- 对带 UI resource 的工具验证:
structuredContent仍能驱动 data mode app- app bridge 能感知
isError
应对:
- 保留显式
transport: "sse"强制旧路径 - 新 HTTP 失败后仅在允许时回退
- 在 UI 中显示当前实际 transport
应对:
- 先定义串行刷新策略
- 若 registry 替换语义不足,先做“提示刷新”而不是直接重复注册
应对:
- 保留正文与
structuredContent - 明确标记 tool-level error
- 避免把 tool error 当成 transport error
应对:
- 对复杂 schema 采用宽松降级
- 避免因为 schema 复杂度让工具不可用