@paybond/kit 0.9.8 → 0.11.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 (368) hide show
  1. package/completion-presets/catalog.json +1187 -0
  2. package/completion-presets/catalog.sha256 +1 -0
  3. package/dev/trace-ui/dashboard.html +617 -0
  4. package/dist/agent/adapter.d.ts +51 -0
  5. package/dist/agent/adapter.js +66 -0
  6. package/dist/agent/attach-bundle.d.ts +37 -0
  7. package/dist/agent/attach-bundle.js +118 -0
  8. package/dist/agent/authorization-cache.d.ts +22 -0
  9. package/dist/agent/authorization-cache.js +36 -0
  10. package/dist/agent/deferred-tools.d.ts +11 -0
  11. package/dist/agent/deferred-tools.js +62 -0
  12. package/dist/agent/discover.d.ts +41 -0
  13. package/dist/agent/discover.js +147 -0
  14. package/dist/agent/evidence.d.ts +9 -0
  15. package/dist/agent/evidence.js +28 -0
  16. package/dist/agent/facade.d.ts +48 -0
  17. package/dist/agent/facade.js +112 -0
  18. package/dist/agent/gateway-trace-reporter.d.ts +28 -0
  19. package/dist/agent/gateway-trace-reporter.js +49 -0
  20. package/dist/agent/generic-runner.d.ts +14 -0
  21. package/dist/agent/generic-runner.js +49 -0
  22. package/dist/agent/generic-sandbox-demo.d.ts +36 -0
  23. package/dist/agent/generic-sandbox-demo.js +82 -0
  24. package/dist/agent/guarded-agent.d.ts +49 -0
  25. package/dist/agent/guarded-agent.js +100 -0
  26. package/dist/agent/index.d.ts +13 -0
  27. package/dist/agent/index.js +13 -0
  28. package/dist/agent/instrument.d.ts +156 -0
  29. package/dist/agent/instrument.js +442 -0
  30. package/dist/agent/interceptor.d.ts +24 -0
  31. package/dist/agent/interceptor.js +440 -0
  32. package/dist/agent/lazy-context-tools.d.ts +15 -0
  33. package/dist/agent/lazy-context-tools.js +81 -0
  34. package/dist/agent/registry-file.d.ts +39 -0
  35. package/dist/agent/registry-file.js +219 -0
  36. package/dist/agent/registry.d.ts +37 -0
  37. package/dist/agent/registry.js +128 -0
  38. package/dist/agent/run.d.ts +124 -0
  39. package/dist/agent/run.js +301 -0
  40. package/dist/agent/types.d.ts +318 -0
  41. package/dist/agent/types.js +42 -0
  42. package/dist/agent-recognition.d.ts +72 -0
  43. package/dist/agent-recognition.js +165 -0
  44. package/dist/bincode-wire.d.ts +18 -0
  45. package/dist/bincode-wire.js +93 -0
  46. package/dist/claude-agents/config.d.ts +21 -0
  47. package/dist/claude-agents/config.js +145 -0
  48. package/dist/claude-agents/index.d.ts +2 -0
  49. package/dist/claude-agents/index.js +2 -0
  50. package/dist/claude-agents/sandbox-demo.d.ts +30 -0
  51. package/dist/claude-agents/sandbox-demo.js +91 -0
  52. package/dist/cli/agent/env-quote.d.ts +1 -0
  53. package/dist/cli/agent/env-quote.js +6 -0
  54. package/dist/cli/agent/env-write.d.ts +8 -0
  55. package/dist/cli/agent/env-write.js +47 -0
  56. package/dist/cli/agent/paybond.d.ts +16 -0
  57. package/dist/cli/agent/paybond.js +55 -0
  58. package/dist/cli/agent/policy-file.d.ts +29 -0
  59. package/dist/cli/agent/policy-file.js +61 -0
  60. package/dist/cli/agent/production-evidence.d.ts +24 -0
  61. package/dist/cli/agent/production-evidence.js +98 -0
  62. package/dist/cli/agent/run-store.d.ts +30 -0
  63. package/dist/cli/agent/run-store.js +42 -0
  64. package/dist/cli/agent/run-trace-store.d.ts +39 -0
  65. package/dist/cli/agent/run-trace-store.js +143 -0
  66. package/dist/cli/agent-run-trace-table.d.ts +9 -0
  67. package/dist/cli/agent-run-trace-table.js +24 -0
  68. package/dist/cli/agent-sandbox-smoke-checklist.d.ts +9 -0
  69. package/dist/cli/agent-sandbox-smoke-checklist.js +50 -0
  70. package/dist/cli/audit-export.d.ts +7 -0
  71. package/dist/cli/audit-export.js +120 -0
  72. package/dist/cli/automation.d.ts +25 -0
  73. package/dist/cli/automation.js +297 -0
  74. package/dist/cli/body.d.ts +7 -0
  75. package/dist/cli/body.js +22 -0
  76. package/dist/cli/color.d.ts +15 -0
  77. package/dist/cli/color.js +39 -0
  78. package/dist/cli/command-spec.d.ts +13 -0
  79. package/dist/cli/command-spec.js +611 -0
  80. package/dist/cli/commands/agent.d.ts +16 -0
  81. package/dist/cli/commands/agent.js +1135 -0
  82. package/dist/cli/commands/dev.d.ts +7 -0
  83. package/dist/cli/commands/dev.js +348 -0
  84. package/dist/cli/commands/discovery.d.ts +8 -0
  85. package/dist/cli/commands/discovery.js +194 -0
  86. package/dist/cli/commands/policy.d.ts +13 -0
  87. package/dist/cli/commands/policy.js +769 -0
  88. package/dist/cli/commands/setup.d.ts +18 -0
  89. package/dist/cli/commands/setup.js +513 -0
  90. package/dist/cli/commands/workflows.d.ts +7 -0
  91. package/dist/cli/commands/workflows.js +214 -0
  92. package/dist/cli/config.d.ts +16 -0
  93. package/dist/cli/config.js +98 -0
  94. package/dist/cli/context.d.ts +22 -0
  95. package/dist/cli/context.js +110 -0
  96. package/dist/cli/credentials.d.ts +21 -0
  97. package/dist/cli/credentials.js +141 -0
  98. package/dist/cli/doctor-agent-middleware.d.ts +5 -0
  99. package/dist/cli/doctor-agent-middleware.js +49 -0
  100. package/dist/cli/doctor-agent.d.ts +15 -0
  101. package/dist/cli/doctor-agent.js +311 -0
  102. package/dist/cli/envelope.d.ts +14 -0
  103. package/dist/cli/envelope.js +46 -0
  104. package/dist/cli/globals.d.ts +23 -0
  105. package/dist/cli/globals.js +248 -0
  106. package/dist/cli/help.d.ts +3 -0
  107. package/dist/cli/help.js +83 -0
  108. package/dist/cli/mcp-install.d.ts +41 -0
  109. package/dist/cli/mcp-install.js +95 -0
  110. package/dist/cli/mcp-policy.d.ts +26 -0
  111. package/dist/cli/mcp-policy.js +110 -0
  112. package/dist/cli/mcp-verify-config.d.ts +37 -0
  113. package/dist/cli/mcp-verify-config.js +172 -0
  114. package/dist/cli/redact.d.ts +4 -0
  115. package/dist/cli/redact.js +88 -0
  116. package/dist/cli/request-id.d.ts +2 -0
  117. package/dist/cli/request-id.js +5 -0
  118. package/dist/cli/router.d.ts +2 -0
  119. package/dist/cli/router.js +378 -0
  120. package/dist/cli/smoke-deep-links.d.ts +15 -0
  121. package/dist/cli/smoke-deep-links.js +63 -0
  122. package/dist/cli/suggest.d.ts +4 -0
  123. package/dist/cli/suggest.js +58 -0
  124. package/dist/cli/support-diagnostics.d.ts +19 -0
  125. package/dist/cli/support-diagnostics.js +47 -0
  126. package/dist/cli/telemetry.d.ts +17 -0
  127. package/dist/cli/telemetry.js +94 -0
  128. package/dist/cli/types.d.ts +72 -0
  129. package/dist/cli/types.js +60 -0
  130. package/dist/cli/ux.d.ts +8 -0
  131. package/dist/cli/ux.js +164 -0
  132. package/dist/cli.d.ts +2 -0
  133. package/dist/cli.js +38 -0
  134. package/dist/completion-catalog-digest.d.ts +2 -0
  135. package/dist/completion-catalog-digest.js +2 -0
  136. package/dist/completion-catalog-integrity.d.ts +2 -0
  137. package/dist/completion-catalog-integrity.js +17 -0
  138. package/dist/completion-catalog.d.ts +49 -0
  139. package/dist/completion-catalog.js +62 -0
  140. package/dist/completion-contract-digest.d.ts +37 -0
  141. package/dist/completion-contract-digest.js +73 -0
  142. package/dist/completion-forbidden-fields.d.ts +5 -0
  143. package/dist/completion-forbidden-fields.js +26 -0
  144. package/dist/completion-init.d.ts +8 -0
  145. package/dist/completion-init.js +334 -0
  146. package/dist/completion-resolve.d.ts +21 -0
  147. package/dist/completion-resolve.js +86 -0
  148. package/dist/completion-validate-evidence.d.ts +24 -0
  149. package/dist/completion-validate-evidence.js +145 -0
  150. package/dist/dev/offline-gateway.d.ts +24 -0
  151. package/dist/dev/offline-gateway.js +102 -0
  152. package/dist/dev/trace-buffer.d.ts +61 -0
  153. package/dist/dev/trace-buffer.js +330 -0
  154. package/dist/dev/trace-security-headers.d.ts +11 -0
  155. package/dist/dev/trace-security-headers.js +16 -0
  156. package/dist/dev/trace-server.d.ts +8 -0
  157. package/dist/dev/trace-server.js +38 -0
  158. package/dist/dev/trace-ui.d.ts +4 -0
  159. package/dist/dev/trace-ui.js +25 -0
  160. package/dist/dev/wiremock-up.d.ts +15 -0
  161. package/dist/dev/wiremock-up.js +118 -0
  162. package/dist/doctor-completion.d.ts +17 -0
  163. package/dist/doctor-completion.js +428 -0
  164. package/dist/gateway-url.d.ts +7 -0
  165. package/dist/gateway-url.js +69 -0
  166. package/dist/index.d.ts +119 -2
  167. package/dist/index.js +267 -6
  168. package/dist/init.js +380 -68
  169. package/dist/langgraph/awrap-tool-call.d.ts +25 -0
  170. package/dist/langgraph/awrap-tool-call.js +81 -0
  171. package/dist/langgraph/config.d.ts +13 -0
  172. package/dist/langgraph/config.js +11 -0
  173. package/dist/langgraph/index.d.ts +4 -0
  174. package/dist/langgraph/index.js +4 -0
  175. package/dist/langgraph/sandbox-demo.d.ts +40 -0
  176. package/dist/langgraph/sandbox-demo.js +96 -0
  177. package/dist/langgraph/tool-node.d.ts +10 -0
  178. package/dist/langgraph/tool-node.js +38 -0
  179. package/dist/login.d.ts +14 -1
  180. package/dist/login.js +130 -63
  181. package/dist/mcp/index.d.ts +1 -0
  182. package/dist/mcp/index.js +1 -0
  183. package/dist/mcp/tool-surface.d.ts +25 -0
  184. package/dist/mcp/tool-surface.js +17 -0
  185. package/dist/mcp-capability-token-cache.d.ts +24 -0
  186. package/dist/mcp-capability-token-cache.js +101 -0
  187. package/dist/mcp-evidence-policy.d.ts +48 -0
  188. package/dist/mcp-evidence-policy.js +117 -0
  189. package/dist/mcp-policy-reload.d.ts +79 -0
  190. package/dist/mcp-policy-reload.js +200 -0
  191. package/dist/mcp-sep2828-evidence.d.ts +36 -0
  192. package/dist/mcp-sep2828-evidence.js +65 -0
  193. package/dist/mcp-server.d.ts +10 -0
  194. package/dist/mcp-server.js +423 -115
  195. package/dist/openai-agents/index.d.ts +40 -0
  196. package/dist/openai-agents/index.js +151 -0
  197. package/dist/openai-agents/sandbox-demo.d.ts +34 -0
  198. package/dist/openai-agents/sandbox-demo.js +118 -0
  199. package/dist/payee-evidence.js +2 -29
  200. package/dist/policy/catalog.d.ts +31 -0
  201. package/dist/policy/catalog.js +48 -0
  202. package/dist/policy/compose-utils.d.ts +3 -0
  203. package/dist/policy/compose-utils.js +4 -0
  204. package/dist/policy/compose.d.ts +20 -0
  205. package/dist/policy/compose.js +240 -0
  206. package/dist/policy/digest.d.ts +7 -0
  207. package/dist/policy/digest.js +75 -0
  208. package/dist/policy/domain.d.ts +15 -0
  209. package/dist/policy/domain.js +28 -0
  210. package/dist/policy/guardrail-spec.d.ts +17 -0
  211. package/dist/policy/guardrail-spec.js +140 -0
  212. package/dist/policy/guardrails.d.ts +48 -0
  213. package/dist/policy/guardrails.js +72 -0
  214. package/dist/policy/index.d.ts +21 -0
  215. package/dist/policy/index.js +21 -0
  216. package/dist/policy/init.d.ts +102 -0
  217. package/dist/policy/init.js +351 -0
  218. package/dist/policy/intent-spec.d.ts +52 -0
  219. package/dist/policy/intent-spec.js +176 -0
  220. package/dist/policy/json-path.d.ts +4 -0
  221. package/dist/policy/json-path.js +23 -0
  222. package/dist/policy/layers-io.d.ts +7 -0
  223. package/dist/policy/layers-io.js +28 -0
  224. package/dist/policy/load-effective.d.ts +22 -0
  225. package/dist/policy/load-effective.js +77 -0
  226. package/dist/policy/load.d.ts +85 -0
  227. package/dist/policy/load.js +164 -0
  228. package/dist/policy/merge.d.ts +29 -0
  229. package/dist/policy/merge.js +297 -0
  230. package/dist/policy/parse-text.d.ts +2 -0
  231. package/dist/policy/parse-text.js +126 -0
  232. package/dist/policy/policy-api.d.ts +45 -0
  233. package/dist/policy/policy-api.js +61 -0
  234. package/dist/policy/presets.d.ts +19 -0
  235. package/dist/policy/presets.js +66 -0
  236. package/dist/policy/registry.d.ts +7 -0
  237. package/dist/policy/registry.js +33 -0
  238. package/dist/policy/reload.d.ts +86 -0
  239. package/dist/policy/reload.js +233 -0
  240. package/dist/policy/render-yaml.d.ts +3 -0
  241. package/dist/policy/render-yaml.js +69 -0
  242. package/dist/policy/sandbox-bootstrap.d.ts +19 -0
  243. package/dist/policy/sandbox-bootstrap.js +66 -0
  244. package/dist/policy/schema.d.ts +204 -0
  245. package/dist/policy/schema.js +255 -0
  246. package/dist/policy/snapshot.d.ts +33 -0
  247. package/dist/policy/snapshot.js +23 -0
  248. package/dist/policy/validate-remote.d.ts +43 -0
  249. package/dist/policy/validate-remote.js +104 -0
  250. package/dist/policy/validate.d.ts +36 -0
  251. package/dist/policy/validate.js +150 -0
  252. package/dist/policy/watcher.d.ts +29 -0
  253. package/dist/policy/watcher.js +112 -0
  254. package/dist/principal-intent.d.ts +52 -0
  255. package/dist/principal-intent.js +193 -37
  256. package/dist/project-init.d.ts +34 -0
  257. package/dist/project-init.js +898 -0
  258. package/dist/sep2828-signature.d.ts +10 -0
  259. package/dist/sep2828-signature.js +134 -0
  260. package/dist/solutions/api.d.ts +22 -0
  261. package/dist/solutions/api.js +40 -0
  262. package/dist/solutions/catalog.d.ts +34 -0
  263. package/dist/solutions/catalog.js +129 -0
  264. package/dist/solutions/index.d.ts +2 -0
  265. package/dist/solutions/index.js +2 -0
  266. package/dist/template-init.d.ts +54 -0
  267. package/dist/template-init.js +203 -0
  268. package/dist/vercel-ai/config.d.ts +15 -0
  269. package/dist/vercel-ai/config.js +13 -0
  270. package/dist/vercel-ai/index.d.ts +4 -0
  271. package/dist/vercel-ai/index.js +4 -0
  272. package/dist/vercel-ai/sandbox-demo.d.ts +44 -0
  273. package/dist/vercel-ai/sandbox-demo.js +153 -0
  274. package/dist/vercel-ai/tool-approval.d.ts +16 -0
  275. package/dist/vercel-ai/tool-approval.js +41 -0
  276. package/dist/vercel-ai/wrap-tools.d.ts +9 -0
  277. package/dist/vercel-ai/wrap-tools.js +40 -0
  278. package/dist/x402-receipt-evidence.d.ts +29 -0
  279. package/dist/x402-receipt-evidence.js +97 -0
  280. package/dist/x402-receipt-signature.d.ts +12 -0
  281. package/dist/x402-receipt-signature.js +211 -0
  282. package/package.json +79 -4
  283. package/solutions/aws.json +17 -0
  284. package/solutions/saas.json +17 -0
  285. package/solutions/shopping.json +17 -0
  286. package/solutions/travel.json +18 -0
  287. package/templates/manifest.json +169 -0
  288. package/templates/openai-shopping-agent/.env.example +3 -0
  289. package/templates/openai-shopping-agent/.github/workflows/smoke.yml +20 -0
  290. package/templates/openai-shopping-agent/LICENSE +201 -0
  291. package/templates/openai-shopping-agent/README.md +29 -0
  292. package/templates/openai-shopping-agent/package.json +22 -0
  293. package/templates/openai-shopping-agent/paybond.policy.yaml +22 -0
  294. package/templates/openai-shopping-agent/src/index.ts +22 -0
  295. package/templates/openai-shopping-agent/src/paybond.config.ts +51 -0
  296. package/templates/openai-shopping-agent/tsconfig.json +13 -0
  297. package/templates/paybond-aws-operator/.env.example +3 -0
  298. package/templates/paybond-aws-operator/.github/workflows/smoke.yml +20 -0
  299. package/templates/paybond-aws-operator/LICENSE +201 -0
  300. package/templates/paybond-aws-operator/README.md +29 -0
  301. package/templates/paybond-aws-operator/package.json +20 -0
  302. package/templates/paybond-aws-operator/paybond.policy.yaml +22 -0
  303. package/templates/paybond-aws-operator/src/index.ts +54 -0
  304. package/templates/paybond-aws-operator/src/paybond.config.ts +51 -0
  305. package/templates/paybond-aws-operator/tsconfig.json +13 -0
  306. package/templates/paybond-claude-agents-demo/.env.example +3 -0
  307. package/templates/paybond-claude-agents-demo/.github/workflows/smoke.yml +20 -0
  308. package/templates/paybond-claude-agents-demo/LICENSE +201 -0
  309. package/templates/paybond-claude-agents-demo/README.md +29 -0
  310. package/templates/paybond-claude-agents-demo/package.json +22 -0
  311. package/templates/paybond-claude-agents-demo/paybond.policy.yaml +22 -0
  312. package/templates/paybond-claude-agents-demo/src/index.ts +22 -0
  313. package/templates/paybond-claude-agents-demo/src/paybond.config.ts +51 -0
  314. package/templates/paybond-claude-agents-demo/tsconfig.json +13 -0
  315. package/templates/paybond-invoice-agent/.env.example +3 -0
  316. package/templates/paybond-invoice-agent/.github/workflows/smoke.yml +19 -0
  317. package/templates/paybond-invoice-agent/LICENSE +201 -0
  318. package/templates/paybond-invoice-agent/README.md +29 -0
  319. package/templates/paybond-invoice-agent/app.py +27 -0
  320. package/templates/paybond-invoice-agent/package.json +6 -0
  321. package/templates/paybond-invoice-agent/paybond.policy.yaml +22 -0
  322. package/templates/paybond-invoice-agent/paybond_config.py +45 -0
  323. package/templates/paybond-invoice-agent/requirements.txt +2 -0
  324. package/templates/paybond-mcp-coding-agent/.env.example +3 -0
  325. package/templates/paybond-mcp-coding-agent/.github/workflows/smoke.yml +20 -0
  326. package/templates/paybond-mcp-coding-agent/LICENSE +201 -0
  327. package/templates/paybond-mcp-coding-agent/README.md +39 -0
  328. package/templates/paybond-mcp-coding-agent/package.json +20 -0
  329. package/templates/paybond-mcp-coding-agent/paybond.policy.yaml +25 -0
  330. package/templates/paybond-mcp-coding-agent/src/index.ts +40 -0
  331. package/templates/paybond-mcp-coding-agent/src/paybond.config.ts +51 -0
  332. package/templates/paybond-mcp-coding-agent/tsconfig.json +13 -0
  333. package/templates/paybond-openai-agents-demo/.env.example +3 -0
  334. package/templates/paybond-openai-agents-demo/.github/workflows/smoke.yml +20 -0
  335. package/templates/paybond-openai-agents-demo/LICENSE +201 -0
  336. package/templates/paybond-openai-agents-demo/README.md +29 -0
  337. package/templates/paybond-openai-agents-demo/package.json +22 -0
  338. package/templates/paybond-openai-agents-demo/paybond.policy.yaml +22 -0
  339. package/templates/paybond-openai-agents-demo/src/index.ts +22 -0
  340. package/templates/paybond-openai-agents-demo/src/paybond.config.ts +51 -0
  341. package/templates/paybond-openai-agents-demo/tsconfig.json +13 -0
  342. package/templates/paybond-procurement-agent/.env.example +3 -0
  343. package/templates/paybond-procurement-agent/.github/workflows/smoke.yml +20 -0
  344. package/templates/paybond-procurement-agent/LICENSE +201 -0
  345. package/templates/paybond-procurement-agent/README.md +29 -0
  346. package/templates/paybond-procurement-agent/package.json +20 -0
  347. package/templates/paybond-procurement-agent/paybond.policy.yaml +25 -0
  348. package/templates/paybond-procurement-agent/src/index.ts +54 -0
  349. package/templates/paybond-procurement-agent/src/paybond.config.ts +51 -0
  350. package/templates/paybond-procurement-agent/tsconfig.json +13 -0
  351. package/templates/paybond-travel-agent/.env.example +3 -0
  352. package/templates/paybond-travel-agent/.github/workflows/smoke.yml +20 -0
  353. package/templates/paybond-travel-agent/LICENSE +201 -0
  354. package/templates/paybond-travel-agent/README.md +29 -0
  355. package/templates/paybond-travel-agent/package.json +23 -0
  356. package/templates/paybond-travel-agent/paybond.policy.yaml +22 -0
  357. package/templates/paybond-travel-agent/src/index.ts +22 -0
  358. package/templates/paybond-travel-agent/src/paybond.config.ts +51 -0
  359. package/templates/paybond-travel-agent/tsconfig.json +13 -0
  360. package/templates/paybond-vercel-shopping-agent/.env.example +3 -0
  361. package/templates/paybond-vercel-shopping-agent/.github/workflows/smoke.yml +20 -0
  362. package/templates/paybond-vercel-shopping-agent/LICENSE +201 -0
  363. package/templates/paybond-vercel-shopping-agent/README.md +29 -0
  364. package/templates/paybond-vercel-shopping-agent/package.json +22 -0
  365. package/templates/paybond-vercel-shopping-agent/paybond.policy.yaml +22 -0
  366. package/templates/paybond-vercel-shopping-agent/src/index.ts +22 -0
  367. package/templates/paybond-vercel-shopping-agent/src/paybond.config.ts +51 -0
  368. package/templates/paybond-vercel-shopping-agent/tsconfig.json +13 -0
@@ -1,9 +1,19 @@
1
1
  #!/usr/bin/env node
2
- // @ts-ignore Node builtins are available in the published CLI runtime.
2
+ import { Buffer } from "node:buffer";
3
3
  import { readFileSync } from "node:fs";
4
- import { GatewayAuthError, GatewayFraudClient, GatewaySignalClient, SignalHttpError, DEFAULT_PAYBOND_GATEWAY_BASE_URL, } from "./index.js";
4
+ import fs from "node:fs/promises";
5
+ import path from "node:path";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+ import { requireSecureGatewayUrl } from "./gateway-url.js";
8
+ import { runCli } from "./cli/router.js";
9
+ import { redactSensitiveFields } from "./cli/redact.js";
10
+ import { MCP_TOOL_ALLOWLIST_ENV, MCP_TOOL_POLICY_ENV, mergeMcpToolPolicy, parseMcpToolAllowlist, parseMcpToolPolicy, resolveMcpToolPolicy, toolAllowedByPolicy, } from "./cli/mcp-policy.js";
11
+ import { MCP_EVIDENCE_POLICY_ENV, McpEvidenceValidationGate, completionEvidenceValidationOk, extractHarborEvidenceValidationInput, extractSandboxGuardrailValidationInput, parseMcpEvidencePolicy, } from "./mcp-evidence-policy.js";
12
+ import { McpCapabilityTokenCache, mcpToolStoresCapabilityToken, parseMcpCapabilityTokenCacheConfig, } from "./mcp-capability-token-cache.js";
13
+ import { createMcpPolicyGatewayAdapter, McpPolicyReloadGate, parseMcpPolicyReloadConfig, } from "./mcp-policy-reload.js";
14
+ import { DEFAULT_PAYBOND_GATEWAY_BASE_URL, GatewayFraudClient, GatewaySignalClient, } from "./index.js";
5
15
  const SERVER_NAME = "Paybond MCP";
6
- const SERVER_VERSION = "0.9.8";
16
+ const SERVER_VERSION = "0.11.0";
7
17
  const MCP_PROTOCOL_VERSION = "2025-11-25";
8
18
  const DEFAULT_PRINCIPAL_PATH = "/v1/auth/principal";
9
19
  const DEFAULT_RECOGNITION_VERIFIER_ID = "paybond-gateway";
@@ -14,7 +24,10 @@ const TOOL_SELECTION_METADATA = {
14
24
  title: "Get Paybond Principal",
15
25
  annotations: readOnlyToolAnnotations("Get Paybond Principal"),
16
26
  outputSchema: outputObjectSchema({
17
- tenant_id: { type: "string", description: "Tenant bound to the configured Paybond API key." },
27
+ tenant_id: {
28
+ type: "string",
29
+ description: "Tenant bound to the configured Paybond API key.",
30
+ },
18
31
  subject: { type: "string" },
19
32
  roles: { type: "array", items: { type: "string" } },
20
33
  }),
@@ -25,10 +38,22 @@ const TOOL_SELECTION_METADATA = {
25
38
  "Do not use this to create, fund, or modify intents; use paybond_authorize_agent_spend as the clearer gate before side-effecting agent tools.",
26
39
  annotations: additiveMutationToolAnnotations("Verify Paybond Capability"),
27
40
  outputSchema: outputObjectSchema({
28
- allow: { type: "boolean", description: "Whether the requested operation is allowed." },
29
- tenant: { type: "string", description: "Tenant echoed by the gateway." },
30
- intent_id: { type: "string", description: "Verified Harbor intent UUID." },
31
- audit_id: { type: "string", description: "Gateway audit identifier when available." },
41
+ allow: {
42
+ type: "boolean",
43
+ description: "Whether the requested operation is allowed.",
44
+ },
45
+ tenant: {
46
+ type: "string",
47
+ description: "Tenant echoed by the gateway.",
48
+ },
49
+ intent_id: {
50
+ type: "string",
51
+ description: "Verified Harbor intent UUID.",
52
+ },
53
+ audit_id: {
54
+ type: "string",
55
+ description: "Gateway audit identifier when available.",
56
+ },
32
57
  }, ["tenant", "intent_id"]),
33
58
  },
34
59
  paybond_authorize_agent_spend: {
@@ -37,10 +62,22 @@ const TOOL_SELECTION_METADATA = {
37
62
  "Do not use this for creating, funding, or changing intents; call paybond_create_spend_intent or paybond_fund_intent first when no funded capability token exists.",
38
63
  annotations: additiveMutationToolAnnotations("Authorize Agent Spend"),
39
64
  outputSchema: outputObjectSchema({
40
- allow: { type: "boolean", description: "Whether the requested operation is allowed." },
41
- tenant: { type: "string", description: "Tenant echoed by the gateway." },
42
- intent_id: { type: "string", description: "Verified Harbor intent UUID." },
43
- audit_id: { type: "string", description: "Gateway audit identifier when available." },
65
+ allow: {
66
+ type: "boolean",
67
+ description: "Whether the requested operation is allowed.",
68
+ },
69
+ tenant: {
70
+ type: "string",
71
+ description: "Tenant echoed by the gateway.",
72
+ },
73
+ intent_id: {
74
+ type: "string",
75
+ description: "Verified Harbor intent UUID.",
76
+ },
77
+ audit_id: {
78
+ type: "string",
79
+ description: "Gateway audit identifier when available.",
80
+ },
44
81
  }, ["tenant", "intent_id"]),
45
82
  },
46
83
  paybond_bootstrap_sandbox_guardrail: {
@@ -57,7 +94,30 @@ const TOOL_SELECTION_METADATA = {
57
94
  sandbox_lifecycle_status: { type: "string" },
58
95
  settlement_rail: { type: "string" },
59
96
  settlement_mode: { type: "string" },
60
- }, ["tenant_id", "intent_id", "capability_token", "operation", "requested_spend_cents", "sandbox_lifecycle_status"]),
97
+ }, [
98
+ "tenant_id",
99
+ "intent_id",
100
+ "capability_token",
101
+ "operation",
102
+ "requested_spend_cents",
103
+ "sandbox_lifecycle_status",
104
+ ]),
105
+ },
106
+ paybond_validate_completion_evidence: {
107
+ title: "Validate Completion Evidence",
108
+ description: "Pre-validates vendor and canonical completion evidence against catalog JSON Schemas and preset forbidden_evidence_fields. " +
109
+ "Required before evidence submit tools when PAYBOND_MCP_EVIDENCE_POLICY=strict. Harbor remains authoritative at submit time.",
110
+ annotations: readOnlyToolAnnotations("Validate Completion Evidence"),
111
+ outputSchema: outputObjectSchema({
112
+ preset_id: { type: "string" },
113
+ ok: { type: "boolean" },
114
+ vendor_schema_ok: { type: "boolean" },
115
+ canonical_schema_ok: { type: "boolean" },
116
+ quality_fields_missing: { type: "array", items: { type: "string" } },
117
+ forbidden_fields_present: { type: "array", items: { type: "string" } },
118
+ pack_stale: { type: "boolean" },
119
+ drift_kinds: { type: "array", items: { type: "string" } },
120
+ }, ["preset_id", "ok"]),
61
121
  },
62
122
  paybond_submit_sandbox_guardrail_evidence: {
63
123
  title: "Submit Sandbox Guardrail Evidence",
@@ -72,13 +132,22 @@ const TOOL_SELECTION_METADATA = {
72
132
  sandbox_lifecycle_status: { type: "string" },
73
133
  predicate_passed: { type: "boolean" },
74
134
  payload_digest: { type: "string" },
75
- }, ["tenant_id", "intent_id", "operation", "requested_spend_cents", "sandbox_lifecycle_status"]),
135
+ }, [
136
+ "tenant_id",
137
+ "intent_id",
138
+ "operation",
139
+ "requested_spend_cents",
140
+ "sandbox_lifecycle_status",
141
+ ]),
76
142
  },
77
143
  paybond_list_intents: {
78
144
  title: "List Harbor Intents",
79
145
  annotations: readOnlyToolAnnotations("List Harbor Intents"),
80
146
  outputSchema: outputObjectSchema({
81
- items: { type: "array", items: { type: "object", additionalProperties: true } },
147
+ items: {
148
+ type: "array",
149
+ items: { type: "object", additionalProperties: true },
150
+ },
82
151
  next_cursor: { type: "string" },
83
152
  }),
84
153
  },
@@ -106,7 +175,10 @@ const TOOL_SELECTION_METADATA = {
106
175
  outputSchema: outputObjectSchema({
107
176
  tenant_id: { type: "string" },
108
177
  score_model_version: { type: "string" },
109
- operators: { type: "array", items: { type: "object", additionalProperties: true } },
178
+ operators: {
179
+ type: "array",
180
+ items: { type: "object", additionalProperties: true },
181
+ },
110
182
  }),
111
183
  },
112
184
  paybond_get_signed_portfolio_artifact: {
@@ -144,14 +216,20 @@ const TOOL_SELECTION_METADATA = {
144
216
  outputSchema: outputObjectSchema({
145
217
  name: { type: "string" },
146
218
  version: { type: "string" },
147
- skills: { type: "array", items: { type: "object", additionalProperties: true } },
219
+ skills: {
220
+ type: "array",
221
+ items: { type: "object", additionalProperties: true },
222
+ },
148
223
  }),
149
224
  },
150
225
  paybond_list_a2a_task_contracts: {
151
226
  title: "List A2A Task Contracts",
152
227
  annotations: readOnlyToolAnnotations("List A2A Task Contracts"),
153
228
  outputSchema: outputObjectSchema({
154
- contracts: { type: "array", items: { type: "object", additionalProperties: true } },
229
+ contracts: {
230
+ type: "array",
231
+ items: { type: "object", additionalProperties: true },
232
+ },
155
233
  }),
156
234
  },
157
235
  paybond_get_a2a_task_contract: {
@@ -273,6 +351,13 @@ const TOOL_SELECTION_METADATA = {
273
351
  }),
274
352
  },
275
353
  };
354
+ function readIntentAllowedTools(intent) {
355
+ const raw = intent.allowed_tools;
356
+ if (!Array.isArray(raw)) {
357
+ return [];
358
+ }
359
+ return raw.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
360
+ }
276
361
  function readEnvFileValue(envFile, key) {
277
362
  let body;
278
363
  try {
@@ -327,8 +412,12 @@ function parseGatewayErrorEnvelope(text) {
327
412
  if (body === null || Array.isArray(body) || typeof body !== "object") {
328
413
  return {};
329
414
  }
330
- const errorCode = typeof body.error === "string" && body.error.trim() ? body.error.trim() : undefined;
331
- const errorMessage = typeof body.message === "string" && body.message.trim() ? body.message.trim() : undefined;
415
+ const errorCode = typeof body.error === "string" && body.error.trim()
416
+ ? body.error.trim()
417
+ : undefined;
418
+ const errorMessage = typeof body.message === "string" && body.message.trim()
419
+ ? body.message.trim()
420
+ : undefined;
332
421
  return { errorCode, errorMessage };
333
422
  }
334
423
  catch {
@@ -369,7 +458,9 @@ class GatewayAPIClient {
369
458
  accept: "application/json",
370
459
  authorization: `Bearer ${this.apiKey}`,
371
460
  ...(extraHeaders ?? {}),
372
- ...(payload === undefined ? {} : { "content-type": "application/json" }),
461
+ ...(payload === undefined
462
+ ? {}
463
+ : { "content-type": "application/json" }),
373
464
  },
374
465
  ...(payload === undefined ? {} : { body: JSON.stringify(payload) }),
375
466
  });
@@ -382,7 +473,8 @@ class GatewayAPIClient {
382
473
  await delay(backoffMs(attempt));
383
474
  continue;
384
475
  }
385
- if ([429, 500, 502, 503, 504].includes(res.status) && attempt + 1 < this.maxRetries) {
476
+ if ([429, 500, 502, 503, 504].includes(res.status) &&
477
+ attempt + 1 < this.maxRetries) {
386
478
  const retryAfter = parseRetryAfterSeconds(res.headers.get("retry-after"));
387
479
  await delay(retryAfter != null ? retryAfter * 1000 : backoffMs(attempt));
388
480
  continue;
@@ -409,7 +501,14 @@ class PaybondMCPRuntime {
409
501
  principalValue = null;
410
502
  signalValue = null;
411
503
  fraudValue = null;
504
+ capabilityTokenCache;
505
+ evidenceGate;
506
+ policyReloadConfig;
507
+ policyGatePromise = null;
412
508
  constructor(settings) {
509
+ this.evidenceGate = new McpEvidenceValidationGate(settings.evidencePolicy ?? parseMcpEvidencePolicy(undefined));
510
+ this.capabilityTokenCache = new McpCapabilityTokenCache(settings.capabilityTokenCache);
511
+ this.policyReloadConfig = settings.policyReload ?? null;
413
512
  this.settings = {
414
513
  gatewayBaseUrl: settings.gatewayBaseUrl ?? DEFAULT_PAYBOND_GATEWAY_BASE_URL,
415
514
  apiKey: settings.apiKey,
@@ -422,6 +521,102 @@ class PaybondMCPRuntime {
422
521
  maxRetries: this.settings.maxRetries,
423
522
  });
424
523
  }
524
+ async policyGate() {
525
+ if (!this.policyReloadConfig) {
526
+ return null;
527
+ }
528
+ this.policyGatePromise ??= McpPolicyReloadGate.open(this.policyReloadConfig, {
529
+ gateway: createMcpPolicyGatewayAdapter(this.gateway),
530
+ });
531
+ return this.policyGatePromise;
532
+ }
533
+ async getPolicyReloadStatus() {
534
+ const gate = await this.policyGate();
535
+ return gate?.status() ?? null;
536
+ }
537
+ async beginPolicyToolCall() {
538
+ const gate = await this.policyGate();
539
+ gate?.beginToolCall();
540
+ }
541
+ async endPolicyToolCall() {
542
+ const gate = await this.policyGate();
543
+ gate?.endToolCall();
544
+ }
545
+ stopPolicyReload() {
546
+ void this.policyGatePromise?.then((gate) => gate?.stop());
547
+ this.policyGatePromise = null;
548
+ }
549
+ async authorizeAgentSpend(init) {
550
+ const gate = await this.policyGate();
551
+ let operation = init.operation;
552
+ let requestedSpendCents = init.requestedSpendCents ?? 0;
553
+ let policyDigest;
554
+ if (gate) {
555
+ const intent = await this.getIntent(init.intentId);
556
+ const allowedTools = readIntentAllowedTools(intent);
557
+ const gated = gate.assertSpendGate({
558
+ toolName: init.toolName,
559
+ operation,
560
+ allowedTools,
561
+ requestedSpendCents: init.requestedSpendCents,
562
+ });
563
+ operation = gated.operation;
564
+ requestedSpendCents = gated.requestedSpendCents;
565
+ policyDigest = gated.policyDigest;
566
+ }
567
+ const body = await this.verifyCapability({
568
+ intentId: init.intentId,
569
+ token: init.token,
570
+ operation,
571
+ requestedSpendCents,
572
+ });
573
+ if (policyDigest) {
574
+ body.policy_digest = policyDigest;
575
+ }
576
+ return body;
577
+ }
578
+ storeCapabilityToken(intentId, token) {
579
+ this.capabilityTokenCache.store(intentId, token);
580
+ }
581
+ async resolveCapabilityToken(intentId, token) {
582
+ const explicit = token?.trim();
583
+ if (explicit) {
584
+ return explicit;
585
+ }
586
+ const stored = this.capabilityTokenCache.resolve(intentId.trim());
587
+ if (stored) {
588
+ return stored;
589
+ }
590
+ throw new Error(`capability token unavailable or expired for intent ${intentId}; create or bootstrap a funded intent first`);
591
+ }
592
+ prepareToolResponse(value, toolName) {
593
+ if (value === null) {
594
+ return null;
595
+ }
596
+ const intentId = String(value.intent_id ?? "").trim();
597
+ const token = value.capability_token;
598
+ if (mcpToolStoresCapabilityToken(toolName) &&
599
+ intentId &&
600
+ typeof token === "string" &&
601
+ token.trim()) {
602
+ this.storeCapabilityToken(intentId, token);
603
+ }
604
+ return redactSensitiveFields(value);
605
+ }
606
+ validateCompletionEvidence(input) {
607
+ const report = this.evidenceGate.validateAndRecord(input);
608
+ return {
609
+ ...report,
610
+ ok: completionEvidenceValidationOk(report),
611
+ };
612
+ }
613
+ requireEvidenceValidation(input) {
614
+ this.evidenceGate.requirePass(input);
615
+ }
616
+ /** Resolve and cache the gateway principal during MCP server startup. */
617
+ async preloadPrincipal() {
618
+ await this.principal();
619
+ }
425
620
  async principal() {
426
621
  this.principalValue ??= this.gateway.getJSON(this.settings.principalPath);
427
622
  const body = await this.principalValue;
@@ -524,6 +719,11 @@ class PaybondMCPRuntime {
524
719
  return body;
525
720
  }
526
721
  async submitSandboxGuardrailEvidence(init) {
722
+ const extracted = extractSandboxGuardrailValidationInput({
723
+ payload: init.payload,
724
+ completionPresetId: init.completionPresetId,
725
+ });
726
+ this.requireEvidenceValidation(extracted);
527
727
  const expectedTenant = await this.tenantId();
528
728
  const payload = {};
529
729
  if (init.payload !== undefined) {
@@ -561,7 +761,6 @@ class PaybondMCPRuntime {
561
761
  const verifier = {
562
762
  tenant_id: await this.tenantId(),
563
763
  verifier_id: DEFAULT_RECOGNITION_VERIFIER_ID,
564
- ...(init.expectedVerifier ?? {}),
565
764
  };
566
765
  return this.gateway.postJSON("/protocol/v2/recognition/verify", {
567
766
  proof: init.proof,
@@ -620,10 +819,14 @@ class PaybondMCPRuntime {
620
819
  async fundHarborIntent(init) {
621
820
  return this.gateway.postJSON(`/harbor/intents/${encodeURIComponent(init.intentId)}/fund`, {}, gatewayMutationHeaders(await this.tenantId(), init.recognitionProof, {
622
821
  ...optionalMutationHeaders(init.idempotencyKey),
623
- ...(init.paymentSignature?.trim() ? { "payment-signature": init.paymentSignature.trim() } : {}),
822
+ ...(init.paymentSignature?.trim()
823
+ ? { "payment-signature": init.paymentSignature.trim() }
824
+ : {}),
624
825
  }));
625
826
  }
626
827
  async submitHarborEvidence(init) {
828
+ const extracted = extractHarborEvidenceValidationInput(init.body, init.completionPresetId);
829
+ this.requireEvidenceValidation(extracted);
627
830
  return this.gateway.postJSON(`/harbor/intents/${encodeURIComponent(init.intentId)}/evidence`, init.body, gatewayMutationHeaders(await this.tenantId(), init.recognitionProof, optionalMutationHeaders(init.idempotencyKey)));
628
831
  }
629
832
  async confirmHarborSettlement(init) {
@@ -643,16 +846,22 @@ function gatewayMutationHeaders(tenantId, recognitionProof, extraHeaders) {
643
846
  [agentRecognitionProofHeader]: encodeRecognitionProofHeader(recognitionProof),
644
847
  };
645
848
  }
849
+ export function formatMcpStdioFrame(response) {
850
+ const body = JSON.stringify(response);
851
+ return `Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`;
852
+ }
646
853
  export class PaybondMCPServer {
647
854
  runtime;
648
855
  tools;
856
+ toolPolicy;
649
857
  initialized = false;
650
858
  constructor(settings) {
651
859
  if (!settings.apiKey.trim()) {
652
860
  throw new Error("PAYBOND_API_KEY is required");
653
861
  }
862
+ this.toolPolicy = resolveMcpToolPolicy(settings.toolPolicy ?? { policy: null, allowlist: [] });
654
863
  this.runtime = new PaybondMCPRuntime(settings);
655
- this.tools = this.buildTools(settings);
864
+ this.tools = this.buildTools(settings).filter((tool) => toolAllowedByPolicy(tool.name, tool.annotations, this.toolPolicy));
656
865
  }
657
866
  listTools() {
658
867
  return this.tools.map((tool) => ({
@@ -660,8 +869,12 @@ export class PaybondMCPServer {
660
869
  title: tool.title,
661
870
  description: tool.description,
662
871
  inputSchema: tool.inputSchema,
663
- ...(tool.outputSchema === undefined ? {} : { outputSchema: tool.outputSchema }),
664
- ...(tool.annotations === undefined ? {} : { annotations: tool.annotations }),
872
+ ...(tool.outputSchema === undefined
873
+ ? {}
874
+ : { outputSchema: tool.outputSchema }),
875
+ ...(tool.annotations === undefined
876
+ ? {}
877
+ : { annotations: tool.annotations }),
665
878
  }));
666
879
  }
667
880
  async callTool(name, args = {}) {
@@ -672,9 +885,26 @@ export class PaybondMCPServer {
672
885
  isError: true,
673
886
  };
674
887
  }
888
+ if (!toolAllowedByPolicy(name, tool.annotations, this.toolPolicy)) {
889
+ return {
890
+ content: [
891
+ {
892
+ type: "text",
893
+ text: `Tool blocked by ${MCP_TOOL_POLICY_ENV}=${this.toolPolicy.policy ?? "spend-write"}: ${name}`,
894
+ },
895
+ ],
896
+ isError: true,
897
+ };
898
+ }
675
899
  try {
676
- const value = await tool.call(args);
677
- return toToolResult(value);
900
+ await this.runtime.beginPolicyToolCall();
901
+ try {
902
+ const value = await tool.call(args);
903
+ return toToolResult(this.runtime.prepareToolResponse(value === null ? null : value, name));
904
+ }
905
+ finally {
906
+ await this.runtime.endPolicyToolCall();
907
+ }
678
908
  }
679
909
  catch (err) {
680
910
  return {
@@ -700,6 +930,7 @@ export class PaybondMCPServer {
700
930
  }
701
931
  switch (method) {
702
932
  case "initialize":
933
+ await this.runtime.preloadPrincipal();
703
934
  return {
704
935
  jsonrpc: "2.0",
705
936
  id: message.id,
@@ -718,9 +949,10 @@ export class PaybondMCPServer {
718
949
  websiteUrl: "https://paybond.ai",
719
950
  },
720
951
  instructions: "This MCP server is tenant-bound to the configured Paybond service-account API key. " +
721
- "Use paybond_create_spend_intent or paybond_fund_intent to obtain the intent_id and " +
722
- "capability_token, then call paybond_authorize_agent_spend before side-effecting tools. " +
723
- "It works with any MCP-compatible host and does not assume a specific model provider.",
952
+ "Use paybond_create_spend_intent or paybond_bootstrap_sandbox_guardrail to obtain a funded intent_id, " +
953
+ "then call paybond_authorize_agent_spend before side-effecting tools. Capability tokens are stored " +
954
+ "inside this MCP server and are not returned to agent logs. It works with any MCP-compatible host " +
955
+ "and does not assume a specific model provider.",
724
956
  },
725
957
  };
726
958
  case "ping":
@@ -740,7 +972,9 @@ export class PaybondMCPServer {
740
972
  case "tools/call": {
741
973
  const params = ensureObject(message.params, "tools/call params");
742
974
  const name = stringArg(params.name, "name");
743
- const args = params.arguments === undefined ? {} : ensureObject(params.arguments, "arguments");
975
+ const args = params.arguments === undefined
976
+ ? {}
977
+ : ensureObject(params.arguments, "arguments");
744
978
  return {
745
979
  jsonrpc: "2.0",
746
980
  id: message.id,
@@ -752,26 +986,36 @@ export class PaybondMCPServer {
752
986
  }
753
987
  }
754
988
  runStdio() {
755
- let buffer = "";
756
- process.stdin.setEncoding("utf8");
989
+ let buffer = Buffer.alloc(0);
757
990
  process.stdin.on("data", (chunk) => {
758
- buffer += chunk;
991
+ buffer = Buffer.concat([buffer, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8")]);
759
992
  while (true) {
760
- const newlineIndex = buffer.indexOf("\n");
761
- if (newlineIndex < 0) {
993
+ const headerEnd = buffer.indexOf("\r\n\r\n");
994
+ if (headerEnd < 0) {
762
995
  break;
763
996
  }
764
- const line = buffer.slice(0, newlineIndex).trim();
765
- buffer = buffer.slice(newlineIndex + 1);
766
- if (!line) {
767
- continue;
997
+ const headerText = buffer.subarray(0, headerEnd).toString("ascii");
998
+ const contentLength = Number.parseInt(headerText
999
+ .split("\r\n")
1000
+ .find((line) => line.toLowerCase().startsWith("content-length:"))
1001
+ ?.split(":", 2)[1]
1002
+ ?.trim() ?? "", 10);
1003
+ if (!Number.isFinite(contentLength) || contentLength <= 0) {
1004
+ break;
768
1005
  }
769
- void this.handleLine(line);
1006
+ const bodyStart = headerEnd + 4;
1007
+ const frameEnd = bodyStart + contentLength;
1008
+ if (buffer.length < frameEnd) {
1009
+ break;
1010
+ }
1011
+ const body = buffer.subarray(bodyStart, frameEnd).toString("utf8");
1012
+ buffer = buffer.subarray(frameEnd);
1013
+ void this.handleLine(body);
770
1014
  }
771
1015
  });
772
1016
  process.stdin.on("end", () => {
773
- if (buffer.trim()) {
774
- void this.handleLine(buffer.trim());
1017
+ if (buffer.length > 0) {
1018
+ void this.handleLine(buffer.toString("utf8"));
775
1019
  }
776
1020
  });
777
1021
  process.stdin.resume();
@@ -791,7 +1035,7 @@ export class PaybondMCPServer {
791
1035
  }
792
1036
  }
793
1037
  writeResponse(response) {
794
- process.stdout.write(`${JSON.stringify(response)}\n`);
1038
+ process.stdout.write(formatMcpStdioFrame(response));
795
1039
  }
796
1040
  buildTools(settings) {
797
1041
  const tools = [
@@ -805,60 +1049,86 @@ export class PaybondMCPServer {
805
1049
  name: "paybond_verify_capability",
806
1050
  description: "Verify a capability token returned by a created or funded Paybond intent for one tenant-bound Harbor intent.",
807
1051
  inputSchema: objectSchema({
808
- intent_id: { type: "string", description: "Canonical Harbor intent UUID." },
1052
+ intent_id: {
1053
+ type: "string",
1054
+ description: "Canonical Harbor intent UUID.",
1055
+ },
809
1056
  token: {
810
1057
  type: "string",
811
- description: "Capability token returned by paybond_create_spend_intent or paybond_fund_intent.",
1058
+ description: "Optional capability token override. When omitted, the MCP server uses the token stored for intent_id.",
1059
+ },
1060
+ operation: {
1061
+ type: "string",
1062
+ description: "Delegated operation or tool name.",
812
1063
  },
813
- operation: { type: "string", description: "Delegated operation or tool name." },
814
1064
  requested_spend_cents: {
815
1065
  type: "integer",
816
1066
  description: "Optional requested spend in cents for this tool call.",
817
1067
  },
818
- }, ["intent_id", "token", "operation"]),
819
- call: async (args) => this.runtime.verifyCapability({
820
- intentId: uuidArg(args.intent_id, "intent_id"),
821
- token: stringArg(args.token, "token"),
822
- operation: stringArg(args.operation, "operation"),
823
- requestedSpendCents: args.requested_spend_cents === undefined
824
- ? 0
825
- : intArg(args.requested_spend_cents, "requested_spend_cents"),
826
- }),
1068
+ }, ["intent_id", "operation"]),
1069
+ call: async (args) => {
1070
+ const intentId = uuidArg(args.intent_id, "intent_id");
1071
+ return this.runtime.authorizeAgentSpend({
1072
+ intentId,
1073
+ token: await this.runtime.resolveCapabilityToken(intentId, optionalString(args.token)),
1074
+ operation: stringArg(args.operation, "operation"),
1075
+ requestedSpendCents: args.requested_spend_cents === undefined
1076
+ ? undefined
1077
+ : intArg(args.requested_spend_cents, "requested_spend_cents"),
1078
+ toolName: stringArg(args.operation, "operation"),
1079
+ });
1080
+ },
827
1081
  },
828
1082
  {
829
1083
  name: "paybond_authorize_agent_spend",
830
1084
  description: "Provider-agnostic spend gate: verify the funded intent's capability token before a side-effecting tool, paid API, vendor action, or settlement workflow executes.",
831
1085
  inputSchema: objectSchema({
832
- intent_id: { type: "string", description: "Canonical Harbor intent UUID." },
1086
+ intent_id: {
1087
+ type: "string",
1088
+ description: "Canonical Harbor intent UUID.",
1089
+ },
833
1090
  token: {
834
1091
  type: "string",
835
- description: "Capability token returned by paybond_create_spend_intent or paybond_fund_intent.",
1092
+ description: "Optional capability token override. When omitted, the MCP server uses the token stored for intent_id.",
1093
+ },
1094
+ operation: {
1095
+ type: "string",
1096
+ description: "Delegated operation or tool name.",
836
1097
  },
837
- operation: { type: "string", description: "Delegated operation or tool name." },
838
1098
  requested_spend_cents: {
839
1099
  type: "integer",
840
1100
  description: "Optional requested spend in cents for this tool call.",
841
1101
  },
842
- }, ["intent_id", "token", "operation"]),
843
- call: async (args) => this.runtime.verifyCapability({
844
- intentId: uuidArg(args.intent_id, "intent_id"),
845
- token: stringArg(args.token, "token"),
846
- operation: stringArg(args.operation, "operation"),
847
- requestedSpendCents: args.requested_spend_cents === undefined
848
- ? 0
849
- : intArg(args.requested_spend_cents, "requested_spend_cents"),
850
- }),
1102
+ }, ["intent_id", "operation"]),
1103
+ call: async (args) => {
1104
+ const intentId = uuidArg(args.intent_id, "intent_id");
1105
+ return this.runtime.authorizeAgentSpend({
1106
+ intentId,
1107
+ token: await this.runtime.resolveCapabilityToken(intentId, optionalString(args.token)),
1108
+ operation: stringArg(args.operation, "operation"),
1109
+ requestedSpendCents: args.requested_spend_cents === undefined
1110
+ ? undefined
1111
+ : intArg(args.requested_spend_cents, "requested_spend_cents"),
1112
+ toolName: stringArg(args.operation, "operation"),
1113
+ });
1114
+ },
851
1115
  },
852
1116
  {
853
1117
  name: "paybond_bootstrap_sandbox_guardrail",
854
1118
  description: "Bootstrap a sandbox-only Paybond guardrail intent for a first paid-tool integration. Tenant scope is derived from the configured service-account API key and the route never touches live settlement rails.",
855
1119
  inputSchema: objectSchema({
856
- operation: { type: "string", description: "Delegated operation or paid tool name." },
1120
+ operation: {
1121
+ type: "string",
1122
+ description: "Delegated operation or paid tool name.",
1123
+ },
857
1124
  requested_spend_cents: {
858
1125
  type: "integer",
859
1126
  description: "Sandbox spend amount in cents to authorize for the sample tool call.",
860
1127
  },
861
- currency: { type: "string", description: "Optional ISO currency code; defaults at the gateway." },
1128
+ currency: {
1129
+ type: "string",
1130
+ description: "Optional ISO currency code; defaults at the gateway.",
1131
+ },
862
1132
  evidence_schema: { type: "object", additionalProperties: true },
863
1133
  metadata: { type: "object", additionalProperties: true },
864
1134
  idempotency_key: { type: "string" },
@@ -867,35 +1137,77 @@ export class PaybondMCPServer {
867
1137
  operation: stringArg(args.operation, "operation"),
868
1138
  requestedSpendCents: intArg(args.requested_spend_cents, "requested_spend_cents"),
869
1139
  currency: optionalString(args.currency),
870
- evidenceSchema: args.evidence_schema === undefined ? undefined : ensureObject(args.evidence_schema, "evidence_schema"),
871
- metadata: args.metadata === undefined ? undefined : ensureObject(args.metadata, "metadata"),
1140
+ evidenceSchema: args.evidence_schema === undefined
1141
+ ? undefined
1142
+ : ensureObject(args.evidence_schema, "evidence_schema"),
1143
+ metadata: args.metadata === undefined
1144
+ ? undefined
1145
+ : ensureObject(args.metadata, "metadata"),
872
1146
  idempotencyKey: optionalString(args.idempotency_key),
873
1147
  }),
874
1148
  },
1149
+ {
1150
+ name: "paybond_validate_completion_evidence",
1151
+ description: "Pre-validates completion evidence against the shared preset catalog. Call this before paybond_submit_*_evidence when PAYBOND_MCP_EVIDENCE_POLICY=strict.",
1152
+ inputSchema: objectSchema({
1153
+ preset_id: { type: "string" },
1154
+ vendor_payload: { type: "object", additionalProperties: true },
1155
+ canonical_payload: { type: "object", additionalProperties: true },
1156
+ frozen_vendor_api_version: { type: "string" },
1157
+ frozen_vendor_schema_digest_hex: { type: "string" },
1158
+ frozen_canonical_schema_digest_hex: { type: "string" },
1159
+ }, ["preset_id"]),
1160
+ call: async (args) => this.runtime.validateCompletionEvidence({
1161
+ presetId: stringArg(args.preset_id, "preset_id"),
1162
+ vendorPayload: args.vendor_payload === undefined
1163
+ ? undefined
1164
+ : ensureObject(args.vendor_payload, "vendor_payload"),
1165
+ canonicalPayload: args.canonical_payload === undefined
1166
+ ? undefined
1167
+ : ensureObject(args.canonical_payload, "canonical_payload"),
1168
+ frozenVendorApiVersion: optionalString(args.frozen_vendor_api_version),
1169
+ frozenVendorSchemaDigestHex: optionalString(args.frozen_vendor_schema_digest_hex),
1170
+ frozenCanonicalSchemaDigestHex: optionalString(args.frozen_canonical_schema_digest_hex),
1171
+ }),
1172
+ },
875
1173
  {
876
1174
  name: "paybond_submit_sandbox_guardrail_evidence",
877
1175
  description: "Submit evidence for a sandbox-only Paybond guardrail intent. Tenant scope is derived from the configured service-account API key and simulator settlement remains sandbox-only.",
878
1176
  inputSchema: objectSchema({
879
- intent_id: { type: "string", description: "Sandbox guardrail intent UUID." },
1177
+ intent_id: {
1178
+ type: "string",
1179
+ description: "Sandbox guardrail intent UUID.",
1180
+ },
880
1181
  payload: { type: "object", additionalProperties: true },
881
1182
  artifacts: { type: "array", items: { type: "string" } },
882
- operation: { type: "string", description: "Optional operation override for the evidence record." },
1183
+ operation: {
1184
+ type: "string",
1185
+ description: "Optional operation override for the evidence record.",
1186
+ },
883
1187
  requested_spend_cents: {
884
1188
  type: "integer",
885
1189
  description: "Optional sandbox spend amount override for the evidence record.",
886
1190
  },
887
1191
  metadata: { type: "object", additionalProperties: true },
1192
+ completion_preset_id: { type: "string" },
888
1193
  idempotency_key: { type: "string" },
889
1194
  }, ["intent_id"]),
890
1195
  call: async (args) => this.runtime.submitSandboxGuardrailEvidence({
891
1196
  intentId: uuidArg(args.intent_id, "intent_id"),
892
- payload: args.payload === undefined ? undefined : ensureObject(args.payload, "payload"),
893
- artifacts: args.artifacts === undefined ? undefined : stringArrayArg(args.artifacts, "artifacts"),
1197
+ payload: args.payload === undefined
1198
+ ? undefined
1199
+ : ensureObject(args.payload, "payload"),
1200
+ artifacts: args.artifacts === undefined
1201
+ ? undefined
1202
+ : stringArrayArg(args.artifacts, "artifacts"),
894
1203
  operation: optionalString(args.operation),
895
1204
  requestedSpendCents: args.requested_spend_cents === undefined
896
1205
  ? undefined
897
1206
  : intArg(args.requested_spend_cents, "requested_spend_cents"),
898
- metadata: args.metadata === undefined ? undefined : ensureObject(args.metadata, "metadata"),
1207
+ metadata: args.metadata === undefined
1208
+ ? undefined
1209
+ : ensureObject(args.metadata, "metadata"),
1210
+ completionPresetId: optionalString(args.completion_preset_id),
899
1211
  idempotencyKey: optionalString(args.idempotency_key),
900
1212
  }),
901
1213
  },
@@ -919,7 +1231,10 @@ export class PaybondMCPServer {
919
1231
  name: "paybond_get_intent",
920
1232
  description: "Fetch one tenant-scoped Harbor intent detail through the gateway operator view.",
921
1233
  inputSchema: objectSchema({
922
- intent_id: { type: "string", description: "Canonical Harbor intent UUID." },
1234
+ intent_id: {
1235
+ type: "string",
1236
+ description: "Canonical Harbor intent UUID.",
1237
+ },
923
1238
  }, ["intent_id"]),
924
1239
  call: async (args) => this.runtime.getIntent(uuidArg(args.intent_id, "intent_id")),
925
1240
  },
@@ -999,20 +1314,17 @@ export class PaybondMCPServer {
999
1314
  },
1000
1315
  {
1001
1316
  name: "paybond_verify_agent_recognition_proof_v1",
1002
- description: "Verify a replay-safe AgentRecognitionProofV1 against an expected purpose, verifier context, and request envelope.",
1317
+ description: "Verify a replay-safe AgentRecognitionProofV1 against an expected purpose and request envelope. " +
1318
+ "Verifier context (tenant_id, verifier_id) is derived from the authenticated MCP session only.",
1003
1319
  inputSchema: objectSchema({
1004
1320
  proof: { type: "object", additionalProperties: true },
1005
1321
  expected_purpose: { type: "string" },
1006
1322
  expected_request: { type: "object", additionalProperties: true },
1007
- expected_verifier: { type: "object", additionalProperties: true },
1008
1323
  }, ["proof", "expected_purpose", "expected_request"]),
1009
1324
  call: async (args) => this.runtime.verifyAgentRecognitionProofV1({
1010
1325
  proof: ensureObject(args.proof, "proof"),
1011
1326
  expectedPurpose: stringArg(args.expected_purpose, "expected_purpose"),
1012
1327
  expectedRequest: ensureObject(args.expected_request, "expected_request"),
1013
- expectedVerifier: args.expected_verifier === undefined
1014
- ? undefined
1015
- : ensureObject(args.expected_verifier, "expected_verifier"),
1016
1328
  }),
1017
1329
  },
1018
1330
  {
@@ -1100,12 +1412,14 @@ export class PaybondMCPServer {
1100
1412
  intent_id: { type: "string" },
1101
1413
  body: { type: "object", additionalProperties: true },
1102
1414
  recognition_proof: { type: "object", additionalProperties: true },
1415
+ completion_preset_id: { type: "string" },
1103
1416
  idempotency_key: { type: "string" },
1104
1417
  }, ["intent_id", "body", "recognition_proof"]),
1105
1418
  call: async (args) => this.runtime.submitHarborEvidence({
1106
1419
  intentId: uuidArg(args.intent_id, "intent_id"),
1107
1420
  body: ensureObject(args.body, "body"),
1108
1421
  recognitionProof: ensureObject(args.recognition_proof, "recognition_proof"),
1422
+ completionPresetId: optionalString(args.completion_preset_id),
1109
1423
  idempotencyKey: optionalString(args.idempotency_key),
1110
1424
  }),
1111
1425
  },
@@ -1116,12 +1430,14 @@ export class PaybondMCPServer {
1116
1430
  intent_id: { type: "string" },
1117
1431
  body: { type: "object", additionalProperties: true },
1118
1432
  recognition_proof: { type: "object", additionalProperties: true },
1433
+ completion_preset_id: { type: "string" },
1119
1434
  idempotency_key: { type: "string" },
1120
1435
  }, ["intent_id", "body", "recognition_proof"]),
1121
1436
  call: async (args) => this.runtime.submitHarborEvidence({
1122
1437
  intentId: uuidArg(args.intent_id, "intent_id"),
1123
1438
  body: ensureObject(args.body, "body"),
1124
1439
  recognitionProof: ensureObject(args.recognition_proof, "recognition_proof"),
1440
+ completionPresetId: optionalString(args.completion_preset_id),
1125
1441
  idempotencyKey: optionalString(args.idempotency_key),
1126
1442
  }),
1127
1443
  },
@@ -1152,14 +1468,18 @@ export function settingsFromEnv(env = process.env) {
1152
1468
  throw new Error("PAYBOND_API_KEY is required; run paybond login or configure your MCP host environment");
1153
1469
  }
1154
1470
  return {
1155
- gatewayBaseUrl: optionalEnv(env.PAYBOND_GATEWAY_URL) ??
1471
+ gatewayBaseUrl: requireSecureGatewayUrl(optionalEnv(env.PAYBOND_GATEWAY_URL) ??
1156
1472
  optionalEnv(env.PAYBOND_GATEWAY_BASE_URL) ??
1157
- DEFAULT_PAYBOND_GATEWAY_BASE_URL,
1473
+ DEFAULT_PAYBOND_GATEWAY_BASE_URL),
1158
1474
  apiKey,
1159
1475
  principalPath: optionalEnv(env.PAYBOND_PRINCIPAL_PATH) ?? DEFAULT_PRINCIPAL_PATH,
1160
1476
  maxRetries: optionalEnv(env.PAYBOND_MCP_MAX_RETRIES)
1161
1477
  ? intArg(optionalEnv(env.PAYBOND_MCP_MAX_RETRIES), "PAYBOND_MCP_MAX_RETRIES")
1162
1478
  : 3,
1479
+ toolPolicy: resolveMcpToolPolicy(mergeMcpToolPolicy(parseMcpToolPolicy(optionalEnv(env[MCP_TOOL_POLICY_ENV])), parseMcpToolAllowlist(optionalEnv(env[MCP_TOOL_ALLOWLIST_ENV])))),
1480
+ evidencePolicy: parseMcpEvidencePolicy(optionalEnv(env[MCP_EVIDENCE_POLICY_ENV])),
1481
+ policyReload: parseMcpPolicyReloadConfig(env),
1482
+ capabilityTokenCache: parseMcpCapabilityTokenCacheConfig(env),
1163
1483
  };
1164
1484
  }
1165
1485
  export function main(argv = process.argv.slice(2)) {
@@ -1182,7 +1502,7 @@ export function main(argv = process.argv.slice(2)) {
1182
1502
  }
1183
1503
  }
1184
1504
  function normalizeBase(url) {
1185
- return url.trim().replace(/\/+$/, "");
1505
+ return requireSecureGatewayUrl(url);
1186
1506
  }
1187
1507
  function parseJSONObject(text, context) {
1188
1508
  let parsed;
@@ -1314,18 +1634,6 @@ function toToolResult(value) {
1314
1634
  structuredContent: value,
1315
1635
  };
1316
1636
  }
1317
- function jsonObjectFromValue(value) {
1318
- if (value === null) {
1319
- return {};
1320
- }
1321
- if (Array.isArray(value)) {
1322
- return { items: value };
1323
- }
1324
- if (typeof value !== "object") {
1325
- return { value };
1326
- }
1327
- return JSON.parse(JSON.stringify(value));
1328
- }
1329
1637
  function responseError(id, code, message) {
1330
1638
  return {
1331
1639
  jsonrpc: "2.0",
@@ -1356,28 +1664,21 @@ function optionalEnv(value) {
1356
1664
  return value?.trim() ? value.trim() : undefined;
1357
1665
  }
1358
1666
  function formatError(err) {
1359
- if (err instanceof Error ||
1360
- err instanceof GatewayAuthError ||
1361
- err instanceof GatewayHTTPError ||
1362
- err instanceof SignalHttpError) {
1667
+ if (err instanceof Error) {
1363
1668
  return err.message;
1364
1669
  }
1365
1670
  return String(err);
1366
1671
  }
1367
1672
  function normalizeFileURL(url) {
1368
- return url.startsWith("file:///var/") ? url.replace("file:///var/", "file:///private/var/") : url;
1673
+ return url.startsWith("file:///var/")
1674
+ ? url.replace("file:///var/", "file:///private/var/")
1675
+ : url;
1369
1676
  }
1370
1677
  async function invokedFromCLI() {
1371
1678
  const scriptPath = process.argv[1];
1372
1679
  if (!scriptPath) {
1373
1680
  return false;
1374
1681
  }
1375
- // @ts-ignore Node builtins are available in the published CLI runtime.
1376
- const fs = (await import("node:fs/promises"));
1377
- // @ts-ignore Node builtins are available in the published CLI runtime.
1378
- const path = (await import("node:path"));
1379
- // @ts-ignore Node builtins are available in the published CLI runtime.
1380
- const url = (await import("node:url"));
1381
1682
  async function realFileURL(filePath) {
1382
1683
  let resolved = path.resolve(filePath);
1383
1684
  try {
@@ -1387,14 +1688,21 @@ async function invokedFromCLI() {
1387
1688
  // If realpath fails, compare the absolute path. This keeps direct execution
1388
1689
  // working even when the script path disappears during process startup.
1389
1690
  }
1390
- return normalizeFileURL(url.pathToFileURL(resolved).href);
1691
+ return normalizeFileURL(pathToFileURL(resolved).href);
1391
1692
  }
1392
- return (await realFileURL(scriptPath)) === (await realFileURL(url.fileURLToPath(import.meta.url)));
1693
+ return ((await realFileURL(scriptPath)) ===
1694
+ (await realFileURL(fileURLToPath(import.meta.url))));
1393
1695
  }
1394
1696
  invokedFromCLI().then((invoked) => {
1395
- if (invoked && main() !== 0) {
1396
- process.exitCode = 1;
1697
+ if (!invoked) {
1698
+ return;
1397
1699
  }
1700
+ runCli(["mcp", "serve", ...process.argv.slice(2)]).then((code) => {
1701
+ process.exitCode = code;
1702
+ }, (err) => {
1703
+ process.stderr.write(`${formatError(err)}\n`);
1704
+ process.exitCode = 1;
1705
+ });
1398
1706
  }, (err) => {
1399
1707
  process.stderr.write(`${formatError(err)}\n`);
1400
1708
  process.exitCode = 1;