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.
- package/dist/ai/index.js +32 -32
- package/dist/ai/index.js.map +3 -5
- package/dist/app/App.d.ts.map +1 -1
- package/dist/app/index.js +1 -1
- package/dist/bin/gemi.js +8 -1
- package/dist/bin/gemi.js.map +3 -3
- package/dist/bun/plugin.js +1 -1
- package/dist/bun/preload.js +1 -1
- package/dist/{chunk-1p85fdrk.js → chunk-0av6xvm6.js} +2 -2
- package/dist/{chunk-1p85fdrk.js.map → chunk-0av6xvm6.js.map} +1 -1
- package/dist/chunk-0z8ejxre.js +5 -0
- package/dist/chunk-0z8ejxre.js.map +12 -0
- package/dist/{chunk-r7b12dmm.js → chunk-15c2vgaf.js} +2 -2
- package/dist/{chunk-r7b12dmm.js.map → chunk-15c2vgaf.js.map} +1 -1
- package/dist/{chunk-fr0arqdj.js → chunk-1hr4xht1.js} +2 -2
- package/dist/{chunk-fr0arqdj.js.map → chunk-1hr4xht1.js.map} +1 -1
- package/dist/{chunk-4t1pbt9p.js → chunk-1myhm0g3.js} +3 -3
- package/dist/{chunk-4t1pbt9p.js.map → chunk-1myhm0g3.js.map} +1 -1
- package/dist/{chunk-v4gwmhtf.js → chunk-1vzks22y.js} +2 -2
- package/dist/{chunk-v4gwmhtf.js.map → chunk-1vzks22y.js.map} +1 -1
- package/dist/{chunk-vzf5pbx3.js → chunk-2tzm58j3.js} +2 -2
- package/dist/{chunk-vzf5pbx3.js.map → chunk-2tzm58j3.js.map} +1 -1
- package/dist/{chunk-qx87cdfg.js → chunk-2z1981d0.js} +2 -2
- package/dist/{chunk-qx87cdfg.js.map → chunk-2z1981d0.js.map} +1 -1
- package/dist/{chunk-mepaedy5.js → chunk-3hrj5rwm.js} +2 -2
- package/dist/{chunk-mepaedy5.js.map → chunk-3hrj5rwm.js.map} +1 -1
- package/dist/{chunk-rh2fad7n.js → chunk-41da9628.js} +1 -1
- package/dist/{chunk-5q4a7yqf.js → chunk-56jky6vf.js} +2 -2
- package/dist/{chunk-5q4a7yqf.js.map → chunk-56jky6vf.js.map} +1 -1
- package/dist/{chunk-5x0aacrn.js → chunk-785b41h1.js} +2 -2
- package/dist/{chunk-5x0aacrn.js.map → chunk-785b41h1.js.map} +1 -1
- package/dist/{chunk-nysqgzp1.js → chunk-7g9yh5ae.js} +2 -2
- package/dist/{chunk-nysqgzp1.js.map → chunk-7g9yh5ae.js.map} +1 -1
- package/dist/{chunk-g8kx549d.js → chunk-7vb4eey2.js} +3 -3
- package/dist/{chunk-g8kx549d.js.map → chunk-7vb4eey2.js.map} +1 -1
- package/dist/{chunk-szr1k584.js → chunk-8rv62v14.js} +2 -2
- package/dist/{chunk-szr1k584.js.map → chunk-8rv62v14.js.map} +1 -1
- package/dist/{chunk-68s1f5d5.js → chunk-98m15b9x.js} +2 -2
- package/dist/{chunk-68s1f5d5.js.map → chunk-98m15b9x.js.map} +1 -1
- package/dist/{chunk-y596ghpz.js → chunk-9b4erdy2.js} +2 -2
- package/dist/{chunk-y596ghpz.js.map → chunk-9b4erdy2.js.map} +1 -1
- package/dist/{chunk-rg4hhxj3.js → chunk-9n1hx3mq.js} +2 -2
- package/dist/{chunk-rg4hhxj3.js.map → chunk-9n1hx3mq.js.map} +1 -1
- package/dist/{chunk-9tpx9ag3.js → chunk-aazmrxj9.js} +2 -2
- package/dist/{chunk-9tpx9ag3.js.map → chunk-aazmrxj9.js.map} +1 -1
- package/dist/{chunk-01qd6xx3.js → chunk-aeh67ynz.js} +3 -3
- package/dist/{chunk-01qd6xx3.js.map → chunk-aeh67ynz.js.map} +1 -1
- package/dist/{chunk-5nqkwa2w.js → chunk-agyfv3f8.js} +1 -1
- package/dist/{chunk-sr18y2ck.js → chunk-bra1a1fq.js} +2 -2
- package/dist/{chunk-sr18y2ck.js.map → chunk-bra1a1fq.js.map} +1 -1
- package/dist/{chunk-y6v0x869.js → chunk-cbqazg9k.js} +2 -2
- package/dist/{chunk-y6v0x869.js.map → chunk-cbqazg9k.js.map} +1 -1
- package/dist/{chunk-k2fh4r0p.js → chunk-d2gfcf85.js} +2 -2
- package/dist/{chunk-k2fh4r0p.js.map → chunk-d2gfcf85.js.map} +1 -1
- package/dist/chunk-d6591xck.js +46 -0
- package/dist/{chunk-6g20zec2.js.map → chunk-d6591xck.js.map} +6 -6
- package/dist/{chunk-fnkjmq94.js → chunk-d9mar37g.js} +2 -2
- package/dist/{chunk-fnkjmq94.js.map → chunk-d9mar37g.js.map} +1 -1
- package/dist/chunk-dexdkh3z.js +14 -0
- package/dist/{chunk-cqnfp0n9.js.map → chunk-dexdkh3z.js.map} +7 -7
- package/dist/{chunk-bq5nqqeq.js → chunk-e573yxpq.js} +1 -1
- package/dist/{chunk-p3zmc8k8.js → chunk-eqse2m6n.js} +2 -2
- package/dist/{chunk-p3zmc8k8.js.map → chunk-eqse2m6n.js.map} +1 -1
- package/dist/{chunk-yyzexrnb.js → chunk-er3wf6ng.js} +2 -2
- package/dist/{chunk-yyzexrnb.js.map → chunk-er3wf6ng.js.map} +1 -1
- package/dist/{chunk-3f1kq32g.js → chunk-fre6f4nk.js} +2 -2
- package/dist/{chunk-3f1kq32g.js.map → chunk-fre6f4nk.js.map} +1 -1
- package/dist/{chunk-qt8nvpqp.js → chunk-fxgxf16k.js} +2 -2
- package/dist/{chunk-qt8nvpqp.js.map → chunk-fxgxf16k.js.map} +1 -1
- package/dist/{chunk-6wymbbes.js → chunk-gts5p6mw.js} +3 -3
- package/dist/{chunk-6wymbbes.js.map → chunk-gts5p6mw.js.map} +1 -1
- package/dist/{chunk-571rvxe6.js → chunk-hdps9n52.js} +2 -2
- package/dist/{chunk-571rvxe6.js.map → chunk-hdps9n52.js.map} +1 -1
- package/dist/{chunk-w45agtch.js → chunk-hytt9qyj.js} +2 -2
- package/dist/{chunk-w45agtch.js.map → chunk-hytt9qyj.js.map} +1 -1
- package/dist/{chunk-de03dewf.js → chunk-jafm3613.js} +2 -2
- package/dist/{chunk-de03dewf.js.map → chunk-jafm3613.js.map} +1 -1
- package/dist/{chunk-dbwhgyg3.js → chunk-jdhdrr2k.js} +2 -2
- package/dist/{chunk-dbwhgyg3.js.map → chunk-jdhdrr2k.js.map} +1 -1
- package/dist/{chunk-d04r0hdf.js → chunk-jmpw6bqz.js} +2 -2
- package/dist/{chunk-d04r0hdf.js.map → chunk-jmpw6bqz.js.map} +1 -1
- package/dist/{chunk-vwprq300.js → chunk-kejwjerj.js} +2 -2
- package/dist/{chunk-vwprq300.js.map → chunk-kejwjerj.js.map} +1 -1
- package/dist/{chunk-wr3e4sez.js → chunk-kqxdsv22.js} +2 -2
- package/dist/{chunk-wr3e4sez.js.map → chunk-kqxdsv22.js.map} +1 -1
- package/dist/{chunk-9vsj0ksk.js → chunk-ktr3k768.js} +3 -3
- package/dist/{chunk-9vsj0ksk.js.map → chunk-ktr3k768.js.map} +1 -1
- package/dist/{chunk-kz4yp5n7.js → chunk-m54s6jpr.js} +2 -2
- package/dist/{chunk-8mbyyh8j.js.map → chunk-m54s6jpr.js.map} +1 -1
- package/dist/{chunk-xqwdn9kb.js → chunk-mazznq15.js} +3 -3
- package/dist/{chunk-xqwdn9kb.js.map → chunk-mazznq15.js.map} +1 -1
- package/dist/{chunk-zng3qexn.js → chunk-mps6ynbh.js} +2 -2
- package/dist/{chunk-zng3qexn.js.map → chunk-mps6ynbh.js.map} +1 -1
- package/dist/{chunk-vdwagp7y.js → chunk-mqfzdfnz.js} +2 -2
- package/dist/{chunk-vdwagp7y.js.map → chunk-mqfzdfnz.js.map} +1 -1
- package/dist/{chunk-mk0rtgd1.js → chunk-mschc94q.js} +2 -2
- package/dist/{chunk-mk0rtgd1.js.map → chunk-mschc94q.js.map} +1 -1
- package/dist/{chunk-x5yq097b.js → chunk-mtbygktb.js} +3 -3
- package/dist/{chunk-x5yq097b.js.map → chunk-mtbygktb.js.map} +1 -1
- package/dist/{chunk-f1y8eggf.js → chunk-n672d4g8.js} +2 -2
- package/dist/{chunk-f1y8eggf.js.map → chunk-n672d4g8.js.map} +1 -1
- package/dist/{chunk-4tp2cr02.js → chunk-pyk3gzvc.js} +2 -2
- package/dist/{chunk-4tp2cr02.js.map → chunk-pyk3gzvc.js.map} +1 -1
- package/dist/{chunk-agw3anaf.js → chunk-qjhw8nje.js} +1 -1
- package/dist/{chunk-vqa3agzw.js → chunk-qsrcdzan.js} +3 -3
- package/dist/{chunk-vqa3agzw.js.map → chunk-qsrcdzan.js.map} +1 -1
- package/dist/{chunk-nksn6xcd.js → chunk-sr942vb1.js} +2 -2
- package/dist/{chunk-nksn6xcd.js.map → chunk-sr942vb1.js.map} +1 -1
- package/dist/{chunk-kexsfyjj.js → chunk-t04f3akb.js} +2 -2
- package/dist/{chunk-kexsfyjj.js.map → chunk-t04f3akb.js.map} +1 -1
- package/dist/chunk-t24p7gc6.js +5 -0
- package/dist/{chunk-fsfbyg5e.js.map → chunk-t24p7gc6.js.map} +1 -1
- package/dist/chunk-t4t3hqe0.js +10 -0
- package/dist/chunk-t4t3hqe0.js.map +38 -0
- package/dist/{chunk-z5hrymvn.js → chunk-t4yh4nf9.js} +3 -3
- package/dist/{chunk-z5hrymvn.js.map → chunk-t4yh4nf9.js.map} +1 -1
- package/dist/{chunk-c7mp2kyp.js → chunk-tn2bryy2.js} +2 -2
- package/dist/{chunk-c7mp2kyp.js.map → chunk-tn2bryy2.js.map} +1 -1
- package/dist/chunk-tw5kwbx4.js +4 -0
- package/dist/{chunk-kp7k4s5c.js.map → chunk-tw5kwbx4.js.map} +3 -3
- package/dist/{chunk-zyer1g7k.js → chunk-tzm3c7n6.js} +4 -4
- package/dist/{chunk-zyer1g7k.js.map → chunk-tzm3c7n6.js.map} +1 -1
- package/dist/{chunk-1se4t9rg.js → chunk-vbdty91k.js} +3 -3
- package/dist/{chunk-1se4t9rg.js.map → chunk-vbdty91k.js.map} +1 -1
- package/dist/{chunk-8mbyyh8j.js → chunk-vw8849ys.js} +2 -2
- package/dist/{chunk-kz4yp5n7.js.map → chunk-vw8849ys.js.map} +1 -1
- package/dist/{chunk-g8sc6scv.js → chunk-vxm6yevm.js} +2 -2
- package/dist/{chunk-g8sc6scv.js.map → chunk-vxm6yevm.js.map} +1 -1
- package/dist/{chunk-qpttgn4k.js → chunk-whtzggn6.js} +3 -3
- package/dist/{chunk-qpttgn4k.js.map → chunk-whtzggn6.js.map} +1 -1
- package/dist/{chunk-7jnpnjth.js → chunk-wyw6p3fg.js} +2 -2
- package/dist/{chunk-7jnpnjth.js.map → chunk-wyw6p3fg.js.map} +1 -1
- package/dist/{chunk-atmzm0z3.js → chunk-wzrt5mac.js} +2 -2
- package/dist/{chunk-atmzm0z3.js.map → chunk-wzrt5mac.js.map} +1 -1
- package/dist/{chunk-y6frz1vm.js → chunk-x7cpth2f.js} +1 -1
- package/dist/{chunk-essqp1ek.js → chunk-xt9tv99x.js} +2 -2
- package/dist/{chunk-essqp1ek.js.map → chunk-xt9tv99x.js.map} +1 -1
- package/dist/{chunk-x5sert1k.js → chunk-yhrye9cm.js} +2 -2
- package/dist/{chunk-x5sert1k.js.map → chunk-yhrye9cm.js.map} +1 -1
- package/dist/{chunk-vc9phr57.js → chunk-zyt2w03d.js} +2 -2
- package/dist/{chunk-vc9phr57.js.map → chunk-zyt2w03d.js.map} +1 -1
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/facades/Storage.d.ts +25 -1
- package/dist/facades/Storage.d.ts.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/http/HttpRequest.d.ts +31 -0
- package/dist/http/HttpRequest.d.ts.map +1 -1
- package/dist/http/McpRouter.d.ts +54 -1
- package/dist/http/McpRouter.d.ts.map +1 -1
- package/dist/http/RateLimitMiddleware.d.ts +4 -1
- package/dist/http/RateLimitMiddleware.d.ts.map +1 -1
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/http/modelOriginated.d.ts +36 -2
- package/dist/http/modelOriginated.d.ts.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/kernel/Kernel.d.ts +3 -0
- package/dist/kernel/Kernel.d.ts.map +1 -1
- package/dist/kernel/index.js +3 -3
- package/dist/kernel/index.js.map +3 -3
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/services/file-storage/drivers/AzureBlobDriver.d.ts +12 -1
- package/dist/services/file-storage/drivers/AzureBlobDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/FileStorageDriver.d.ts +32 -1
- package/dist/services/file-storage/drivers/FileStorageDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/FileSystemDriver.d.ts +22 -1
- package/dist/services/file-storage/drivers/FileSystemDriver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/S3Driver.d.ts +14 -1
- package/dist/services/file-storage/drivers/S3Driver.d.ts.map +1 -1
- package/dist/services/file-storage/drivers/types.d.ts +26 -0
- package/dist/services/file-storage/drivers/types.d.ts.map +1 -1
- package/dist/services/index.d.ts +8 -3
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +44 -9
- package/dist/services/index.js.map +8 -5
- package/dist/services/mcp/McpRegistry.d.ts +190 -29
- package/dist/services/mcp/McpRegistry.d.ts.map +1 -1
- package/dist/services/mcp/http/McpHttpServer.d.ts +153 -0
- package/dist/services/mcp/http/McpHttpServer.d.ts.map +1 -0
- package/dist/services/mcp/http/callers.d.ts +131 -0
- package/dist/services/mcp/http/callers.d.ts.map +1 -0
- package/dist/services/mcp/http/limits.d.ts +11 -0
- package/dist/services/mcp/http/limits.d.ts.map +1 -0
- package/dist/services/mcp/http/oauth/McpOAuthServer.d.ts +150 -0
- package/dist/services/mcp/http/oauth/McpOAuthServer.d.ts.map +1 -0
- package/dist/services/mcp/http/oauth/consentPage.d.ts +14 -0
- package/dist/services/mcp/http/oauth/consentPage.d.ts.map +1 -0
- package/dist/services/mcp/http/oauth/store.d.ts +98 -0
- package/dist/services/mcp/http/oauth/store.d.ts.map +1 -0
- package/dist/services/mcp/http/protocol.d.ts +95 -0
- package/dist/services/mcp/http/protocol.d.ts.map +1 -0
- package/dist/services/mcp/http/signedState.d.ts +25 -0
- package/dist/services/mcp/http/signedState.d.ts.map +1 -0
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +1 -1
- package/dist/services/router/ApiRouteDispatcher.d.ts +29 -0
- package/dist/services/router/ApiRouteDispatcher.d.ts.map +1 -1
- package/dist/services/router/RouteServiceProvider.d.ts +6 -0
- package/dist/services/router/RouteServiceProvider.d.ts.map +1 -1
- package/dist/services/router/config.d.ts +16 -0
- package/dist/services/router/config.d.ts.map +1 -1
- package/dist/stats/route-table.js +1 -1
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/vitest/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3z9vhjd7.js +0 -5
- package/dist/chunk-3z9vhjd7.js.map +0 -10
- package/dist/chunk-5zzhypmt.js +0 -5
- package/dist/chunk-5zzhypmt.js.map +0 -33
- package/dist/chunk-6g20zec2.js +0 -46
- package/dist/chunk-cqnfp0n9.js +0 -14
- package/dist/chunk-fsfbyg5e.js +0 -5
- package/dist/chunk-kp7k4s5c.js +0 -4
- /package/dist/{chunk-rh2fad7n.js.map → chunk-41da9628.js.map} +0 -0
- /package/dist/{chunk-5nqkwa2w.js.map → chunk-agyfv3f8.js.map} +0 -0
- /package/dist/{chunk-bq5nqqeq.js.map → chunk-e573yxpq.js.map} +0 -0
- /package/dist/{chunk-agw3anaf.js.map → chunk-qjhw8nje.js.map} +0 -0
- /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,
|
|
21
|
-
* one however it likes, and a run with no ambient request is refused
|
|
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
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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
|
-
|
|
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.
|
|
47
|
-
*
|
|
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:
|
|
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
|
|
65
|
-
*
|
|
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
|
-
*
|
|
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?:
|
|
74
|
-
destructiveHint?:
|
|
75
|
-
idempotentHint?:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
162
|
-
*
|
|
163
|
-
*
|
|
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
|
|
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":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAK,KAAK,SAAS,EAAmB,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAEV,SAAS,EAKT,SAAS,EACV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,
|
|
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"}
|