gemi 0.113.0 → 0.115.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 (238) hide show
  1. package/dist/ai/index.js +32 -32
  2. package/dist/ai/index.js.map +3 -5
  3. package/dist/app/App.d.ts.map +1 -1
  4. package/dist/app/index.js +1 -1
  5. package/dist/bin/gemi.js +8 -1
  6. package/dist/bin/gemi.js.map +3 -3
  7. package/dist/bun/plugin.js +1 -1
  8. package/dist/bun/preload.js +1 -1
  9. package/dist/{chunk-1p85fdrk.js → chunk-0av6xvm6.js} +2 -2
  10. package/dist/{chunk-1p85fdrk.js.map → chunk-0av6xvm6.js.map} +1 -1
  11. package/dist/chunk-0z8ejxre.js +5 -0
  12. package/dist/chunk-0z8ejxre.js.map +12 -0
  13. package/dist/{chunk-r7b12dmm.js → chunk-15c2vgaf.js} +2 -2
  14. package/dist/{chunk-r7b12dmm.js.map → chunk-15c2vgaf.js.map} +1 -1
  15. package/dist/{chunk-fr0arqdj.js → chunk-1hr4xht1.js} +2 -2
  16. package/dist/{chunk-fr0arqdj.js.map → chunk-1hr4xht1.js.map} +1 -1
  17. package/dist/{chunk-4t1pbt9p.js → chunk-1myhm0g3.js} +3 -3
  18. package/dist/{chunk-4t1pbt9p.js.map → chunk-1myhm0g3.js.map} +1 -1
  19. package/dist/{chunk-v4gwmhtf.js → chunk-1vzks22y.js} +2 -2
  20. package/dist/{chunk-v4gwmhtf.js.map → chunk-1vzks22y.js.map} +1 -1
  21. package/dist/{chunk-vzf5pbx3.js → chunk-2tzm58j3.js} +2 -2
  22. package/dist/{chunk-vzf5pbx3.js.map → chunk-2tzm58j3.js.map} +1 -1
  23. package/dist/{chunk-qx87cdfg.js → chunk-2z1981d0.js} +2 -2
  24. package/dist/{chunk-qx87cdfg.js.map → chunk-2z1981d0.js.map} +1 -1
  25. package/dist/{chunk-mepaedy5.js → chunk-3hrj5rwm.js} +2 -2
  26. package/dist/{chunk-mepaedy5.js.map → chunk-3hrj5rwm.js.map} +1 -1
  27. package/dist/{chunk-rh2fad7n.js → chunk-41da9628.js} +1 -1
  28. package/dist/{chunk-5q4a7yqf.js → chunk-56jky6vf.js} +2 -2
  29. package/dist/{chunk-5q4a7yqf.js.map → chunk-56jky6vf.js.map} +1 -1
  30. package/dist/{chunk-5x0aacrn.js → chunk-785b41h1.js} +2 -2
  31. package/dist/{chunk-5x0aacrn.js.map → chunk-785b41h1.js.map} +1 -1
  32. package/dist/{chunk-nysqgzp1.js → chunk-7g9yh5ae.js} +2 -2
  33. package/dist/{chunk-nysqgzp1.js.map → chunk-7g9yh5ae.js.map} +1 -1
  34. package/dist/{chunk-g8kx549d.js → chunk-7vb4eey2.js} +3 -3
  35. package/dist/{chunk-g8kx549d.js.map → chunk-7vb4eey2.js.map} +1 -1
  36. package/dist/{chunk-szr1k584.js → chunk-8rv62v14.js} +2 -2
  37. package/dist/{chunk-szr1k584.js.map → chunk-8rv62v14.js.map} +1 -1
  38. package/dist/{chunk-68s1f5d5.js → chunk-98m15b9x.js} +2 -2
  39. package/dist/{chunk-68s1f5d5.js.map → chunk-98m15b9x.js.map} +1 -1
  40. package/dist/{chunk-y596ghpz.js → chunk-9b4erdy2.js} +2 -2
  41. package/dist/{chunk-y596ghpz.js.map → chunk-9b4erdy2.js.map} +1 -1
  42. package/dist/{chunk-rg4hhxj3.js → chunk-9n1hx3mq.js} +2 -2
  43. package/dist/{chunk-rg4hhxj3.js.map → chunk-9n1hx3mq.js.map} +1 -1
  44. package/dist/{chunk-9tpx9ag3.js → chunk-aazmrxj9.js} +2 -2
  45. package/dist/{chunk-9tpx9ag3.js.map → chunk-aazmrxj9.js.map} +1 -1
  46. package/dist/{chunk-01qd6xx3.js → chunk-aeh67ynz.js} +3 -3
  47. package/dist/{chunk-01qd6xx3.js.map → chunk-aeh67ynz.js.map} +1 -1
  48. package/dist/{chunk-5nqkwa2w.js → chunk-agyfv3f8.js} +1 -1
  49. package/dist/{chunk-sr18y2ck.js → chunk-bra1a1fq.js} +2 -2
  50. package/dist/{chunk-sr18y2ck.js.map → chunk-bra1a1fq.js.map} +1 -1
  51. package/dist/{chunk-y6v0x869.js → chunk-cbqazg9k.js} +2 -2
  52. package/dist/{chunk-y6v0x869.js.map → chunk-cbqazg9k.js.map} +1 -1
  53. package/dist/{chunk-k2fh4r0p.js → chunk-d2gfcf85.js} +2 -2
  54. package/dist/{chunk-k2fh4r0p.js.map → chunk-d2gfcf85.js.map} +1 -1
  55. package/dist/chunk-d6591xck.js +46 -0
  56. package/dist/{chunk-6g20zec2.js.map → chunk-d6591xck.js.map} +6 -6
  57. package/dist/{chunk-fnkjmq94.js → chunk-d9mar37g.js} +2 -2
  58. package/dist/{chunk-fnkjmq94.js.map → chunk-d9mar37g.js.map} +1 -1
  59. package/dist/chunk-dexdkh3z.js +14 -0
  60. package/dist/{chunk-cqnfp0n9.js.map → chunk-dexdkh3z.js.map} +7 -7
  61. package/dist/{chunk-bq5nqqeq.js → chunk-e573yxpq.js} +1 -1
  62. package/dist/{chunk-p3zmc8k8.js → chunk-eqse2m6n.js} +2 -2
  63. package/dist/{chunk-p3zmc8k8.js.map → chunk-eqse2m6n.js.map} +1 -1
  64. package/dist/{chunk-yyzexrnb.js → chunk-er3wf6ng.js} +2 -2
  65. package/dist/{chunk-yyzexrnb.js.map → chunk-er3wf6ng.js.map} +1 -1
  66. package/dist/{chunk-3f1kq32g.js → chunk-fre6f4nk.js} +2 -2
  67. package/dist/{chunk-3f1kq32g.js.map → chunk-fre6f4nk.js.map} +1 -1
  68. package/dist/{chunk-qt8nvpqp.js → chunk-fxgxf16k.js} +2 -2
  69. package/dist/{chunk-qt8nvpqp.js.map → chunk-fxgxf16k.js.map} +1 -1
  70. package/dist/{chunk-6wymbbes.js → chunk-gts5p6mw.js} +3 -3
  71. package/dist/{chunk-6wymbbes.js.map → chunk-gts5p6mw.js.map} +1 -1
  72. package/dist/{chunk-571rvxe6.js → chunk-hdps9n52.js} +2 -2
  73. package/dist/{chunk-571rvxe6.js.map → chunk-hdps9n52.js.map} +1 -1
  74. package/dist/{chunk-w45agtch.js → chunk-hytt9qyj.js} +2 -2
  75. package/dist/{chunk-w45agtch.js.map → chunk-hytt9qyj.js.map} +1 -1
  76. package/dist/{chunk-de03dewf.js → chunk-jafm3613.js} +2 -2
  77. package/dist/{chunk-de03dewf.js.map → chunk-jafm3613.js.map} +1 -1
  78. package/dist/{chunk-dbwhgyg3.js → chunk-jdhdrr2k.js} +2 -2
  79. package/dist/{chunk-dbwhgyg3.js.map → chunk-jdhdrr2k.js.map} +1 -1
  80. package/dist/{chunk-d04r0hdf.js → chunk-jmpw6bqz.js} +2 -2
  81. package/dist/{chunk-d04r0hdf.js.map → chunk-jmpw6bqz.js.map} +1 -1
  82. package/dist/{chunk-vwprq300.js → chunk-kejwjerj.js} +2 -2
  83. package/dist/{chunk-vwprq300.js.map → chunk-kejwjerj.js.map} +1 -1
  84. package/dist/{chunk-wr3e4sez.js → chunk-kqxdsv22.js} +2 -2
  85. package/dist/{chunk-wr3e4sez.js.map → chunk-kqxdsv22.js.map} +1 -1
  86. package/dist/{chunk-9vsj0ksk.js → chunk-ktr3k768.js} +3 -3
  87. package/dist/{chunk-9vsj0ksk.js.map → chunk-ktr3k768.js.map} +1 -1
  88. package/dist/{chunk-kz4yp5n7.js → chunk-m54s6jpr.js} +2 -2
  89. package/dist/{chunk-8mbyyh8j.js.map → chunk-m54s6jpr.js.map} +1 -1
  90. package/dist/{chunk-xqwdn9kb.js → chunk-mazznq15.js} +3 -3
  91. package/dist/{chunk-xqwdn9kb.js.map → chunk-mazznq15.js.map} +1 -1
  92. package/dist/{chunk-zng3qexn.js → chunk-mps6ynbh.js} +2 -2
  93. package/dist/{chunk-zng3qexn.js.map → chunk-mps6ynbh.js.map} +1 -1
  94. package/dist/{chunk-vdwagp7y.js → chunk-mqfzdfnz.js} +2 -2
  95. package/dist/{chunk-vdwagp7y.js.map → chunk-mqfzdfnz.js.map} +1 -1
  96. package/dist/{chunk-mk0rtgd1.js → chunk-mschc94q.js} +2 -2
  97. package/dist/{chunk-mk0rtgd1.js.map → chunk-mschc94q.js.map} +1 -1
  98. package/dist/{chunk-x5yq097b.js → chunk-mtbygktb.js} +3 -3
  99. package/dist/{chunk-x5yq097b.js.map → chunk-mtbygktb.js.map} +1 -1
  100. package/dist/{chunk-f1y8eggf.js → chunk-n672d4g8.js} +2 -2
  101. package/dist/{chunk-f1y8eggf.js.map → chunk-n672d4g8.js.map} +1 -1
  102. package/dist/{chunk-4tp2cr02.js → chunk-pyk3gzvc.js} +2 -2
  103. package/dist/{chunk-4tp2cr02.js.map → chunk-pyk3gzvc.js.map} +1 -1
  104. package/dist/{chunk-agw3anaf.js → chunk-qjhw8nje.js} +1 -1
  105. package/dist/{chunk-vqa3agzw.js → chunk-qsrcdzan.js} +3 -3
  106. package/dist/{chunk-vqa3agzw.js.map → chunk-qsrcdzan.js.map} +1 -1
  107. package/dist/{chunk-nksn6xcd.js → chunk-sr942vb1.js} +2 -2
  108. package/dist/{chunk-nksn6xcd.js.map → chunk-sr942vb1.js.map} +1 -1
  109. package/dist/{chunk-kexsfyjj.js → chunk-t04f3akb.js} +2 -2
  110. package/dist/{chunk-kexsfyjj.js.map → chunk-t04f3akb.js.map} +1 -1
  111. package/dist/chunk-t24p7gc6.js +5 -0
  112. package/dist/{chunk-fsfbyg5e.js.map → chunk-t24p7gc6.js.map} +1 -1
  113. package/dist/chunk-t4t3hqe0.js +10 -0
  114. package/dist/chunk-t4t3hqe0.js.map +38 -0
  115. package/dist/{chunk-z5hrymvn.js → chunk-t4yh4nf9.js} +3 -3
  116. package/dist/{chunk-z5hrymvn.js.map → chunk-t4yh4nf9.js.map} +1 -1
  117. package/dist/{chunk-c7mp2kyp.js → chunk-tn2bryy2.js} +2 -2
  118. package/dist/{chunk-c7mp2kyp.js.map → chunk-tn2bryy2.js.map} +1 -1
  119. package/dist/chunk-tw5kwbx4.js +4 -0
  120. package/dist/{chunk-kp7k4s5c.js.map → chunk-tw5kwbx4.js.map} +3 -3
  121. package/dist/{chunk-zyer1g7k.js → chunk-tzm3c7n6.js} +4 -4
  122. package/dist/{chunk-zyer1g7k.js.map → chunk-tzm3c7n6.js.map} +1 -1
  123. package/dist/{chunk-1se4t9rg.js → chunk-vbdty91k.js} +3 -3
  124. package/dist/{chunk-1se4t9rg.js.map → chunk-vbdty91k.js.map} +1 -1
  125. package/dist/{chunk-8mbyyh8j.js → chunk-vw8849ys.js} +2 -2
  126. package/dist/{chunk-kz4yp5n7.js.map → chunk-vw8849ys.js.map} +1 -1
  127. package/dist/{chunk-g8sc6scv.js → chunk-vxm6yevm.js} +2 -2
  128. package/dist/{chunk-g8sc6scv.js.map → chunk-vxm6yevm.js.map} +1 -1
  129. package/dist/{chunk-qpttgn4k.js → chunk-whtzggn6.js} +3 -3
  130. package/dist/{chunk-qpttgn4k.js.map → chunk-whtzggn6.js.map} +1 -1
  131. package/dist/{chunk-7jnpnjth.js → chunk-wyw6p3fg.js} +2 -2
  132. package/dist/{chunk-7jnpnjth.js.map → chunk-wyw6p3fg.js.map} +1 -1
  133. package/dist/{chunk-atmzm0z3.js → chunk-wzrt5mac.js} +2 -2
  134. package/dist/{chunk-atmzm0z3.js.map → chunk-wzrt5mac.js.map} +1 -1
  135. package/dist/{chunk-y6frz1vm.js → chunk-x7cpth2f.js} +1 -1
  136. package/dist/{chunk-essqp1ek.js → chunk-xt9tv99x.js} +2 -2
  137. package/dist/{chunk-essqp1ek.js.map → chunk-xt9tv99x.js.map} +1 -1
  138. package/dist/{chunk-x5sert1k.js → chunk-yhrye9cm.js} +2 -2
  139. package/dist/{chunk-x5sert1k.js.map → chunk-yhrye9cm.js.map} +1 -1
  140. package/dist/{chunk-vc9phr57.js → chunk-zyt2w03d.js} +2 -2
  141. package/dist/{chunk-vc9phr57.js.map → chunk-zyt2w03d.js.map} +1 -1
  142. package/dist/config/index.js +1 -1
  143. package/dist/console/run.js +2 -2
  144. package/dist/console/run.js.map +1 -1
  145. package/dist/container/index.js +2 -2
  146. package/dist/container/index.js.map +1 -1
  147. package/dist/database/index.js +2 -2
  148. package/dist/database/index.js.map +1 -1
  149. package/dist/email/index.js +2 -2
  150. package/dist/email/index.js.map +1 -1
  151. package/dist/facades/Storage.d.ts +25 -1
  152. package/dist/facades/Storage.d.ts.map +1 -1
  153. package/dist/facades/index.js +2 -2
  154. package/dist/facades/index.js.map +1 -1
  155. package/dist/foundation/index.js +2 -2
  156. package/dist/foundation/index.js.map +1 -1
  157. package/dist/http/HttpRequest.d.ts +31 -0
  158. package/dist/http/HttpRequest.d.ts.map +1 -1
  159. package/dist/http/McpRouter.d.ts +54 -1
  160. package/dist/http/McpRouter.d.ts.map +1 -1
  161. package/dist/http/RateLimitMiddleware.d.ts +4 -1
  162. package/dist/http/RateLimitMiddleware.d.ts.map +1 -1
  163. package/dist/http/index.d.ts +1 -0
  164. package/dist/http/index.d.ts.map +1 -1
  165. package/dist/http/index.js +2 -2
  166. package/dist/http/index.js.map +1 -1
  167. package/dist/http/modelOriginated.d.ts +36 -2
  168. package/dist/http/modelOriginated.d.ts.map +1 -1
  169. package/dist/i18n/dictionaryRuntime.js +2 -2
  170. package/dist/i18n/dictionaryRuntime.js.map +1 -1
  171. package/dist/i18n/index.js +2 -2
  172. package/dist/i18n/index.js.map +1 -1
  173. package/dist/kernel/Kernel.d.ts +3 -0
  174. package/dist/kernel/Kernel.d.ts.map +1 -1
  175. package/dist/kernel/index.js +3 -3
  176. package/dist/kernel/index.js.map +3 -3
  177. package/dist/orm/index.js +2 -2
  178. package/dist/orm/index.js.map +1 -1
  179. package/dist/server/index.js +2 -2
  180. package/dist/server/index.js.map +1 -1
  181. package/dist/services/file-storage/drivers/AzureBlobDriver.d.ts +12 -1
  182. package/dist/services/file-storage/drivers/AzureBlobDriver.d.ts.map +1 -1
  183. package/dist/services/file-storage/drivers/FileStorageDriver.d.ts +32 -1
  184. package/dist/services/file-storage/drivers/FileStorageDriver.d.ts.map +1 -1
  185. package/dist/services/file-storage/drivers/FileSystemDriver.d.ts +22 -1
  186. package/dist/services/file-storage/drivers/FileSystemDriver.d.ts.map +1 -1
  187. package/dist/services/file-storage/drivers/S3Driver.d.ts +14 -1
  188. package/dist/services/file-storage/drivers/S3Driver.d.ts.map +1 -1
  189. package/dist/services/file-storage/drivers/types.d.ts +26 -0
  190. package/dist/services/file-storage/drivers/types.d.ts.map +1 -1
  191. package/dist/services/index.d.ts +8 -3
  192. package/dist/services/index.d.ts.map +1 -1
  193. package/dist/services/index.js +44 -9
  194. package/dist/services/index.js.map +8 -5
  195. package/dist/services/mcp/McpRegistry.d.ts +190 -29
  196. package/dist/services/mcp/McpRegistry.d.ts.map +1 -1
  197. package/dist/services/mcp/http/McpHttpServer.d.ts +153 -0
  198. package/dist/services/mcp/http/McpHttpServer.d.ts.map +1 -0
  199. package/dist/services/mcp/http/callers.d.ts +131 -0
  200. package/dist/services/mcp/http/callers.d.ts.map +1 -0
  201. package/dist/services/mcp/http/limits.d.ts +11 -0
  202. package/dist/services/mcp/http/limits.d.ts.map +1 -0
  203. package/dist/services/mcp/http/oauth/McpOAuthServer.d.ts +150 -0
  204. package/dist/services/mcp/http/oauth/McpOAuthServer.d.ts.map +1 -0
  205. package/dist/services/mcp/http/oauth/consentPage.d.ts +14 -0
  206. package/dist/services/mcp/http/oauth/consentPage.d.ts.map +1 -0
  207. package/dist/services/mcp/http/oauth/store.d.ts +98 -0
  208. package/dist/services/mcp/http/oauth/store.d.ts.map +1 -0
  209. package/dist/services/mcp/http/protocol.d.ts +95 -0
  210. package/dist/services/mcp/http/protocol.d.ts.map +1 -0
  211. package/dist/services/mcp/http/signedState.d.ts +25 -0
  212. package/dist/services/mcp/http/signedState.d.ts.map +1 -0
  213. package/dist/services/queue/work.js +2 -2
  214. package/dist/services/queue/work.js.map +1 -1
  215. package/dist/services/router/ApiRouteDispatcher.d.ts +29 -0
  216. package/dist/services/router/ApiRouteDispatcher.d.ts.map +1 -1
  217. package/dist/services/router/RouteServiceProvider.d.ts +6 -0
  218. package/dist/services/router/RouteServiceProvider.d.ts.map +1 -1
  219. package/dist/services/router/config.d.ts +16 -0
  220. package/dist/services/router/config.d.ts.map +1 -1
  221. package/dist/stats/route-table.js +1 -1
  222. package/dist/support/index.js +2 -2
  223. package/dist/support/index.js.map +1 -1
  224. package/dist/vitest/index.js +1 -1
  225. package/package.json +1 -1
  226. package/dist/chunk-3z9vhjd7.js +0 -5
  227. package/dist/chunk-3z9vhjd7.js.map +0 -10
  228. package/dist/chunk-5zzhypmt.js +0 -5
  229. package/dist/chunk-5zzhypmt.js.map +0 -33
  230. package/dist/chunk-6g20zec2.js +0 -46
  231. package/dist/chunk-cqnfp0n9.js +0 -14
  232. package/dist/chunk-fsfbyg5e.js +0 -5
  233. package/dist/chunk-kp7k4s5c.js +0 -4
  234. /package/dist/{chunk-rh2fad7n.js.map → chunk-41da9628.js.map} +0 -0
  235. /package/dist/{chunk-5nqkwa2w.js.map → chunk-agyfv3f8.js.map} +0 -0
  236. /package/dist/{chunk-bq5nqqeq.js.map → chunk-e573yxpq.js.map} +0 -0
  237. /package/dist/{chunk-agw3anaf.js.map → chunk-qjhw8nje.js.map} +0 -0
  238. /package/dist/{chunk-y6frz1vm.js.map → chunk-x7cpth2f.js.map} +0 -0
@@ -1,4 +1,7 @@
1
1
  import type { ToolContext } from "../../ai/Agent";
2
+ import type { User } from "../../auth/types";
3
+ import type { ProgressSink } from "../../http/modelOriginated";
4
+ import { type SafeFetchOptions } from "../../http/safeFetch";
2
5
  import { ToolError } from "../../ai/redact";
3
6
  import { type AnySchema, type Schema } from "../../ai/Schema";
4
7
  import type { RouteSource } from "../../http/ApiRouter";
@@ -17,25 +20,103 @@ import type { ApiRouteDispatcher, DispatchCredentials } from "../router/ApiRoute
17
20
  * That producer *does* read ambient state, since a run no longer carries a
18
21
  * request (see `AgentContext`), and the boundary is what keeps that from
19
22
  * mattering here: the registry is handed a caller and dispatches as that
20
- * caller, so a second producer — a job, a test, v2's remote client — supplies
21
- * one however it likes, and a run with no ambient request is refused by
22
- * `toAgentTools` before the registry is reached rather than dispatching as
23
+ * caller, so a second producer — a job, a test, the remote transport —
24
+ * supplies one however it likes, and a run with no ambient request is refused
25
+ * by `toAgentTools` before the registry is reached rather than dispatching as
23
26
  * nobody.
24
27
  * The call is dispatched with that request's credentials, so it runs as that
25
28
  * user, through that route's middleware.
26
29
  *
27
- * `remote` is v2's MCP client with a bearer token. It is typed so the seam
28
- * exists and every entry point already takes it; each of them refuses it,
29
- * because a token resolver is what makes it safe and there is none yet.
30
- * Reading the caller from `RequestContext` instead would have been shorter,
31
- * and would have left v2 a registry that only works inside a gemi request.
30
+ * `remote` is an MCP client over HTTP (#762). `req` is its request to the MCP
31
+ * endpoint, and `principal` is what a caller resolver made of the credential
32
+ * it carried — an OAuth access token or an app API key — after verifying it.
33
+ * Nothing of the request's own credentials is forwarded: the call is
34
+ * dispatched as `principal.user`, set on the route's request context before
35
+ * its middleware runs, so `auth`, policies and the route's own checks decide
36
+ * exactly as they would for that user's direct request. See
37
+ * `ApiRouteDispatcher.dispatchAs`'s `identity`.
32
38
  */
33
39
  export type McpCaller = {
34
40
  kind: "local";
35
41
  req: HttpRequest<any, any>;
36
42
  } | {
37
43
  kind: "remote";
38
- token: string;
44
+ req: HttpRequest<any, any>;
45
+ principal: McpRemotePrincipal;
46
+ };
47
+ /**
48
+ * A remote caller, as a resolver verified it.
49
+ *
50
+ * Built only by a resolver, from a credential it checked — never from what a
51
+ * client says about itself.
52
+ */
53
+ export type McpRemotePrincipal = {
54
+ /** The user every call runs as. */
55
+ user: User;
56
+ /** Which resolver vouched for the credential: `"oauth"`, `"api-key"`, or an app's own. */
57
+ via: string;
58
+ /**
59
+ * A stable id for the credential: the OAuth grant, the API key. Not the
60
+ * secret itself. Keys the rate-limit budget the caller's tool calls spend,
61
+ * and is what a log line names.
62
+ */
63
+ id: string;
64
+ /** The scopes the credential carries. Decides which tools the caller sees. */
65
+ scopes: readonly string[];
66
+ /** The OAuth client the token was issued to, when there is one. */
67
+ clientId?: string;
68
+ };
69
+ /**
70
+ * One scope a remote credential can carry, as an `McpRouter` declares it: the
71
+ * tools it reaches, by tag and by name, and the sentence a consent screen
72
+ * shows for it.
73
+ */
74
+ export type McpScope = {
75
+ /** What a user is agreeing to, in their words: "Read and edit your site's pages". */
76
+ description: string;
77
+ /** Every tool carrying one of these tags. */
78
+ tags?: readonly string[];
79
+ /** These tools, by name. */
80
+ names?: readonly string[];
81
+ };
82
+ /**
83
+ * The scope a router without `scopes` gets: every tool it declares. A router
84
+ * that wants a credential to reach only some of them declares its own.
85
+ */
86
+ export declare const DEFAULT_MCP_SCOPE = "mcp";
87
+ /** How a remote caller's file arguments are read. */
88
+ export type McpRemoteFileOptions = {
89
+ /** The largest file accepted, in bytes, decoded. Default 10 MiB. */
90
+ maxBytes?: number;
91
+ /**
92
+ * Lets a remote caller name a file by an `https` URL, fetched through
93
+ * `safeFetch` — public addresses only, no credentials sent, bounded in size
94
+ * and time. Off by default: a URL argument makes the server fetch whatever
95
+ * the model was steered to name. `true` takes `safeFetch`'s defaults; an
96
+ * object is passed to it (`allow` a list of hosts, say), with `maxSize`
97
+ * capped at `maxBytes`.
98
+ */
99
+ fetchUrls?: boolean | SafeFetchOptions;
100
+ };
101
+ /** What `McpRegistry` takes beside the router and the dispatcher. */
102
+ export type McpRegistryOptions = {
103
+ /** Remote callers' file arguments. See `McpRemoteFileOptions`. */
104
+ files?: McpRemoteFileOptions;
105
+ };
106
+ /** What `execute` takes beside the call itself. */
107
+ export type McpExecuteOptions = {
108
+ /**
109
+ * That the user approved this call, for a tool with `requiresApproval`.
110
+ * The remote transport sets it after an elicitation the user accepted; a
111
+ * remote call to such a tool without it is refused, so a transport that
112
+ * forgot to ask fails closed. Local calls are approved by the agent loop
113
+ * before `execute` is reached, and ignore it.
114
+ */
115
+ approved?: boolean;
116
+ /** Aborts the dispatched route: its `req.signal`. The client went away, or cancelled. */
117
+ signal?: AbortSignal;
118
+ /** Receives the route's `req.reportProgress` reports. */
119
+ progress?: ProgressSink;
39
120
  };
40
121
  /**
41
122
  * One tool call, as the app's hooks see it: who is calling, the request their
@@ -43,13 +124,14 @@ export type McpCaller = {
43
124
  * agent run makes — the run's tool context.
44
125
  *
45
126
  * `req` is `caller.req`, repeated so a hook that only wants the request does
46
- * not have to narrow the caller. `ctx` is absent when `McpRegistry.execute` is
47
- * called without one (a test, a script dispatching a tool directly).
127
+ * not have to narrow the caller. For a remote caller it is the request to the
128
+ * MCP endpoint, run inside a request context whose user is
129
+ * `caller.principal.user`, so `req.ctx().user` names the same user for both
130
+ * callers. `ctx` is absent for a remote caller, and when `McpRegistry.execute`
131
+ * is called without one (a test, a script dispatching a tool directly).
48
132
  */
49
133
  export type McpCallContext = {
50
- caller: Extract<McpCaller, {
51
- kind: "local";
52
- }>;
134
+ caller: McpCaller;
53
135
  req: HttpRequest<any, any>;
54
136
  tool: McpToolDescriptor;
55
137
  input: Record<string, unknown>;
@@ -61,18 +143,26 @@ export type McpCallContext = {
61
143
  */
62
144
  export type McpCredentials = DispatchCredentials;
63
145
  /**
64
- * MCP's tool annotations, from the verb. They drive confirmation prompts in
65
- * remote clients, which is why they are set now rather than when v2 lands:
66
- * every app would otherwise have to revisit its MCP file to get them.
146
+ * MCP's tool annotations. They drive confirmation prompts in remote clients,
147
+ * which is why they are set from v1 on rather than when the remote caller
148
+ * lands: every app would otherwise have to revisit its MCP file to get them.
67
149
  *
68
- * Only what the verb says is set. POST and PATCH carry nothing, and MCP's
150
+ * The verb sets the defaults, and only what it says: GET is read-only, DELETE
151
+ * destructive, PUT idempotent. POST and PATCH carry nothing, and MCP's
69
152
  * defaults for an unannotated tool — not read-only, possibly destructive — are
70
- * the honest answer for them.
153
+ * the honest answer for them. A route meta's `annotations` overrides them hint
154
+ * by hint (#760), `false` included.
155
+ *
156
+ * `destructiveHint` and `idempotentHint` only mean something for a tool that
157
+ * is not read-only, so a tool left read-only with either set is refused at
158
+ * boot: one of the two is a mistake, and a client would read the wrong one.
71
159
  */
72
160
  export type McpToolAnnotations = {
73
- readOnlyHint?: true;
74
- destructiveHint?: true;
75
- idempotentHint?: true;
161
+ readOnlyHint?: boolean;
162
+ destructiveHint?: boolean;
163
+ idempotentHint?: boolean;
164
+ /** Whether the tool reaches beyond the app's own data — a third-party API, the web. */
165
+ openWorldHint?: boolean;
76
166
  };
77
167
  /**
78
168
  * One tool, described without committing to who consumes it.
@@ -103,7 +193,9 @@ export interface McpToolDescriptor {
103
193
  * as `outputSchema`.
104
194
  */
105
195
  readonly outputSchema?: AnySchema;
106
- readonly annotations: McpToolAnnotations;
196
+ /** The meta's `title`: a name for a client to show. Absent when it declares none. */
197
+ readonly title?: string;
198
+ readonly annotations: Readonly<McpToolAnnotations>;
107
199
  readonly tags: readonly string[];
108
200
  readonly requiresApproval: boolean;
109
201
  /** The controller method mounted at the route, when there is one (#502). */
@@ -129,6 +221,15 @@ export declare class McpToolError extends ToolError {
129
221
  readonly status?: number;
130
222
  constructor(message: string, status?: number);
131
223
  }
224
+ /**
225
+ * A remote call the transport must not run as asked: a tool the caller cannot
226
+ * see, or one that needs the user's approval and does not have it. Not a
227
+ * `ToolError` — it is the transport's to handle, not the model's to read.
228
+ */
229
+ export declare class McpCallRefusedError extends Error {
230
+ readonly reason: "unknown-tool" | "approval-required";
231
+ constructor(message: string, reason: "unknown-tool" | "approval-required");
232
+ }
132
233
  /**
133
234
  * The tools an app's `McpRouter` declares, resolved against the api route
134
235
  * table, and the one place a call to them is dispatched.
@@ -156,19 +257,44 @@ export declare class McpRegistry<R extends McpRouter<any> = McpRouter<any>> {
156
257
  */
157
258
  readonly __router?: R;
158
259
  private readonly plans;
159
- constructor(router: McpRouter<any>, dispatcher: Pick<ApiRouteDispatcher, "flatRoutes" | "dispatchAs" | "getRouteHandlerAndParams">);
260
+ /** Each scope, resolved to the names of the tools it reaches. */
261
+ private readonly scopeTools;
262
+ private readonly files;
263
+ constructor(router: McpRouter<any>, dispatcher: Pick<ApiRouteDispatcher, "flatRoutes" | "dispatchAs" | "getRouteHandlerAndParams">, options?: McpRegistryOptions);
160
264
  /**
161
- * The tools `caller` may see. v1 has only local callers, and every declared
162
- * tool is visible to every one of them; `filter` is taken now so the shape
163
- * v2's per-token visibility needs is the shape callers already use.
265
+ * The tools `caller` may see, narrowed by `filter`.
266
+ *
267
+ * A local caller sees every declared tool. A remote one sees the tools a
268
+ * scope it carries reaches, as it can call them (see `Plan.remote`): a
269
+ * credential that carries no scope sees nothing, and a tool no scope reaches
270
+ * is never listed remotely. Visibility is checked again by `execute`, so a
271
+ * client naming a tool it was not shown gets what it would for a tool that
272
+ * does not exist.
164
273
  */
165
274
  list(caller: McpCaller, filter?: McpToolFilter): McpToolDescriptor[];
166
275
  /**
167
276
  * The same listing without a caller, for a projection built once before any
168
- * caller exists — `toAgentTools`. It is not per-caller visibility, and a v2
277
+ * caller exists — `toAgentTools`. It is not per-caller visibility, and a
169
278
  * remote listing must go through `list`.
170
279
  */
171
280
  descriptors(filter?: McpToolFilter): McpToolDescriptor[];
281
+ /** The largest file a remote caller may send, in bytes. */
282
+ get maxFileBytes(): number;
283
+ /**
284
+ * The scopes a remote credential can carry, with what each one is for —
285
+ * what a consent screen lists and the authorization server advertises. The
286
+ * router's `scopes`, or `DEFAULT_MCP_SCOPE` reaching every tool when it
287
+ * declares none.
288
+ */
289
+ scopes(): {
290
+ name: string;
291
+ description: string;
292
+ }[];
293
+ /**
294
+ * The scopes that reach the tool `name`: what a client missing all of them
295
+ * has to ask for. Empty for a tool no scope reaches, or none by that name.
296
+ */
297
+ scopesFor(name: string): string[];
172
298
  /**
173
299
  * Calls the tool `name` as `caller`, and answers the route's JSON.
174
300
  *
@@ -183,6 +309,12 @@ export declare class McpRegistry<R extends McpRouter<any> = McpRouter<any>> {
183
309
  * Nothing here reads an attachment any other way — the store has no
184
310
  * unscoped lookup, and this must not become one.
185
311
  *
312
+ * A remote caller has neither a tool context nor attachments. It is held to
313
+ * the tools its scopes reach, and to `requiresApproval` (see
314
+ * `McpExecuteOptions.approved`): either refusal is an
315
+ * `McpCallRefusedError`, for the transport. Its files arrive in the
316
+ * arguments, as base64 or — when the app allows it — an `https` URL.
317
+ *
186
318
  * A 2xx answers its JSON, or its text, cut at `MAX_RESULT_BODY`; a body
187
319
  * that is neither — a file a route serves — is described, not shown. A tool
188
320
  * whose meta has a `result` or an `output` answers its JSON put through
@@ -194,10 +326,39 @@ export declare class McpRegistry<R extends McpRouter<any> = McpRouter<any>> {
194
326
  * message is not something to hand a model that may be steered by whoever
195
327
  * wrote the document it is reading.
196
328
  */
197
- execute(caller: McpCaller, name: string, args: unknown, ctx?: ToolContext): Promise<unknown>;
329
+ execute(caller: McpCaller, name: string, args: unknown, ctx?: ToolContext, options?: McpExecuteOptions): Promise<unknown>;
198
330
  private plan;
331
+ /**
332
+ * What a remote caller sends for a file field: `{ name, mimeType, data }`,
333
+ * or `{ name, mimeType, url }` when the app fetches URLs.
334
+ *
335
+ * Built by hand, as `combineSchemas` is, rather than with `s`: `s` writes
336
+ * the strict structured-output form, where an optional field is a required
337
+ * one that may be `null`, and an MCP client validating its arguments
338
+ * against that would demand `data` and `url` both. Exactly one of the two is
339
+ * checked when the file is read (`remoteFile`), where the refusal can say
340
+ * so.
341
+ */
342
+ private remoteFileSchema;
199
343
  private fillPath;
200
344
  private formData;
345
+ /**
346
+ * A remote caller's file argument, as a `File`: its base64 `data` decoded,
347
+ * or its `url` fetched through `safeFetch` when the app allows that. Every
348
+ * refusal is the model's to read and correct — a file too large, data that
349
+ * is not base64, a URL that is not `https` or not reachable — since it is
350
+ * about what the model sent, not about the server.
351
+ */
352
+ private remoteFile;
353
+ /** Whether a remote principal carries a scope that reaches the tool `name`. */
354
+ private grants;
355
+ /**
356
+ * The router's `scopes`, each resolved to tool names once, at boot. A tag or
357
+ * name no tool has is refused, since it is a typo that would leave a scope
358
+ * reaching less than its description promises; so is a scope that reaches
359
+ * nothing, and a name a scope token cannot be.
360
+ */
361
+ private resolveScopes;
201
362
  /**
202
363
  * A 2xx put through the meta's `result` and `output`, for a tool that has
203
364
  * either.
@@ -1 +1 @@
1
- {"version":3,"file":"McpRegistry.d.ts","sourceRoot":"","sources":["../../../services/mcp/McpRegistry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"McpRegistry.d.ts","sourceRoot":"","sources":["../../../services/mcp/McpRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ import { type NonceStore } from "../../../ai/store/Nonces";
2
+ import { type McpRegistry } from "../McpRegistry";
3
+ import { type McpCallerResolver } from "./callers";
4
+ /**
5
+ * `route.mcp.remote`: the MCP endpoint remote clients connect to (#762).
6
+ */
7
+ export type McpRemoteHttpConfig = {
8
+ /**
9
+ * Off unless `true`. The endpoint is not mounted, and nothing below is
10
+ * read, until an app turns it on.
11
+ */
12
+ enabled?: boolean;
13
+ /**
14
+ * The endpoint's canonical URL, like `"https://example.com/mcp"`: where it
15
+ * is served (its path), which host it answers on, and the OAuth `resource`
16
+ * tokens must be issued for. `https`, or `http` on localhost. Required when
17
+ * `enabled`.
18
+ */
19
+ url?: string;
20
+ /**
21
+ * Who may call: tried in order, and at least one is required — the boot is
22
+ * refused without one, since an endpoint that resolves nobody would be
23
+ * either useless or, worse, open. See `McpCallerResolver`,
24
+ * `McpOAuthServer` and `McpApiKeyResolver`.
25
+ */
26
+ resolvers?: McpCallerResolver[];
27
+ /**
28
+ * Browser origins allowed to call the endpoint, besides its own. A request
29
+ * with any other `Origin` is refused with 403 — what keeps a page the user
30
+ * visits, or a DNS-rebound host, from talking to it. Requests without an
31
+ * `Origin` (every non-browser client) are not affected.
32
+ */
33
+ allowedOrigins?: readonly string[];
34
+ /**
35
+ * Each remote credential's budget at the endpoint, per `window` seconds:
36
+ * every JSON-RPC request counts once. Default 600 per 60 s. `false` turns
37
+ * it off. Tool calls also spend their routes' own `rate-limit` budgets,
38
+ * keyed on the credential.
39
+ */
40
+ rateLimit?: {
41
+ limit: number;
42
+ window: number;
43
+ } | false;
44
+ /** The largest request body accepted, in bytes. Default: room for one file of `files.maxBytes` as base64, plus 1 MiB. */
45
+ maxBodyBytes?: number;
46
+ /** What `initialize` and `server/discover` say about the server. */
47
+ server?: {
48
+ name?: string;
49
+ version?: string;
50
+ instructions?: string;
51
+ };
52
+ /**
53
+ * Where single-use approvals are spent. The default remembers them in
54
+ * this process, which is right for one instance; with several, use a shared
55
+ * store (`RedisNonceStore`), or an approval answered to one instance could
56
+ * be replayed to another within its ten minutes.
57
+ */
58
+ nonces?: NonceStore;
59
+ /** How long a legacy client waits to answer an approval prompt, in ms. Default 10 minutes. */
60
+ approvalTimeoutMs?: number;
61
+ };
62
+ /**
63
+ * The MCP endpoint: Streamable HTTP, for remote MCP clients (#762).
64
+ *
65
+ * One URL, POST only. It serves both eras of the protocol (see
66
+ * `./protocol.ts`): a modern client is served statelessly, and a legacy one
67
+ * through a session opened by `initialize`. Every request is authenticated —
68
+ * there is no unauthenticated method — by the configured resolvers, and
69
+ * every tool call is handed to `McpRegistry.execute` as a remote caller, so
70
+ * the route's middleware is the only authorization, exactly as for the
71
+ * user's own request.
72
+ *
73
+ * Mounted by `App.fetch` ahead of routing when `route.mcp.remote.enabled`.
74
+ */
75
+ export declare class McpHttpServer {
76
+ private readonly registry;
77
+ static token: string;
78
+ readonly endpoint: URL;
79
+ private readonly resolvers;
80
+ private readonly context;
81
+ private readonly allowedOrigins;
82
+ private readonly rateLimit;
83
+ private readonly maxBodyBytes;
84
+ private readonly serverInfo;
85
+ private readonly instructions?;
86
+ private readonly nonces;
87
+ private readonly approvalTimeoutMs;
88
+ /** Legacy elicitations waiting for the client's answer, by the request id they were sent under. */
89
+ private readonly pending;
90
+ /** Legacy calls in flight, so `notifications/cancelled` can stop one. */
91
+ private readonly inflight;
92
+ constructor(registry: McpRegistry, config: McpRemoteHttpConfig);
93
+ /** The endpoint's URL as a resource identifier: no trailing slash, no query. */
94
+ get resource(): string;
95
+ /**
96
+ * Answers a request that is the endpoint's, or one of its resolvers' (OAuth
97
+ * metadata and endpoints), and `null` for anything else.
98
+ *
99
+ * Only on the configured host. The name a client used is compared, not
100
+ * trusted: a DNS-rebinding page reaches this server under its own host name,
101
+ * and is answered by the app's ordinary routes, never by this.
102
+ */
103
+ handle(req: Request): Promise<Response | null>;
104
+ private post;
105
+ private dispatch;
106
+ private modern;
107
+ private legacy;
108
+ private complete;
109
+ private initialize;
110
+ /**
111
+ * The legacy session a request names, verified and bound to the credential
112
+ * it was opened under. A session id is not a credential — every request is
113
+ * authenticated on its own — but one opened under somebody else's token is
114
+ * refused all the same (404, which tells the client to start over), so a
115
+ * session id handed to a victim cannot carry the attacker's negotiation
116
+ * into the victim's calls.
117
+ */
118
+ private session;
119
+ private checkModernHeaders;
120
+ private callTool;
121
+ private toolResult;
122
+ /**
123
+ * Asks the user whether a `requiresApproval` tool may run, and answers
124
+ * either that it may (`approved`) or the result to send instead.
125
+ *
126
+ * Modern clients are asked statelessly: the call is answered
127
+ * `input_required` with an elicitation and a signed `requestState` bound to
128
+ * the credential, the tool, a digest of the arguments and ten minutes; the
129
+ * retry carries the user's answer and the state back, and the state is
130
+ * spent so the same approval cannot run the call twice. Legacy clients are
131
+ * asked on the call's own stream and the call waits for the answer.
132
+ *
133
+ * A client that cannot ask is refused: the call does not run unapproved.
134
+ */
135
+ private approval;
136
+ private spendNonce;
137
+ /**
138
+ * Runs `handler` and answers its result: as one JSON response, or — when
139
+ * the client asked for progress, or a legacy approval has to be asked on
140
+ * the way — as an SSE stream that ends with it. Closing the stream cancels
141
+ * the call.
142
+ */
143
+ private respond;
144
+ private unauthorized;
145
+ /**
146
+ * Counts a credential that was refused, per client address: 30 a minute,
147
+ * then 429. Keys are not guessable, but every guess is a store lookup, and
148
+ * the budget keeps a flood of them from becoming one.
149
+ */
150
+ private failedAttempt;
151
+ private spend;
152
+ }
153
+ //# sourceMappingURL=McpHttpServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpHttpServer.d.ts","sourceRoot":"","sources":["../../../../services/mcp/http/McpHttpServer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAK7E,OAAO,EAIL,KAAK,WAAW,EAGjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAe,KAAK,iBAAiB,EAA0B,MAAM,WAAW,CAAC;AAuBxF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,CAAC;IACtD,yHAAyH;IACzH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE;;;;;OAKG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,8FAA8F;IAC9F,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AA6CF;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAa;IAsBtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IArB3B,MAAM,CAAC,KAAK,SAAqB;IAEjC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAC/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,mGAAmG;IACnG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGpB;IACJ,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;gBAG5C,QAAQ,EAAE,WAAW,EACtC,MAAM,EAAE,mBAAmB;IA+C7B,gFAAgF;IAChF,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;;;;;;OAOG;IACG,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;YAwCtC,IAAI;YA8DJ,QAAQ;YA8FR,MAAM;YAwBN,MAAM;IAapB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,UAAU;IA6BlB;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO;IAiBf,OAAO,CAAC,kBAAkB;YAkCZ,QAAQ;IA0DtB,OAAO,CAAC,UAAU;IAIlB;;;;;;;;;;;;OAYG;YACW,QAAQ;YAyFR,UAAU;IAaxB;;;;;OAKG;YACW,OAAO;IA4CrB,OAAO,CAAC,YAAY;IAapB;;;;OAIG;YACW,aAAa;YAMb,KAAK;CAKpB"}
@@ -0,0 +1,131 @@
1
+ import type { User } from "../../../auth/types";
2
+ import type { McpRegistry, McpRemotePrincipal } from "../McpRegistry";
3
+ /**
4
+ * What a caller resolver is told about the server it resolves for.
5
+ */
6
+ export type McpResolveContext = {
7
+ /**
8
+ * The MCP endpoint's canonical URL, from config — the OAuth `resource` and
9
+ * the audience a token must have been issued for. Never read off the
10
+ * request: a `Host` header is the client's to write.
11
+ */
12
+ resource: string;
13
+ /** The tools, and the scopes that reach them. */
14
+ registry: McpRegistry;
15
+ };
16
+ /**
17
+ * What a resolver made of a request's credential.
18
+ *
19
+ * `invalid_token` answers 401: missing, malformed, expired, revoked, or
20
+ * issued for another audience. The description is sent to the client in the
21
+ * `WWW-Authenticate` header, so it says what is wrong with the credential and
22
+ * never anything about the user or the store.
23
+ */
24
+ export type McpResolution = {
25
+ ok: true;
26
+ principal: McpRemotePrincipal;
27
+ } | {
28
+ ok: false;
29
+ error: "invalid_token";
30
+ description: string;
31
+ };
32
+ /**
33
+ * Turns the credential on a request to the MCP endpoint into a principal: the
34
+ * user every tool call runs as, and the scopes that decide which tools they
35
+ * see. The transport refuses to start without one, and the request is
36
+ * answered 401 unless one of them resolves it.
37
+ *
38
+ * Resolvers are asked in order. One that answers `null` does not recognise the
39
+ * credential (or there is none) and the next is asked; one that answers a
40
+ * refusal ends the request, so a token one resolver issued and revoked cannot
41
+ * be retried against another.
42
+ *
43
+ * A resolver builds the principal from a credential it *verified* — looked up,
44
+ * checked against its audience and expiry — and never from anything else the
45
+ * request says. The principal's user is put on every dispatched route's
46
+ * request context as a signed-in user would be; a resolver that believed a
47
+ * header would sign anybody in as anybody.
48
+ */
49
+ export interface McpCallerResolver {
50
+ /** Recorded as `principal.via`, and `req.mcpGrant().via`. */
51
+ readonly name: string;
52
+ resolve(req: Request, context: McpResolveContext): Promise<McpResolution | null>;
53
+ /**
54
+ * The `WWW-Authenticate` value for a request no resolver claimed, so a
55
+ * client knows how to get a credential. The first resolver that has one is
56
+ * used.
57
+ */
58
+ challenge?(context: McpResolveContext, options?: {
59
+ scope?: string[];
60
+ }): string | null;
61
+ /**
62
+ * HTTP endpoints of the resolver's own — an OAuth authorization server's
63
+ * metadata, registration, authorize and token endpoints. Asked before the
64
+ * MCP endpoint, for every request to the configured origin. `null` passes.
65
+ */
66
+ handle?(req: Request, context: McpResolveContext): Promise<Response | null>;
67
+ /** Called once, when the transport is built: a place to refuse a bad config at boot. */
68
+ boot?(context: McpResolveContext): void;
69
+ }
70
+ /** The bearer token on a request, or `null`. Never anything from the query string. */
71
+ export declare function bearerToken(req: Request): string | null;
72
+ /** What `McpApiKeyResolver`'s `verify` answers for a key it knows. */
73
+ export type McpApiKey = {
74
+ /** The user the key acts as. */
75
+ user: User;
76
+ /** The key's own id (a row id), never the key: it keys rate limits and logs. */
77
+ id: string;
78
+ /** The scopes the key carries; see `McpRouter.scopes`. */
79
+ scopes: readonly string[];
80
+ };
81
+ export type McpApiKeyResolverOptions = {
82
+ /**
83
+ * The prefix every key of this app starts with, like `"kyte_mcp_"`.
84
+ * Required: a bearer token without it is left for the next resolver (an
85
+ * OAuth access token), and a key is never looked up by a resolver that did
86
+ * not issue it. Also what makes a leaked key recognisable to a secret
87
+ * scanner.
88
+ */
89
+ prefix: string;
90
+ /**
91
+ * Looks the key up. Store keys hashed — `McpApiKeyResolver.hash(key)` — and
92
+ * look up by the hash, so a database read is not a list of working keys.
93
+ * Answer `null` for an unknown, expired or revoked key.
94
+ */
95
+ verify(key: string, req: Request): Promise<McpApiKey | null>;
96
+ };
97
+ /**
98
+ * Remote callers authenticated by an API key the app issued: a user creates
99
+ * one in the app's settings and pastes it into an MCP client as a bearer
100
+ * token. Simpler than OAuth, for clients configured by hand (Claude Code,
101
+ * scripts); a hosted client such as Claude.ai's connectors uses OAuth.
102
+ *
103
+ * ```ts
104
+ * remote: {
105
+ * enabled: true,
106
+ * url: "https://example.com/mcp",
107
+ * resolvers: [
108
+ * new McpApiKeyResolver({
109
+ * prefix: "ex_mcp_",
110
+ * verify: async (key) => {
111
+ * const row = await ApiKey.findFirst({ where: { hash: McpApiKeyResolver.hash(key), revokedAt: null }, include: { user: true } });
112
+ * return row && { user: row.user, id: row.publicId, scopes: row.scopes };
113
+ * },
114
+ * }),
115
+ * ],
116
+ * }
117
+ * ```
118
+ */
119
+ export declare class McpApiKeyResolver implements McpCallerResolver {
120
+ private readonly options;
121
+ readonly name = "api-key";
122
+ constructor(options: McpApiKeyResolverOptions);
123
+ /** A new key: the prefix and 32 random bytes, base64url. Show it once, store its hash. */
124
+ static generate(prefix: string): string;
125
+ /** What to store for a key and look it up by: SHA-256, hex. */
126
+ static hash(key: string): string;
127
+ /** Compares two hashes without leaking where they differ. */
128
+ static hashesMatch(a: string, b: string): boolean;
129
+ resolve(req: Request): Promise<McpResolution | null>;
130
+ }
131
+ //# sourceMappingURL=callers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callers.d.ts","sourceRoot":"","sources":["../../../../services/mcp/http/callers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEtE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,kBAAkB,CAAA;CAAE,GAC3C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,iBAAiB;IAChC,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACjF;;;;OAIG;IACH,SAAS,CAAC,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,MAAM,GAAG,IAAI,CAAC;IACtF;;;;OAIG;IACH,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC5E,wFAAwF;IACxF,IAAI,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACzC;AAED,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKvD;AAED,sEAAsE;AACtE,MAAM,MAAM,SAAS,GAAG;IACtB,gCAAgC;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,gFAAgF;IAChF,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;CAC9D,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,iBAAkB,YAAW,iBAAiB;IAG7C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,IAAI,aAAa;gBAEG,OAAO,EAAE,wBAAwB;IAW9D,0FAA0F;IAC1F,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIvC,+DAA+D;IAC/D,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIhC,6DAA6D;IAC7D,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAM3C,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;CAiB3D"}
@@ -0,0 +1,11 @@
1
+ export type Budget = {
2
+ limit: number;
3
+ window: number;
4
+ };
5
+ /**
6
+ * Spends one unit of `key`'s budget with the app's `RateLimiter`. Answers
7
+ * `null` when it fits, or the seconds to wait when it does not. No limiter
8
+ * bound (a kernel without the provider) means no limit.
9
+ */
10
+ export declare function overBudget(key: string, budget: Budget): Promise<number | null>;
11
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../../../services/mcp/http/limits.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKpF"}