• Joined on 2026-07-21

@bpos/mcp-contract (3.6.0)

Published 2026-10-19 16:59:24 +08:00 by root

Installation

@bpos:registry=https://gitea.akhr-ai.com/api/packages/ChaiHao/npm/
npm install @bpos/mcp-contract@3.6.0
"@bpos/mcp-contract": "3.6.0"

About this package

MCP 契约 —— BPOS 作为 MCP 服务器对 host 那条线上的形状(服务、工具的入参 / 出参 zod、资源 URI 模版)。

@bpos/mcp-contract —— MCP 契约

BPOS 作为 MCP 服务器,对 host 那条线上的全部形状。(系统设计 §10.8)

仓里有四份契约,各有各的两头。这一份的读者是 host(执行人自己的桌面 AI 助手):

契约 两头 凭据 面
web/api/contracts 人 ⇄ 系统 会话令牌 /api/v1
contract/activity-contract 活动 ⇄ 系统 能力令牌 /activity-api/v1
contract/data-contract 数仓 ⇄ 系统 库角色 没有 HTTP
本包 host ⇄ 系统 接入令牌 /mcp/v1/<服务>

四份互不引用(tests/boundary.test.ts 与 server 的 tests/boundaries.test.ts R8b 两头钉)。 同一件事(一张工单)在四份里可以有四种摆法,因为读者不同:屏要渲色渲章,活动要事件与名词, 数仓要列与语义,host 里的模型要的是「我该填哪几格、交付物放哪儿」。

里面有什么

名字 是什么
MCP_CONTRACT_VERSION 本包的版本(与 package.json 同一个数,用例钉)
MCP_PROTOCOL_VERSION MCP 规范的修订版(此刻 2026-07-28)——服务端、桥、契约套件都读这一格,别处不抄
MCP_SERVER_NAME serverInfo.name(bpos);版本那一格由服务端现填
MCP_SERVICES · mcpServiceSchema 服务名的事实源。一期只有 desk(代理办单)
SERVICES · toolCountOf · toolOf 每一种服务的工具表与那一句 instructions;条数现算
DESK_TOOLS desk.* 工具的名、标题、给模型的一句、入参 / 出参 zod(条数现算,本文不抄一个数)
artifactBriefSchema 等 取单答复的 artifact 段:做什么、按什么口径、思路与步骤、验收标准、参照与模版、槽的规格与草稿
RESOURCE_TEMPLATES · orderIdOfUri · fileShaOfUri 两个只读投影的 URI 模版与解析
MCP_ERROR_CODES 这张面独有的几个码(stale-baseline · rate-limited · truncated)
fileRefSchema 等 工具入参 / 出参里反复用到的几样小形状

工具表从这里扫出去:服务端按 SERVICES 注册(键不在这里的 handler 拒绝启动,出站按同一份 zod 自校验),系统模块服务卡上「工具几个」、连接说明抽屉那张表、《MCP 接入手册》那张表, 全部现算。抄一个数的那天它不会报错,只会静默地少一件。

工具表(desk,代理办单)

次序就是 tools/list 的次序,也是人办一张单的次序:

desk.list_orders → desk.get_order → desk.get_task_context → desk.save_order → desk.upload_file → desk.deliver_artifact → desk.say → desk.lookup

全部落在执行人面:没有管理面的写、没有审批签批、没有提交。要人定的事(起单、挑执行人、 加额度、签批、提交)回工作台——那是另一个人(或同一个人在另一张面上)的事。

办一张代理单的那条主路是三步:取单读 artifact 段 → 在 host 里做 → deliver_artifact 交上去 (单份替换,多份追加)——这张面上没有第四步:提交只在工作台。件上别的格用 save_order 填,别的文件用 upload_file 传。

什么改动要升大版本

判据与脚手架契约那一条同构,问的是「已经配好的 host 会不会因此办不成事」:

  • 破(大版本):撤一件工具 · 给入参加一格必填 · 收窄取值集 · 换 MCP_PROTOCOL_VERSION (那是换了一套话在说)。
  • 不破(小版本):加一件工具 · 给出参加一格 · 给入参加一格可选的——老 host 不知道它, 也永远不会收到它。

升版的同一次提交把外层 AI-Native/CLAUDE.md 的「契约版本」表那一格改到。

1.1.0:协同工单 = 制品卡的替代(系统设计 §10.8、附录 B 43)。两样,都不破:

  1. 加第十件工具 desk.deliver_artifact:入参 { orderId, fileName, mediaType?, contentBase64 }, 一步把交付物写进 deliverable 指的那一格——进文件库 → 覆盖槽里旧的那一份 → 推进基线 → 工作日志留一行「交付物已替换」。出参 { file, replaced?, baseline }。它不放行(放行仍是 desk.release_order),也不带基线(它只动这一格),但会推进基线:手上攥着旧基线的 保存会撞 stale-baseline。拒绝各说各的:不是协同单 · 单不在待处理 · 超上限(写明多大、 上限多大)· 格式不在允许集(写明允许哪几种)。 从前这条路是两步(upload_file 拿回 fileRef,再由模型原样搬进一个它并不认识的格, 整份 data 送回 save_order)——少搬一格的症状是「传上去了,交付物那一格还是空的」。
  2. desk.get_order 的出参加一段 host:{ brief, prompt?, steps, standard?, criteria?, references[], deliverable{ field, label, documentType, spec{ formats, maxBytes } }, draft? } ——系统按定义拼,没写的缺席;拼不出交付物那一格的规格时整段缺席,不摆半份。 只有协同单有它。

server/discover 的 instructions 与 desk.upload_file 的说明同一次改到新路。mcp-bridge 不动 (它不引本包,工具表从远端现问)。

2.0.0:desk.answer_card 的 kind 收窄——撤 'artifact'。制品卡 6.0 就撤了(产品设计 §1.5:制品从工单来),服务端早就只收 decision / elicitation(chatCardReplySchema 里已经 没有那一形),这里补齐同一把尺,连带三句提到「制品卡」的说明也改准。按上面的判据「收窄取值集」 是大版本:配着 1.1.0 发 kind: 'artifact' 的 host 会被服务端拒——此刻没有任何 host 在用, 这一版纯粹是把入参与服务端早已成立的事实对齐,不留一条能通过校验、却注定被业务判定拒绝的路。

2.0.1:instructions 与十件工具的说明收边界——只在用户要办协同工单时用,写系统状态的几件要用户 明确要求;不改任何工具的形状。缺陷是 host 的模型会把「协同办单」当成一个常驻话题——一连上、或用户 聊别的事,就主动列单、把这几件工具当通用的文件 / 查询 / 记录工具。DESK_INSTRUCTIONS 第一句先划 边界(什么时候才该用这里的工具、什么时候一件都别调),desk.save_order 等六件写系统 / 写留痕的 工具在 description 开头各加一句「只在用户要求…时调」,desk.get_order 等四件只读的加【只读】一类 标记。纯文字改动,入参出参一字未动,按判据是小版本(不破:老 host 该能调的还是都能调)。

3.0.0:落定不在这张面上——设计已改(工单落定的事务只有工作台一个入口),这一版把契约 跟到。按判据「撤一件工具」是大版本:

  1. 撤 desk.release_order、desk.answer_card(剩八件,次序不变)。这张面本就不该有能 办完一张单的工具——host 做到交回交付物为止,人在工作台看过再提交;对话区没有卡,也就没有 可答的卡。配着旧版本发这两件调用的 host 会在协议层被拒(未知工具,-32602)。
  2. desk.get_order 的答复:撤 guide · standard · actions(作业指导书与「怎么算 做完」并进了 artifact,actions 随放行一起没了意义);host 段改现名 artifact 并重排——{ task, prompt, criteria, references[], steps, slot, draft? }:brief 改名 task,deliverable 改名 slot,prompt、criteria、steps 从可选/半可选收成必有 (活动定义协同单时就要给全:task、prompt 非空,criteria、steps 各至少一条),撤单独 的 standard——判「做到什么份上算好」只剩 criteria 一把尺。orderBriefSchema 里的 deliverable 也撤:槽指到哪一格只在 artifact.slot 里给,列单这一层用不上。
  3. 工具说明里提到放行、release_order、actions 的句子改成不提;desk.deliver_artifact 的 说明与 DESK_INSTRUCTIONS 都补一句「先逐条对照 criteria 自查,达标再交」(系统设计 §10.8 点名两处都要有——系统判不了达没达标,这句话是唯一的兜底)。完整的新说明与服务器提示词归 下一版契约。
  4. desk.get_task_context 答复里一条对话(chat[])不再有卡:k 从四档收到三档(撤 'card'),帮着答卡的 cardId、answered 两格一并撤。对话区没有卡(系统设计 §4.8): 决策卡、补格卡都撤了,要人拿主意改派一张轻工单;留着这两格的话,读到旧留痕的人会以为这 一面还答得了卡。

mcp-bridge 不动(它不引本包,工具表从远端现问)。

3.0.1:取单答复里判据的 id 收成标识符(小写字母开头,只含小写字母 / 数字 / 下划线), 与定义那一侧(activity-contract 的 criterionSchema)同一条规则。从前写的是「非空字符串」, 而这条线上的 id 一律由活动的定义来——定义那一侧造不出别的形状,松着写等于向 host 许诺一种 永远不会出现的 id,照它造出来的 checked[] 在工作台那一头一个都对不上。

补丁:按判据「已经配好的 host 会不会因此办不成事」——答不会。它收的是出参里一格的形状, host 读得到的值一个字都没变(系统本来就只答得出标识符);入参没动、工具没增减、取值集没收窄。

3.1.0:「协同办单」改叫「代理办单」(定义者 2026-09-22 定;活动契约 10.0.0 把工单种类 collaborate 改成了 agent)。服务 id desk 一个字不动,改的只是文案:DESK_INSTRUCTIONS 与十件工具说明里的「协同办单 / 协同工单 / 协同单」一律改成「代理…」。

小版本:按判据「已经配好的 host 会不会因此办不成事」——答不会。工具没增减、入参出参的形状 一个字没动、取值集没收窄、协议修订版照旧;变的只是模型读的那几句话。

3.2.0:desk.get_order 的表格那一格带上列(需求响应全量手测里由真的 MCP host 办比价单撞出: 表格从前只答 { name, label, kind: 'table', access },host 不知道哪几列能改、「基准」那一列有哪几个 取值,只能翻别的单猜)。fieldSpecSchema 多两格可选的:columns(每一列的名、人读名、类型、 三档权限、取值集——权限与件上同一条规矩:rows.edit 里的、不是算格的改得动,rows.required 里的必填,整张表格只读时每一列都只读)与 rows({ add, remove });只在 kind: 'table' 的 格上有。同一次把两句说明改准:desk.get_order 说出表格给列;desk.save_order 从前写着「保存 不叫醒活动」,而表单声明了保存即复核的单存完会叫醒活动、复核提示写回件上——改成照实说。

小版本:按判据「出参加一格」——老 host 不认识这两格,照旧办得成事;入参、工具、取值集一字未动。

3.3.0:基线会被哪几下推进,说明里说全(需求响应第二套全量手测里真的 MCP host 办代理单撞出: 交完交付物、存完一次之后接着存,都撞了 stale-baseline,靠拒绝里那句「重新取一遍」才绕回来)。 从前 desk.save_order 的说明只写「期间有人在工作台上动过这张单」会被拒,可推进基线的还有两下: 交付物交上去(desk.deliver_artifact 的答复里就是新的那一枚,说明里一个字没提);声明了保存即复核的单, 存完活动把复核提示写回件上又推进一次(存的答复里那一枚过几秒就旧了)。两件工具的说明、baseline 那一格的 describe 与 MCP_ERROR_CODES.staleBaseline 的注释改成照实说。

小版本:纯文字改动(与 3.1.0 同一条判据)——工具没增减、入参出参的形状一个字没动、取值集没收窄、 协议修订版照旧;变的只是模型读的那几句话。

3.4.0:引用格与表格的列说得出自己(需求响应两遍全量手测里真的 host 都提过:引用那一格只答 kind: 'ref',不知道指哪张表、值写成什么样,只能照别的格里已有的值抄;表格的列没有说明)。 fieldSpecSchema 与 columnSpecSchema 多一格可选的 ref(refSpecSchema:指向哪张表的地址与人读名、 主键列、这张单能不能 desk.lookup 它),columnSpecSchema 多一格可选的 note(按登记表取形的列带登记里 那一列的说明);desk.lookup 答的每一行多一格 _key——这一行的主键串,往引用格里填就原样用它(编码只在 系统一处,值里的 ; = % 都转义;列名都以小写字母开头,不会撞名)。两件工具的说明同一次说出这几样。

小版本:按判据「出参加一格」——老 host 不认识这几格,照旧办得成事;入参、工具、取值集一字未动。

跑

npm install
npm run typecheck && npm test

发到 Gitea 私有 npm 的步骤与另外两个包同一条,见 contract/README.md。

3.5.0:动态并行在 host 这一侧说得出自己。一步按上一步交出的清单散开成几份、各有各的人: orderBriefSchema(列单与取单共用)多一格可选的 piece(pieceSpecSchema:第几份 / 这一批共几份)——同一个人 办两份时两张同名的单靠它分得开;desk.get_task_context 的每一步多一格可选的 pieces(共几份、收口几份、我手上 几份),那一步的 executor 是空串。清单是人在上一步的单上填的,那张单若是代理单,host 得填「给谁」: fieldSpecSchema 与 columnSpecSchema 多一格可选的 member(memberSpecSchema:值填成员的 id、名册用哪件工具取), 另加一件只读工具 desk.list_members——这张单挑得了的人(在用、进得了工作台、左轨有「任务」,不限角色),只答 id 与 名字;单上没有成员格、单不是他的、单不在待处理都拒。desk.get_order 的说明同一次说出这几样。

同一版另一样:文本格说得出自己是不是多行。fieldSpecSchema 与 columnSpecSchema 多一格可选的 multiline(文本格与文本列标了多行的才带,带就是 true);desk.get_order 的说明说出它,desk.save_order 的说明加一句文本格的写法——带 multiline 的可以分行、空行分段、行首「- 」或「1. 」写列表、**…** 加重,别写标题、表格、链接与 HTML(屏上不渲);没带的写一行。保存那一道不为换行拒。

同一版再一样:查的时候说得出在填哪一格。desk.lookup 的入参多两格可选的:field(在填哪一格,表格里的列写成 表格.列)与 row(那张表格里的第几行,从 0 起)——带了,系统把那一格声明的筛选与这张单上已存的它的上级那一格并进查询,只答挑得进那一格的行;不带照旧查整张表。

同一版还有:查对象表时经关系表反查。desk.lookup 的 q 除了目标表自己的列,也经这张单能查的对象表与台账里引到它的记录反查,这样命中的行另带 _via(一组短句:凭哪张表的哪个值)——行本来就是开放对象,出参的形状不动;它的说明同一次说出这一样。

小版本:按判据「加工具、出参加一格、入参加一格可选的」——老 host 不认识这几样,照旧办得成事;已有工具的次序、取值集一字未动,入参只多可选的格。

3.6.0:取单 artifact.slot 增加可选 multiple,多份槽的完整文件集合在可选 artifact.drafts,draft 保留首份兼容旧 host。desk.deliver_artifact 入参与出参不变,按声明追加或替换;多份按摘要去重,移除或替换某份通过最新 baseline 保存完整数组。

Dependencies

Dependencies

ID Version
zod 4.4.3

Development Dependencies

ID Version
@types/node ^24.0.0
tsx ^4.19.0
typescript ^5.6.0
Details
npm
2026-10-19 16:59:24 +08:00
0
UNLICENSED
latest
22 KiB
Assets (1)
Versions (11) View all
3.6.0 2026-10-19
3.5.0 2026-10-12
3.4.0 2026-09-27
3.3.0 2026-09-27
3.2.0 2026-09-26