@zackbart/connecta 0.34.0 → 0.35.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 (428) hide show
  1. package/CHANGELOG.md +393 -0
  2. package/README.md +62 -105
  3. package/SECURITY.md +3 -2
  4. package/bin/connecta.mjs +41 -16
  5. package/bin/version.mjs +1 -1
  6. package/dist/access-tokens.d.ts +2 -1
  7. package/dist/access-tokens.js +66 -30
  8. package/dist/activity.d.ts +1 -1
  9. package/dist/activity.js +2 -0
  10. package/dist/agent-config.d.ts +23 -0
  11. package/dist/agent-config.js +59 -0
  12. package/dist/agent-description.js +16 -0
  13. package/dist/agent-identity.js +4 -4
  14. package/dist/agent-observation.js +39 -0
  15. package/dist/auth/clerk-sdk/client.d.ts +2 -0
  16. package/dist/auth/clerk-sdk/generated.js +554 -563
  17. package/dist/auth/clerk-transport.js +70 -3
  18. package/dist/auth/clerk.d.ts +13 -0
  19. package/dist/auth/clerk.js +653 -246
  20. package/dist/auth/cloudflare-access.js +46 -42
  21. package/dist/auth/downstream-client-metadata.js +2 -2
  22. package/dist/auth/downstream-oauth.js +2051 -1160
  23. package/dist/auth/downstream-revocation.js +88 -88
  24. package/dist/auth/native-call.js +20 -0
  25. package/dist/auth/native.js +184 -0
  26. package/dist/auth/oauth-start-reset.js +11 -5
  27. package/dist/auth/oauth-token-response.js +121 -102
  28. package/dist/auth/oauth-v2-migration.js +97 -78
  29. package/dist/auth/renewable-grant.js +10 -0
  30. package/dist/auth/static-oauth.js +663 -271
  31. package/dist/auth/vercel-agent.js +266 -0
  32. package/dist/auth-admission.js +204 -0
  33. package/dist/auth-elicitation.js +350 -241
  34. package/dist/authorization-handoff.js +164 -90
  35. package/dist/call-admission-context.js +3 -10
  36. package/dist/call-admission.js +2 -0
  37. package/dist/call-classification.js +9 -0
  38. package/dist/call-recovery.js +32 -13
  39. package/dist/canonical-json.js +8 -0
  40. package/dist/catalog-cache.js +369 -213
  41. package/dist/catalog-service.js +659 -530
  42. package/dist/catalog.js +5 -1
  43. package/dist/concurrency.js +0 -25
  44. package/dist/config-defaults.d.ts +1 -0
  45. package/dist/config-defaults.js +1 -0
  46. package/dist/config-schema.d.ts +3 -1
  47. package/dist/config-schema.js +13 -3
  48. package/dist/config.d.ts +40 -6
  49. package/dist/config.js +40 -26
  50. package/dist/connector-caller.d.ts +4 -0
  51. package/dist/connector-caller.js +17 -4
  52. package/dist/connectors/api-connector.d.ts +15 -7
  53. package/dist/connectors/api-connector.js +147 -57
  54. package/dist/connectors/guarded-fetch.d.ts +51 -17
  55. package/dist/connectors/guarded-fetch.js +215 -121
  56. package/dist/connectors/negotiation-cache.js +20 -10
  57. package/dist/connectors/option-shapes.js +1 -1
  58. package/dist/connectors/remote-mcp.d.ts +12 -30
  59. package/dist/connectors/remote-mcp.js +960 -564
  60. package/dist/d1.js +10 -243
  61. package/dist/derived-context.js +5 -0
  62. package/dist/describe-config.d.ts +5 -1
  63. package/dist/describe-config.js +3 -0
  64. package/dist/downstream-input.js +347 -260
  65. package/dist/errors.d.ts +87 -6
  66. package/dist/errors.js +114 -4
  67. package/dist/execute.js +87 -50
  68. package/dist/executor-admission.js +3 -0
  69. package/dist/executors/quickjs.js +163 -112
  70. package/dist/guarded-transport.js +50 -0
  71. package/dist/guest-runtime.js +1 -1
  72. package/dist/http/client.js +439 -0
  73. package/dist/http/errors.js +558 -0
  74. package/dist/http/fields.js +49 -0
  75. package/dist/http/hatch-paging.js +318 -0
  76. package/dist/http/hatch.js +1279 -0
  77. package/dist/http/json-schema.js +267 -0
  78. package/dist/http/node-transport.js +241 -0
  79. package/dist/http/oauth.js +162 -0
  80. package/dist/http/paging.js +228 -0
  81. package/dist/http/provider.js +221 -0
  82. package/dist/http/safety.js +82 -0
  83. package/dist/http/services.js +79 -0
  84. package/dist/http/tools.js +383 -0
  85. package/dist/http/vendor-index.js +138 -0
  86. package/dist/http/vendor.js +448 -0
  87. package/dist/http/write-request.js +66 -0
  88. package/dist/http-policy.d.ts +11 -0
  89. package/dist/http-policy.js +45 -0
  90. package/dist/inbound-credential.js +1 -1
  91. package/dist/index.d.ts +2 -2
  92. package/dist/index.js +4 -0
  93. package/dist/invocation-auth.js +30 -19
  94. package/dist/invocation.js +221 -87
  95. package/dist/mcp-result.js +0 -4
  96. package/dist/membership.d.ts +4 -0
  97. package/dist/meta-output.js +1 -1
  98. package/dist/meta-tools.js +534 -408
  99. package/dist/native-recovery.js +52 -0
  100. package/dist/native-tools.js +382 -0
  101. package/dist/node.d.ts +4 -3
  102. package/dist/node.js +45 -8
  103. package/dist/oauth-handoff.js +177 -104
  104. package/dist/oauth-partition.js +6 -20
  105. package/dist/oauth-sealing.js +6 -7
  106. package/dist/operation-vocabulary.js +101 -0
  107. package/dist/operator-record.d.ts +2 -2
  108. package/dist/operator-record.js +17 -4
  109. package/dist/operator-ui/agents.d.ts +5 -4
  110. package/dist/operator-ui/agents.js +17 -7
  111. package/dist/operator-ui/config-summary.js +8 -4
  112. package/dist/operator-ui/connection-map.js +9 -6
  113. package/dist/operator-ui/contract.d.ts +7 -3
  114. package/dist/operator-ui/endpoints.js +5 -14
  115. package/dist/operator-ui/fix-prompts.d.ts +1 -1
  116. package/dist/operator-ui/fix-prompts.js +0 -8
  117. package/dist/operator-ui/generated.js +3 -3
  118. package/dist/operator-ui/health.js +52 -0
  119. package/dist/operator-ui/model.d.ts +2 -3
  120. package/dist/operator-ui/overview.js +11 -19
  121. package/dist/operator-ui/setup-commands.js +0 -4
  122. package/dist/operator-ui/view.d.ts +5 -29
  123. package/dist/operator-ui/view.js +3 -59
  124. package/dist/program-writes.js +47 -26
  125. package/dist/provider-call-facts.d.ts +115 -0
  126. package/dist/provider-call-facts.js +182 -0
  127. package/dist/provider-call.d.ts +112 -0
  128. package/dist/provider-call.js +271 -0
  129. package/dist/provider.d.ts +71 -32
  130. package/dist/provider.js +134 -40
  131. package/dist/providers/_shared/google/hatch.js +91 -0
  132. package/dist/providers/_shared/google/kit.js +537 -0
  133. package/dist/providers/_shared/google/result-size.js +15 -2
  134. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  135. package/dist/providers/_shared/google/service-account.js +8 -4
  136. package/dist/providers/_shared/google/workspace.d.ts +8 -209
  137. package/dist/providers/_shared/google/workspace.js +7 -426
  138. package/dist/providers/_shared/rest/compact-index.js +86 -0
  139. package/dist/providers/_shared/rest/dispatch.js +3 -23
  140. package/dist/providers/_shared/rest/kit.js +546 -0
  141. package/dist/providers/_shared/rest/operation-index.js +230 -14
  142. package/dist/providers/_shared/rest/response-media.js +11 -0
  143. package/dist/providers/_shared/rest/tools.js +101 -78
  144. package/dist/providers/_shared/rest/value-safety.js +353 -195
  145. package/dist/providers/_shared/sensitive-fields.js +27 -0
  146. package/dist/providers/breeze/api.js +584 -0
  147. package/dist/providers/breeze/index.d.ts +3 -3
  148. package/dist/providers/breeze/index.js +67 -1420
  149. package/dist/providers/breeze/openapi.generated.js +60 -0
  150. package/dist/providers/breeze/skill.generated.js +2 -6
  151. package/dist/providers/breeze/tools.js +696 -0
  152. package/dist/providers/ccb/api.js +496 -0
  153. package/dist/providers/ccb/index.d.ts +17 -37
  154. package/dist/providers/ccb/index.js +77 -1702
  155. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  156. package/dist/providers/ccb/lib/constants.js +74 -0
  157. package/dist/providers/ccb/lib/guide.js +9 -0
  158. package/dist/providers/ccb/lib/verdicts.js +387 -0
  159. package/dist/providers/ccb/openapi.generated.js +397 -0
  160. package/dist/providers/ccb/safety.js +295 -0
  161. package/dist/providers/ccb/skill.generated.js +2 -6
  162. package/dist/providers/ccb/tools.js +853 -0
  163. package/dist/providers/cloudflare/api.js +1066 -0
  164. package/dist/providers/cloudflare/index.d.ts +7 -22
  165. package/dist/providers/cloudflare/index.js +80 -194
  166. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  167. package/dist/providers/cloudflare/lib/config.js +2 -0
  168. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  169. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  170. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  171. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  172. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  173. package/dist/providers/cloudflare/openapi.generated.js +3299 -3208
  174. package/dist/providers/cloudflare/{value-safety.js → safety.js} +538 -18
  175. package/dist/providers/cloudflare/skill.generated.js +2 -10
  176. package/dist/providers/cloudflare/tools.js +360 -0
  177. package/dist/providers/docs/api.js +51 -0
  178. package/dist/providers/docs/index.d.ts +1 -12
  179. package/dist/providers/docs/index.js +53 -1165
  180. package/dist/providers/docs/lib/constants.d.ts +18 -0
  181. package/dist/providers/docs/lib/constants.js +18 -0
  182. package/dist/providers/docs/lib/discovery.js +26 -0
  183. package/dist/providers/docs/lib/requests.js +48 -0
  184. package/dist/providers/docs/lib/schemas.js +168 -0
  185. package/dist/providers/docs/openapi.generated.js +16 -0
  186. package/dist/providers/docs/safety.js +54 -0
  187. package/dist/providers/docs/skill.generated.js +2 -6
  188. package/dist/providers/docs/tools.js +802 -0
  189. package/dist/providers/drive/api.js +177 -0
  190. package/dist/providers/drive/index.d.ts +1 -12
  191. package/dist/providers/drive/index.js +38 -1448
  192. package/dist/providers/drive/lib/constants.d.ts +6 -0
  193. package/dist/providers/drive/lib/constants.js +6 -0
  194. package/dist/providers/drive/lib/contracts.js +532 -0
  195. package/dist/providers/drive/lib/hatch.js +197 -0
  196. package/dist/providers/drive/openapi.generated.js +77 -0
  197. package/dist/providers/drive/safety.js +90 -0
  198. package/dist/providers/drive/skill.generated.js +2 -6
  199. package/dist/providers/drive/tools.js +1290 -0
  200. package/dist/providers/forms/api.js +71 -0
  201. package/dist/providers/forms/index.d.ts +1 -12
  202. package/dist/providers/forms/index.js +49 -1145
  203. package/dist/providers/forms/lib/constants.d.ts +14 -0
  204. package/dist/providers/forms/lib/constants.js +19 -0
  205. package/dist/providers/forms/lib/hatch.js +72 -0
  206. package/dist/providers/forms/openapi.generated.js +23 -0
  207. package/dist/providers/forms/safety.js +34 -0
  208. package/dist/providers/forms/skill.generated.js +2 -8
  209. package/dist/providers/forms/tools.js +1024 -0
  210. package/dist/providers/github/api.js +150 -0
  211. package/dist/providers/github/index.d.ts +4 -5
  212. package/dist/providers/github/index.js +30 -87
  213. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  214. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  215. package/dist/providers/github/lib/discovery.js +132 -0
  216. package/dist/providers/github/lib/operations.js +58 -0
  217. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  218. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  219. package/dist/providers/github/openapi.generated.js +1216 -0
  220. package/dist/providers/github/safety.js +216 -0
  221. package/dist/providers/github/skill.generated.js +2 -5
  222. package/dist/providers/github/tools.js +506 -0
  223. package/dist/providers/gmail/api.js +114 -0
  224. package/dist/providers/gmail/index.d.ts +1 -12
  225. package/dist/providers/gmail/index.js +73 -1621
  226. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  227. package/dist/providers/gmail/lib/constants.js +16 -0
  228. package/dist/providers/gmail/lib/index.js +173 -0
  229. package/dist/providers/gmail/lib/schemas.js +176 -0
  230. package/dist/providers/gmail/lib/threading.js +120 -0
  231. package/dist/providers/gmail/openapi.generated.js +92 -0
  232. package/dist/providers/gmail/safety.js +21 -0
  233. package/dist/providers/gmail/skill.generated.js +2 -6
  234. package/dist/providers/gmail/tools.js +1435 -0
  235. package/dist/providers/overflow/api.js +1008 -0
  236. package/dist/providers/overflow/index.d.ts +3 -17
  237. package/dist/providers/overflow/index.js +60 -1488
  238. package/dist/providers/overflow/skill.generated.js +2 -5
  239. package/dist/providers/overflow/tools.js +873 -0
  240. package/dist/providers/planning-center/api.js +467 -0
  241. package/dist/providers/planning-center/index.d.ts +6 -35
  242. package/dist/providers/planning-center/index.js +69 -2445
  243. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  244. package/dist/providers/planning-center/lib/constants.js +83 -0
  245. package/dist/providers/planning-center/lib/discovery.js +40 -0
  246. package/dist/providers/planning-center/lib/guide.js +39 -0
  247. package/dist/providers/planning-center/lib/json-api.js +83 -0
  248. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  249. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  250. package/dist/providers/planning-center/safety.js +188 -0
  251. package/dist/providers/planning-center/skill.generated.js +2 -27
  252. package/dist/providers/planning-center/tools.js +1010 -0
  253. package/dist/providers/sheets/api.js +133 -0
  254. package/dist/providers/sheets/index.d.ts +4 -16
  255. package/dist/providers/sheets/index.js +61 -1172
  256. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  257. package/dist/providers/sheets/lib/constants.js +14 -0
  258. package/dist/providers/sheets/lib/hatch.js +163 -0
  259. package/dist/providers/sheets/lib/requests.js +105 -0
  260. package/dist/providers/sheets/lib/schemas.js +138 -0
  261. package/dist/providers/sheets/openapi.generated.js +30 -0
  262. package/dist/providers/sheets/safety.js +27 -0
  263. package/dist/providers/sheets/skill.generated.js +2 -7
  264. package/dist/providers/sheets/tools.js +734 -0
  265. package/dist/providers/slides/api.js +147 -0
  266. package/dist/providers/slides/index.d.ts +2 -10
  267. package/dist/providers/slides/index.js +48 -2555
  268. package/dist/providers/slides/lib/constants.d.ts +11 -0
  269. package/dist/providers/slides/lib/constants.js +11 -0
  270. package/dist/providers/slides/lib/requests.js +60 -0
  271. package/dist/providers/slides/lib/schemas.js +565 -0
  272. package/dist/providers/slides/openapi.generated.js +18 -0
  273. package/dist/providers/slides/skill.generated.js +2 -6
  274. package/dist/providers/slides/tools.js +1968 -0
  275. package/dist/providers/stripe/api.js +401 -0
  276. package/dist/providers/stripe/index.d.ts +7 -27
  277. package/dist/providers/stripe/index.js +75 -191
  278. package/dist/providers/stripe/lib/config.d.ts +4 -0
  279. package/dist/providers/stripe/lib/config.js +2 -0
  280. package/dist/providers/stripe/openapi.generated.js +4 -3
  281. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  282. package/dist/providers/stripe/skill.generated.js +2 -10
  283. package/dist/providers/stripe/tools.js +77 -0
  284. package/dist/providers/tithely/api.js +531 -0
  285. package/dist/providers/tithely/index.d.ts +19 -0
  286. package/dist/providers/tithely/index.js +86 -965
  287. package/dist/providers/tithely/skill.generated.js +2 -5
  288. package/dist/providers/tithely/tools.js +426 -0
  289. package/dist/providers/vercel/api.js +551 -0
  290. package/dist/providers/vercel/index.d.ts +11 -25
  291. package/dist/providers/vercel/index.js +67 -261
  292. package/dist/providers/vercel/lib/config.d.ts +2 -0
  293. package/dist/providers/vercel/lib/config.js +2 -0
  294. package/dist/providers/vercel/lib/index.js +117 -0
  295. package/dist/providers/vercel/lib/logs.js +100 -0
  296. package/dist/providers/vercel/lib/pin.js +270 -0
  297. package/dist/providers/vercel/openapi.generated.js +398 -376
  298. package/dist/providers/vercel/{value-safety.js → safety.js} +261 -42
  299. package/dist/providers/vercel/skill.generated.js +2 -7
  300. package/dist/providers/vercel/tools.js +642 -0
  301. package/dist/redaction-identity.js +47 -0
  302. package/dist/redaction-marker.js +125 -0
  303. package/dist/registry.d.ts +30 -28
  304. package/dist/registry.js +446 -413
  305. package/dist/routes/access-tokens.js +1 -1
  306. package/dist/routes/actor-labels.js +1 -1
  307. package/dist/routes/connect.js +1 -1
  308. package/dist/routes/dispatch.js +103 -0
  309. package/dist/routes/mcp.js +170 -79
  310. package/dist/routes/oauth.js +3 -1
  311. package/dist/routes/operator.js +2 -2
  312. package/dist/routes/shared.d.ts +5 -4
  313. package/dist/routes/shared.js +244 -177
  314. package/dist/routes/skills.js +10 -8
  315. package/dist/routes/ui-config.js +27 -3
  316. package/dist/routes/ui-data.js +29 -22
  317. package/dist/routes/ui.js +1 -1
  318. package/dist/runtime/call-admission.js +0 -26
  319. package/dist/runtime/call-entry.js +30 -0
  320. package/dist/runtime/call.js +556 -0
  321. package/dist/runtime/connector-scope.js +7 -0
  322. package/dist/runtime/credential-probe.js +34 -0
  323. package/dist/runtime/executor.js +40 -0
  324. package/dist/runtime/native-storage.js +63 -0
  325. package/dist/runtime/registry.js +27 -0
  326. package/dist/runtime/request-scope.js +72 -0
  327. package/dist/runtime/run.js +15 -7
  328. package/dist/runtime/shared-read.js +34 -5
  329. package/dist/runtime/storage.js +34 -21
  330. package/dist/sent-secrets.d.ts +194 -37
  331. package/dist/sent-secrets.js +1743 -340
  332. package/dist/server.js +5 -56
  333. package/dist/skills.js +330 -224
  334. package/dist/sqlite.js +15 -14
  335. package/dist/storage/d1-copy.js +255 -0
  336. package/dist/storage/d1-driver.js +15 -0
  337. package/dist/storage/keys.js +28 -0
  338. package/dist/storage/sql-driver.js +88 -0
  339. package/dist/storage/sql-native.js +544 -0
  340. package/dist/storage/sql-schema.d.ts +6 -0
  341. package/dist/storage/sql-schema.js +15 -0
  342. package/dist/storage/sql.d.ts +14 -20
  343. package/dist/storage/sql.js +29 -535
  344. package/dist/timeout.js +0 -26
  345. package/dist/tool-safety.js +20 -10
  346. package/dist/types.d.ts +11 -99
  347. package/dist/upward.js +3 -0
  348. package/dist/usage-guide.js +3 -1
  349. package/dist/validate.d.ts +4 -2
  350. package/dist/validate.js +86 -9
  351. package/dist/version.d.ts +1 -1
  352. package/dist/version.js +1 -1
  353. package/dist/worker.js +312 -292
  354. package/dist/workspace-subject.js +5 -1
  355. package/dist/write-outcome.js +454 -34
  356. package/documentation/README.md +27 -7
  357. package/documentation/architecture.md +2550 -186
  358. package/documentation/auth.md +821 -98
  359. package/documentation/code-mode.md +56 -21
  360. package/documentation/deploying.md +164 -20
  361. package/documentation/hosted-mcp-migration.md +460 -0
  362. package/documentation/integrating.md +144 -105
  363. package/documentation/meta-tools.md +411 -34
  364. package/documentation/operating.md +28 -4
  365. package/documentation/operator-tests.md +11 -2
  366. package/documentation/operator-ui.md +103 -33
  367. package/documentation/provider-auth-migration.md +38 -63
  368. package/documentation/provider-migration-0.29.md +10 -5
  369. package/documentation/provider-migration-0.35.md +975 -0
  370. package/documentation/providers.md +965 -0
  371. package/examples/worker/AGENTS.md +23 -9
  372. package/examples/worker/README.md +254 -135
  373. package/examples/worker/alchemy.run.ts +116 -0
  374. package/examples/worker/gitignore +10 -0
  375. package/examples/worker/src/connecta.config.ts +23 -21
  376. package/examples/worker/wrangler.jsonc +14 -5
  377. package/guides/connecting-agents.md +157 -0
  378. package/guides/how-it-works.md +156 -0
  379. package/guides/safety-and-trust.md +153 -0
  380. package/package.json +27 -42
  381. package/templates/node/.env.example +3 -0
  382. package/templates/node/README.md +22 -2
  383. package/templates/node/docker-compose.yml +1 -0
  384. package/templates/node/package.json +3 -2
  385. package/templates/node/src/connecta.config.ts +8 -0
  386. package/dist/catalog-drift.d.ts +0 -134
  387. package/dist/catalog-drift.js +0 -493
  388. package/dist/providers/_shared/request-token.js +0 -83
  389. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  390. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  391. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  392. package/dist/providers/basecamp/index.d.ts +0 -43
  393. package/dist/providers/basecamp/index.js +0 -997
  394. package/dist/providers/basecamp/skill.generated.js +0 -9
  395. package/dist/providers/cloudflare/rest.d.ts +0 -37
  396. package/dist/providers/cloudflare/rest.js +0 -1078
  397. package/dist/providers/github/hosted.js +0 -218
  398. package/dist/providers/github/rest.js +0 -321
  399. package/dist/providers/infisical/index.d.ts +0 -7
  400. package/dist/providers/infisical/index.js +0 -713
  401. package/dist/providers/infisical/skill.generated.js +0 -8
  402. package/dist/providers/linear/index.d.ts +0 -55
  403. package/dist/providers/linear/index.js +0 -352
  404. package/dist/providers/linear/skill.generated.js +0 -8
  405. package/dist/providers/mixpanel/index.d.ts +0 -57
  406. package/dist/providers/mixpanel/index.js +0 -468
  407. package/dist/providers/mixpanel/operations.js +0 -20
  408. package/dist/providers/mixpanel/rest.js +0 -603
  409. package/dist/providers/mixpanel/skill.generated.js +0 -10
  410. package/dist/providers/mixpanel/value-safety.js +0 -16
  411. package/dist/providers/notion/index.d.ts +0 -65
  412. package/dist/providers/notion/index.js +0 -368
  413. package/dist/providers/notion/openapi.generated.js +0 -75
  414. package/dist/providers/notion/rest.d.ts +0 -24
  415. package/dist/providers/notion/rest.js +0 -1226
  416. package/dist/providers/notion/skill.generated.js +0 -11
  417. package/dist/providers/notion/value-safety.js +0 -56
  418. package/dist/providers/revenuecat/index.d.ts +0 -49
  419. package/dist/providers/revenuecat/index.js +0 -557
  420. package/dist/providers/revenuecat/skill.generated.js +0 -11
  421. package/dist/providers/stripe/rest.d.ts +0 -14
  422. package/dist/providers/stripe/rest.js +0 -402
  423. package/dist/providers/vercel/rest.d.ts +0 -20
  424. package/dist/providers/vercel/rest.js +0 -1020
  425. package/dist/providers/wispr-flow/index.d.ts +0 -14
  426. package/dist/providers/wispr-flow/index.js +0 -117
  427. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  428. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
@@ -64,7 +64,7 @@ export async function routeAccessTokens(context, manager) {
64
64
  if (mutating && !isSameOrigin(request, baseUrl)) {
65
65
  return privateJson({ error: "same-origin request required" }, { status: 403 });
66
66
  }
67
- const admin = await authorizeUiIdentity(request, baseUrl, opts.config.auth, "access token management", context.runtimeContext);
67
+ const admin = await authorizeUiIdentity(request, baseUrl, opts.config.auth, "access token management", context.runtimeContext, opts.config.logger);
68
68
  if (!admin.ok)
69
69
  return admin.response;
70
70
  // Interactive maintainers alone manage agent tokens (#837); anyone else
@@ -75,7 +75,7 @@ function labelLookups(actors, auth) {
75
75
  export function resolveActorLabels(actors, auth) {
76
76
  return Effect.suspend(() => {
77
77
  const labels = new Map();
78
- const resolve = ({ key, id, provider }) => Effect.tryPromise(() => Promise.resolve(provider.activityActorLabel(id))).pipe(Effect.map(cleanActorLabel), Effect.orElseSucceed(() => undefined), Effect.map((label) => {
78
+ const resolve = ({ key, id, provider }) => Effect.tryPromise((signal) => Promise.resolve(provider.activityActorLabel(id, signal))).pipe(Effect.map(cleanActorLabel), Effect.orElseSucceed(() => undefined), Effect.map((label) => {
79
79
  if (label)
80
80
  labels.set(key, label);
81
81
  }));
@@ -84,7 +84,7 @@ async function connect(context) {
84
84
  headers: { Location: target.href, "Cache-Control": "no-store", "Referrer-Policy": "no-referrer" },
85
85
  });
86
86
  };
87
- const authz = await authorizeUiIdentity(request, baseUrl, opts.config.auth, "OAuth connection", runtimeContext);
87
+ const authz = await authorizeUiIdentity(request, baseUrl, opts.config.auth, "OAuth connection", runtimeContext, opts.config.logger);
88
88
  if (!authz.ok) {
89
89
  // Access sign-in is enforced at the edge. Clerk needs its own sign-in page.
90
90
  // The sign-in page returns to this link, which then sends a maintainer on
@@ -0,0 +1,103 @@
1
+ import { Context, Effect, Scheduler } from "effect";
2
+ import * as HttpRouter from "effect/http/HttpRouter";
3
+ import * as HttpServerError from "effect/http/HttpServerError";
4
+ import * as HttpServerRequest from "effect/http/HttpServerRequest";
5
+ import * as HttpServerResponse from "effect/http/HttpServerResponse";
6
+ import { notFoundResponse } from "../branding.js";
7
+ import { isAgentPath } from "./agent-path.js";
8
+ import { MCP_CORS_HEADERS } from "./mcp.js";
9
+ import { routeConnect } from "./connect.js";
10
+ import { routeOAuthCallback } from "./oauth.js";
11
+ import { routeOAuthClientMetadata } from "./oauth-client-metadata.js";
12
+ // Only execution provides this service. Registration never sees request state.
13
+ class CurrentRoute extends Context.Service()("connecta/CurrentRoute") {
14
+ }
15
+ /** Private, request-free route tables, owned by one fetch handler. */
16
+ export function createRouteDispatcher(mcp, metadata, health) {
17
+ let tables;
18
+ const missing = (context) => notFoundResponse(context.request, context.opts.config);
19
+ const fallback = (context) => Effect.gen(function* () {
20
+ if (context.request.method === "OPTIONS") {
21
+ return ((yield* mcp(context)) ??
22
+ (yield* metadata(context.request, context.baseUrl)) ??
23
+ new Response(null, { status: 204, headers: MCP_CORS_HEADERS }));
24
+ }
25
+ return (yield* mcp(context)) ?? missing(context);
26
+ });
27
+ const afterUi = (program) => (context) => Effect.gen(function* () {
28
+ const ui = context.opts.config.ui;
29
+ const response = ui ? yield* Effect.promise(() => ui.handle(context)) : null;
30
+ return response ?? (yield* program(context));
31
+ });
32
+ const optional = (program) => (context) => Effect.flatMap(program(context), (response) => (response ? Effect.succeed(response) : fallback(context)));
33
+ const agentProgram = (context) => Effect.map(mcp(context), (response) => response ?? missing(context));
34
+ const wrap = (program) => Effect.flatMap(CurrentRoute, (current) => {
35
+ current.entered = true;
36
+ return Effect.map(Effect.suspend(() => program(current.context)), HttpServerResponse.raw);
37
+ });
38
+ // make/addAll/asHttpEffect are entirely synchronous for these fixed tables.
39
+ // Bound only their registration/publication so concurrent first edges cannot
40
+ // yield halfway through and build duplicate tables. No callbacks or I/O here.
41
+ const initialize = Effect.suspend(() => {
42
+ if (tables)
43
+ return Effect.succeed(tables);
44
+ return Effect.gen(function* () {
45
+ const human = yield* HttpRouter.make;
46
+ const agent = yield* HttpRouter.make;
47
+ const humanRoutes = [
48
+ HttpRouter.route("*", "/oauth/client-metadata/*", wrap((context) => {
49
+ const response = routeOAuthClientMetadata(context);
50
+ return response ? Effect.succeed(response) : afterUi(fallback)(context);
51
+ })),
52
+ HttpRouter.route("*", "/connect/*", wrap(afterUi(optional(routeConnect)))),
53
+ HttpRouter.route("*", "/oauth/callback/*", wrap(afterUi(optional(routeOAuthCallback)))),
54
+ HttpRouter.route("*", "/.well-known/*", wrap(afterUi((context) => {
55
+ if (!context.path.startsWith("/.well-known/"))
56
+ return fallback(context);
57
+ return Effect.gen(function* () {
58
+ return ((yield* mcp(context)) ??
59
+ (yield* metadata(context.request, context.baseUrl)) ??
60
+ (context.request.method === "OPTIONS"
61
+ ? new Response(null, { status: 204, headers: MCP_CORS_HEADERS })
62
+ : missing(context)));
63
+ });
64
+ }))),
65
+ HttpRouter.route("*", "/health", wrap(afterUi((context) => context.path === "/health" && context.request.method !== "OPTIONS"
66
+ ? Effect.promise(health)
67
+ : fallback(context)))),
68
+ HttpRouter.route("*", "/mcp/*", wrap(afterUi(fallback))),
69
+ ];
70
+ // addAll's Request markers describe execution dependencies, not services
71
+ // used during registration. CurrentRoute is supplied below on every call;
72
+ // the error marker is handled by the existing edge, never by registration.
73
+ yield* human.addAll(humanRoutes);
74
+ yield* agent.addAll([HttpRouter.route("*", "*", wrap(agentProgram))]);
75
+ tables = { human: human.asHttpEffect(), agent: agent.asHttpEffect() };
76
+ return tables;
77
+ });
78
+ }).pipe(Effect.provideService(HttpRouter.RouterConfig, {
79
+ ignoreDuplicateSlashes: false,
80
+ ignoreTrailingSlash: false,
81
+ caseSensitive: true,
82
+ }), Effect.provideService(Scheduler.PreventSchedulerYield, true), Effect.uninterruptible);
83
+ return (context) => Effect.gen(function* () {
84
+ const routers = yield* initialize;
85
+ const current = { context, entered: false };
86
+ const agent = isAgentPath(context.path);
87
+ // Dispatch only selects paths. Methods, body and headers belong to the
88
+ // original request in CurrentRoute; a GET projection also covers arbitrary
89
+ // extension methods outside FindMyWay's finite wildcard-method list.
90
+ // Escape '%' once so the matcher cannot decode raw prefixes or reject an
91
+ // invalid escape in an otherwise owned suffix; ';' is its query delimiter.
92
+ const request = HttpServerRequest.fromWeb(new Request(context.url)).modify({
93
+ url: context.path.replaceAll("%", "%25").replaceAll(";", "%3B"),
94
+ });
95
+ return yield* Effect.scoped(agent ? routers.agent : routers.human).pipe(Effect.provideService(CurrentRoute, current), Effect.provideService(HttpServerRequest.HttpServerRequest, request), Effect.map(HttpServerResponse.toWeb), Effect.catch((error) => !current.entered &&
96
+ HttpServerError.isHttpServerError(error) &&
97
+ error.reason instanceof HttpServerError.RouteNotFound
98
+ ? agent
99
+ ? agentProgram(context)
100
+ : afterUi(fallback)(context)
101
+ : Effect.fail(error)));
102
+ });
103
+ }
@@ -1,5 +1,10 @@
1
+ import { upwardStep } from "../upward.js";
2
+ import { authCall, authInvoke, authFlow, authMethod } from "../auth/native.js";
3
+ import { registryProgram } from "../runtime/registry.js";
4
+ import { requestOwner, RequestScope } from "../runtime/request-scope.js";
5
+ import { observeAgentAdmission } from "../agent-observation.js";
1
6
  import { bindActivityRequest } from "../activity-request.js";
2
- import { closeConnectorScope } from "../connector-scope.js";
7
+ import { closeScope } from "../runtime/connector-scope.js";
3
8
  import { executeLimits } from "../config.js";
4
9
  import { oauthConnectUrl, oauthConnectLink, oauthConnectLinkProgress, closeOAuthConnectLinks, claimAuthRetry, oauthConnectUnavailable, } from "../oauth-handoff.js";
5
10
  import { AuthElicitation } from "../auth-elicitation.js";
@@ -9,6 +14,7 @@ import { registerExecuteTool } from "../execute.js";
9
14
  import { ExecutorAdmissionError } from "../executor-admission.js";
10
15
  import { registerMetaTools } from "../meta-tools.js";
11
16
  import { endpointInstructions } from "../skills.js";
17
+ import { NATIVE_TOOLS_LIST_TTL_MS, NativeSurface, nativeRequestHint } from "../native-tools.js";
12
18
  import { registerSkills } from "./skills.js";
13
19
  import { failureRecord, logFailure } from "../operator-record.js";
14
20
  import { redactAgentOutput, sentSecretsForRequest } from "../sent-secrets.js";
@@ -16,12 +22,9 @@ import { detach } from "../runtime/run.js";
16
22
  import { agentEndpointPool, isAgentPath } from "./agent-path.js";
17
23
  import { admitsMaintainer, agentPool, authorize, authorizeAgent, mayManageConnector, memberPool, } from "./shared.js";
18
24
  /**
19
- * The SDK's own bound on the body it reads. Since server 2.1.0 the SDK
20
- * answers anything over 4 MiB with its own 413, which would quietly shadow
21
- * the bound the host already enforces: `listen()`'s `maxBodyBytes` on Node,
22
- * the platform's request limit on Workers. The host owns that decision, as it
23
- * did before the SDK had an opinion, so the SDK is told to have none. Its
24
- * option must be finite.
25
+ * Core checks admission.requests.maxBodyBytes after authentication and endpoint
26
+ * admission, before any SDK/body-hint reader. The SDK's separate 4 MiB default
27
+ * must not shadow a configured larger bound. Its option must be finite.
25
28
  */
26
29
  const SDK_BODY_BOUND = { maxRequestBodySize: Number.MAX_SAFE_INTEGER };
27
30
  // Identity, not a status/header a custom auth response could imitate.
@@ -33,12 +36,12 @@ const deadlineResponses = new WeakSet();
33
36
  */
34
37
  export const MAX_LISTEN_CLASSIFICATION_BYTES = 64 * 1024;
35
38
  /**
36
- * Whether an admitted, authenticated request is a modern `subscriptions/listen`.
37
- * Reads at most `MAX_LISTEN_CLASSIFICATION_BYTES` of a clone, then stops and
38
- * cancels the body: `"too_large"` past the cap, `"aborted"` when the request
39
- * ended or its lifetime ran out while reading.
39
+ * Check an authenticated, endpoint-admitted body while streaming. The clone
40
+ * preserves the SDK's body and protocol validation. Only a listen candidate
41
+ * needs decoding/classification; other bodies retain no second text copy.
42
+ * Cancel both tee branches past the bound or when the request ends.
40
43
  */
41
- async function classifyListen(request, signal) {
44
+ async function inspectRequestBody(request, signal, maxBytes, listen) {
42
45
  const reader = request.clone().body?.getReader();
43
46
  if (!reader)
44
47
  return "other";
@@ -50,7 +53,7 @@ async function classifyListen(request, signal) {
50
53
  if (signal.aborted)
51
54
  onAbort();
52
55
  try {
53
- const decoder = new TextDecoder();
56
+ const decoder = listen ? new TextDecoder() : undefined;
54
57
  let text = "";
55
58
  let bytes = 0;
56
59
  for (;;) {
@@ -58,15 +61,18 @@ async function classifyListen(request, signal) {
58
61
  if (done)
59
62
  break;
60
63
  bytes += value.byteLength;
61
- if (bytes > MAX_LISTEN_CLASSIFICATION_BYTES) {
64
+ if (bytes > maxBytes) {
62
65
  void reader.cancel().catch(() => { });
63
66
  void request.body?.cancel().catch(() => { });
64
67
  return "too_large";
65
68
  }
66
- text += decoder.decode(value, { stream: true });
69
+ if (decoder)
70
+ text += decoder.decode(value, { stream: true });
67
71
  }
68
72
  if (signal.aborted)
69
73
  return "aborted";
74
+ if (!decoder)
75
+ return "other";
70
76
  const protocolVersion = request.headers.get("MCP-Protocol-Version");
71
77
  const method = request.headers.get("Mcp-Method");
72
78
  const route = classifyInboundRequest({
@@ -319,7 +325,9 @@ function serveMcp(request, requestSignal, requestScope, opts, baseUrl, actor, re
319
325
  // The modern handler tears its own down after the exchange; the legacy
320
326
  // transport never does, and neither may stay wired to an ended request.
321
327
  const servers = [];
322
- const createServer = () => {
328
+ // A native pool lists its downstream tools directly (pools.<name>.surface).
329
+ const native = pool !== undefined ? opts.pools.get(pool)?.native : undefined;
330
+ const createServer = authMethod((hint) => authFlow(function* () {
323
331
  const authElicitation = new AuthElicitation({
324
332
  vault: opts.config.vault,
325
333
  publicUrl: opts.config.publicUrl,
@@ -327,10 +335,18 @@ function serveMcp(request, requestSignal, requestScope, opts, baseUrl, actor, re
327
335
  principal: principalKey,
328
336
  registry,
329
337
  canManage: canManageAuth,
330
- connectLink: (id, force, after) => oauthConnectLink(opts, opts.config.publicUrl ?? baseUrl, id, principalKey, force, Boolean(opts.config.vault?.seal && opts.config.vault.open), after),
331
- linkProgress: (id, nonce) => oauthConnectLinkProgress(opts, baseUrl, id, nonce),
332
- closeLinks: (id, nonces) => closeOAuthConnectLinks(opts, baseUrl, id, nonces),
333
- claimRetry: (id, nonce) => claimAuthRetry(opts, baseUrl, id, nonce),
338
+ connectLink: authMethod((id, force, after) => authCall(oauthConnectLink, [
339
+ opts,
340
+ opts.config.publicUrl ?? baseUrl,
341
+ id,
342
+ principalKey,
343
+ force,
344
+ Boolean(opts.config.vault?.seal && opts.config.vault.open),
345
+ after,
346
+ ])),
347
+ linkProgress: authMethod((id, nonce) => authCall(oauthConnectLinkProgress, [opts, baseUrl, id, nonce])),
348
+ closeLinks: authMethod((id, nonces) => authCall(closeOAuthConnectLinks, [opts, baseUrl, id, nonces])),
349
+ claimRetry: authMethod((id, nonce) => authCall(claimAuthRetry, [opts, baseUrl, id, nonce])),
334
350
  unavailable: oauthConnectUnavailable(opts),
335
351
  credentialUi: Boolean(opts.config.ui && opts.config.vault),
336
352
  requestSignal,
@@ -344,17 +360,18 @@ function serveMcp(request, requestSignal, requestScope, opts, baseUrl, actor, re
344
360
  // Instructions differ per endpoint only by the admitted pool's
345
361
  // description. Every cache hint below is private, so a client keeps
346
362
  // what it learned per endpoint URL and never shares it across them.
347
- instructions: endpointInstructions(pool !== undefined ? opts.pools.get(pool)?.description : undefined),
363
+ instructions: endpointInstructions(pool !== undefined ? opts.pools.get(pool)?.description : undefined, native),
348
364
  inputRequired: { legacyShim: false },
349
365
  requestState: { verify: (state, context) => authElicitation.verify(state, context) },
350
366
  cacheHints: {
351
367
  "server/discover": { ttlMs: 3_600_000, cacheScope: "private" },
352
368
  "tools/list": {
353
- ttlMs: 3_600_000,
369
+ ttlMs: native ? NATIVE_TOOLS_LIST_TTL_MS : 3_600_000,
354
370
  cacheScope: "private",
355
371
  },
356
372
  },
357
373
  });
374
+ servers.push(server);
358
375
  const activity = opts.config.activity?.store
359
376
  ? {
360
377
  sink: opts.config.activity?.store,
@@ -378,14 +395,16 @@ function serveMcp(request, requestSignal, requestScope, opts, baseUrl, actor, re
378
395
  probeTimeoutMs: opts.config.discovery.probeTimeoutMs,
379
396
  ...(runtimeContext?.waitUntil ? { defer: runtimeContext.waitUntil.bind(runtimeContext) } : {}),
380
397
  });
381
- registerMetaTools(server, registry, {
398
+ const diagnostics = native ? { ...native, catalogErrors: [] } : undefined;
399
+ const nativeRoute = registerMetaTools(server, registry, {
400
+ native: diagnostics,
382
401
  authElicitation,
383
402
  client,
384
403
  baseUrl,
385
404
  requestScope,
386
405
  readOnly,
387
406
  canManageAuth,
388
- oauthConnectUrl: (id, force) => oauthConnectUrl(opts, baseUrl, id, principalKey, force),
407
+ oauthConnectUrl: authMethod((id, force) => authCall(oauthConnectUrl, [opts, baseUrl, id, principalKey, force])),
389
408
  oauthConnectUnavailable: oauthConnectUnavailable(opts),
390
409
  credentialHandoffUrl: opts.config.ui?.credentialHandoffUrl(baseUrl),
391
410
  ...(activity ? { activity } : {}),
@@ -395,39 +414,62 @@ function serveMcp(request, requestSignal, requestScope, opts, baseUrl, actor, re
395
414
  requestSignal,
396
415
  ...(runtimeContext?.waitUntil ? { defer: runtimeContext.waitUntil.bind(runtimeContext) } : {}),
397
416
  });
398
- registerExecuteTool(server, registry, {
399
- authElicitation,
400
- client,
401
- baseUrl,
402
- requestScope,
403
- executor: opts.executor,
404
- defaultToolTimeoutMs: opts.config.calls.defaultTimeoutMs ?? opts.config.execute.hostCallTimeoutMs,
405
- logger: opts.config.logger,
406
- ...(activity ? { activity } : {}),
407
- requestSignal,
408
- ...(runtimeContext?.waitUntil ? { defer: runtimeContext.waitUntil.bind(runtimeContext) } : {}),
409
- ...executeLimits(opts.config),
410
- readOnly,
411
- });
412
- servers.push(server);
417
+ if (!native || native.executeCode) {
418
+ registerExecuteTool(server, registry, {
419
+ authElicitation,
420
+ client,
421
+ baseUrl,
422
+ requestScope,
423
+ executor: opts.executor,
424
+ defaultToolTimeoutMs: opts.config.calls.defaultTimeoutMs ?? opts.config.execute.hostCallTimeoutMs,
425
+ logger: opts.config.logger,
426
+ ...(activity ? { activity } : {}),
427
+ requestSignal,
428
+ ...(runtimeContext?.waitUntil ? { defer: runtimeContext.waitUntil.bind(runtimeContext) } : {}),
429
+ ...executeLimits(opts.config),
430
+ readOnly,
431
+ native: native !== undefined,
432
+ });
433
+ }
434
+ if (native && nativeRoute && hint) {
435
+ yield* upwardStep(authInvoke(new NativeSurface(registry, {
436
+ baseUrl,
437
+ executeCode: native.executeCode,
438
+ route: nativeRoute,
439
+ bind: (context) => authElicitation.bind(context),
440
+ catalogErrors: diagnostics.catalogErrors,
441
+ logger: opts.config.logger,
442
+ requestScope,
443
+ requestSignal,
444
+ probeTimeoutMs: opts.config.discovery.probeTimeoutMs,
445
+ discoveryConcurrency: opts.config.discovery.concurrency,
446
+ readOnly,
447
+ ...(runtimeContext?.waitUntil ? { defer: runtimeContext.waitUntil.bind(runtimeContext) } : {}),
448
+ }), "register", [server, hint]));
449
+ }
413
450
  return server;
414
- };
415
- const exchange = async () => {
451
+ }));
452
+ const exchange = authFlow(function* () {
416
453
  // The v2 entry's built-in legacy fallback streams 2025 results as SSE.
417
454
  // Connecta's established wire contract is JSON, so retain the documented
418
455
  // user-land legacy branch with the same transport setting while the modern
419
456
  // branch uses the fetch-native handler.
420
- if (!(await isLegacyRequest(request, undefined, SDK_BODY_BOUND))) {
421
- const response = await createMcpHandler(createServer, {
457
+ if (!(yield* upwardStep(authCall(isLegacyRequest, [request, undefined, SDK_BODY_BOUND])))) {
458
+ const response = yield* upwardStep(authInvoke(createMcpHandler(authMethod(() => authFlow(function* () {
459
+ const hint = native
460
+ ? yield* upwardStep(authCall(nativeRequestHint, [request, true]))
461
+ : undefined;
462
+ return yield* upwardStep(authCall(createServer, [hint]));
463
+ })), {
422
464
  ...SDK_BODY_BOUND,
423
465
  legacy: "reject",
424
466
  // Keep the SDK's validation and prevent it from opening an SSE stream.
425
467
  // Its capacity error below becomes our permanent unsupported method.
426
468
  maxSubscriptions: 0,
427
469
  onerror: (error) => logFailure(opts.config.logger, "MCP handler error", failureRecord({}, error), "error"),
428
- }).fetch(request);
470
+ }), "fetch", [request]));
429
471
  if (request.headers.get("Mcp-Method") === "subscriptions/listen" && response.status === 200) {
430
- const body = await response.clone().json();
472
+ const body = yield* upwardStep(authInvoke(response.clone(), "json", []));
431
473
  if (isJSONRPCErrorResponse(body) &&
432
474
  body.error.code === -32603 &&
433
475
  body.error.message === "Subscription limit reached") {
@@ -441,24 +483,27 @@ function serveMcp(request, requestSignal, requestScope, opts, baseUrl, actor, re
441
483
  return response;
442
484
  }
443
485
  // Fresh server + transport per legacy request, stateless and JSON-shaped.
444
- const server = createServer();
486
+ const hint = native
487
+ ? yield* upwardStep(authCall(nativeRequestHint, [request, false]))
488
+ : undefined;
489
+ const server = yield* upwardStep(authCall(createServer, [hint]));
445
490
  const transport = new WebStandardStreamableHTTPServerTransport({
446
491
  ...SDK_BODY_BOUND,
447
492
  enableJsonResponse: true,
448
493
  });
449
- await server.connect(transport);
450
- return transport.handleRequest(request);
451
- };
494
+ yield* upwardStep(authInvoke(server, "connect", [transport]));
495
+ return yield* upwardStep(authInvoke(transport, "handleRequest", [request]));
496
+ });
452
497
  return Effect.addFinalizer(() => Effect.sync(() => {
453
498
  for (const server of servers)
454
499
  void server.close().catch(() => { });
455
- })).pipe(Effect.andThen(Effect.promise(async () => {
456
- const response = await exchange();
500
+ })).pipe(Effect.andThen(authFlow(function* () {
501
+ const response = yield* upwardStep(exchange);
457
502
  // Both SDK transports serialize here. This also covers SDK-generated
458
503
  // JSON-RPC errors and allowed HTTP 4xx text, outside tool result shaping.
459
504
  if (!response.body)
460
505
  return response;
461
- const body = await response.text();
506
+ const body = yield* upwardStep(authInvoke(response, "text", []));
462
507
  let text;
463
508
  if (response.headers.get("Content-Type")?.includes("application/json")) {
464
509
  // Structured redaction also joins text blocks before a secret split
@@ -596,6 +641,7 @@ export function createMcpRoute(opts) {
596
641
  let deadlineTimer;
597
642
  return scopedToBody(Effect.gen(function* () {
598
643
  yield* Effect.addFinalizer(() => Effect.sync(() => {
644
+ requestOwner(requestScope).close();
599
645
  if (!localAbort.signal.aborted) {
600
646
  localAbort.abort(request.signal.reason ?? new Error("MCP request ended."));
601
647
  }
@@ -654,9 +700,23 @@ export function createMcpRoute(opts) {
654
700
  // shares it, to save only the lookups an abandoned authorization
655
701
  // finishes on its own.
656
702
  // Agent endpoints consult only the `cta_` adapter; human endpoints refuse `cta_`.
657
- const admit = () => agentEndpoint
658
- ? authorizeAgent(localRequest, baseUrl, opts.config.auth)
659
- : authorize(localRequest, baseUrl, opts.config.auth, runtimeContext);
703
+ const admit = authMethod(() => agentEndpoint
704
+ ? authCall(authorizeAgent, [
705
+ localRequest,
706
+ baseUrl,
707
+ opts.config.auth,
708
+ opts.config.logger,
709
+ runtimeContext?.waitUntil.bind(runtimeContext),
710
+ ])
711
+ : authCall(authorize, [
712
+ localRequest,
713
+ baseUrl,
714
+ opts.config.auth,
715
+ runtimeContext,
716
+ true,
717
+ false,
718
+ opts.config.logger,
719
+ ]));
660
720
  // Plain /mcp admits maintainers and serves the whole catalog; a pool
661
721
  // admits its members, people at /mcp/<pool> and agents at
662
722
  // /agent/<pool>, and serves exactly its tools (INV-4).
@@ -680,7 +740,7 @@ export function createMcpRoute(opts) {
680
740
  : undefined;
681
741
  };
682
742
  const handled = Effect.gen(function* () {
683
- const authz = yield* Effect.promise(admit);
743
+ const authz = yield* authCall(admit, []);
684
744
  if (!authz.ok) {
685
745
  const response = authz.response;
686
746
  // Preserve the auth adapter's challenge and status. The MCP host must
@@ -726,8 +786,15 @@ export function createMcpRoute(opts) {
726
786
  return notFound();
727
787
  }
728
788
  const { access, readOnly, poolOwner } = scope;
729
- if (listenHeader) {
730
- const verdict = yield* Effect.promise(() => classifyListen(localRequest, localAbort.signal));
789
+ // Admission, not completed-call activity. This fact carries no live
790
+ // identity or credential and never changes the admission verdict.
791
+ if (agentEndpoint && authz.identity.agent && opts.config.agents.includes(authz.identity.agent)) {
792
+ yield* observeAgentAdmission(opts.config.storage, authz.identity.agent, new Date().toISOString(), opts.config.discovery.probeTimeoutMs);
793
+ }
794
+ {
795
+ const maxBodyBytes = opts.config.admission.requests.maxBodyBytes;
796
+ const bound = listenHeader ? Math.min(maxBodyBytes, MAX_LISTEN_CLASSIFICATION_BYTES) : maxBodyBytes;
797
+ const verdict = yield* Effect.promise(() => inspectRequestBody(localRequest, localAbort.signal, bound, listenHeader));
731
798
  // The deadline timer aborts a stalled read; its body is already cancelled.
732
799
  if (verdict === "aborted") {
733
800
  return cors(mcpRefusal(sentSecrets, 504, -33003, "MCP request lifetime exceeded."));
@@ -735,7 +802,7 @@ export function createMcpRoute(opts) {
735
802
  if (verdict === "too_large") {
736
803
  return cors(mcpRefusal(sentSecrets, 413, -33006, "MCP request body too large."));
737
804
  }
738
- if (verdict === "other") {
805
+ if (listenHeader && verdict === "other") {
739
806
  const late = yield* Effect.result(admitted(opts.requestAdmission, request.signal));
740
807
  if (Result.isFailure(late))
741
808
  return yield* refuseAdmission(late.failure);
@@ -762,13 +829,15 @@ export function createMcpRoute(opts) {
762
829
  ...(authz.principalKey ? { principalKey: authz.principalKey } : {}),
763
830
  endpoint: new URL(request.url).pathname,
764
831
  origin: request.headers.get("Origin"),
765
- currentResultAccess: async (address, classification, signal, access) => {
832
+ currentResultAccess: authMethod((dependencies, classification, signal) => authFlow(function* () {
766
833
  signal?.throwIfAborted();
767
- const current = await admit();
834
+ const current = yield* upwardStep(authCall(admit, []));
768
835
  if (!current.ok) {
769
- await current.response.body?.cancel().catch(() => { });
836
+ yield* upwardStep(authCall(() => current.response.body?.cancel().catch(() => { }), []));
837
+ signal?.throwIfAborted();
770
838
  return false;
771
839
  }
840
+ signal?.throwIfAborted();
772
841
  if (current.subjectKey !== authz.subjectKey || current.principalKey !== authz.principalKey)
773
842
  return false;
774
843
  // Paging re-admits the caller at this endpoint, as a new request would.
@@ -784,27 +853,49 @@ export function createMcpRoute(opts) {
784
853
  });
785
854
  if (classification === "write" && currentReadOnly)
786
855
  return false;
787
- if (address === undefined)
788
- return true;
789
- // Skill and resource content requires a whole grant; catalog metadata requires visibility.
790
- if (!address.includes("."))
791
- return Boolean(access === "catalog" ? view.getConnector(address) : view.getResourceConnector(address));
792
- const resolved = view.resolveAddress(address);
793
- if (!resolved)
794
- return false;
856
+ // Both admission and catalogs belong to this pass only. A second
857
+ // pass after reading the page must observe revocation afresh.
795
858
  const requestScope = {};
859
+ const catalogs = new Map();
796
860
  try {
797
- const tool = (await view.getTools(resolved.connector.id, baseUrl, requestScope, signal ? { signal } : {})).find((tool) => tool.name === resolved.toolName);
798
- signal?.throwIfAborted();
799
- return Boolean(tool &&
800
- (access === "catalog" ||
801
- (classification === "read" && tool.classification === "read") ||
802
- !currentReadOnly));
861
+ for (const dependency of dependencies) {
862
+ signal?.throwIfAborted();
863
+ if (dependency.classification === "write" && currentReadOnly)
864
+ return false;
865
+ // Skill and resource content requires a whole grant; catalog metadata requires visibility.
866
+ if (dependency.tool === undefined) {
867
+ if (!(dependency.access === "catalog"
868
+ ? view.getConnector(dependency.connector)
869
+ : view.getResourceConnector(dependency.connector)))
870
+ return false;
871
+ continue;
872
+ }
873
+ const resolved = view.resolveAddress(`${dependency.connector}.${dependency.tool}`);
874
+ if (!resolved)
875
+ return false;
876
+ let catalog = catalogs.get(resolved.connector.id);
877
+ if (!catalog) {
878
+ // Track even a failed load so its scope is always closed.
879
+ catalog = { connector: resolved.connector, tools: [] };
880
+ catalogs.set(resolved.connector.id, catalog);
881
+ catalog.tools = yield* upwardStep(registryProgram(view, "getTools", resolved.connector.id, baseUrl, requestScope, signal ? { signal } : {}));
882
+ }
883
+ signal?.throwIfAborted();
884
+ const tool = catalog.tools.find((tool) => tool.name === resolved.toolName);
885
+ if (!(tool &&
886
+ (dependency.access === "catalog" ||
887
+ (dependency.classification === "read" && tool.classification === "read") ||
888
+ !currentReadOnly)))
889
+ return false;
890
+ }
891
+ return true;
803
892
  }
804
893
  finally {
805
- await closeConnectorScope(resolved.connector, view.contextFor(resolved.connector.id, baseUrl, requestScope), runtimeContext?.waitUntil?.bind(runtimeContext));
894
+ for (const [id, { connector }] of catalogs) {
895
+ yield* upwardStep(closeScope(connector, view.contextFor(id, baseUrl, requestScope), runtimeContext?.waitUntil?.bind(runtimeContext)));
896
+ }
806
897
  }
807
- },
898
+ })),
808
899
  caller: callerFor(authz.identity, poolOwner),
809
900
  });
810
901
  }
@@ -833,7 +924,7 @@ export function createMcpRoute(opts) {
833
924
  return Option.isSome(bounded)
834
925
  ? bounded.value
835
926
  : cors(mcpRefusal(sentSecrets, 504, -33003, "MCP request lifetime exceeded."));
836
- }), localAbort.signal);
927
+ }).pipe(Effect.provideService(RequestScope, requestOwner(requestScope))), localAbort.signal);
837
928
  }
838
929
  return { handle: routeMcp, rejectOrigin };
839
930
  }
@@ -167,8 +167,10 @@ async function finishOAuthCallback(context) {
167
167
  }
168
168
  try {
169
169
  const expectedPrincipalKey = callbackTarget?.principalKey;
170
- const browserIdentity = await authorizeUiIdentity(context.request, baseUrl, opts.config.auth, "OAuth callback", context.runtimeContext);
170
+ const browserIdentity = await authorizeUiIdentity(context.request, baseUrl, opts.config.auth, "OAuth callback", context.runtimeContext, opts.config.logger);
171
171
  if (!browserIdentity.ok) {
172
+ if (browserIdentity.response.status === 503)
173
+ return browserIdentity.response;
172
174
  if (browserIdentity.response.status === 401 && authorizationCredential(context.request).kind !== "absent")
173
175
  return browserIdentity.response;
174
176
  // A Clerk browser handshake refreshes its session and returns to this
@@ -41,11 +41,11 @@ function admitted(result) {
41
41
  }
42
42
  /** Any configured caller. The gate's refusal, challenge headers and all, is the answer. */
43
43
  export function authorized({ request, baseUrl, opts, runtimeContext }, partitionIdentity = true) {
44
- return Effect.suspend(() => admitted(authorize(request, baseUrl, opts.config.auth, runtimeContext, partitionIdentity)));
44
+ return Effect.suspend(() => admitted(authorize(request, baseUrl, opts.config.auth, runtimeContext, partitionIdentity, false, opts.config.logger)));
45
45
  }
46
46
  /** A signed-in person, for a route that changes how a connector authenticates. */
47
47
  export function authorizedPerson({ request, baseUrl, opts, runtimeContext }, purpose) {
48
- return Effect.suspend(() => admitted(authorizeUiIdentity(request, baseUrl, opts.config.auth, purpose, runtimeContext)));
48
+ return Effect.suspend(() => admitted(authorizeUiIdentity(request, baseUrl, opts.config.auth, purpose, runtimeContext, opts.config.logger)));
49
49
  }
50
50
  /** The partition an identity carries into a registry view of the given connectors. */
51
51
  export function scopeFor(authz, connectorIds = "all") {
@@ -4,6 +4,7 @@ import type { AdmissionController } from "../executor-admission.js";
4
4
  import type { Registry } from "../registry.js";
5
5
  import { type ResolvedPool } from "../membership.js";
6
6
  import type { AuthenticatedIdentity, Executor, IdentityReference, InboundAuth, InboundAuthRuntimeContext } from "../types.js";
7
+ import type { Logger } from "../types.js";
7
8
  import type { ResolvedConfig } from "../config.js";
8
9
  export { msg } from "../errors.js";
9
10
  export interface ServerOptions {
@@ -65,7 +66,7 @@ export declare function authMetadata(request: Request, baseUrl: string, auth: re
65
66
  provider: InboundAuth;
66
67
  response: Response;
67
68
  } | null>;
68
- export declare function authorize(request: Request, baseUrl: string, auth: readonly InboundAuth[], runtimeContext?: RuntimeExecutionContext, partitionIdentity?: boolean, interactiveOnly?: boolean): Promise<{
69
+ export declare function authorize(request: Request, baseUrl: string, auth: readonly InboundAuth[], runtimeContext?: RuntimeExecutionContext, partitionIdentity?: boolean, interactiveOnly?: boolean, logger?: Logger): Promise<{
69
70
  ok: true;
70
71
  actor: ActivityActor;
71
72
  identity: AuthenticatedIdentity;
@@ -78,14 +79,14 @@ export declare function authorize(request: Request, baseUrl: string, auth: reado
78
79
  }>;
79
80
  /**
80
81
  * Admission at an agent endpoint, `/agent/<pool>` (#837). Only the built-in
81
- * `cta_` adapter is consulted: Clerk and Access never run, cookies and Clerk
82
+ * agent credential adapters are consulted: Clerk and Access never run, cookies and Clerk
82
83
  * handshake parameters are stripped, and the runtime context, which carries
83
84
  * Access's `ctx.access` even on a bypassed path, is never passed. Anything but
84
85
  * an admitted declared agent gets the machine-only challenge.
85
86
  */
86
- export declare function authorizeAgent(request: Request, baseUrl: string, auth: readonly InboundAuth[]): Promise<Awaited<ReturnType<typeof authorize>>>;
87
+ export declare function authorizeAgent(request: Request, baseUrl: string, auth: readonly InboundAuth[], logger?: Logger, settle?: (pending: Promise<unknown>) => void): Promise<Awaited<ReturnType<typeof authorize>>>;
87
88
  /** Human routes reject machine credentials before any verification or storage I/O. */
88
- export declare function authorizeUiIdentity(request: Request, baseUrl: string, auth: readonly InboundAuth[], purpose: string, runtimeContext?: RuntimeExecutionContext): Promise<Awaited<ReturnType<typeof authorize>>>;
89
+ export declare function authorizeUiIdentity(request: Request, baseUrl: string, auth: readonly InboundAuth[], purpose: string, runtimeContext?: RuntimeExecutionContext, logger?: Logger): Promise<Awaited<ReturnType<typeof authorize>>>;
89
90
  export declare function isSameOrigin(request: Request, baseUrl: string): boolean;
90
91
  export declare function withSecurityHeaders(response: Response, requestUrl: URL, _path: string): Response;
91
92
  type AuthorizedIdentity = Extract<Awaited<ReturnType<typeof authorize>>, {