Skip to content

Commit ee5d59c

Browse files
committed
refactor(mcp): extract pure contracts and harden registry
1 parent 860a843 commit ee5d59c

13 files changed

Lines changed: 1020 additions & 686 deletions

File tree

docs/architecture/core-decomposition.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,12 @@ owner 边界,否则不要把一个 feature group 继续拆成更小的 crate
8484
- 在声明 P3 边界收敛前,运行 `node scripts/check-core-boundaries.mjs`,确认已拆出的
8585
owner crate 没有新增 `bitfun-core` 反向依赖,并确认 `core-types``runtime-ports`
8686
`agent-tools` 没有引入重 runtime / concrete service 依赖。
87-
- 已迁移回 `bitfun-core` 的 legacy facade 只能 re-export owner crate;例如 Git 旧路径、
88-
remote SSH types/workspace path + unresolved-key helper facade、MCP tool contract facade、MCP protocol types facade、
89-
MCP config location facade 和 announcement types facade 由边界脚本检查,不得重新承载实现逻辑。
87+
- 已迁移回 `bitfun-core` 的 legacy facade 只能 re-export owner crate 或做窄错误映射;例如 Git 旧路径、
88+
remote SSH types/workspace path + unresolved-key helper facade、MCP tool contract facade、MCP protocol types / JSON-RPC
89+
request builder facade、MCP config location / cursor-format facade、MCP server config facade 和 announcement types facade
90+
由边界脚本检查,不得重新承载实现逻辑。
9091
- 对仍嵌在 core runtime 文件中的旧公开类型,必须至少保留禁止回流检查;例如 MCP server
91-
type/status 已由 owner crate 拥有,`MCPServerProcess` 只保留 runtime 逻辑。
92+
type/status/config 已由 owner crate 拥有,`MCPServerProcess` 只保留 runtime 逻辑。
9293
- `bitfun-runtime-ports` 必须保持 DTO/trait-only;不得依赖 concrete manager、
9394
service implementation、app crate 或 platform adapter。
9495
- `bitfun-core-types` 不得依赖 runtime manager、service crate、agent runtime、

docs/plans/core-decomposition-plan.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ product-full = ["git", "mcp", "remote-ssh", "remote-connect", "announcement", "f
969969
- [ ] 再迁移 `remote-ssh`,保留 `ssh-remote` 语义。
970970
- [x] 先迁移 `remote-ssh` 的纯 contract/type、workspace path/identity helper 与 unresolved-session-key helper,runtime manager / fs / terminal 仍保留在 core。
971971
- [ ] 再迁移 `mcp`,动态工具通过 `DynamicToolProvider` 接入。
972-
- [x] 先迁移 `mcp` 的纯 tool-name / tool-info / protocol types / config location / server type-status contract,config service / server process / adapter / auth / dynamic tools 仍保留在 core。
972+
- [x] 先迁移 `mcp` 的纯 tool-name / tool-info / protocol types / config location / server type-status、server config、cursor-format 和 JSON-RPC request builder contract,config service / server process / adapter / auth / transport / dynamic tools 仍保留在 core。
973973
- [x] 先迁移 `announcement` 的纯 types contract,scheduler / state store / content loader / remote fetch 仍保留在 core。
974974
- [ ] 最后迁移 `remote-connect`,通过 `AgentSubmissionPort``SessionTranscriptReader``EventSink` 解耦 agent runtime。
975975
- [x] 已迁移的集成能力保持 core 旧路径 re-export。
@@ -978,7 +978,7 @@ product-full = ["git", "mcp", "remote-ssh", "remote-connect", "announcement", "f
978978
**当前安全迁移状态(2026-05-12):**
979979

980980
- 已迁移到 `bitfun-services-integrations``service::file_watch`,通过 `file-watch` / `product-full` feature 启用,并保持 `core::service::file_watch` 旧路径。
981-
- `git` 已完成 DTO/params/graph/raw command output/text parser/arg builder、`GitError`、`GitService` runtime implementation 与 git utils 迁移;`bitfun-core::service::git::*` 仅保留 legacy facade re-export。`remote-ssh` 已迁移纯 contract/type、workspace path/identity helper 与 unresolved-session-key helper;SSH runtime manager / fs / terminal、password vault 与 PathManager-backed session mirror assembly 仍保留在 core。`mcp` 仅迁移了 tool-name / tool-info / protocol types / config location / server type-status contract,config service / json config / cursor format / jsonrpc / transport / server process / adapter / auth / dynamic tools 仍保留在 core;`announcement` 仅迁移了纯 types contract,scheduler / state store / content loader / remote fetch 仍保留在 core;`remote-connect` 尚未迁移。它们涉及 SSH runtime、MCP dynamic tool provider、remote agent submission 与 announcement config/path 边界,继续前需要单独确认端口方案与等价性测试。
981+
- `git` 已完成 DTO/params/graph/raw command output/text parser/arg builder、`GitError`、`GitService` runtime implementation 与 git utils 迁移;`bitfun-core::service::git::*` 仅保留 legacy facade re-export。`remote-ssh` 已迁移纯 contract/type、workspace path/identity helper 与 unresolved-session-key helper;SSH runtime manager / fs / terminal、password vault 与 PathManager-backed session mirror assembly 仍保留在 core。`mcp` 已迁移 tool-name / tool-info / protocol types / config location / server type-status、server config、cursor-format 和 JSON-RPC request builder contract,并用 owner crate contract test 锁定 wire shape、transport default、validation message 与 Cursor 兼容格式;config service / json config save-load orchestration / transport / server process / adapter / auth / dynamic tools 仍保留在 core;`announcement` 仅迁移了纯 types contract,scheduler / state store / content loader / remote fetch 仍保留在 core;`remote-connect` 尚未迁移。它们涉及 SSH runtime、MCP dynamic tool provider、remote agent submission 与 announcement config/path 边界,继续前需要单独确认端口方案与等价性测试。
982982
- 最新主干的 Deep Review capacity / cost / queue、context profile、evidence ledger、session manifest、stream dedupe、search remote/fallback 与 session rollback persistence 仍属于 core runtime 或对应产品 runtime,不在本轮 `services-integrations` 迁移范围内;如果后续迁移 remote-connect / MCP / search / session,需要先定义运行状态 port 合约和等价测试。
983983

984984
**验证:**
@@ -1508,8 +1508,8 @@ cargo check --workspace
15081508

15091509
- 已完成中等粒度 owner crate 成型的安全部分:`bitfun-services-core``bitfun-services-integrations``bitfun-agent-tools``bitfun-tool-packs``bitfun-product-domains` 均已加入 workspace。
15101510
- 已迁移的模块均由 core facade re-export,未改变产品默认 feature、构建脚本或 release 脚本。
1511-
- Git feature group 已闭环迁移到 `bitfun-services-integrations``git` feature:DTO/params/graph/raw command output/text parser/arg builder、`GitError``GitService` runtime implementation 与 git utils 均由 integrations owner crate 拥有,并通过 `bitfun-core::service::git::*` 保留旧路径兼容。`GitService` 所需的 Windows `libgit2` system-link 边界挂在该 crate 的 `git` feature 上;`bitfun-core` 仍因未迁移的 remote-connect runtime 保留其它 `git2` 使用。remote-ssh 本轮进一步外移 workspace path/identity 与 unresolved-session-key helper,并用 owner crate contract test 锁定 normalized path、mirror subpath、hostname sanitization、stable id 和 unresolved key 输出;PathManager-backed mirror root、global workspace registry、SSH manager/fs/terminal/runtime 仍留在 core。
1512-
- 未声明完成的 P2 剩余部分:remote-ssh runtime、MCP server/adapter/auth/dynamic tools、remote-connect 等重 service 迁移、concrete tool implementation 迁移、tool registry/provider 化、miniapp/function-agent 运行逻辑迁移。这些会触碰 `PathManager``BitFunError``ToolUseContext`、workspace service、snapshot wrapper、`AgentSubmissionPort` 或 AI service 边界,需要在继续前显式确认。
1511+
- Git feature group 已闭环迁移到 `bitfun-services-integrations``git` feature:DTO/params/graph/raw command output/text parser/arg builder、`GitError``GitService` runtime implementation 与 git utils 均由 integrations owner crate 拥有,并通过 `bitfun-core::service::git::*` 保留旧路径兼容。`GitService` 所需的 Windows `libgit2` system-link 边界挂在该 crate 的 `git` feature 上;`bitfun-core` 仍因未迁移的 remote-connect runtime 保留其它 `git2` 使用。remote-ssh 本轮进一步外移 workspace path/identity 与 unresolved-session-key helper,并用 owner crate contract test 锁定 normalized path、mirror subpath、hostname sanitization、stable id 和 unresolved key 输出;PathManager-backed mirror root、global workspace registry、SSH manager/fs/terminal/runtime 仍留在 core。MCP 本轮进一步外移 server config、cursor-format 与 JSON-RPC request builder 纯合约,core 旧路径继续做兼容 facade 和 `BitFunError` 映射。
1512+
- 未声明完成的 P2 剩余部分:remote-ssh runtime、MCP config service orchestration / server process / transport / adapter / auth / dynamic tools、remote-connect 等重 service 迁移、concrete tool implementation 迁移、tool registry/provider 化、miniapp/function-agent 运行逻辑迁移。这些会触碰 `PathManager``BitFunError``ToolUseContext`、workspace service、snapshot wrapper、`AgentSubmissionPort` 或 AI service 边界,需要在继续前显式确认。
15131513
- 本次 rebase 后重新核对最新主干 Deep Review capacity/cost/queue、context profile、evidence ledger 与 session manifest 变更:当前 PR 已完成 Git feature group 的 owner crate 归属迁移,但未改动这些 Deep Review 行为路径;后续迁移必须补端口设计和等价测试后再推进。
15141514
- 本次 P2 后续复核结论:上述高耦合剩余项不是纯文件搬迁;若继续迁移会改变依赖方向或需要新增 port/provider 行为合约。因此当前 PR 将它们显式保留为 core-owned runtime,并通过 P3 boundary check 防止已拆 owner crate 回流依赖 core。
15151515

@@ -1560,10 +1560,10 @@ cargo check --workspace
15601560
- 本次 rebase 到 `origin/main` 后,PR #680 的三颗等价提交已进入主干;新增 CLI 重构与 agent execution hardening 没有改变本轮 `services-integrations` / service facade 迁移内容,但会把后续 CLI 产品检查、agent registry/provider 与 session/tool runtime 外移的等价性门槛抬高。
15611561
- 质量边界:本阶段只证明已拆 owner crate 不依赖回 `bitfun-core`,并证明 Git 旧路径仍通过当前 Rust workspace 检查;不声明 remote connect、MCP dynamic tools、snapshot wrapping、miniapp/function-agent runtime 的外移完成。
15621562
- boundary check 已扩展到 `core-types``runtime-ports``agent-tools` 的轻量边界,并覆盖 Cargo inline 依赖和 dependency table 依赖声明,后续不能绕过脚本把重 runtime、concrete service、platform adapter 或 CLI/TUI presentation 依赖带入这些 contract crate。
1563-
- boundary check 也已锁定 `bitfun-core::service::git``bitfun-core::service::remote_ssh::types`、remote-ssh workspace path/identity/unresolved-key helper、`bitfun-core::service::mcp::{tool_info,tool_name}``bitfun-core::service::mcp::protocol::types``bitfun-core::service::mcp::config::location``bitfun-core::service::announcement::types` 的旧路径 facade-only 状态,并禁止在 `MCPServerProcess` runtime 文件重新定义已外移的 server type/status contract。
1563+
- boundary check 也已锁定 `bitfun-core::service::git``bitfun-core::service::remote_ssh::types`、remote-ssh workspace path/identity/unresolved-key helper、`bitfun-core::service::mcp::{tool_info,tool_name}``bitfun-core::service::mcp::protocol::{types,jsonrpc}``bitfun-core::service::mcp::config::{location,cursor_format}``bitfun-core::service::mcp::server::config``bitfun-core::service::announcement::types` 的旧路径 facade-only / 禁止回流状态,并禁止在 `MCPServerProcess` runtime 文件重新定义已外移的 server type/status contract。
15641564
- 后续迁移必须拆成可独立审核的提交:先补 port/provider 设计和等价测试,再按 `remote-ssh` runtime、MCP runtime、`remote-connect` 的顺序一次迁移一个 service feature group。
15651565
- tool registry / concrete tool implementation 外移必须先有工具清单等价测试,并保留 dynamic provider metadata;不能把注册名解析、snapshot wrapper 或 runtime restriction 行为改成隐式约定。
1566-
- 已新增内置工具清单基线测试,后续 registry/provider 外移必须先保持该清单和注册顺序等价,再评估 owner crate 边界。
1566+
- 已新增并扩展内置工具清单基线测试,后续 registry/provider 外移必须先保持该清单、注册顺序、runtime collection 顺序、dynamic provider metadata 顺序和修改类工具 snapshot wrapper 等价,再评估 owner crate 边界。
15671567
- miniapp 与 function-agent runtime 外移必须先明确 Git/AI service、PathManager、process execution 和 permission policy 边界;如果需要行为合约变化,必须作为后续单独 PR 并先确认。
15681568
- `bitfun-core default = []` 和依赖版本收敛仍是后续独立评估项,不与 runtime 外移或构建脚本调整混在同一批提交。
15691569

scripts/check-core-boundaries.mjs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,97 @@ const forbiddenContentRules = [
177177
},
178178
],
179179
},
180+
{
181+
path: 'src/crates/core/src/service/mcp/server/config.rs',
182+
patterns: [
183+
{
184+
regex: /\bpub enum MCPServerTransport\b/,
185+
message: 'core MCP server config facade must not redefine MCPServerTransport; use the integrations contract',
186+
},
187+
{
188+
regex: /\bpub struct MCPServerOAuthConfig\b/,
189+
message: 'core MCP server config facade must not redefine OAuth config; use the integrations contract',
190+
},
191+
{
192+
regex: /\bpub struct MCPServerXaaConfig\b/,
193+
message: 'core MCP server config facade must not redefine XAA config; use the integrations contract',
194+
},
195+
{
196+
regex: /\bpub struct MCPServerConfig\b/,
197+
message: 'core MCP server config facade must not redefine server config; use the integrations contract',
198+
},
199+
{
200+
regex: /\bfn default_true\b/,
201+
message: 'core MCP server config facade must not redefine config serde defaults; use the integrations contract',
202+
},
203+
{
204+
regex: /\bpub fn resolved_transport\b/,
205+
message: 'core MCP server config facade must not redefine transport defaults; use the integrations contract',
206+
},
207+
{
208+
regex: /\bpub fn validate\b/,
209+
message: 'core MCP server config facade must not redefine config validation; use the integrations contract',
210+
},
211+
],
212+
},
213+
{
214+
path: 'src/crates/core/src/service/mcp/config/cursor_format.rs',
215+
patterns: [
216+
{
217+
regex: /\bfn parse_source\b/,
218+
message: 'core MCP cursor facade must not redefine source parsing; use the integrations contract',
219+
},
220+
{
221+
regex: /\bfn parse_transport\b/,
222+
message: 'core MCP cursor facade must not redefine transport parsing; use the integrations contract',
223+
},
224+
{
225+
regex: /\bfn parse_legacy_type\b/,
226+
message: 'core MCP cursor facade must not redefine legacy type parsing; use the integrations contract',
227+
},
228+
],
229+
},
230+
{
231+
path: 'src/crates/core/src/service/mcp/protocol/jsonrpc.rs',
232+
patterns: [
233+
{
234+
regex: /\bfn serialize_params\b/,
235+
message: 'core MCP jsonrpc facade must not redefine request parameter serialization; use the integrations contract',
236+
},
237+
{
238+
regex: /\bpub fn create_initialize_request\b/,
239+
message: 'core MCP jsonrpc facade must not redefine initialize request builders; use the integrations contract',
240+
},
241+
{
242+
regex: /\bpub fn create_resources_list_request\b/,
243+
message: 'core MCP jsonrpc facade must not redefine resources/list request builders; use the integrations contract',
244+
},
245+
{
246+
regex: /\bpub fn create_resources_read_request\b/,
247+
message: 'core MCP jsonrpc facade must not redefine resources/read request builders; use the integrations contract',
248+
},
249+
{
250+
regex: /\bpub fn create_prompts_list_request\b/,
251+
message: 'core MCP jsonrpc facade must not redefine prompts/list request builders; use the integrations contract',
252+
},
253+
{
254+
regex: /\bpub fn create_prompts_get_request\b/,
255+
message: 'core MCP jsonrpc facade must not redefine prompts/get request builders; use the integrations contract',
256+
},
257+
{
258+
regex: /\bpub fn create_tools_list_request\b/,
259+
message: 'core MCP jsonrpc facade must not redefine tools/list request builders; use the integrations contract',
260+
},
261+
{
262+
regex: /\bpub fn create_tools_call_request\b/,
263+
message: 'core MCP jsonrpc facade must not redefine tools/call request builders; use the integrations contract',
264+
},
265+
{
266+
regex: /\bpub fn create_ping_request\b/,
267+
message: 'core MCP jsonrpc facade must not redefine ping request builders; use the integrations contract',
268+
},
269+
],
270+
},
180271
{
181272
path: 'src/crates/core/src/service/remote_ssh/workspace_state.rs',
182273
patterns: [
@@ -357,6 +448,56 @@ function runManifestParserSelfTest() {
357448
throw new Error(`remote SSH workspace boundary rule must forbid helper: ${helper}`);
358449
}
359450
}
451+
452+
const mcpJsonrpcRule = forbiddenContentRules.find(
453+
(rule) => rule.path === 'src/crates/core/src/service/mcp/protocol/jsonrpc.rs',
454+
);
455+
if (!mcpJsonrpcRule) {
456+
throw new Error('missing MCP JSON-RPC boundary rule');
457+
}
458+
const mcpJsonrpcHelpers = [
459+
'serialize_params',
460+
'create_initialize_request',
461+
'create_resources_list_request',
462+
'create_resources_read_request',
463+
'create_prompts_list_request',
464+
'create_prompts_get_request',
465+
'create_tools_list_request',
466+
'create_tools_call_request',
467+
'create_ping_request',
468+
];
469+
const mcpJsonrpcRuleText = mcpJsonrpcRule.patterns
470+
.map((pattern) => pattern.regex.source)
471+
.join('\n');
472+
for (const helper of mcpJsonrpcHelpers) {
473+
if (!mcpJsonrpcRuleText.includes(helper)) {
474+
throw new Error(`MCP JSON-RPC boundary rule must forbid helper: ${helper}`);
475+
}
476+
}
477+
478+
const mcpServerConfigRule = forbiddenContentRules.find(
479+
(rule) => rule.path === 'src/crates/core/src/service/mcp/server/config.rs',
480+
);
481+
if (!mcpServerConfigRule) {
482+
throw new Error('missing MCP server config boundary rule');
483+
}
484+
const mcpServerConfigContracts = [
485+
'MCPServerTransport',
486+
'MCPServerOAuthConfig',
487+
'MCPServerXaaConfig',
488+
'MCPServerConfig',
489+
'default_true',
490+
'resolved_transport',
491+
'validate',
492+
];
493+
const mcpServerConfigRuleText = mcpServerConfigRule.patterns
494+
.map((pattern) => pattern.regex.source)
495+
.join('\n');
496+
for (const contract of mcpServerConfigContracts) {
497+
if (!mcpServerConfigRuleText.includes(contract)) {
498+
throw new Error(`MCP server config boundary rule must forbid contract: ${contract}`);
499+
}
500+
}
360501
}
361502

362503
function checkCargoManifest(crateDir) {

0 commit comments

Comments
 (0)