open-multi-agent-kit 0.98.3 → 0.98.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +11 -2
  3. package/dist/cli/args.d.ts +1 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +14 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/help.d.ts.map +1 -1
  8. package/dist/cli/help.js +3 -0
  9. package/dist/cli/help.js.map +1 -1
  10. package/dist/cli/mcp-attach.d.ts +3 -3
  11. package/dist/cli/mcp-attach.d.ts.map +1 -1
  12. package/dist/cli/mcp-attach.js +5 -4
  13. package/dist/cli/mcp-attach.js.map +1 -1
  14. package/dist/cli/model-contract.d.ts +5 -0
  15. package/dist/cli/model-contract.d.ts.map +1 -0
  16. package/dist/cli/model-contract.js +45 -0
  17. package/dist/cli/model-contract.js.map +1 -0
  18. package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -1
  19. package/dist/commands/adaptorch-doctor-cli.js +32 -10
  20. package/dist/commands/adaptorch-doctor-cli.js.map +1 -1
  21. package/dist/commands/init-cli.d.ts +12 -0
  22. package/dist/commands/init-cli.d.ts.map +1 -0
  23. package/dist/commands/init-cli.js +76 -0
  24. package/dist/commands/init-cli.js.map +1 -0
  25. package/dist/commands/provider-sync-cli.d.ts +27 -0
  26. package/dist/commands/provider-sync-cli.d.ts.map +1 -0
  27. package/dist/commands/provider-sync-cli.js +177 -0
  28. package/dist/commands/provider-sync-cli.js.map +1 -0
  29. package/dist/commands/run-command.d.ts +8 -0
  30. package/dist/commands/run-command.d.ts.map +1 -0
  31. package/dist/commands/run-command.js +26 -0
  32. package/dist/commands/run-command.js.map +1 -0
  33. package/dist/core/active-skill-state.d.ts +7 -0
  34. package/dist/core/active-skill-state.d.ts.map +1 -0
  35. package/dist/core/active-skill-state.js +25 -0
  36. package/dist/core/active-skill-state.js.map +1 -0
  37. package/dist/core/agent-session-services.d.ts +2 -0
  38. package/dist/core/agent-session-services.d.ts.map +1 -1
  39. package/dist/core/agent-session-services.js +2 -0
  40. package/dist/core/agent-session-services.js.map +1 -1
  41. package/dist/core/agent-session.d.ts +0 -1
  42. package/dist/core/agent-session.d.ts.map +1 -1
  43. package/dist/core/agent-session.js +30 -85
  44. package/dist/core/agent-session.js.map +1 -1
  45. package/dist/core/codex-chatgpt-web-bridge.d.ts +99 -0
  46. package/dist/core/codex-chatgpt-web-bridge.d.ts.map +1 -0
  47. package/dist/core/codex-chatgpt-web-bridge.js +192 -0
  48. package/dist/core/codex-chatgpt-web-bridge.js.map +1 -0
  49. package/dist/core/codex-chatgpt-web-sync.d.ts +50 -0
  50. package/dist/core/codex-chatgpt-web-sync.d.ts.map +1 -0
  51. package/dist/core/codex-chatgpt-web-sync.js +119 -0
  52. package/dist/core/codex-chatgpt-web-sync.js.map +1 -0
  53. package/dist/core/compaction/compaction-headroom.d.ts +30 -0
  54. package/dist/core/compaction/compaction-headroom.d.ts.map +1 -0
  55. package/dist/core/compaction/compaction-headroom.js +48 -0
  56. package/dist/core/compaction/compaction-headroom.js.map +1 -0
  57. package/dist/core/compaction/compaction.d.ts +2 -29
  58. package/dist/core/compaction/compaction.d.ts.map +1 -1
  59. package/dist/core/compaction/compaction.js +19 -47
  60. package/dist/core/compaction/compaction.js.map +1 -1
  61. package/dist/core/compaction/overflow-retry-guard.d.ts +20 -0
  62. package/dist/core/compaction/overflow-retry-guard.d.ts.map +1 -0
  63. package/dist/core/compaction/overflow-retry-guard.js +38 -0
  64. package/dist/core/compaction/overflow-retry-guard.js.map +1 -0
  65. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  66. package/dist/core/context-budget-headroom-types.js +1 -1
  67. package/dist/core/context-budget-headroom-types.js.map +1 -1
  68. package/dist/core/context-budget-token-counter-types.d.ts +27 -0
  69. package/dist/core/context-budget-token-counter-types.d.ts.map +1 -0
  70. package/dist/core/context-budget-token-counter-types.js +2 -0
  71. package/dist/core/context-budget-token-counter-types.js.map +1 -0
  72. package/dist/core/context-budget-token-counter.d.ts +2 -26
  73. package/dist/core/context-budget-token-counter.d.ts.map +1 -1
  74. package/dist/core/context-budget-token-counter.js +2 -0
  75. package/dist/core/context-budget-token-counter.js.map +1 -1
  76. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  77. package/dist/core/context-budget-v2-scoring.js +14 -10
  78. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  79. package/dist/core/domain-router.d.ts.map +1 -1
  80. package/dist/core/domain-router.js +1 -1
  81. package/dist/core/domain-router.js.map +1 -1
  82. package/dist/core/grok-harness-dispatch.d.ts +4 -0
  83. package/dist/core/grok-harness-dispatch.d.ts.map +1 -1
  84. package/dist/core/grok-harness-dispatch.js +20 -3
  85. package/dist/core/grok-harness-dispatch.js.map +1 -1
  86. package/dist/core/grok-harness.d.ts +15 -9
  87. package/dist/core/grok-harness.d.ts.map +1 -1
  88. package/dist/core/grok-harness.js +34 -8
  89. package/dist/core/grok-harness.js.map +1 -1
  90. package/dist/core/mcp/tools.d.ts +2 -2
  91. package/dist/core/mcp/tools.d.ts.map +1 -1
  92. package/dist/core/mcp/tools.js +29 -3
  93. package/dist/core/mcp/tools.js.map +1 -1
  94. package/dist/core/model-registry-schema.d.ts +1081 -0
  95. package/dist/core/model-registry-schema.d.ts.map +1 -0
  96. package/dist/core/model-registry-schema.js +148 -0
  97. package/dist/core/model-registry-schema.js.map +1 -0
  98. package/dist/core/model-registry.d.ts.map +1 -1
  99. package/dist/core/model-registry.js +1 -146
  100. package/dist/core/model-registry.js.map +1 -1
  101. package/dist/core/model-resolver.d.ts +2 -1
  102. package/dist/core/model-resolver.d.ts.map +1 -1
  103. package/dist/core/model-resolver.js +2 -1
  104. package/dist/core/model-resolver.js.map +1 -1
  105. package/dist/core/prompt-preset.d.ts +1 -1
  106. package/dist/core/prompt-preset.d.ts.map +1 -1
  107. package/dist/core/prompt-preset.js +16 -1
  108. package/dist/core/prompt-preset.js.map +1 -1
  109. package/dist/core/provider-display-names.d.ts.map +1 -1
  110. package/dist/core/provider-display-names.js +1 -0
  111. package/dist/core/provider-display-names.js.map +1 -1
  112. package/dist/core/provider-resilience.d.ts +8 -0
  113. package/dist/core/provider-resilience.d.ts.map +1 -1
  114. package/dist/core/provider-resilience.js +20 -3
  115. package/dist/core/provider-resilience.js.map +1 -1
  116. package/dist/core/provider-usage-types.d.ts +42 -0
  117. package/dist/core/provider-usage-types.d.ts.map +1 -0
  118. package/dist/core/provider-usage-types.js +2 -0
  119. package/dist/core/provider-usage-types.js.map +1 -0
  120. package/dist/core/provider-usage.d.ts +2 -31
  121. package/dist/core/provider-usage.d.ts.map +1 -1
  122. package/dist/core/provider-usage.js +4 -0
  123. package/dist/core/provider-usage.js.map +1 -1
  124. package/dist/core/redaction.d.ts.map +1 -1
  125. package/dist/core/redaction.js +18 -2
  126. package/dist/core/redaction.js.map +1 -1
  127. package/dist/core/sandbox/policy-merge.d.ts +6 -0
  128. package/dist/core/sandbox/policy-merge.d.ts.map +1 -0
  129. package/dist/core/sandbox/policy-merge.js +74 -0
  130. package/dist/core/sandbox/policy-merge.js.map +1 -0
  131. package/dist/core/sandbox/policy-paths.d.ts +4 -0
  132. package/dist/core/sandbox/policy-paths.d.ts.map +1 -0
  133. package/dist/core/sandbox/policy-paths.js +21 -0
  134. package/dist/core/sandbox/policy-paths.js.map +1 -0
  135. package/dist/core/sandbox/policy-types.d.ts +75 -0
  136. package/dist/core/sandbox/policy-types.d.ts.map +1 -0
  137. package/dist/core/sandbox/policy-types.js +2 -0
  138. package/dist/core/sandbox/policy-types.js.map +1 -0
  139. package/dist/core/sandbox/policy.d.ts +3 -77
  140. package/dist/core/sandbox/policy.d.ts.map +1 -1
  141. package/dist/core/sandbox/policy.js +3 -98
  142. package/dist/core/sandbox/policy.js.map +1 -1
  143. package/dist/core/sdk-provider-stream.d.ts +14 -0
  144. package/dist/core/sdk-provider-stream.d.ts.map +1 -0
  145. package/dist/core/sdk-provider-stream.js +38 -0
  146. package/dist/core/sdk-provider-stream.js.map +1 -0
  147. package/dist/core/sdk.d.ts +5 -1
  148. package/dist/core/sdk.d.ts.map +1 -1
  149. package/dist/core/sdk.js +17 -33
  150. package/dist/core/sdk.js.map +1 -1
  151. package/dist/core/session-failure-cause.d.ts.map +1 -1
  152. package/dist/core/session-failure-cause.js +10 -3
  153. package/dist/core/session-failure-cause.js.map +1 -1
  154. package/dist/core/session-run-termination.d.ts +18 -0
  155. package/dist/core/session-run-termination.d.ts.map +1 -0
  156. package/dist/core/session-run-termination.js +61 -0
  157. package/dist/core/session-run-termination.js.map +1 -0
  158. package/dist/core/session-termination.d.ts.map +1 -1
  159. package/dist/core/session-termination.js +1 -1
  160. package/dist/core/session-termination.js.map +1 -1
  161. package/dist/core/skill-selector.d.ts +40 -0
  162. package/dist/core/skill-selector.d.ts.map +1 -0
  163. package/dist/core/skill-selector.js +102 -0
  164. package/dist/core/skill-selector.js.map +1 -0
  165. package/dist/core/tools/render-utils.d.ts.map +1 -1
  166. package/dist/core/tools/render-utils.js +2 -4
  167. package/dist/core/tools/render-utils.js.map +1 -1
  168. package/dist/core/turn-metrics-record.d.ts +55 -0
  169. package/dist/core/turn-metrics-record.d.ts.map +1 -0
  170. package/dist/core/turn-metrics-record.js +149 -0
  171. package/dist/core/turn-metrics-record.js.map +1 -0
  172. package/dist/core/turn-metrics.d.ts +4 -56
  173. package/dist/core/turn-metrics.d.ts.map +1 -1
  174. package/dist/core/turn-metrics.js +12 -60
  175. package/dist/core/turn-metrics.js.map +1 -1
  176. package/dist/guardrails/evidence-system.d.ts +1 -1
  177. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  178. package/dist/guardrails/evidence-system.js +18 -29
  179. package/dist/guardrails/evidence-system.js.map +1 -1
  180. package/dist/guardrails/merge-gate-result.d.ts +4 -0
  181. package/dist/guardrails/merge-gate-result.d.ts.map +1 -0
  182. package/dist/guardrails/merge-gate-result.js +32 -0
  183. package/dist/guardrails/merge-gate-result.js.map +1 -0
  184. package/dist/main.d.ts.map +1 -1
  185. package/dist/main.js +22 -22
  186. package/dist/main.js.map +1 -1
  187. package/dist/modes/interactive/interactive-login-options.d.ts +27 -0
  188. package/dist/modes/interactive/interactive-login-options.d.ts.map +1 -0
  189. package/dist/modes/interactive/interactive-login-options.js +54 -0
  190. package/dist/modes/interactive/interactive-login-options.js.map +1 -0
  191. package/dist/modes/interactive/interactive-mode.d.ts +7 -4
  192. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/dist/modes/interactive/interactive-mode.js +138 -140
  194. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/dist/modes/interactive/interactive-resume-command.d.ts +3 -0
  196. package/dist/modes/interactive/interactive-resume-command.d.ts.map +1 -0
  197. package/dist/modes/interactive/interactive-resume-command.js +24 -0
  198. package/dist/modes/interactive/interactive-resume-command.js.map +1 -0
  199. package/dist/modes/interactive/interactive-tool-result.d.ts +32 -0
  200. package/dist/modes/interactive/interactive-tool-result.d.ts.map +1 -0
  201. package/dist/modes/interactive/interactive-tool-result.js +59 -0
  202. package/dist/modes/interactive/interactive-tool-result.js.map +1 -0
  203. package/dist/modes/print-mode.d.ts.map +1 -1
  204. package/dist/modes/print-mode.js +22 -0
  205. package/dist/modes/print-mode.js.map +1 -1
  206. package/dist/utils/clipboard-image.d.ts.map +1 -1
  207. package/dist/utils/clipboard-image.js +10 -60
  208. package/dist/utils/clipboard-image.js.map +1 -1
  209. package/dist/utils/terminal-links.d.ts +13 -0
  210. package/dist/utils/terminal-links.d.ts.map +1 -0
  211. package/dist/utils/terminal-links.js +68 -0
  212. package/dist/utils/terminal-links.js.map +1 -0
  213. package/dist/utils/windows-clipboard-image.d.ts +16 -0
  214. package/dist/utils/windows-clipboard-image.d.ts.map +1 -0
  215. package/dist/utils/windows-clipboard-image.js +87 -0
  216. package/dist/utils/windows-clipboard-image.js.map +1 -0
  217. package/docs/adaptorch-onboarding.md +80 -0
  218. package/docs/containerization.md +12 -0
  219. package/docs/context-files.md +97 -0
  220. package/docs/correctness-wall.md +8 -0
  221. package/docs/custom-provider.md +35 -0
  222. package/docs/development.md +18 -3
  223. package/docs/environment-variables.md +2 -0
  224. package/docs/grok-harness.md +4 -0
  225. package/docs/harness-boundaries.md +154 -0
  226. package/docs/harness-improvements.md +90 -0
  227. package/docs/json.md +19 -0
  228. package/docs/keybindings.md +1 -1
  229. package/docs/mcp.md +22 -2
  230. package/docs/metrics.md +66 -16
  231. package/docs/model-catalog-refresh.md +190 -0
  232. package/docs/model-contract.md +168 -0
  233. package/docs/models.md +21 -4
  234. package/docs/provider-resilience.md +5 -3
  235. package/docs/providers.md +68 -1
  236. package/docs/quickstart.md +4 -0
  237. package/docs/release-audit-0.98.4.md +112 -0
  238. package/docs/review-bundle-followup.md +195 -0
  239. package/docs/runtime-algorithms.md +19 -0
  240. package/docs/sdk.md +11 -2
  241. package/docs/sessions.md +1 -1
  242. package/docs/settings.md +17 -1
  243. package/docs/skills.md +2 -0
  244. package/docs/tb21-audit.md +131 -0
  245. package/docs/terminal-setup.md +20 -0
  246. package/docs/usage.md +23 -1
  247. package/docs/windows.md +48 -0
  248. package/examples/README.md +4 -0
  249. package/examples/context/AGENTS.md +64 -0
  250. package/examples/context/CLAUDE.md +17 -0
  251. package/examples/context/INTERNET.md +42 -0
  252. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  253. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  254. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  255. package/examples/extensions/gondolin/package-lock.json +2 -2
  256. package/examples/extensions/gondolin/package.json +1 -1
  257. package/examples/extensions/sandbox/package-lock.json +2 -2
  258. package/examples/extensions/sandbox/package.json +1 -1
  259. package/examples/extensions/with-deps/package-lock.json +2 -2
  260. package/examples/extensions/with-deps/package.json +1 -1
  261. package/npm-shrinkwrap.json +18 -18
  262. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7E,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,oEAAoE;AACpE,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAKvC,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ7E;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAsBhG;AAED,MAAM,WAAW,8BAA8B;IAC9C,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,aAAa,EACnB,OAAO,GAAE,8BAAmC,GAC1C,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAiCzC","sourcesContent":["/**\n * Adapt an MCP tool into a harness `ToolDefinition`.\n *\n * Two things make this small:\n * - `validateToolArguments` already accepts a plain JSON Schema, so an MCP\n * `inputSchema` is passed straight through instead of being re-modelled in\n * TypeBox.\n * - MCP content blocks are already text/image, which is exactly what the\n * harness renders.\n *\n * Naming: tools are exposed as `<server>__<tool>` so two servers can ship a\n * `search` without colliding, and so a model can tell where a tool came from.\n */\n\nimport type { ImageContent, TextContent } from \"omk-ai\";\nimport type { TSchema } from \"typebox\";\nimport type { AgentToolResult, ToolDefinition } from \"../extensions/types.ts\";\nimport type { McpClient, McpContentBlock, McpToolSchema } from \"./client.ts\";\n\n/** Tool-name separator between the server label and the server's own tool name. */\nexport const MCP_TOOL_NAME_SEPARATOR = \"__\";\n/** Providers reject long tool names; this is the common ceiling. */\nexport const MAX_TOOL_NAME_LENGTH = 64;\n\n/** Empty-object schema used when a server omits `inputSchema`. */\nconst EMPTY_OBJECT_SCHEMA = { type: \"object\", properties: {} } as const;\n\nexport interface McpToolDetails {\n\treadonly server: string;\n\treadonly tool: string;\n\treadonly isError: boolean;\n\treadonly structuredContent?: unknown;\n}\n\n/** Reduce an arbitrary label to the character set providers accept for tool names. */\nexport function sanitizeToolNameSegment(segment: string): string {\n\treturn segment.replace(/[^a-zA-Z0-9_-]/gu, \"_\").replace(/_{2,}/gu, \"_\");\n}\n\n/**\n * Build the exposed tool name. Over-long names keep the server prefix and\n * truncate the tool segment, because the prefix is what disambiguates.\n */\nexport function buildMcpToolName(serverName: string, toolName: string): string {\n\tconst server = sanitizeToolNameSegment(serverName);\n\tconst tool = sanitizeToolNameSegment(toolName);\n\tconst full = `${server}${MCP_TOOL_NAME_SEPARATOR}${tool}`;\n\tif (full.length <= MAX_TOOL_NAME_LENGTH) return full;\n\tconst room = MAX_TOOL_NAME_LENGTH - server.length - MCP_TOOL_NAME_SEPARATOR.length;\n\tif (room <= 0) return full.slice(0, MAX_TOOL_NAME_LENGTH);\n\treturn `${server}${MCP_TOOL_NAME_SEPARATOR}${tool.slice(0, room)}`;\n}\n\n/** Map MCP content blocks onto the harness content union, dropping unrenderable kinds. */\nexport function mapMcpContent(blocks: readonly McpContentBlock[]): (TextContent | ImageContent)[] {\n\tconst out: (TextContent | ImageContent)[] = [];\n\tfor (const block of blocks) {\n\t\tif (block.type === \"text\" && typeof block.text === \"string\") {\n\t\t\tout.push({ type: \"text\", text: block.text });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"image\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\t\tout.push({ type: \"image\", data: block.data, mimeType: block.mimeType });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"resource\" && typeof block.resource === \"object\" && block.resource !== null) {\n\t\t\tconst resource = block.resource as Record<string, unknown>;\n\t\t\tif (typeof resource.text === \"string\") {\n\t\t\t\tout.push({ type: \"text\", text: resource.text });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t// Unknown block kinds are summarized rather than dropped silently.\n\t\tout.push({ type: \"text\", text: `[unsupported MCP content block: ${String(block.type)}]` });\n\t}\n\treturn out;\n}\n\nexport interface CreateMcpToolDefinitionOptions {\n\t/** Per-call deadline. Falls back to the client's default. */\n\treadonly callTimeoutMs?: number;\n}\n\n/**\n * Wrap one MCP tool. The returned definition executes in `parallel` mode: MCP\n * tools declare no filesystem claims, so the DAG scheduler cannot prove a\n * conflict and must not serialize them by default.\n */\nexport function createMcpToolDefinition(\n\tserverName: string,\n\tclient: McpClient,\n\ttool: McpToolSchema,\n\toptions: CreateMcpToolDefinitionOptions = {},\n): ToolDefinition<TSchema, McpToolDetails> {\n\tconst exposedName = buildMcpToolName(serverName, tool.name);\n\tconst parameters = (tool.inputSchema ?? EMPTY_OBJECT_SCHEMA) as unknown as TSchema;\n\n\treturn {\n\t\tname: exposedName,\n\t\tlabel: tool.title ?? tool.name,\n\t\tdescription: tool.description ?? `MCP tool \"${tool.name}\" from server \"${serverName}\".`,\n\t\tparameters,\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params): Promise<AgentToolResult<McpToolDetails>> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool(tool.name, params, options.callTimeoutMs);\n\t\t\t\tconst content = mapMcpContent(result.content);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: content.length > 0 ? content : [{ type: \"text\", text: \"(no content)\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tserver: serverName,\n\t\t\t\t\t\ttool: tool.name,\n\t\t\t\t\t\tisError: result.isError,\n\t\t\t\t\t\tstructuredContent: result.structuredContent,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\t// A dead or hung server degrades this one tool call, not the turn.\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\t\t\tdetails: { server: serverName, tool: tool.name, isError: true },\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7E,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,oEAAoE;AACpE,eAAO,MAAM,oBAAoB,KAAK,CAAC;AA8BvC,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ7E;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAsBhG;AAED,MAAM,WAAW,8BAA8B;IAC9C,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,aAAa,EACnB,OAAO,GAAE,8BAAmC,GAC1C,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAiCzC","sourcesContent":["/**\n * Adapt an MCP tool into a harness `ToolDefinition`.\n *\n * Two things make this small:\n * - `validateToolArguments` already accepts a plain JSON Schema, so an MCP\n * `inputSchema` is passed through with only its root coerced instead of being\n * re-modelled in TypeBox.\n * - MCP content blocks are already text/image, which is exactly what the\n * harness renders.\n *\n * Naming: tools are exposed as `<server>__<tool>` so two servers can ship a\n * `search` without colliding, and so a model can tell where a tool came from.\n */\n\nimport type { ImageContent, TextContent } from \"omk-ai\";\nimport type { TSchema } from \"typebox\";\nimport type { AgentToolResult, ToolDefinition } from \"../extensions/types.ts\";\nimport type { McpClient, McpContentBlock, McpToolSchema } from \"./client.ts\";\n\n/** Tool-name separator between the server label and the server's own tool name. */\nexport const MCP_TOOL_NAME_SEPARATOR = \"__\";\n/** Providers reject long tool names; this is the common ceiling. */\nexport const MAX_TOOL_NAME_LENGTH = 64;\n\n/** Empty-object schema used when a server omits `inputSchema`. */\nconst EMPTY_OBJECT_SCHEMA = { type: \"object\", properties: {} } as const;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Coerce a server-supplied schema root into the object shape providers require.\n *\n * Tool arguments always arrive as a JSON object, so a root typed as anything\n * else is a server bug — `mcp-obsidian@1.0.0` answers `tools/list` with\n * `{ \"$schema\": \"http://json-schema.org/draft-07/schema#\" }`, and xAI ends the\n * whole run with `400 \"tool parameter root must be an object type\"`. Fixing it\n * here, at the boundary, degrades one schema instead of the session, and covers\n * every provider rather than only the ones that re-normalize tool payloads.\n *\n * Already-valid schemas are returned by identity: no per-tool copy, and TypeBox\n * symbols and prototypes survive untouched.\n */\nfunction toObjectRootSchema(schema: Record<string, unknown> | undefined): Record<string, unknown> {\n\tif (!isRecord(schema)) return EMPTY_OBJECT_SCHEMA;\n\tif (schema.type === \"object\" && isRecord(schema.properties)) return schema;\n\tconst root: Record<string, unknown> = { ...schema, type: \"object\" };\n\tif (!isRecord(root.properties)) root.properties = {};\n\treturn root;\n}\n\nexport interface McpToolDetails {\n\treadonly server: string;\n\treadonly tool: string;\n\treadonly isError: boolean;\n\treadonly structuredContent?: unknown;\n}\n\n/** Reduce an arbitrary label to the character set providers accept for tool names. */\nexport function sanitizeToolNameSegment(segment: string): string {\n\treturn segment.replace(/[^a-zA-Z0-9_-]/gu, \"_\").replace(/_{2,}/gu, \"_\");\n}\n\n/**\n * Build the exposed tool name. Over-long names keep the server prefix and\n * truncate the tool segment, because the prefix is what disambiguates.\n */\nexport function buildMcpToolName(serverName: string, toolName: string): string {\n\tconst server = sanitizeToolNameSegment(serverName);\n\tconst tool = sanitizeToolNameSegment(toolName);\n\tconst full = `${server}${MCP_TOOL_NAME_SEPARATOR}${tool}`;\n\tif (full.length <= MAX_TOOL_NAME_LENGTH) return full;\n\tconst room = MAX_TOOL_NAME_LENGTH - server.length - MCP_TOOL_NAME_SEPARATOR.length;\n\tif (room <= 0) return full.slice(0, MAX_TOOL_NAME_LENGTH);\n\treturn `${server}${MCP_TOOL_NAME_SEPARATOR}${tool.slice(0, room)}`;\n}\n\n/** Map MCP content blocks onto the harness content union, dropping unrenderable kinds. */\nexport function mapMcpContent(blocks: readonly McpContentBlock[]): (TextContent | ImageContent)[] {\n\tconst out: (TextContent | ImageContent)[] = [];\n\tfor (const block of blocks) {\n\t\tif (block.type === \"text\" && typeof block.text === \"string\") {\n\t\t\tout.push({ type: \"text\", text: block.text });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"image\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\t\tout.push({ type: \"image\", data: block.data, mimeType: block.mimeType });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"resource\" && typeof block.resource === \"object\" && block.resource !== null) {\n\t\t\tconst resource = block.resource as Record<string, unknown>;\n\t\t\tif (typeof resource.text === \"string\") {\n\t\t\t\tout.push({ type: \"text\", text: resource.text });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t// Unknown block kinds are summarized rather than dropped silently.\n\t\tout.push({ type: \"text\", text: `[unsupported MCP content block: ${String(block.type)}]` });\n\t}\n\treturn out;\n}\n\nexport interface CreateMcpToolDefinitionOptions {\n\t/** Per-call deadline. Falls back to the client's default. */\n\treadonly callTimeoutMs?: number;\n}\n\n/**\n * Wrap one MCP tool. The returned definition executes in `parallel` mode: MCP\n * tools declare no filesystem claims, so the DAG scheduler cannot prove a\n * conflict and must not serialize them by default.\n */\nexport function createMcpToolDefinition(\n\tserverName: string,\n\tclient: McpClient,\n\ttool: McpToolSchema,\n\toptions: CreateMcpToolDefinitionOptions = {},\n): ToolDefinition<TSchema, McpToolDetails> {\n\tconst exposedName = buildMcpToolName(serverName, tool.name);\n\tconst parameters = toObjectRootSchema(tool.inputSchema) as unknown as TSchema;\n\n\treturn {\n\t\tname: exposedName,\n\t\tlabel: tool.title ?? tool.name,\n\t\tdescription: tool.description ?? `MCP tool \"${tool.name}\" from server \"${serverName}\".`,\n\t\tparameters,\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params): Promise<AgentToolResult<McpToolDetails>> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool(tool.name, params, options.callTimeoutMs);\n\t\t\t\tconst content = mapMcpContent(result.content);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: content.length > 0 ? content : [{ type: \"text\", text: \"(no content)\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tserver: serverName,\n\t\t\t\t\t\ttool: tool.name,\n\t\t\t\t\t\tisError: result.isError,\n\t\t\t\t\t\tstructuredContent: result.structuredContent,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\t// A dead or hung server degrades this one tool call, not the turn.\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\t\t\tdetails: { server: serverName, tool: tool.name, isError: true },\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Two things make this small:
5
5
  * - `validateToolArguments` already accepts a plain JSON Schema, so an MCP
6
- * `inputSchema` is passed straight through instead of being re-modelled in
7
- * TypeBox.
6
+ * `inputSchema` is passed through with only its root coerced instead of being
7
+ * re-modelled in TypeBox.
8
8
  * - MCP content blocks are already text/image, which is exactly what the
9
9
  * harness renders.
10
10
  *
@@ -17,6 +17,32 @@ export const MCP_TOOL_NAME_SEPARATOR = "__";
17
17
  export const MAX_TOOL_NAME_LENGTH = 64;
18
18
  /** Empty-object schema used when a server omits `inputSchema`. */
19
19
  const EMPTY_OBJECT_SCHEMA = { type: "object", properties: {} };
20
+ function isRecord(value) {
21
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22
+ }
23
+ /**
24
+ * Coerce a server-supplied schema root into the object shape providers require.
25
+ *
26
+ * Tool arguments always arrive as a JSON object, so a root typed as anything
27
+ * else is a server bug — `mcp-obsidian@1.0.0` answers `tools/list` with
28
+ * `{ "$schema": "http://json-schema.org/draft-07/schema#" }`, and xAI ends the
29
+ * whole run with `400 "tool parameter root must be an object type"`. Fixing it
30
+ * here, at the boundary, degrades one schema instead of the session, and covers
31
+ * every provider rather than only the ones that re-normalize tool payloads.
32
+ *
33
+ * Already-valid schemas are returned by identity: no per-tool copy, and TypeBox
34
+ * symbols and prototypes survive untouched.
35
+ */
36
+ function toObjectRootSchema(schema) {
37
+ if (!isRecord(schema))
38
+ return EMPTY_OBJECT_SCHEMA;
39
+ if (schema.type === "object" && isRecord(schema.properties))
40
+ return schema;
41
+ const root = { ...schema, type: "object" };
42
+ if (!isRecord(root.properties))
43
+ root.properties = {};
44
+ return root;
45
+ }
20
46
  /** Reduce an arbitrary label to the character set providers accept for tool names. */
21
47
  export function sanitizeToolNameSegment(segment) {
22
48
  return segment.replace(/[^a-zA-Z0-9_-]/gu, "_").replace(/_{2,}/gu, "_");
@@ -67,7 +93,7 @@ export function mapMcpContent(blocks) {
67
93
  */
68
94
  export function createMcpToolDefinition(serverName, client, tool, options = {}) {
69
95
  const exposedName = buildMcpToolName(serverName, tool.name);
70
- const parameters = (tool.inputSchema ?? EMPTY_OBJECT_SCHEMA);
96
+ const parameters = toObjectRootSchema(tool.inputSchema);
71
97
  return {
72
98
  name: exposedName,
73
99
  label: tool.title ?? tool.name,
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/core/mcp/tools.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Adapt an MCP tool into a harness `ToolDefinition`.\n *\n * Two things make this small:\n * - `validateToolArguments` already accepts a plain JSON Schema, so an MCP\n * `inputSchema` is passed straight through instead of being re-modelled in\n * TypeBox.\n * - MCP content blocks are already text/image, which is exactly what the\n * harness renders.\n *\n * Naming: tools are exposed as `<server>__<tool>` so two servers can ship a\n * `search` without colliding, and so a model can tell where a tool came from.\n */\n\nimport type { ImageContent, TextContent } from \"omk-ai\";\nimport type { TSchema } from \"typebox\";\nimport type { AgentToolResult, ToolDefinition } from \"../extensions/types.ts\";\nimport type { McpClient, McpContentBlock, McpToolSchema } from \"./client.ts\";\n\n/** Tool-name separator between the server label and the server's own tool name. */\nexport const MCP_TOOL_NAME_SEPARATOR = \"__\";\n/** Providers reject long tool names; this is the common ceiling. */\nexport const MAX_TOOL_NAME_LENGTH = 64;\n\n/** Empty-object schema used when a server omits `inputSchema`. */\nconst EMPTY_OBJECT_SCHEMA = { type: \"object\", properties: {} } as const;\n\nexport interface McpToolDetails {\n\treadonly server: string;\n\treadonly tool: string;\n\treadonly isError: boolean;\n\treadonly structuredContent?: unknown;\n}\n\n/** Reduce an arbitrary label to the character set providers accept for tool names. */\nexport function sanitizeToolNameSegment(segment: string): string {\n\treturn segment.replace(/[^a-zA-Z0-9_-]/gu, \"_\").replace(/_{2,}/gu, \"_\");\n}\n\n/**\n * Build the exposed tool name. Over-long names keep the server prefix and\n * truncate the tool segment, because the prefix is what disambiguates.\n */\nexport function buildMcpToolName(serverName: string, toolName: string): string {\n\tconst server = sanitizeToolNameSegment(serverName);\n\tconst tool = sanitizeToolNameSegment(toolName);\n\tconst full = `${server}${MCP_TOOL_NAME_SEPARATOR}${tool}`;\n\tif (full.length <= MAX_TOOL_NAME_LENGTH) return full;\n\tconst room = MAX_TOOL_NAME_LENGTH - server.length - MCP_TOOL_NAME_SEPARATOR.length;\n\tif (room <= 0) return full.slice(0, MAX_TOOL_NAME_LENGTH);\n\treturn `${server}${MCP_TOOL_NAME_SEPARATOR}${tool.slice(0, room)}`;\n}\n\n/** Map MCP content blocks onto the harness content union, dropping unrenderable kinds. */\nexport function mapMcpContent(blocks: readonly McpContentBlock[]): (TextContent | ImageContent)[] {\n\tconst out: (TextContent | ImageContent)[] = [];\n\tfor (const block of blocks) {\n\t\tif (block.type === \"text\" && typeof block.text === \"string\") {\n\t\t\tout.push({ type: \"text\", text: block.text });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"image\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\t\tout.push({ type: \"image\", data: block.data, mimeType: block.mimeType });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"resource\" && typeof block.resource === \"object\" && block.resource !== null) {\n\t\t\tconst resource = block.resource as Record<string, unknown>;\n\t\t\tif (typeof resource.text === \"string\") {\n\t\t\t\tout.push({ type: \"text\", text: resource.text });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t// Unknown block kinds are summarized rather than dropped silently.\n\t\tout.push({ type: \"text\", text: `[unsupported MCP content block: ${String(block.type)}]` });\n\t}\n\treturn out;\n}\n\nexport interface CreateMcpToolDefinitionOptions {\n\t/** Per-call deadline. Falls back to the client's default. */\n\treadonly callTimeoutMs?: number;\n}\n\n/**\n * Wrap one MCP tool. The returned definition executes in `parallel` mode: MCP\n * tools declare no filesystem claims, so the DAG scheduler cannot prove a\n * conflict and must not serialize them by default.\n */\nexport function createMcpToolDefinition(\n\tserverName: string,\n\tclient: McpClient,\n\ttool: McpToolSchema,\n\toptions: CreateMcpToolDefinitionOptions = {},\n): ToolDefinition<TSchema, McpToolDetails> {\n\tconst exposedName = buildMcpToolName(serverName, tool.name);\n\tconst parameters = (tool.inputSchema ?? EMPTY_OBJECT_SCHEMA) as unknown as TSchema;\n\n\treturn {\n\t\tname: exposedName,\n\t\tlabel: tool.title ?? tool.name,\n\t\tdescription: tool.description ?? `MCP tool \"${tool.name}\" from server \"${serverName}\".`,\n\t\tparameters,\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params): Promise<AgentToolResult<McpToolDetails>> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool(tool.name, params, options.callTimeoutMs);\n\t\t\t\tconst content = mapMcpContent(result.content);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: content.length > 0 ? content : [{ type: \"text\", text: \"(no content)\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tserver: serverName,\n\t\t\t\t\t\ttool: tool.name,\n\t\t\t\t\t\tisError: result.isError,\n\t\t\t\t\t\tstructuredContent: result.structuredContent,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\t// A dead or hung server degrades this one tool call, not the turn.\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\t\t\tdetails: { server: serverName, tool: tool.name, isError: true },\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/core/mcp/tools.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Adapt an MCP tool into a harness `ToolDefinition`.\n *\n * Two things make this small:\n * - `validateToolArguments` already accepts a plain JSON Schema, so an MCP\n * `inputSchema` is passed through with only its root coerced instead of being\n * re-modelled in TypeBox.\n * - MCP content blocks are already text/image, which is exactly what the\n * harness renders.\n *\n * Naming: tools are exposed as `<server>__<tool>` so two servers can ship a\n * `search` without colliding, and so a model can tell where a tool came from.\n */\n\nimport type { ImageContent, TextContent } from \"omk-ai\";\nimport type { TSchema } from \"typebox\";\nimport type { AgentToolResult, ToolDefinition } from \"../extensions/types.ts\";\nimport type { McpClient, McpContentBlock, McpToolSchema } from \"./client.ts\";\n\n/** Tool-name separator between the server label and the server's own tool name. */\nexport const MCP_TOOL_NAME_SEPARATOR = \"__\";\n/** Providers reject long tool names; this is the common ceiling. */\nexport const MAX_TOOL_NAME_LENGTH = 64;\n\n/** Empty-object schema used when a server omits `inputSchema`. */\nconst EMPTY_OBJECT_SCHEMA = { type: \"object\", properties: {} } as const;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Coerce a server-supplied schema root into the object shape providers require.\n *\n * Tool arguments always arrive as a JSON object, so a root typed as anything\n * else is a server bug — `mcp-obsidian@1.0.0` answers `tools/list` with\n * `{ \"$schema\": \"http://json-schema.org/draft-07/schema#\" }`, and xAI ends the\n * whole run with `400 \"tool parameter root must be an object type\"`. Fixing it\n * here, at the boundary, degrades one schema instead of the session, and covers\n * every provider rather than only the ones that re-normalize tool payloads.\n *\n * Already-valid schemas are returned by identity: no per-tool copy, and TypeBox\n * symbols and prototypes survive untouched.\n */\nfunction toObjectRootSchema(schema: Record<string, unknown> | undefined): Record<string, unknown> {\n\tif (!isRecord(schema)) return EMPTY_OBJECT_SCHEMA;\n\tif (schema.type === \"object\" && isRecord(schema.properties)) return schema;\n\tconst root: Record<string, unknown> = { ...schema, type: \"object\" };\n\tif (!isRecord(root.properties)) root.properties = {};\n\treturn root;\n}\n\nexport interface McpToolDetails {\n\treadonly server: string;\n\treadonly tool: string;\n\treadonly isError: boolean;\n\treadonly structuredContent?: unknown;\n}\n\n/** Reduce an arbitrary label to the character set providers accept for tool names. */\nexport function sanitizeToolNameSegment(segment: string): string {\n\treturn segment.replace(/[^a-zA-Z0-9_-]/gu, \"_\").replace(/_{2,}/gu, \"_\");\n}\n\n/**\n * Build the exposed tool name. Over-long names keep the server prefix and\n * truncate the tool segment, because the prefix is what disambiguates.\n */\nexport function buildMcpToolName(serverName: string, toolName: string): string {\n\tconst server = sanitizeToolNameSegment(serverName);\n\tconst tool = sanitizeToolNameSegment(toolName);\n\tconst full = `${server}${MCP_TOOL_NAME_SEPARATOR}${tool}`;\n\tif (full.length <= MAX_TOOL_NAME_LENGTH) return full;\n\tconst room = MAX_TOOL_NAME_LENGTH - server.length - MCP_TOOL_NAME_SEPARATOR.length;\n\tif (room <= 0) return full.slice(0, MAX_TOOL_NAME_LENGTH);\n\treturn `${server}${MCP_TOOL_NAME_SEPARATOR}${tool.slice(0, room)}`;\n}\n\n/** Map MCP content blocks onto the harness content union, dropping unrenderable kinds. */\nexport function mapMcpContent(blocks: readonly McpContentBlock[]): (TextContent | ImageContent)[] {\n\tconst out: (TextContent | ImageContent)[] = [];\n\tfor (const block of blocks) {\n\t\tif (block.type === \"text\" && typeof block.text === \"string\") {\n\t\t\tout.push({ type: \"text\", text: block.text });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"image\" && typeof block.data === \"string\" && typeof block.mimeType === \"string\") {\n\t\t\tout.push({ type: \"image\", data: block.data, mimeType: block.mimeType });\n\t\t\tcontinue;\n\t\t}\n\t\tif (block.type === \"resource\" && typeof block.resource === \"object\" && block.resource !== null) {\n\t\t\tconst resource = block.resource as Record<string, unknown>;\n\t\t\tif (typeof resource.text === \"string\") {\n\t\t\t\tout.push({ type: \"text\", text: resource.text });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t// Unknown block kinds are summarized rather than dropped silently.\n\t\tout.push({ type: \"text\", text: `[unsupported MCP content block: ${String(block.type)}]` });\n\t}\n\treturn out;\n}\n\nexport interface CreateMcpToolDefinitionOptions {\n\t/** Per-call deadline. Falls back to the client's default. */\n\treadonly callTimeoutMs?: number;\n}\n\n/**\n * Wrap one MCP tool. The returned definition executes in `parallel` mode: MCP\n * tools declare no filesystem claims, so the DAG scheduler cannot prove a\n * conflict and must not serialize them by default.\n */\nexport function createMcpToolDefinition(\n\tserverName: string,\n\tclient: McpClient,\n\ttool: McpToolSchema,\n\toptions: CreateMcpToolDefinitionOptions = {},\n): ToolDefinition<TSchema, McpToolDetails> {\n\tconst exposedName = buildMcpToolName(serverName, tool.name);\n\tconst parameters = toObjectRootSchema(tool.inputSchema) as unknown as TSchema;\n\n\treturn {\n\t\tname: exposedName,\n\t\tlabel: tool.title ?? tool.name,\n\t\tdescription: tool.description ?? `MCP tool \"${tool.name}\" from server \"${serverName}\".`,\n\t\tparameters,\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params): Promise<AgentToolResult<McpToolDetails>> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool(tool.name, params, options.callTimeoutMs);\n\t\t\t\tconst content = mapMcpContent(result.content);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: content.length > 0 ? content : [{ type: \"text\", text: \"(no content)\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tserver: serverName,\n\t\t\t\t\t\ttool: tool.name,\n\t\t\t\t\t\tisError: result.isError,\n\t\t\t\t\t\tstructuredContent: result.structuredContent,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\t// A dead or hung server degrades this one tool call, not the turn.\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\t\t\tdetails: { server: serverName, tool: tool.name, isError: true },\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t};\n}\n"]}