@try-works/dsh-model-as-tool 0.1.3 → 0.4.0

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 (260) hide show
  1. package/bin/dsh-tool-mode-credentials.mjs +20 -0
  2. package/bin/dsh-tool-mode.mjs +202 -0
  3. package/catalog/desert-ant-models.json +693 -693
  4. package/client/client.model-tools.js +614 -0
  5. package/client/index.js +1717 -0
  6. package/lib/adapters/index.d.ts.map +1 -1
  7. package/lib/adapters/index.js +4 -4
  8. package/lib/bindings.d.ts.map +1 -1
  9. package/lib/bindings.js +26 -25
  10. package/lib/capability.d.ts.map +1 -1
  11. package/lib/capability.js +17 -0
  12. package/lib/capture-path.d.ts +97 -0
  13. package/lib/capture-path.d.ts.map +1 -0
  14. package/lib/capture-path.js +152 -0
  15. package/lib/diagnostics.d.ts +166 -0
  16. package/lib/diagnostics.d.ts.map +1 -0
  17. package/lib/diagnostics.js +135 -0
  18. package/lib/extension-dependencies.d.ts +325 -0
  19. package/lib/extension-dependencies.d.ts.map +1 -0
  20. package/lib/extension-dependencies.js +858 -0
  21. package/lib/extension-dispatch.d.ts +117 -0
  22. package/lib/extension-dispatch.d.ts.map +1 -0
  23. package/lib/extension-dispatch.js +124 -0
  24. package/lib/extension-registrar.d.ts +100 -0
  25. package/lib/extension-registrar.d.ts.map +1 -0
  26. package/lib/extension-registrar.js +134 -0
  27. package/lib/extensions-api.d.ts +221 -0
  28. package/lib/extensions-api.d.ts.map +1 -0
  29. package/lib/extensions-api.js +17 -0
  30. package/lib/extensions-remote.d.ts +54 -0
  31. package/lib/extensions-remote.d.ts.map +1 -0
  32. package/lib/extensions-remote.js +66 -0
  33. package/lib/extensions-service.d.ts +367 -0
  34. package/lib/extensions-service.d.ts.map +1 -0
  35. package/lib/extensions-service.js +1527 -0
  36. package/lib/harness-llm.d.ts +138 -0
  37. package/lib/harness-llm.d.ts.map +1 -0
  38. package/lib/harness-llm.js +218 -0
  39. package/lib/harness-serving.d.ts +95 -0
  40. package/lib/harness-serving.d.ts.map +1 -0
  41. package/lib/harness-serving.js +157 -0
  42. package/lib/headless.d.ts +97 -0
  43. package/lib/headless.d.ts.map +1 -0
  44. package/lib/headless.js +349 -0
  45. package/lib/http-acquisition.d.ts +27 -0
  46. package/lib/http-acquisition.d.ts.map +1 -0
  47. package/lib/http-acquisition.js +136 -0
  48. package/lib/index.d.ts +271 -7
  49. package/lib/index.d.ts.map +1 -1
  50. package/lib/index.js +2644 -70
  51. package/lib/invocation-accounting.d.ts +169 -0
  52. package/lib/invocation-accounting.d.ts.map +1 -0
  53. package/lib/invocation-accounting.js +148 -0
  54. package/lib/legacy-migration.d.ts +95 -0
  55. package/lib/legacy-migration.d.ts.map +1 -0
  56. package/lib/legacy-migration.js +429 -0
  57. package/lib/managed-workers.d.ts +151 -0
  58. package/lib/managed-workers.d.ts.map +1 -0
  59. package/lib/managed-workers.js +249 -0
  60. package/lib/mcp/client-grant.d.ts +74 -0
  61. package/lib/mcp/client-grant.d.ts.map +1 -0
  62. package/lib/mcp/client-grant.js +60 -0
  63. package/lib/mcp/credential-cli.d.ts +38 -0
  64. package/lib/mcp/credential-cli.d.ts.map +1 -0
  65. package/lib/mcp/credential-cli.js +148 -0
  66. package/lib/mcp/credential-store.d.ts +143 -0
  67. package/lib/mcp/credential-store.d.ts.map +1 -0
  68. package/lib/mcp/credential-store.js +454 -0
  69. package/lib/mcp/host-binding.d.ts +25 -0
  70. package/lib/mcp/host-binding.d.ts.map +1 -1
  71. package/lib/mcp/host-binding.js +107 -14
  72. package/lib/mcp/http.d.ts +68 -18
  73. package/lib/mcp/http.d.ts.map +1 -1
  74. package/lib/mcp/http.js +390 -62
  75. package/lib/mcp/oauth.d.ts +149 -0
  76. package/lib/mcp/oauth.d.ts.map +1 -0
  77. package/lib/mcp/oauth.js +396 -0
  78. package/lib/mcp/protocol.d.ts +46 -7
  79. package/lib/mcp/protocol.d.ts.map +1 -1
  80. package/lib/mcp/protocol.js +63 -16
  81. package/lib/mcp/rate-limit.d.ts +68 -0
  82. package/lib/mcp/rate-limit.d.ts.map +1 -0
  83. package/lib/mcp/rate-limit.js +114 -0
  84. package/lib/mcp/sdk-v2.d.ts +17 -0
  85. package/lib/mcp/sdk-v2.d.ts.map +1 -0
  86. package/lib/mcp/sdk-v2.js +181 -0
  87. package/lib/mcp/server.d.ts +11 -1
  88. package/lib/mcp/server.d.ts.map +1 -1
  89. package/lib/mcp/server.js +80 -13
  90. package/lib/mcp/stdio.d.ts.map +1 -1
  91. package/lib/mcp/stdio.js +9 -1
  92. package/lib/mcp/subscriptions.d.ts +43 -1
  93. package/lib/mcp/subscriptions.d.ts.map +1 -1
  94. package/lib/mcp/subscriptions.js +90 -9
  95. package/lib/model-qualification.d.ts +192 -0
  96. package/lib/model-qualification.d.ts.map +1 -0
  97. package/lib/model-qualification.js +178 -0
  98. package/lib/planning.d.ts +246 -0
  99. package/lib/planning.d.ts.map +1 -0
  100. package/lib/planning.js +457 -0
  101. package/lib/prepared-assets.d.ts +178 -0
  102. package/lib/prepared-assets.d.ts.map +1 -0
  103. package/lib/prepared-assets.js +286 -0
  104. package/lib/provider-bridge.d.ts +37 -0
  105. package/lib/provider-bridge.d.ts.map +1 -1
  106. package/lib/provider-bridge.js +189 -12
  107. package/lib/ptc-authority.d.ts +140 -0
  108. package/lib/ptc-authority.d.ts.map +1 -0
  109. package/lib/ptc-authority.js +216 -0
  110. package/lib/ptc-runtime.d.ts +156 -0
  111. package/lib/ptc-runtime.d.ts.map +1 -0
  112. package/lib/ptc-runtime.js +191 -0
  113. package/lib/publication.d.ts +2 -1
  114. package/lib/publication.d.ts.map +1 -1
  115. package/lib/publication.js +13 -5
  116. package/lib/receipt.d.ts.map +1 -1
  117. package/lib/receipt.js +8 -0
  118. package/lib/title-proposal.d.ts +194 -0
  119. package/lib/title-proposal.d.ts.map +1 -0
  120. package/lib/title-proposal.js +244 -0
  121. package/lib/tool-mode-run.d.ts +235 -0
  122. package/lib/tool-mode-run.d.ts.map +1 -0
  123. package/lib/tool-mode-run.js +283 -0
  124. package/lib/types.d.ts +3 -1
  125. package/lib/types.d.ts.map +1 -1
  126. package/lib/update-surface.d.ts +79 -0
  127. package/lib/update-surface.d.ts.map +1 -0
  128. package/lib/update-surface.js +224 -0
  129. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts +38 -0
  130. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts.map +1 -0
  131. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.js +445 -0
  132. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts +14 -0
  133. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts.map +1 -0
  134. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.js +63 -0
  135. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts +14 -0
  136. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts.map +1 -0
  137. package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.js +76 -0
  138. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -1
  139. package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +69 -55
  140. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +4 -1
  141. package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -1
  142. package/node_modules/@try-works/tool-mode-contracts/lib/index.js +26 -2
  143. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +28 -2
  144. package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -1
  145. package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +93 -10
  146. package/node_modules/@try-works/tool-mode-contracts/package.json +0 -1
  147. package/node_modules/@try-works/tool-mode-extension-sdk/bin/dsh-tool-mode.mjs +20 -0
  148. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts +80 -0
  149. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts.map +1 -0
  150. package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.js +533 -0
  151. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts +83 -0
  152. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts.map +1 -0
  153. package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.js +125 -0
  154. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts +70 -0
  155. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts.map +1 -0
  156. package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.js +201 -0
  157. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts +57 -0
  158. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts.map +1 -0
  159. package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.js +83 -0
  160. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts +32 -0
  161. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts.map +1 -0
  162. package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.js +32 -0
  163. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts +86 -0
  164. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts.map +1 -0
  165. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.js +191 -0
  166. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts +126 -0
  167. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts.map +1 -0
  168. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.js +297 -0
  169. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts +216 -0
  170. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts.map +1 -0
  171. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.js +800 -0
  172. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts +210 -0
  173. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts.map +1 -0
  174. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.js +368 -0
  175. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts +63 -0
  176. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts.map +1 -0
  177. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.js +149 -0
  178. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts +35 -0
  179. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts.map +1 -0
  180. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.js +179 -0
  181. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts +179 -0
  182. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts.map +1 -0
  183. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.js +235 -0
  184. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +367 -0
  185. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -0
  186. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +807 -0
  187. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts +44 -0
  188. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts.map +1 -0
  189. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.js +243 -0
  190. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts +185 -0
  191. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
  192. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
  193. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
  194. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
  195. package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
  196. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
  197. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
  198. package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
  199. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
  200. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
  201. package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
  202. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
  203. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
  204. package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
  205. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +118 -0
  206. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
  207. package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
  208. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
  209. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
  210. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
  211. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +150 -0
  212. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
  213. package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +670 -0
  214. package/node_modules/@try-works/tool-mode-extension-sdk/package.json +53 -0
  215. package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
  216. package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
  217. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +427 -0
  218. package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
  219. package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +592 -0
  220. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +60 -0
  221. package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
  222. package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +936 -0
  223. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
  224. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
  225. package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +200 -0
  226. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
  227. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
  228. package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
  229. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +105 -0
  230. package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
  231. package/node_modules/@try-works/tool-mode-recipes/lib/images.js +129 -0
  232. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
  233. package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
  234. package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
  235. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +325 -0
  236. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
  237. package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1310 -0
  238. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
  239. package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
  240. package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
  241. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +227 -0
  242. package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
  243. package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +407 -0
  244. package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
  245. package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
  246. package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
  247. package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
  248. package/package.json +43 -15
  249. package/remote/spec.mjs +462 -0
  250. package/remote/typert.host.mjs +14 -0
  251. package/remote/typert.remote-client.mjs +16 -0
  252. package/lib/adapters/tongue.d.ts +0 -31
  253. package/lib/adapters/tongue.d.ts.map +0 -1
  254. package/lib/adapters/tongue.js +0 -93
  255. package/lib/adapters/voz.d.ts +0 -28
  256. package/lib/adapters/voz.d.ts.map +0 -1
  257. package/lib/adapters/voz.js +0 -102
  258. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts +0 -0
  259. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts.map +0 -0
  260. /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.js +0 -0
@@ -22,8 +22,13 @@
22
22
  *
23
23
  * @module @try-works/dsh-model-as-tool/mcp/host-binding
24
24
  */
25
+ import { Ajv } from 'ajv';
26
+ import { redactText } from "./../receipt.js";
27
+ import { accountInvocation, classifyOutcome, PhaseTimer, } from "../invocation-accounting.js";
25
28
  /** The reserved root field the host authors, never the implementation. */
26
29
  const RESERVED_META = 'meta';
30
+ const ajv = new Ajv({ allErrors: true, strict: false, allowUnionTypes: true });
31
+ const payloadValidators = new Map();
27
32
  /**
28
33
  * Derive the payload schema from a contract's final output schema (§16.4).
29
34
  *
@@ -44,6 +49,40 @@ export function derivePayloadSchema(outputSchema) {
44
49
  }
45
50
  return clone;
46
51
  }
52
+ /** Render Ajv errors as bounded, path-qualified text. */
53
+ function renderValidationErrors(errors) {
54
+ return (errors ?? [])
55
+ .map(error => `${error.instancePath || '(root)'} ${error.message ?? 'is invalid'}`)
56
+ .slice(0, 8)
57
+ .join('; ');
58
+ }
59
+ /** Validator for the externally advertised payload schema. */
60
+ function payloadValidator(contract) {
61
+ const existing = payloadValidators.get(contract.contract);
62
+ if (existing !== undefined)
63
+ return existing;
64
+ const validate = ajv.compile(derivePayloadSchema(contract.outputSchema));
65
+ payloadValidators.set(contract.contract, validate);
66
+ return validate;
67
+ }
68
+ /**
69
+ * Convert a host result into the MCP payload shape and validate it.
70
+ *
71
+ * Host-native results may include the reserved `meta` envelope because the DSH tool contract
72
+ * validates that full value. MCP §16.4 publishes the payload schema with `meta` removed, so the
73
+ * external value must be the same payload with only that reserved field omitted. A malformed host
74
+ * result is returned as a tool error rather than a success-shaped `structuredContent`.
75
+ */
76
+ function payloadForMcp(contract, value) {
77
+ const payload = typeof value === 'object' && value !== null && !Array.isArray(value)
78
+ ? Object.fromEntries(Object.entries(value).filter(([key]) => key !== RESERVED_META))
79
+ : value;
80
+ const validate = payloadValidator(contract);
81
+ if (!validate(payload)) {
82
+ return { ok: false, reason: `tool result violates the advertised MCP output schema: ${renderValidationErrors(validate.errors)}` };
83
+ }
84
+ return { ok: true, value: payload };
85
+ }
47
86
  /**
48
87
  * Build the MCP host surface over a DSH tool surface.
49
88
  *
@@ -78,7 +117,7 @@ export function createMcpHost(options) {
78
117
  }
79
118
  return out;
80
119
  },
81
- async callTool(name, args, signal) {
120
+ async callTool(name, args, signal, caller) {
82
121
  const definition = options.surface.published.find(tool => tool.toolName === name);
83
122
  // A tool that is not EXPORTABLE must not be callable either. Looking only for
84
123
  // its presence in `published` would let a client invoke by name exactly the
@@ -92,14 +131,67 @@ export function createMcpHost(options) {
92
131
  isError: true,
93
132
  };
94
133
  }
95
- const outcome = await options.surface.execute({
96
- name,
97
- arguments: args,
98
- signal,
99
- // Server-issued, monotonically increasing. A caller-supplied identity would
100
- // let a caller forge a receipt (BASE-05).
101
- callId: `mcp_${Date.now().toString(36)}_${(++counter).toString(36)}`,
102
- });
134
+ /**
135
+ * ACCOUNTING, wrapped around the dispatch (OBS-02).
136
+ *
137
+ * The timer measures the external call's own phases and the outcome is classified
138
+ * from what was OBSERVED, not assumed — a cancelled external call must not be
139
+ * recorded as a failure, so the abort state is read from the caller's own signal.
140
+ * The CALLER'S grant identity rides the record (SEC-04): identity only, never the
141
+ * payload, so the operator can tell which client called.
142
+ */
143
+ const callId = `mcp_${Date.now().toString(36)}_${(++counter).toString(36)}`;
144
+ const timer = new PhaseTimer();
145
+ timer.begin('inference');
146
+ let outcome;
147
+ try {
148
+ outcome = await options.surface.execute({
149
+ name,
150
+ arguments: args,
151
+ signal,
152
+ // Server-issued, monotonically increasing. A caller-supplied identity would
153
+ // let a caller forge a receipt (BASE-05).
154
+ callId,
155
+ ...caller === undefined ? {} : { caller },
156
+ });
157
+ }
158
+ catch (error) {
159
+ options.onAccounted?.(accountInvocation({
160
+ receiptId: callId,
161
+ timings: timer.finish(),
162
+ failureClass: classifyOutcome({ ok: false, aborted: signal.aborted }),
163
+ reason: error instanceof Error ? redactText(error.message) : String(error),
164
+ input: args,
165
+ engineVersion: options.engineVersion ?? 'unknown',
166
+ ...caller === undefined ? {} : { grantId: caller.grantId, clientId: caller.clientId },
167
+ }));
168
+ throw error;
169
+ }
170
+ // CORRELATION (the round-65 review's finding): the contract payload's
171
+ // reserved meta carries the NATIVE receipt id the host dispatch issued, so
172
+ // the external accounting joins the native ring by that id when the result
173
+ // carries one — the two rings are no longer unjoinable. A value without
174
+ // meta (a tool that predates the meta contract) falls back to the
175
+ // server-issued id.
176
+ const nativeReceiptId = (() => {
177
+ const meta = outcome.value?.meta;
178
+ return typeof meta?.receiptId === 'string' ? meta.receiptId : callId;
179
+ })();
180
+ options.onAccounted?.(accountInvocation({
181
+ receiptId: nativeReceiptId,
182
+ timings: timer.finish(),
183
+ failureClass: classifyOutcome({
184
+ ok: outcome.isError !== true,
185
+ aborted: signal.aborted,
186
+ refused: outcome.isError === true,
187
+ }),
188
+ ...outcome.isError === true && outcome.message !== undefined ? { reason: redactText(outcome.message) } : {},
189
+ input: args,
190
+ // An error carries no result, so nothing crossed the boundary as output.
191
+ output: outcome.isError === true ? undefined : outcome.value,
192
+ engineVersion: options.engineVersion ?? 'unknown',
193
+ ...caller === undefined ? {} : { grantId: caller.grantId, clientId: caller.clientId },
194
+ }));
103
195
  if (outcome.isError) {
104
196
  return {
105
197
  structured: null,
@@ -108,12 +200,13 @@ export function createMcpHost(options) {
108
200
  isError: true,
109
201
  };
110
202
  }
203
+ const payload = payloadForMcp(definition.contract, outcome.value ?? null);
204
+ if (!payload.ok) {
205
+ return { structured: null, text: payload.reason, isError: true };
206
+ }
111
207
  return {
112
- // The canonical value, post-policy, exactly as the host returned it: a
113
- // redaction here would be a content-only control, which MCP-11 says is not a
114
- // confidentiality control at all.
115
- structured: outcome.value ?? null,
116
- text: renderBounded(outcome.value),
208
+ structured: payload.value,
209
+ text: renderBounded(payload.value),
117
210
  };
118
211
  },
119
212
  };
package/lib/mcp/http.d.ts CHANGED
@@ -16,7 +16,10 @@
16
16
  *
17
17
  * @module @try-works/dsh-model-as-tool/mcp/http
18
18
  */
19
- import { type McpHost } from './server.ts';
19
+ import type { McpHost } from './server.ts';
20
+ import { type LocalOAuthServer } from './oauth.ts';
21
+ import { type RateLimitPolicy } from './rate-limit.ts';
22
+ import { type ClientGrantConfig } from './client-grant.ts';
20
23
  /** How the endpoint authenticates. */
21
24
  export interface StaticTokenAuth {
22
25
  /**
@@ -31,7 +34,31 @@ export interface StaticTokenAuth {
31
34
  readonly token: string;
32
35
  /** The caller identity recorded for the grant, for receipts and audit. */
33
36
  readonly clientId: string;
37
+ /**
38
+ * The durable credential store holding GENERATED static-token credentials (SEC-01).
39
+ *
40
+ * When present, a presented bearer token is also checked against the stored
41
+ * credentials (constant-time over the whole registry), and the matched client's
42
+ * OWN identity drives grants, receipts and rate limiting — never the configured
43
+ * primary `clientId`. Absent keeps the single-token behavior.
44
+ */
45
+ readonly registry?: import('./credential-store.ts').ClientCredentialStore;
46
+ }
47
+ /** The OAuth 2.1 resource-server scheme (P26-15). */
48
+ export interface OAuthResourceServerAuth {
49
+ /**
50
+ * The scheme this endpoint implements: the local embedded authorization server
51
+ * issues HS256 credentials and this endpoint verifies them per RFC 6750, with
52
+ * audience and scope validation and per-client revocation.
53
+ */
54
+ readonly scheme: 'oauth-resource-server';
55
+ /** The embedded server: verifier, issuer and revocation registry. */
56
+ readonly server: LocalOAuthServer;
57
+ /** The scope a caller must hold to reach the MCP endpoint. */
58
+ readonly requiredScope?: readonly string[];
34
59
  }
60
+ /** The union of supported authentication schemes. */
61
+ export type HttpAuth = StaticTokenAuth | OAuthResourceServerAuth;
35
62
  /** Transport configuration. */
36
63
  export interface HttpTransportConfig {
37
64
  /** Path the endpoint serves. */
@@ -50,9 +77,31 @@ export interface HttpTransportConfig {
50
77
  * rather than a missing one, and CORS is not used as authentication anywhere.
51
78
  */
52
79
  readonly allowedOrigins: readonly string[];
53
- readonly auth: StaticTokenAuth;
80
+ readonly auth: HttpAuth;
81
+ /**
82
+ * Per-client request rate limiting (AT-12).
83
+ *
84
+ * Absent means the DEFAULT policy applies — 60 requests per client per minute — so
85
+ * the transport is bounded by default rather than only when someone remembers to ask.
86
+ * A policy overrides the default; `false` disables limiting explicitly. The count is
87
+ * keyed on the AUTHENTICATED client identity (the static-token `clientId` or the OAuth
88
+ * subject), never on the socket address, and an unauthenticated request never moves a
89
+ * counter — counting auth failures would leak credential existence through 429 timing.
90
+ */
91
+ readonly rateLimit?: RateLimitPolicy | false;
92
+ /**
93
+ * Per-client external grants (SEC-04).
94
+ *
95
+ * After authentication, each client's grant is DERIVED here — from this
96
+ * configuration, the authenticated identity and the live published surface — and
97
+ * travels with the call as caller identity. Absent means the default: every client
98
+ * is granted exactly the live surface, recorded under its own `external:<clientId>`
99
+ * grant identity. A request body can never supply or extend a grant (BASE-05).
100
+ */
101
+ readonly grants?: ClientGrantConfig;
54
102
  }
55
- /** A conservative default: loopback, the illustrative port, a small body cap. */
103
+ /** A conservative default: loopback, the illustrative port, a small body cap,
104
+ * and the default per-client rate limit (AT-12). */
56
105
  export declare const DEFAULT_HTTP_CONFIG: Omit<HttpTransportConfig, 'auth'>;
57
106
  /** One HTTP request, described rather than received. */
58
107
  export interface HttpRequestDescription {
@@ -75,35 +124,36 @@ export interface HttpResponseDescription {
75
124
  /** Whether an address is loopback. */
76
125
  export declare function isLoopback(address: string): boolean;
77
126
  /**
78
- * Build the request handler.
79
- *
80
- * Ordering is deliberate and matches P26-16's list: transport identity (loopback,
81
- * size, method, path) is settled before authentication, and authentication before
82
- * any protocol parsing. A request that is not from the loopback is refused without
83
- * its token being examined at all.
84
- * @param config - the transport configuration.
85
- * @param host - the MCP surface.
86
- * @returns the handler.
127
+ * Shared, guarded Fetch/stream core. The Node adapter's toNodeHandler is NOT
128
+ * used directly: its early 413 has a different wire envelope, it does not watch
129
+ * IncomingMessage.aborted, and its close/drain listeners are not removed.
130
+ * Use its official bounded Request conversion only AFTER our unchanged gate.
87
131
  */
132
+ export declare function createHttpStreamHandler(config: HttpTransportConfig, host: McpHost): (request: HttpRequestDescription, signal?: AbortSignal) => Promise<Response>;
133
+ /** Finite, materializing test facade; production sockets use the stream core. */
88
134
  export declare function createHttpHandler(config: HttpTransportConfig, host: McpHost): (request: HttpRequestDescription) => Promise<HttpResponseDescription>;
89
135
  /**
90
136
  * Whether this transport may claim OAuth conformance.
91
137
  *
92
- * It may not. `P26-15` permits a static-token mode while forbidding the claim, and
93
- * this returns false so a status report or a compatibility matrix cannot assert
94
- * otherwise by accident.
95
- * @returns always false, for the static-token scheme.
138
+ * The static-token scheme may not; the oauth-resource-server scheme may, because
139
+ * it verifies HS256 credentials, audience, expiry and scope against the embedded
140
+ * server and answers RFC 6750 challenges — a conformant subset, not an invention.
141
+ * The claim is per-DEPLOYMENT, which is what a status report needs: a host using
142
+ * static tokens must still report false.
143
+ * @param auth - the live auth configuration.
144
+ * @returns whether the live scheme may claim the OAuth 2.1 resource-server profile.
96
145
  */
97
- export declare function claimsOAuthConformance(): boolean;
146
+ export declare function claimsOAuthConformance(auth: HttpAuth): boolean;
98
147
  /**
99
148
  * The authentication profile this transport reports.
100
149
  *
101
150
  * A machine-readable statement of what is actually implemented, so a client or an
102
151
  * operator can tell custom authentication from the OAuth profile without reading
103
152
  * the source.
153
+ * @param auth - the live auth configuration.
104
154
  * @returns the auth profile description.
105
155
  */
106
- export declare function authProfile(): Record<string, unknown>;
156
+ export declare function authProfile(auth: HttpAuth): Record<string, unknown>;
107
157
  /** A bound endpoint. */
108
158
  export interface BoundEndpoint {
109
159
  /** The address actually bound, which for port 0 is the one the OS chose. */
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,aAAa,CAAA;AAGpD,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,+BAA+B;AAC/B,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,YAAY;IACZ,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,mDAAmD;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1C,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAC/B;AAED,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,EAAE,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAMjE,CAAA;AAED,wDAAwD;AACxD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IAC9D,oBAAoB;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kDAAkD;IAClD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B;AAED,yBAAyB;AACzB,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,sCAAsC;AACtC,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAMnD;AAgCD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,OAAO,GACZ,CAAC,OAAO,EAAE,sBAAsB,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAkGvE;AASD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQrD;AAED,wBAAwB;AACxB,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uCAAuC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,yCAAyC;IACzC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,aAAa,CAAC,CA8DxB"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"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"}