@frontmcp/sdk 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +192 -164
- package/package.json +7 -4
- package/src/__test-utils__/fixtures/hook.fixtures.d.ts +46 -0
- package/src/__test-utils__/fixtures/hook.fixtures.js +114 -0
- package/src/__test-utils__/fixtures/hook.fixtures.js.map +1 -0
- package/src/__test-utils__/fixtures/index.d.ts +7 -0
- package/src/__test-utils__/fixtures/index.js +11 -0
- package/src/__test-utils__/fixtures/index.js.map +1 -0
- package/src/__test-utils__/fixtures/plugin.fixtures.d.ts +46 -0
- package/src/__test-utils__/fixtures/plugin.fixtures.js +127 -0
- package/src/__test-utils__/fixtures/plugin.fixtures.js.map +1 -0
- package/src/__test-utils__/fixtures/provider.fixtures.d.ts +69 -0
- package/src/__test-utils__/fixtures/provider.fixtures.js +131 -0
- package/src/__test-utils__/fixtures/provider.fixtures.js.map +1 -0
- package/src/__test-utils__/fixtures/scope.fixtures.d.ts +14 -0
- package/src/__test-utils__/fixtures/scope.fixtures.js +59 -0
- package/src/__test-utils__/fixtures/scope.fixtures.js.map +1 -0
- package/src/__test-utils__/fixtures/tool.fixtures.d.ts +36 -0
- package/src/__test-utils__/fixtures/tool.fixtures.js +91 -0
- package/src/__test-utils__/fixtures/tool.fixtures.js.map +1 -0
- package/src/__test-utils__/helpers/assertion.helpers.d.ts +45 -0
- package/src/__test-utils__/helpers/assertion.helpers.js +153 -0
- package/src/__test-utils__/helpers/assertion.helpers.js.map +1 -0
- package/src/__test-utils__/helpers/async.helpers.d.ts +48 -0
- package/src/__test-utils__/helpers/async.helpers.js +112 -0
- package/src/__test-utils__/helpers/async.helpers.js.map +1 -0
- package/src/__test-utils__/helpers/index.d.ts +6 -0
- package/src/__test-utils__/helpers/index.js +10 -0
- package/src/__test-utils__/helpers/index.js.map +1 -0
- package/src/__test-utils__/helpers/setup.helpers.d.ts +54 -0
- package/src/__test-utils__/helpers/setup.helpers.js +106 -0
- package/src/__test-utils__/helpers/setup.helpers.js.map +1 -0
- package/src/__test-utils__/index.d.ts +9 -0
- package/src/__test-utils__/index.js +14 -0
- package/src/__test-utils__/index.js.map +1 -0
- package/src/__test-utils__/mocks/flow-instance.mock.d.ts +50 -0
- package/src/__test-utils__/mocks/flow-instance.mock.js +72 -0
- package/src/__test-utils__/mocks/flow-instance.mock.js.map +1 -0
- package/src/__test-utils__/mocks/hook-registry.mock.d.ts +25 -0
- package/src/__test-utils__/mocks/hook-registry.mock.js +65 -0
- package/src/__test-utils__/mocks/hook-registry.mock.js.map +1 -0
- package/src/__test-utils__/mocks/index.d.ts +8 -0
- package/src/__test-utils__/mocks/index.js +12 -0
- package/src/__test-utils__/mocks/index.js.map +1 -0
- package/src/__test-utils__/mocks/plugin-registry.mock.d.ts +43 -0
- package/src/__test-utils__/mocks/plugin-registry.mock.js +70 -0
- package/src/__test-utils__/mocks/plugin-registry.mock.js.map +1 -0
- package/src/__test-utils__/mocks/provider-registry.mock.d.ts +39 -0
- package/src/__test-utils__/mocks/provider-registry.mock.js +72 -0
- package/src/__test-utils__/mocks/provider-registry.mock.js.map +1 -0
- package/src/__test-utils__/mocks/tool-registry.mock.d.ts +43 -0
- package/src/__test-utils__/mocks/tool-registry.mock.js +79 -0
- package/src/__test-utils__/mocks/tool-registry.mock.js.map +1 -0
- package/src/app/app.utils.js.map +1 -1
- package/src/app/instances/app.local.instance.js +8 -11
- package/src/app/instances/app.local.instance.js.map +1 -1
- package/src/auth/auth.registry.d.ts +2 -2
- package/src/auth/auth.registry.js +3 -3
- package/src/auth/auth.registry.js.map +1 -1
- package/src/auth/flows/oauth.authorize.flow.d.ts +8 -8
- package/src/auth/flows/oauth.register.flow.d.ts +4 -4
- package/src/auth/flows/oauth.token.flow.d.ts +4 -4
- package/src/auth/flows/well-known.jwks.flow.d.ts +12 -12
- package/src/auth/flows/well-known.oauth-authorization-server.flow.d.ts +8 -8
- package/src/auth/flows/well-known.prm.flow.d.ts +4 -4
- package/src/auth/instances/instance.local-primary-auth.d.ts +3 -2
- package/src/auth/instances/instance.local-primary-auth.js +4 -2
- package/src/auth/instances/instance.local-primary-auth.js.map +1 -1
- package/src/auth/instances/instance.remote-primary-auth.d.ts +3 -2
- package/src/auth/instances/instance.remote-primary-auth.js +3 -1
- package/src/auth/instances/instance.remote-primary-auth.js.map +1 -1
- package/src/auth/jwks/jwks.service.js +0 -1
- package/src/auth/jwks/jwks.service.js.map +1 -1
- package/src/common/decorators/tool.decorator.d.ts +97 -36
- package/src/common/decorators/tool.decorator.js +0 -1
- package/src/common/decorators/tool.decorator.js.map +1 -1
- package/src/common/entries/scope.entry.d.ts +1 -0
- package/src/common/entries/scope.entry.js +6 -0
- package/src/common/entries/scope.entry.js.map +1 -1
- package/src/common/entries/tool.entry.d.ts +54 -11
- package/src/common/entries/tool.entry.js +19 -0
- package/src/common/entries/tool.entry.js.map +1 -1
- package/src/common/interfaces/internal/registry.interface.d.ts +10 -2
- package/src/common/interfaces/internal/registry.interface.js.map +1 -1
- package/src/common/interfaces/plugin.interface.d.ts +1 -1
- package/src/common/interfaces/plugin.interface.js.map +1 -1
- package/src/common/interfaces/tool.interface.d.ts +12 -7
- package/src/common/interfaces/tool.interface.js +1 -1
- package/src/common/interfaces/tool.interface.js.map +1 -1
- package/src/common/metadata/front-mcp.metadata.d.ts +145 -145
- package/src/common/metadata/hook.metadata.d.ts +4 -2
- package/src/common/metadata/hook.metadata.js.map +1 -1
- package/src/common/metadata/prompt.metadata.d.ts +28 -28
- package/src/common/metadata/prompt.metadata.js.map +1 -1
- package/src/common/metadata/resource.metadata.d.ts +54 -54
- package/src/common/metadata/tool.metadata.d.ts +190 -7
- package/src/common/metadata/tool.metadata.js +41 -6
- package/src/common/metadata/tool.metadata.js.map +1 -1
- package/src/common/records/scope.record.d.ts +2 -2
- package/src/common/records/scope.record.js.map +1 -1
- package/src/common/schemas/http-output.schema.d.ts +106 -106
- package/src/common/tokens/tool.tokens.js.map +1 -1
- package/src/common/types/options/logging.options.d.ts +1 -2
- package/src/common/types/options/logging.options.js +1 -9
- package/src/common/types/options/logging.options.js.map +1 -1
- package/src/common/types/options/server-info.options.d.ts +19 -19
- package/src/errors/error-handler.d.ts +65 -0
- package/src/errors/error-handler.js +107 -0
- package/src/errors/error-handler.js.map +1 -0
- package/src/errors/index.d.ts +2 -0
- package/src/errors/index.js +26 -0
- package/src/errors/index.js.map +1 -0
- package/src/errors/mcp.error.d.ts +156 -0
- package/src/errors/mcp.error.js +243 -0
- package/src/errors/mcp.error.js.map +1 -0
- package/src/flows/flow.instance.js +7 -6
- package/src/flows/flow.instance.js.map +1 -1
- package/src/flows/flow.registry.js +1 -1
- package/src/flows/flow.registry.js.map +1 -1
- package/src/front-mcp/front-mcp.providers.d.ts +20 -20
- package/src/hooks/hook.registry.d.ts +5 -3
- package/src/hooks/hook.registry.js +13 -1
- package/src/hooks/hook.registry.js.map +1 -1
- package/src/plugin/plugin.registry.d.ts +7 -2
- package/src/plugin/plugin.registry.js +23 -11
- package/src/plugin/plugin.registry.js.map +1 -1
- package/src/prompt/prompt.registry.js +1 -0
- package/src/prompt/prompt.registry.js.map +1 -1
- package/src/resource/resource.registry.js +1 -0
- package/src/resource/resource.registry.js.map +1 -1
- package/src/scope/scope.instance.js +8 -2
- package/src/scope/scope.instance.js.map +1 -1
- package/src/scope/scope.registry.js +3 -2
- package/src/scope/scope.registry.js.map +1 -1
- package/src/scope/scope.utils.js +6 -4
- package/src/scope/scope.utils.js.map +1 -1
- package/src/store/adapters/store.memory.adapter.js +3 -1
- package/src/store/adapters/store.memory.adapter.js.map +1 -1
- package/src/tool/flows/call-tool.flow.d.ts +1012 -676
- package/src/tool/flows/call-tool.flow.js +94 -61
- package/src/tool/flows/call-tool.flow.js.map +1 -1
- package/src/tool/flows/tools-list.flow.d.ts +347 -590
- package/src/tool/flows/tools-list.flow.js +76 -49
- package/src/tool/flows/tools-list.flow.js.map +1 -1
- package/src/tool/tool.instance.d.ts +27 -8
- package/src/tool/tool.instance.js +40 -5
- package/src/tool/tool.instance.js.map +1 -1
- package/src/tool/tool.registry.js +19 -21
- package/src/tool/tool.registry.js.map +1 -1
- package/src/tool/tool.utils.d.ts +3 -2
- package/src/tool/tool.utils.js +377 -14
- package/src/tool/tool.utils.js.map +1 -1
- package/src/transport/adapters/transport.sse.adapter.js +2 -1
- package/src/transport/adapters/transport.sse.adapter.js.map +1 -1
- package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
- package/src/transport/flows/handle.sse.flow.js +6 -13
- package/src/transport/flows/handle.sse.flow.js.map +1 -1
- package/src/transport/flows/handle.streamable-http.flow.js +1 -0
- package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
- package/src/transport/mcp-handlers/call-tool-request.handler.d.ts +1 -1
- package/src/transport/mcp-handlers/call-tool-request.handler.js +10 -5
- package/src/transport/mcp-handlers/call-tool-request.handler.js.map +1 -1
- package/src/transport/mcp-handlers/index.d.ts +151 -268
- package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +124 -216
- package/src/transport/transport.local.js +1 -0
- package/src/transport/transport.local.js.map +1 -1
- package/src/utils/string.utils.js +1 -1
- package/src/utils/string.utils.js.map +1 -1
|
@@ -15,6 +15,7 @@ const oauth_token_flow_1 = tslib_1.__importDefault(require("../flows/oauth.token
|
|
|
15
15
|
const jwks_1 = require("../jwks");
|
|
16
16
|
const DEFAULT_NO_AUTH_SECRET = (0, crypto_1.randomBytes)(32);
|
|
17
17
|
class LocalPrimaryAuth extends common_1.FrontMcpAuth {
|
|
18
|
+
scope;
|
|
18
19
|
providers;
|
|
19
20
|
host;
|
|
20
21
|
port;
|
|
@@ -23,13 +24,14 @@ class LocalPrimaryAuth extends common_1.FrontMcpAuth {
|
|
|
23
24
|
secret;
|
|
24
25
|
logger;
|
|
25
26
|
jwks = new jwks_1.JwksService();
|
|
26
|
-
constructor(providers, metadata) {
|
|
27
|
+
constructor(scope, providers, metadata) {
|
|
27
28
|
super(metadata);
|
|
29
|
+
this.scope = scope;
|
|
28
30
|
this.providers = providers;
|
|
29
31
|
this.logger = this.providers.getActiveScope().logger.child('LocalPrimaryAuth');
|
|
30
32
|
this.port = this.providers.getActiveScope().metadata.http?.port ?? 3001;
|
|
31
33
|
this.host = 'localhost';
|
|
32
|
-
this.issuer = `http://${this.host}:${this.port}`;
|
|
34
|
+
this.issuer = `http://${this.host}:${this.port}${scope.fullPath}`;
|
|
33
35
|
if (process.env["JWT_SECRET"]) {
|
|
34
36
|
this.secret = new TextEncoder().encode(process.env["JWT_SECRET"]);
|
|
35
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.local-primary-auth.js","sourceRoot":"","sources":["../../../../src/auth/instances/instance.local-primary-auth.ts"],"names":[],"mappings":";;;;AAAA,+BAA6B;AAE7B,mCAA+C;AAC/C,
|
|
1
|
+
{"version":3,"file":"instance.local-primary-auth.js","sourceRoot":"","sources":["../../../../src/auth/instances/instance.local-primary-auth.ts"],"names":[],"mappings":"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","sourcesContent":["import {SignJWT} from \"jose\";\nimport {URL} from 'url';\nimport {randomBytes, randomUUID} from \"crypto\";\nimport {FrontMcpAuth, FrontMcpLogger, LocalAuthOptions, ProviderScope, ScopeEntry, ServerRequest} from '../../common';\nimport ProviderRegistry from '../../provider/provider.registry';\nimport WellKnownPrmFlow from '../flows/well-known.prm.flow';\nimport WellKnownAsFlow from '../flows/well-known.oauth-authorization-server.flow';\nimport WellKnownJwksFlow from '../flows/well-known.jwks.flow';\nimport SessionVerifyFlow from '../flows/session.verify.flow';\nimport OauthAuthorizeFlow from \"../flows/oauth.authorize.flow\";\nimport OauthRegisterFlow from \"../flows/oauth.register.flow\";\nimport OauthTokenFlow from \"../flows/oauth.token.flow\";\nimport {JwksService} from \"../jwks\";\n\n\nconst DEFAULT_NO_AUTH_SECRET = randomBytes(32)\n\nexport class LocalPrimaryAuth extends FrontMcpAuth {\n readonly host: string;\n readonly port: number;\n readonly issuer: string;\n readonly keys: any[] = [];\n readonly secret: Uint8Array;\n readonly logger: FrontMcpLogger;\n private jwks = new JwksService();\n\n constructor(private scope:ScopeEntry,private providers: ProviderRegistry, metadata: LocalAuthOptions) {\n super(metadata);\n this.logger = this.providers.getActiveScope().logger.child('LocalPrimaryAuth');\n this.port = this.providers.getActiveScope().metadata.http?.port ?? 3001;\n this.host = 'localhost';\n this.issuer = `http://${this.host}:${this.port}${scope.fullPath}`\n\n if (process.env[\"JWT_SECRET\"]) {\n this.secret = new TextEncoder().encode(process.env[\"JWT_SECRET\"])\n } else {\n this.logger.warn('JWT_SECRET is not set, using default secret')\n this.secret = DEFAULT_NO_AUTH_SECRET;\n }\n this.ready = this.initialize();\n }\n\n\n async signAnonymousJwt() {\n const sub = randomUUID()\n return new SignJWT({sub, role: 'user', anonymous: true})\n .setProtectedHeader({alg: 'HS256', typ: 'JWT'})\n .setIssuedAt()\n .setIssuer(this.issuer)\n .setExpirationTime('1d')\n .sign(this.secret)\n }\n\n protected async initialize(): Promise<void> {\n // TODO: create separated jwk service for local/remote auth options\n this.providers.injectProvider({\n value: this.jwks,\n metadata: {\n scope: ProviderScope.GLOBAL,\n name: 'auth:jwk-service',\n },\n provide: JwksService,\n });\n\n await this.registerAuthFlows();\n\n\n return Promise.resolve();\n }\n\n override fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n return fetch(input, init);\n }\n\n override validate(request: ServerRequest): Promise<void> {\n return Promise.resolve();\n }\n\n\n private async registerAuthFlows() {\n const scope = this.providers.getActiveScope();\n await scope.registryFlows(\n WellKnownPrmFlow, /** /.well-known/oauth-protected-resource */\n WellKnownAsFlow, /** /.well-known/oauth-authorization-server */\n WellKnownJwksFlow, /** /.well-known/jwks.json */\n SessionVerifyFlow, /** Session verification flow */\n\n OauthAuthorizeFlow,\n OauthTokenFlow,\n OauthRegisterFlow\n );\n }\n}"]}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { FrontMcpAuth, RemoteAuthOptions, ServerRequest } from '../../common';
|
|
1
|
+
import { FrontMcpAuth, RemoteAuthOptions, ScopeEntry, ServerRequest } from '../../common';
|
|
2
2
|
import { URL } from 'url';
|
|
3
3
|
import ProviderRegistry from '../../provider/provider.registry';
|
|
4
4
|
export declare class RemotePrimaryAuth extends FrontMcpAuth<RemoteAuthOptions> {
|
|
5
|
+
private readonly scope;
|
|
5
6
|
private readonly providers;
|
|
6
7
|
ready: Promise<void>;
|
|
7
8
|
private jwks;
|
|
8
|
-
constructor(providers: ProviderRegistry, options: RemoteAuthOptions);
|
|
9
|
+
constructor(scope: ScopeEntry, providers: ProviderRegistry, options: RemoteAuthOptions);
|
|
9
10
|
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
10
11
|
validate(request: ServerRequest): Promise<void>;
|
|
11
12
|
get issuer(): string;
|
|
@@ -9,11 +9,13 @@ const well_known_oauth_authorization_server_flow_1 = tslib_1.__importDefault(req
|
|
|
9
9
|
const well_known_jwks_flow_1 = tslib_1.__importDefault(require("../flows/well-known.jwks.flow"));
|
|
10
10
|
const session_verify_flow_1 = tslib_1.__importDefault(require("../flows/session.verify.flow"));
|
|
11
11
|
class RemotePrimaryAuth extends common_1.FrontMcpAuth {
|
|
12
|
+
scope;
|
|
12
13
|
providers;
|
|
13
14
|
ready;
|
|
14
15
|
jwks = new jwks_1.JwksService();
|
|
15
|
-
constructor(providers, options) {
|
|
16
|
+
constructor(scope, providers, options) {
|
|
16
17
|
super(options);
|
|
18
|
+
this.scope = scope;
|
|
17
19
|
this.providers = providers;
|
|
18
20
|
this.ready = this.initialize();
|
|
19
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.remote-primary-auth.js","sourceRoot":"","sources":["../../../../src/auth/instances/instance.remote-primary-auth.ts"],"names":[],"mappings":";;;;AAAA,
|
|
1
|
+
{"version":3,"file":"instance.remote-primary-auth.js","sourceRoot":"","sources":["../../../../src/auth/instances/instance.remote-primary-auth.ts"],"names":[],"mappings":";;;;AAAA,yCAAuG;AAGvG,kCAAoC;AACpC,+FAA4D;AAC5D,6IAAkF;AAClF,iGAA8D;AAC9D,+FAA6D;AAI7D,MAAa,iBAAkB,SAAQ,qBAA+B;IAIvC;IAAoC;IAHxD,KAAK,CAAgB;IACtB,IAAI,GAAG,IAAI,kBAAW,EAAE,CAAC;IAEjC,YAA6B,KAAiB,EAAmB,SAA2B,EAAE,OAA0B;QACtH,KAAK,CAAC,OAAO,CAAC,CAAC;QADY,UAAK,GAAL,KAAK,CAAY;QAAmB,cAAS,GAAT,SAAS,CAAkB;QAE1F,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IACjC,CAAC;IAEQ,KAAK,CAAC,KAAwB,EAAE,IAAkB;QACzD,OAAO,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;IAEQ,QAAQ,CAAC,OAAsB;QACtC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAGD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;IAC9B,CAAC;IAES,KAAK,CAAC,UAAU;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC;QAE9C,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;YAC5B,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,QAAQ,EAAE;gBACR,KAAK,EAAE,sBAAa,CAAC,MAAM;gBAC3B,IAAI,EAAE,kBAAkB;aACzB;YACD,OAAO,EAAE,kBAAW;SACrB,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACpC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAGO,KAAK,CAAC,iBAAiB,CAAC,KAAY;QAC1C,MAAM,KAAK,CAAC,aAAa,CACvB,6BAAgB,EAAE,4CAA4C,CAC9D,oDAAe,EAAE,8CAA8C,CAC/D,8BAAiB,EAAE,6BAA6B,CAChD,6BAAiB,CAClB,CAAC;IACJ,CAAC;CACF;AA/CD,8CA+CC","sourcesContent":["import {FrontMcpAuth, ProviderScope, RemoteAuthOptions, ScopeEntry, ServerRequest} from '../../common';\nimport {URL} from 'url';\nimport ProviderRegistry from '../../provider/provider.registry';\nimport {JwksService} from '../jwks';\nimport WellKnownPrmFlow from '../flows/well-known.prm.flow';\nimport WellKnownAsFlow from '../flows/well-known.oauth-authorization-server.flow';\nimport WellKnownJwksFlow from '../flows/well-known.jwks.flow';\nimport SessionVerifyFlow from '../flows/session.verify.flow';\nimport {Scope} from '../../scope';\n\n\nexport class RemotePrimaryAuth extends FrontMcpAuth<RemoteAuthOptions> {\n override ready: Promise<void>;\n private jwks = new JwksService();\n\n constructor(private readonly scope: ScopeEntry, private readonly providers: ProviderRegistry, options: RemoteAuthOptions) {\n super(options);\n this.ready = this.initialize();\n }\n\n override fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n return fetch(input, init);\n }\n\n override validate(request: ServerRequest): Promise<void> {\n return Promise.resolve();\n }\n\n\n get issuer(): string {\n return this.options.baseUrl;\n }\n\n protected async initialize() {\n const scope = this.providers.getActiveScope();\n\n this.providers.injectProvider({\n value: this.jwks,\n metadata: {\n scope: ProviderScope.GLOBAL,\n name: 'auth:jwk-service',\n },\n provide: JwksService,\n });\n\n await this.registerAuthFlows(scope);\n return Promise.resolve();\n }\n\n\n private async registerAuthFlows(scope: Scope) {\n await scope.registryFlows(\n WellKnownPrmFlow, /** /.well-known/oauth-protected-resource */\n WellKnownAsFlow, /** /.well-known/oauth-authorization-server */\n WellKnownJwksFlow, /** /.well-known/jwks.json */\n SessionVerifyFlow, /** Session verification flow */\n );\n }\n}"]}
|
|
@@ -92,7 +92,6 @@ class JwksService {
|
|
|
92
92
|
const { payload, protectedHeader } = await (0, jose_1.jwtVerify)(token, JWKS, {
|
|
93
93
|
issuer: [
|
|
94
94
|
(0, jwks_utils_1.normalizeIssuer)(p.issuerUrl),
|
|
95
|
-
// ]
|
|
96
95
|
].concat((draftPayload?.['iss'] ? [draftPayload['iss']] : [])), // used because current cloud gateway have invalid issuer
|
|
97
96
|
});
|
|
98
97
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwks.service.js","sourceRoot":"","sources":["../../../../src/auth/jwks/jwks.service.ts"],"names":[],"mappings":"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","sourcesContent":["// auth/jwks/jwks.service.ts\nimport crypto from 'node:crypto';\nimport {jwtVerify, createLocalJWKSet, decodeProtectedHeader, JSONWebKeySet} from 'jose';\nimport {JwksServiceOptions, ProviderVerifyRef, VerifyResult} from './jwks.types';\nimport {normalizeIssuer, trimSlash, decodeJwtPayloadSafe} from './jwks.utils';\n\nexport class JwksService {\n private readonly opts: Required<JwksServiceOptions>;\n\n // Orchestrator signing material\n private orchestratorKey!: {\n kid: string;\n privateKey: crypto.KeyObject;\n publicJwk: JSONWebKeySet;\n createdAt: number;\n };\n\n // Provider JWKS cache (providerId -> jwks + fetchedAt)\n private providerJwks = new Map<string, { jwks: JSONWebKeySet; fetchedAt: number }>();\n\n constructor(opts?: JwksServiceOptions) {\n this.opts = {\n orchestratorAlg: opts?.orchestratorAlg ?? 'RS256',\n rotateDays: opts?.rotateDays ?? 30,\n providerJwksTtlMs: opts?.providerJwksTtlMs ?? 6 * 60 * 60 * 1000, // 6h\n networkTimeoutMs: opts?.networkTimeoutMs ?? 5000, // 5s\n };\n }\n\n // ===========================================================================\n // Public JWKS (what /.well-known/jwks.json serves)\n // ===========================================================================\n\n /** Gateway's public JWKS (publish at /.well-known/jwks.json when orchestrated). */\n getPublicJwks(): JSONWebKeySet {\n return this.getOrchestratorJwks();\n }\n\n // ===========================================================================\n // Scope-aware verification API\n // ===========================================================================\n\n /** Verify a token issued by the gateway itself (orchestrated mode). */\n async verifyGatewayToken(token: string, expectedIssuer: string): Promise<VerifyResult> {\n try {\n // TODO: add support for local/remote proxy mode\n // current implementation for anonymous mode only\n\n // const jwks = this.getPublicJwks();\n // const JWKS = createLocalJWKSet(jwks);\n // const {payload, protectedHeader} = await jwtVerify(token, JWKS, {\n // issuer: normalizeIssuer(expectedIssuer),\n // });\n // return {\n // ok: true,\n // issuer: payload?.iss as string | undefined,\n // sub: payload?.sub as string | undefined,\n // header: protectedHeader,\n // payload,\n // };\n\n const payload = decodeJwtPayloadSafe(token);\n if (!payload) {\n return {\n ok: false,\n error: 'invalid bearer token'\n }\n }\n return {\n ok: true,\n issuer: expectedIssuer,\n sub: payload['sub'] as string,\n payload,\n header: decodeProtectedHeader(token),\n }\n } catch (err: any) {\n return {ok: false, error: err?.message ?? 'verification_failed'};\n }\n }\n\n /**\n * Verify a token against candidate transparent providers.\n * Ensures JWKS are available (cached/TTL/AS discovery) per provider.\n */\n async verifyTransparentToken(token: string, candidates: ProviderVerifyRef[]): Promise<VerifyResult> {\n if (!candidates?.length) return {ok: false, error: 'no_providers'};\n\n // Helpful only for error messages\n let kid: string | undefined;\n try {\n const header = decodeProtectedHeader(token);\n\n kid = typeof header?.kid === 'string' ? header.kid : undefined;\n } catch {\n /* empty */\n }\n\n for (const p of candidates) {\n try {\n const jwks = await this.getJwksForProvider(p);\n if (!jwks?.keys?.length) continue;\n const draftPayload = decodeJwtPayloadSafe(token);\n const JWKS = createLocalJWKSet(jwks);\n const {payload, protectedHeader} = await jwtVerify(token, JWKS, {\n issuer: [\n normalizeIssuer(p.issuerUrl),\n\n // ]\n ].concat((draftPayload?.['iss'] ? [draftPayload['iss']] : []) as string[]), // used because current cloud gateway have invalid issuer\n });\n\n return {\n ok: true,\n issuer: payload?.iss as string | undefined,\n sub: payload?.sub as string | undefined,\n providerId: p.id,\n header: protectedHeader,\n payload,\n };\n } catch (e) {\n console.log('failed to verify token for provider: ', p.id, e);\n // try next provider\n }\n }\n\n return {ok: false, error: `no_provider_verified${kid ? ` (kid=${kid})` : ''}`};\n }\n\n // ===========================================================================\n // Provider JWKS (cache + preload + discovery)\n // ===========================================================================\n\n /** Directly set provider JWKS (e.g., inline keys from config). */\n setProviderJwks(providerId: string, jwks: JSONWebKeySet) {\n this.providerJwks.set(providerId, {jwks, fetchedAt: Date.now()});\n }\n\n /**\n * Ensure JWKS for a provider:\n * 1) inline jwks (if provided) → cache & return\n * 2) cached & fresh (TTL) → return\n * 3) explicit jwksUri → fetch, cache, return\n * 4) discover jwks_uri via AS → fetch AS metadata, then jwks_uri, cache, return\n */\n async getJwksForProvider(ref: ProviderVerifyRef): Promise<JSONWebKeySet | undefined> {\n // Inline keys win\n if (ref.jwks?.keys?.length) {\n this.setProviderJwks(ref.id, ref.jwks);\n return ref.jwks;\n }\n\n // Cache hit and fresh?\n const cached = this.providerJwks.get(ref.id);\n if (cached && Date.now() - cached.fetchedAt < this.opts.providerJwksTtlMs) {\n return cached.jwks;\n }\n\n // If we have a jwksUri, try it\n if (ref.jwksUri) {\n const fromUri = await this.tryFetchJwks(ref.id, ref.jwksUri);\n if (fromUri?.keys?.length) return fromUri;\n }\n\n // Discover via AS .well-known\n const issuer = trimSlash(ref.issuerUrl);\n const meta = await this.tryFetchAsMeta(`${issuer}/.well-known/oauth-authorization-server`);\n const uri = meta && typeof meta === 'object' && meta.jwks_uri ? String(meta.jwks_uri) : undefined;\n if (uri) {\n const fromMeta = await this.tryFetchJwks(ref.id, uri);\n if (fromMeta?.keys?.length) return fromMeta;\n }\n\n return cached?.jwks; // return stale if we had anything, else undefined\n }\n\n // ===========================================================================\n // Orchestrator keys (generation/rotation)\n // ===========================================================================\n\n /** Return the orchestrator public JWKS (generates/rotates as needed). */\n getOrchestratorJwks(): JSONWebKeySet {\n this.ensureOrchestratorKey();\n return this.orchestratorKey.publicJwk;\n }\n\n /** Return private signing key + kid for issuing orchestrator tokens. */\n getOrchestratorSigningKey(): { kid: string; key: crypto.KeyObject; alg: string } {\n this.ensureOrchestratorKey();\n return {kid: this.orchestratorKey.kid, key: this.orchestratorKey.privateKey, alg: this.opts.orchestratorAlg};\n }\n\n // ===========================================================================\n // Internals (fetch, rotation, helpers)\n // ===========================================================================\n\n private async tryFetchJwks(providerId: string, uri: string): Promise<JSONWebKeySet | undefined> {\n try {\n const jwks = await this.fetchJson<JSONWebKeySet>(uri);\n if (jwks?.keys?.length) {\n this.setProviderJwks(providerId, jwks);\n return jwks;\n }\n } catch {\n /* empty */\n }\n return undefined;\n }\n\n private async tryFetchAsMeta(url: string): Promise<any | undefined> {\n try {\n return await this.fetchJson(url);\n } catch {\n return undefined;\n }\n }\n\n private async fetchJson<T = any>(url: string): Promise<T> {\n const ctl = typeof AbortController !== 'undefined' ? new AbortController() : undefined;\n const timer = setTimeout(() => ctl?.abort(), this.opts.networkTimeoutMs);\n try {\n const res = await fetch(url, {\n method: 'GET',\n headers: {accept: 'application/json'},\n signal: ctl?.signal,\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private ensureOrchestratorKey() {\n const now = Date.now();\n const maxAge = this.opts.rotateDays * 24 * 60 * 60 * 1000;\n if (!this.orchestratorKey || now - this.orchestratorKey.createdAt > maxAge) {\n this.orchestratorKey = this.generateKey(this.opts.orchestratorAlg);\n }\n }\n\n private generateKey(alg: 'RS256' | 'ES256') {\n if (alg === 'RS256') {\n const {privateKey, publicKey} = crypto.generateKeyPairSync('rsa', {modulusLength: 2048});\n const kid = crypto.randomBytes(8).toString('hex');\n const publicJwk = publicKey.export({format: 'jwk'});\n Object.assign(publicJwk, {kid, alg: 'RS256', use: 'sig', kty: 'RSA'});\n return {kid, privateKey, publicJwk: {keys: [publicJwk]}, createdAt: Date.now()};\n } else {\n const {privateKey, publicKey} = crypto.generateKeyPairSync('ec', {namedCurve: 'P-256'});\n const kid = crypto.randomBytes(8).toString('hex');\n const publicJwk = publicKey.export({format: 'jwk'});\n Object.assign(publicJwk, {kid, alg: 'ES256', use: 'sig', kty: 'EC'});\n return {kid, privateKey, publicJwk: {keys: [publicJwk]}, createdAt: Date.now()};\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"jwks.service.js","sourceRoot":"","sources":["../../../../src/auth/jwks/jwks.service.ts"],"names":[],"mappings":"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","sourcesContent":["// auth/jwks/jwks.service.ts\nimport crypto from 'node:crypto';\nimport {jwtVerify, createLocalJWKSet, decodeProtectedHeader, JSONWebKeySet} from 'jose';\nimport {JwksServiceOptions, ProviderVerifyRef, VerifyResult} from './jwks.types';\nimport {normalizeIssuer, trimSlash, decodeJwtPayloadSafe} from './jwks.utils';\n\nexport class JwksService {\n private readonly opts: Required<JwksServiceOptions>;\n\n // Orchestrator signing material\n private orchestratorKey!: {\n kid: string;\n privateKey: crypto.KeyObject;\n publicJwk: JSONWebKeySet;\n createdAt: number;\n };\n\n // Provider JWKS cache (providerId -> jwks + fetchedAt)\n private providerJwks = new Map<string, { jwks: JSONWebKeySet; fetchedAt: number }>();\n\n constructor(opts?: JwksServiceOptions) {\n this.opts = {\n orchestratorAlg: opts?.orchestratorAlg ?? 'RS256',\n rotateDays: opts?.rotateDays ?? 30,\n providerJwksTtlMs: opts?.providerJwksTtlMs ?? 6 * 60 * 60 * 1000, // 6h\n networkTimeoutMs: opts?.networkTimeoutMs ?? 5000, // 5s\n };\n }\n\n // ===========================================================================\n // Public JWKS (what /.well-known/jwks.json serves)\n // ===========================================================================\n\n /** Gateway's public JWKS (publish at /.well-known/jwks.json when orchestrated). */\n getPublicJwks(): JSONWebKeySet {\n return this.getOrchestratorJwks();\n }\n\n // ===========================================================================\n // Scope-aware verification API\n // ===========================================================================\n\n /** Verify a token issued by the gateway itself (orchestrated mode). */\n async verifyGatewayToken(token: string, expectedIssuer: string): Promise<VerifyResult> {\n try {\n // TODO: add support for local/remote proxy mode\n // current implementation for anonymous mode only\n\n // const jwks = this.getPublicJwks();\n // const JWKS = createLocalJWKSet(jwks);\n // const {payload, protectedHeader} = await jwtVerify(token, JWKS, {\n // issuer: normalizeIssuer(expectedIssuer),\n // });\n // return {\n // ok: true,\n // issuer: payload?.iss as string | undefined,\n // sub: payload?.sub as string | undefined,\n // header: protectedHeader,\n // payload,\n // };\n\n const payload = decodeJwtPayloadSafe(token);\n if (!payload) {\n return {\n ok: false,\n error: 'invalid bearer token'\n }\n }\n return {\n ok: true,\n issuer: expectedIssuer,\n sub: payload['sub'] as string,\n payload,\n header: decodeProtectedHeader(token),\n }\n } catch (err: any) {\n return {ok: false, error: err?.message ?? 'verification_failed'};\n }\n }\n\n /**\n * Verify a token against candidate transparent providers.\n * Ensures JWKS are available (cached/TTL/AS discovery) per provider.\n */\n async verifyTransparentToken(token: string, candidates: ProviderVerifyRef[]): Promise<VerifyResult> {\n if (!candidates?.length) return {ok: false, error: 'no_providers'};\n\n // Helpful only for error messages\n let kid: string | undefined;\n try {\n const header = decodeProtectedHeader(token);\n\n kid = typeof header?.kid === 'string' ? header.kid : undefined;\n } catch {\n /* empty */\n }\n\n for (const p of candidates) {\n try {\n const jwks = await this.getJwksForProvider(p);\n if (!jwks?.keys?.length) continue;\n const draftPayload = decodeJwtPayloadSafe(token);\n const JWKS = createLocalJWKSet(jwks);\n const {payload, protectedHeader} = await jwtVerify(token, JWKS, {\n issuer: [\n normalizeIssuer(p.issuerUrl),\n ].concat((draftPayload?.['iss'] ? [draftPayload['iss']] : []) as string[]), // used because current cloud gateway have invalid issuer\n });\n\n return {\n ok: true,\n issuer: payload?.iss as string | undefined,\n sub: payload?.sub as string | undefined,\n providerId: p.id,\n header: protectedHeader,\n payload,\n };\n } catch (e) {\n console.log('failed to verify token for provider: ', p.id, e);\n // try next provider\n }\n }\n\n return {ok: false, error: `no_provider_verified${kid ? ` (kid=${kid})` : ''}`};\n }\n\n // ===========================================================================\n // Provider JWKS (cache + preload + discovery)\n // ===========================================================================\n\n /** Directly set provider JWKS (e.g., inline keys from config). */\n setProviderJwks(providerId: string, jwks: JSONWebKeySet) {\n this.providerJwks.set(providerId, {jwks, fetchedAt: Date.now()});\n }\n\n /**\n * Ensure JWKS for a provider:\n * 1) inline jwks (if provided) → cache & return\n * 2) cached & fresh (TTL) → return\n * 3) explicit jwksUri → fetch, cache, return\n * 4) discover jwks_uri via AS → fetch AS metadata, then jwks_uri, cache, return\n */\n async getJwksForProvider(ref: ProviderVerifyRef): Promise<JSONWebKeySet | undefined> {\n // Inline keys win\n if (ref.jwks?.keys?.length) {\n this.setProviderJwks(ref.id, ref.jwks);\n return ref.jwks;\n }\n\n // Cache hit and fresh?\n const cached = this.providerJwks.get(ref.id);\n if (cached && Date.now() - cached.fetchedAt < this.opts.providerJwksTtlMs) {\n return cached.jwks;\n }\n\n // If we have a jwksUri, try it\n if (ref.jwksUri) {\n const fromUri = await this.tryFetchJwks(ref.id, ref.jwksUri);\n if (fromUri?.keys?.length) return fromUri;\n }\n\n // Discover via AS .well-known\n const issuer = trimSlash(ref.issuerUrl);\n const meta = await this.tryFetchAsMeta(`${issuer}/.well-known/oauth-authorization-server`);\n const uri = meta && typeof meta === 'object' && meta.jwks_uri ? String(meta.jwks_uri) : undefined;\n if (uri) {\n const fromMeta = await this.tryFetchJwks(ref.id, uri);\n if (fromMeta?.keys?.length) return fromMeta;\n }\n\n return cached?.jwks; // return stale if we had anything, else undefined\n }\n\n // ===========================================================================\n // Orchestrator keys (generation/rotation)\n // ===========================================================================\n\n /** Return the orchestrator public JWKS (generates/rotates as needed). */\n getOrchestratorJwks(): JSONWebKeySet {\n this.ensureOrchestratorKey();\n return this.orchestratorKey.publicJwk;\n }\n\n /** Return private signing key + kid for issuing orchestrator tokens. */\n getOrchestratorSigningKey(): { kid: string; key: crypto.KeyObject; alg: string } {\n this.ensureOrchestratorKey();\n return {kid: this.orchestratorKey.kid, key: this.orchestratorKey.privateKey, alg: this.opts.orchestratorAlg};\n }\n\n // ===========================================================================\n // Internals (fetch, rotation, helpers)\n // ===========================================================================\n\n private async tryFetchJwks(providerId: string, uri: string): Promise<JSONWebKeySet | undefined> {\n try {\n const jwks = await this.fetchJson<JSONWebKeySet>(uri);\n if (jwks?.keys?.length) {\n this.setProviderJwks(providerId, jwks);\n return jwks;\n }\n } catch {\n /* empty */\n }\n return undefined;\n }\n\n private async tryFetchAsMeta(url: string): Promise<any | undefined> {\n try {\n return await this.fetchJson(url);\n } catch {\n return undefined;\n }\n }\n\n private async fetchJson<T = any>(url: string): Promise<T> {\n const ctl = typeof AbortController !== 'undefined' ? new AbortController() : undefined;\n const timer = setTimeout(() => ctl?.abort(), this.opts.networkTimeoutMs);\n try {\n const res = await fetch(url, {\n method: 'GET',\n headers: {accept: 'application/json'},\n signal: ctl?.signal,\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private ensureOrchestratorKey() {\n const now = Date.now();\n const maxAge = this.opts.rotateDays * 24 * 60 * 60 * 1000;\n if (!this.orchestratorKey || now - this.orchestratorKey.createdAt > maxAge) {\n this.orchestratorKey = this.generateKey(this.opts.orchestratorAlg);\n }\n }\n\n private generateKey(alg: 'RS256' | 'ES256') {\n if (alg === 'RS256') {\n const {privateKey, publicKey} = crypto.generateKeyPairSync('rsa', {modulusLength: 2048});\n const kid = crypto.randomBytes(8).toString('hex');\n const publicJwk = publicKey.export({format: 'jwk'});\n Object.assign(publicJwk, {kid, alg: 'RS256', use: 'sig', kty: 'RSA'});\n return {kid, privateKey, publicJwk: {keys: [publicJwk]}, createdAt: Date.now()};\n } else {\n const {privateKey, publicKey} = crypto.generateKeyPairSync('ec', {namedCurve: 'P-256'});\n const kid = crypto.randomBytes(8).toString('hex');\n const publicJwk = publicKey.export({format: 'jwk'});\n Object.assign(publicJwk, {kid, alg: 'ES256', use: 'sig', kty: 'EC'});\n return {kid, privateKey, publicJwk: {keys: [publicJwk]}, createdAt: Date.now()};\n }\n }\n}\n"]}
|
|
@@ -1,42 +1,103 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
import { ToolMetadata } from '../metadata';
|
|
2
|
+
import { ToolMetadata, ImageOutputSchema, AudioOutputSchema, ResourceOutputSchema, ResourceLinkOutputSchema, ToolInputType, ToolOutputType } from '../metadata';
|
|
3
3
|
import z from 'zod';
|
|
4
|
-
import { ToolContext } from
|
|
5
|
-
export type FrontMcpToolExecuteHandler<
|
|
4
|
+
import { ToolContext } from '../interfaces';
|
|
5
|
+
export type FrontMcpToolExecuteHandler<InSchema extends ToolInputType, OutSchema extends ToolOutputType, In = ToolInputOf<{
|
|
6
|
+
inputSchema: InSchema;
|
|
7
|
+
}>, Out = ToolOutputOf<{
|
|
8
|
+
outputSchema: OutSchema;
|
|
9
|
+
}>> = (input: In, ctx: ToolContext<InSchema, OutSchema>) => Out | Promise<Out>;
|
|
6
10
|
/**
|
|
7
11
|
* Decorator that marks a class as a McpTool module and provides metadata
|
|
8
12
|
*/
|
|
9
|
-
declare function frontMcpTool<T extends ToolMetadata,
|
|
10
|
-
export { FrontMcpTool, FrontMcpTool as Tool, frontMcpTool, frontMcpTool as tool
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
13
|
+
declare function frontMcpTool<T extends ToolMetadata, InSchema extends ToolInputType = T['inputSchema'], OutSchema extends ToolOutputType = T['outputSchema']>(providedMetadata: T): (handler: FrontMcpToolExecuteHandler<InSchema, OutSchema>) => () => void;
|
|
14
|
+
export { FrontMcpTool, FrontMcpTool as Tool, frontMcpTool, frontMcpTool as tool };
|
|
15
|
+
/**
|
|
16
|
+
* This is a modified version of the original decorator, with the following changes:
|
|
17
|
+
* - Added support for ZodRawShape as inputSchema
|
|
18
|
+
* - Added support for outputSchema: any of the allowed forms
|
|
19
|
+
* - Added rich error messages for input/output type mismatches
|
|
20
|
+
*
|
|
21
|
+
* Don't move below code outside the decorator file, it will break the module augmentation.
|
|
22
|
+
*/
|
|
23
|
+
type __Shape = z.ZodRawShape;
|
|
24
|
+
type __AsZodObj<T> = T extends z.ZodObject<infer S> ? z.ZodObject<S> : T extends z.ZodRawShape ? z.ZodObject<T> : never;
|
|
25
|
+
export type ToolInputOf<Opt> = Opt extends {
|
|
26
|
+
inputSchema: infer I;
|
|
27
|
+
} ? z.infer<__AsZodObj<I>> : never;
|
|
28
|
+
/**
|
|
29
|
+
* Helper to infer the return type from any Zod schema,
|
|
30
|
+
* including ZodRawShape.
|
|
31
|
+
*/
|
|
32
|
+
type __InferZod<S> = S extends z.ZodTypeAny ? z.infer<S> : S extends z.ZodRawShape ? z.infer<z.ZodObject<S>> : never;
|
|
33
|
+
/**
|
|
34
|
+
* Infers the *output type* from a *single schema definition*
|
|
35
|
+
* based on the new ToolSingleOutputType.
|
|
36
|
+
*/
|
|
37
|
+
type __InferFromSingleSchema<S> = S extends 'image' ? z.infer<typeof ImageOutputSchema> : S extends 'audio' ? z.infer<typeof AudioOutputSchema> : S extends 'resource' ? z.infer<typeof ResourceOutputSchema> : S extends 'resource_link' ? z.infer<typeof ResourceLinkOutputSchema> : S extends 'string' ? string : S extends 'number' ? number : S extends 'boolean' ? boolean : S extends 'date' ? Date : S extends z.ZodTypeAny | z.ZodRawShape ? __InferZod<S> : any;
|
|
38
|
+
/**
|
|
39
|
+
* Infers a tuple/array of output types from an array of schemas
|
|
40
|
+
*/
|
|
41
|
+
type __InferFromArraySchema<A> = A extends readonly any[] ? {
|
|
42
|
+
[K in keyof A]: __InferFromSingleSchema<A[K]>;
|
|
43
|
+
} : never;
|
|
44
|
+
/**
|
|
45
|
+
* Main output type inference.
|
|
46
|
+
* Handles single schemas, arrays of schemas, or no schema.
|
|
47
|
+
*/
|
|
48
|
+
export type ToolOutputOf<Opt> = Opt extends {
|
|
49
|
+
outputSchema: infer O;
|
|
50
|
+
} ? O extends readonly any[] ? __InferFromArraySchema<O> : __InferFromSingleSchema<O> : any;
|
|
51
|
+
type __PrimitiveOutputType = 'string' | 'number' | 'date' | 'boolean' | z.ZodString | z.ZodNumber | z.ZodBoolean | z.ZodBigInt | z.ZodDate;
|
|
52
|
+
type __ImageOutputType = 'image';
|
|
53
|
+
type __AudioOutputType = 'audio';
|
|
54
|
+
type __ResourceOutputType = 'resource';
|
|
55
|
+
type __ResourceLinkOutputType = 'resource_link';
|
|
56
|
+
type __StructuredOutputType = z.ZodRawShape | z.ZodObject<any> | z.ZodArray<any> | z.ZodUnion<[z.ZodObject<any>, ...z.ZodObject<any>[]]> | z.ZodDiscriminatedUnion<any, any>;
|
|
57
|
+
type __ToolSingleOutputType = __PrimitiveOutputType | __ImageOutputType | __AudioOutputType | __ResourceOutputType | __ResourceLinkOutputType | __StructuredOutputType;
|
|
58
|
+
type __OutputSchema = __ToolSingleOutputType | __ToolSingleOutputType[];
|
|
59
|
+
export type ToolMetadataOptions<I extends __Shape, O extends __OutputSchema> = ToolMetadata<I | z.ZodObject<I>, // inputSchema can be a raw shape or ZodObject
|
|
60
|
+
O>;
|
|
61
|
+
type __Ctor = (new (...a: any[]) => any) | (abstract new (...a: any[]) => any);
|
|
62
|
+
type __A<C extends __Ctor> = C extends new (...a: infer A) => any ? A : C extends abstract new (...a: infer A) => any ? A : never;
|
|
63
|
+
type __R<C extends __Ctor> = C extends new (...a: any[]) => infer R ? R : C extends abstract new (...a: any[]) => infer R ? R : never;
|
|
64
|
+
type __Param<C extends __Ctor> = __R<C> extends {
|
|
65
|
+
execute: (arg: infer P, ...r: any) => any;
|
|
66
|
+
} ? P : never;
|
|
67
|
+
type __Return<C extends __Ctor> = __R<C> extends {
|
|
68
|
+
execute: (...a: any) => infer R;
|
|
69
|
+
} ? R : never;
|
|
70
|
+
type __Unwrap<T> = T extends Promise<infer U> ? U : T;
|
|
71
|
+
type __IsAny<T> = 0 extends 1 & T ? true : false;
|
|
72
|
+
type __MustExtendCtx<C extends __Ctor> = __R<C> extends ToolContext ? unknown : {
|
|
73
|
+
'Tool class error': 'Class must extend ToolContext';
|
|
74
|
+
};
|
|
75
|
+
type __MustParam<C extends __Ctor, In> = __IsAny<In> extends true ? unknown : __IsAny<__Param<C>> extends true ? {
|
|
76
|
+
'execute() parameter error': "Parameter type must not be 'any'.";
|
|
77
|
+
expected_input_type: In;
|
|
78
|
+
} : __Param<C> extends In ? In extends __Param<C> ? unknown : {
|
|
79
|
+
'execute() parameter error': 'Parameter type is too wide. It must exactly match the input schema.';
|
|
80
|
+
expected_input_type: In;
|
|
81
|
+
actual_parameter_type: __Param<C>;
|
|
82
|
+
} : {
|
|
83
|
+
'execute() parameter error': 'Parameter type does not match the input schema.';
|
|
84
|
+
expected_input_type: In;
|
|
85
|
+
actual_parameter_type: __Param<C>;
|
|
86
|
+
};
|
|
87
|
+
type __MustReturn<C extends __Ctor, Out> = __IsAny<Out> extends true ? unknown : __Unwrap<__Return<C>> extends Out ? unknown : {
|
|
88
|
+
'execute() return type error': "The method's return type is not assignable to the expected output schema type.";
|
|
89
|
+
expected_output_type: Out;
|
|
90
|
+
'actual_return_type (unwrapped)': __Unwrap<__Return<C>>;
|
|
91
|
+
};
|
|
92
|
+
type __Rewrap<C extends __Ctor, In, Out> = C extends abstract new (...a: __A<C>) => __R<C> ? C & (abstract new (...a: __A<C>) => ToolContext<any, any, In, Out> & __R<C>) : C extends new (...a: __A<C>) => __R<C> ? C & (new (...a: __A<C>) => ToolContext<any, any, In, Out> & __R<C>) : never;
|
|
93
|
+
declare module '@frontmcp/sdk' {
|
|
94
|
+
function Tool<I extends __Shape, O extends __OutputSchema, // Use our new output schema constraint
|
|
95
|
+
T extends ToolMetadataOptions<I, O> & {
|
|
96
|
+
outputSchema: any;
|
|
97
|
+
}>(opts: T): <C extends __Ctor>(cls: C & __MustExtendCtx<C> & __MustParam<C, ToolInputOf<T>> & // <-- Will now show a rich error
|
|
98
|
+
__MustReturn<C, ToolOutputOf<T>>) => __Rewrap<C, ToolInputOf<T>, ToolOutputOf<T>>;
|
|
99
|
+
function Tool<I extends __Shape, T extends ToolMetadataOptions<I, any> & {
|
|
100
|
+
outputSchema?: never;
|
|
101
|
+
}>(opts: T): <C extends __Ctor>(cls: C & __MustExtendCtx<C> & __MustParam<C, ToolInputOf<T>> & // <-- Will now show a rich error
|
|
102
|
+
__MustReturn<C, ToolOutputOf<T>>) => __Rewrap<C, ToolInputOf<T>, ToolOutputOf<T>>;
|
|
42
103
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.decorator.js","sourceRoot":"","sources":["../../../../src/common/decorators/tool.decorator.ts"],"names":[],"mappings":";AAAA,aAAa;;AAoDX,oCAAY;AACI,4BAAI;AACpB,oCAAY;AACI,4BAAI;AArDtB,4BAA0B;AAC1B,sCAAmE;AACnE,0CAAqE;AAIrE;;GAEG;AACH,SAAS,YAAY,CAAC,gBAA8B;IAElD,OAAO,CAAC,MAAW,EAAE,EAAE;QACrB,MAAM,QAAQ,GAAG,qCAA0B,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpE,OAAO,CAAC,cAAc,CAAC,2BAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,2BAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,OAAO,CAAC,cAAc,CAAC,2BAAkB,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;YACnF,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,OAAO,CAAC,cAAc,CAAC,6BAAoB,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC,CAAC;AACJ,CAAC;AAKD;;GAEG;AACH,SAAS,YAAY,CAGnB,gBAAmB;IACnB,OAAO,CAAC,OAAO,EAAE,EAAE;QACjB,MAAM,QAAQ,GAAG,qCAA0B,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpE,MAAM,YAAY,GAAG;YACnB,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE;YAC1B,CAAC,2BAAkB,CAAC,IAAI,CAAC,EAAE,eAAe;YAC1C,CAAC,2BAAkB,CAAC,QAAQ,CAAC,EAAE,QAAQ;SACxC,CAAC,CAAC;QACH,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC;AACJ,CAAC","sourcesContent":["// @ts-ignore\n\nimport 'reflect-metadata';\nimport {extendedToolMetadata, FrontMcpToolTokens} from '../tokens';\nimport {ToolMetadata, frontMcpToolMetadataSchema} from '../metadata';\nimport z from 'zod';\nimport {ToolContext} from \"../interfaces\";\n\n/**\n * Decorator that marks a class as a McpTool module and provides metadata\n */\nfunction FrontMcpTool(providedMetadata: ToolMetadata): ClassDecorator {\n\n return (target: any) => {\n const metadata = frontMcpToolMetadataSchema.parse(providedMetadata);\n Reflect.defineMetadata(FrontMcpToolTokens.type, true, target);\n const extended = {};\n for (const property in metadata) {\n if (FrontMcpToolTokens[property]) {\n Reflect.defineMetadata(FrontMcpToolTokens[property], metadata[property], target);\n } else {\n extended[property] = metadata[property];\n }\n }\n Reflect.defineMetadata(extendedToolMetadata, extended, target);\n };\n}\n\n\nexport type FrontMcpToolExecuteHandler<In extends object, Out extends object> = (input: In, ctx: ToolContext<In, Out>) => Out | Promise<Out>;\n\n/**\n * Decorator that marks a class as a McpTool module and provides metadata\n */\nfunction frontMcpTool<T extends ToolMetadata,\n In extends object = z.baseObjectInputType<T['inputSchema']>,\n Out extends object = T['outputSchema'] extends z.ZodRawShape ? z.baseObjectInputType<T['outputSchema']> : object\n>(providedMetadata: T): (handler: FrontMcpToolExecuteHandler<In, Out>) => (() => void) {\n return (execute) => {\n const metadata = frontMcpToolMetadataSchema.parse(providedMetadata);\n const toolFunction = function () {\n return execute;\n };\n Object.assign(toolFunction, {\n [FrontMcpToolTokens.type]: 'function-tool',\n [FrontMcpToolTokens.metadata]: metadata,\n });\n return toolFunction;\n };\n}\n\nexport {\n FrontMcpTool,\n FrontMcpTool as Tool,\n frontMcpTool,\n frontMcpTool as tool,\n};\n\n\ndeclare module \"@frontmcp/sdk\" {\n // ---------- zod helpers ----------\n type __Shape = z.ZodRawShape; // = Record<string, z.ZodTypeAny>\n type __AsZodObj<T> =\n T extends z.ZodObject<infer S> ? z.ZodObject<S> :\n T extends z.ZodRawShape ? z.ZodObject<T> :\n never;\n\n export type __InputOf<Opt> =\n Opt extends { inputSchema: infer I } ? z.infer<__AsZodObj<I>> : never;\n\n export type __OutputOf<Opt> =\n Opt extends { outputSchema: infer O } ? z.infer<__AsZodObj<O>> : never;\n\n export type __ToolOptions<I extends __Shape, O extends __Shape> = ToolMetadata<I | z.ZodObject<I>, O | z.ZodObject<O>>;\n\n // ---------- ctor & reflection ----------\n type __Ctor = new (...a: any[]) => any | (abstract new (...a: any[]) => any);\n type __A<C extends __Ctor> = C extends new (...a: infer A) => any ? A\n : C extends abstract new (...a: infer A) => any ? A : never;\n type __R<C extends __Ctor> = C extends new (...a: any[]) => infer R ? R\n : C extends abstract new (...a: any[]) => infer R ? R : never;\n\n type __Param<C extends __Ctor> =\n __R<C> extends { execute: (arg: infer P, ...r: any) => any } ? P : never;\n\n type __Return<C extends __Ctor> =\n __R<C> extends { execute: (...a: any) => infer R } ? R : never;\n\n type __Unwrap<T> = T extends Promise<infer U> ? U : T;\n type __IsAny<T> = 0 extends (1 & T) ? true : false;\n\n // ---------- friendly branded errors ----------\n type __Err<M extends string> = { __type_error__: M } & { never?: never };\n\n // Must extend ToolContext\n type __MustExtendCtx<C extends __Ctor> =\n __R<C> extends ToolContext ? {} :\n __Err<\"Class must extend ToolContext\">;\n\n // execute param must exactly match In (and not be any)\n type __MustParam<C extends __Ctor, In> =\n __IsAny<__Param<C>> extends true\n ? __Err<\"execute(input) must not be any and must exactly match input schema\">\n : __Param<C> extends In\n ? (In extends __Param<C> ? {} : __Err<\"execute(input) must be exactly the input schema (no widening or narrowing)\">)\n : __Err<\"execute(input) parameter does not match input schema\">;\n\n // execute return must be Out or Promise<Out>\n type __MustReturn<C extends __Ctor, Out> =\n __Unwrap<__Return<C>> extends Out ? {} :\n __Err<\"execute return type must be output schema or Promise<output schema>\">;\n\n // Rewrapped constructor: preserve concrete/abstract + original type, but guarantee ToolContext<In,Out> on instance\n type __Rewrap<C extends __Ctor, In, Out> =\n C extends abstract new (...a: __A<C>) => __R<C>\n ? C & (abstract new (...a: __A<C>) => (ToolContext<In, Out> & __R<C>))\n : C extends new (...a: __A<C>) => __R<C>\n ? C & (new (...a: __A<C>) => (ToolContext<In, Out> & __R<C>))\n : never;\n\n // ---------- the decorator ----------\n // @ts-expect-error - Module augmentation requires decorator overload\n export function Tool<\n I extends __Shape,\n O extends __Shape,\n T extends __ToolOptions<I, O>\n >(opts: T): <\n C extends __Ctor\n >(cls: C &\n __MustExtendCtx<C> &\n __MustParam<C, __InputOf<T>> &\n __MustReturn<C, __OutputOf<T>>\n ) => __Rewrap<C, __InputOf<T>, __OutputOf<T>>;\n}"]}
|
|
1
|
+
{"version":3,"file":"tool.decorator.js","sourceRoot":"","sources":["../../../../src/common/decorators/tool.decorator.ts"],"names":[],"mappings":";;AA8DS,oCAAY;AAAkB,4BAAI;AAAE,oCAAY;AAAkB,4BAAI;AA9D/E,4BAA0B;AAC1B,sCAAqE;AACrE,0CASqB;AAIrB;;GAEG;AACH,SAAS,YAAY,CAAC,gBAA8B;IAClD,OAAO,CAAC,MAAW,EAAE,EAAE;QACrB,MAAM,QAAQ,GAAG,qCAA0B,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpE,OAAO,CAAC,cAAc,CAAC,2BAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,2BAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,OAAO,CAAC,cAAc,CAAC,2BAAkB,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;YACnF,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,OAAO,CAAC,cAAc,CAAC,6BAAoB,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC,CAAC;AACJ,CAAC;AASD;;GAEG;AACH,SAAS,YAAY,CAInB,gBAAmB;IACnB,OAAO,CAAC,OAAO,EAAE,EAAE;QACjB,MAAM,QAAQ,GAAG,qCAA0B,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpE,MAAM,YAAY,GAAG;YACnB,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE;YAC1B,CAAC,2BAAkB,CAAC,IAAI,CAAC,EAAE,eAAe;YAC1C,CAAC,2BAAkB,CAAC,QAAQ,CAAC,EAAE,QAAQ;SACxC,CAAC,CAAC;QACH,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import 'reflect-metadata';\nimport { extendedToolMetadata, FrontMcpToolTokens } from '../tokens';\nimport {\n ToolMetadata,\n frontMcpToolMetadataSchema,\n ImageOutputSchema,\n AudioOutputSchema,\n ResourceOutputSchema,\n ResourceLinkOutputSchema,\n ToolInputType,\n ToolOutputType,\n} from '../metadata';\nimport z from 'zod';\nimport { ToolContext } from '../interfaces';\n\n/**\n * Decorator that marks a class as a McpTool module and provides metadata\n */\nfunction FrontMcpTool(providedMetadata: ToolMetadata): ClassDecorator {\n return (target: any) => {\n const metadata = frontMcpToolMetadataSchema.parse(providedMetadata);\n Reflect.defineMetadata(FrontMcpToolTokens.type, true, target);\n const extended = {};\n for (const property in metadata) {\n if (FrontMcpToolTokens[property]) {\n Reflect.defineMetadata(FrontMcpToolTokens[property], metadata[property], target);\n } else {\n extended[property] = metadata[property];\n }\n }\n Reflect.defineMetadata(extendedToolMetadata, extended, target);\n };\n}\n\nexport type FrontMcpToolExecuteHandler<\n InSchema extends ToolInputType,\n OutSchema extends ToolOutputType,\n In = ToolInputOf<{ inputSchema: InSchema }>,\n Out = ToolOutputOf<{ outputSchema: OutSchema }>,\n> = (input: In, ctx: ToolContext<InSchema, OutSchema>) => Out | Promise<Out>;\n\n/**\n * Decorator that marks a class as a McpTool module and provides metadata\n */\nfunction frontMcpTool<\n T extends ToolMetadata,\n InSchema extends ToolInputType = T['inputSchema'],\n OutSchema extends ToolOutputType = T['outputSchema'],\n>(providedMetadata: T): (handler: FrontMcpToolExecuteHandler<InSchema, OutSchema>) => () => void {\n return (execute) => {\n const metadata = frontMcpToolMetadataSchema.parse(providedMetadata);\n const toolFunction = function () {\n return execute;\n };\n Object.assign(toolFunction, {\n [FrontMcpToolTokens.type]: 'function-tool',\n [FrontMcpToolTokens.metadata]: metadata,\n });\n return toolFunction;\n };\n}\n\nexport { FrontMcpTool, FrontMcpTool as Tool, frontMcpTool, frontMcpTool as tool };\n\n/**\n * This is a modified version of the original decorator, with the following changes:\n * - Added support for ZodRawShape as inputSchema\n * - Added support for outputSchema: any of the allowed forms\n * - Added rich error messages for input/output type mismatches\n *\n * Don't move below code outside the decorator file, it will break the module augmentation.\n */\n// ---------- zod helpers ----------\ntype __Shape = z.ZodRawShape;\ntype __AsZodObj<T> = T extends z.ZodObject<infer S> ? z.ZodObject<S> : T extends z.ZodRawShape ? z.ZodObject<T> : never;\n\nexport type ToolInputOf<Opt> = Opt extends { inputSchema: infer I } ? z.infer<__AsZodObj<I>> : never;\n\n// ---------- output inference helpers for NEW schemas ----------\n\n/**\n * Helper to infer the return type from any Zod schema,\n * including ZodRawShape.\n */\ntype __InferZod<S> = S extends z.ZodTypeAny ? z.infer<S> : S extends z.ZodRawShape ? z.infer<z.ZodObject<S>> : never;\n\n/**\n * Infers the *output type* from a *single schema definition*\n * based on the new ToolSingleOutputType.\n */\ntype __InferFromSingleSchema<S> =\n // Handle specific MCP type literals\n S extends 'image'\n ? z.infer<typeof ImageOutputSchema>\n : S extends 'audio'\n ? z.infer<typeof AudioOutputSchema>\n : S extends 'resource'\n ? z.infer<typeof ResourceOutputSchema>\n : S extends 'resource_link'\n ? z.infer<typeof ResourceLinkOutputSchema>\n : // Handle primitive type literals\n S extends 'string'\n ? string\n : S extends 'number'\n ? number\n : S extends 'boolean'\n ? boolean\n : S extends 'date'\n ? Date\n : // Handle all Zod schemas (primitives, objects, arrays, etc.)\n // This will correctly infer z.ZodString to string, etc.\n S extends z.ZodTypeAny | z.ZodRawShape\n ? __InferZod<S>\n : // Fallback for unknown/unrecognized schema\n any;\n\n/**\n * Infers a tuple/array of output types from an array of schemas\n */\ntype __InferFromArraySchema<A> = A extends readonly any[] ? { [K in keyof A]: __InferFromSingleSchema<A[K]> } : never;\n\n/**\n * Main output type inference.\n * Handles single schemas, arrays of schemas, or no schema.\n */\nexport type ToolOutputOf<Opt> = Opt extends { outputSchema: infer O }\n ? O extends readonly any[] // Check for array/tuple first\n ? __InferFromArraySchema<O>\n : __InferFromSingleSchema<O> // Handle a single schema\n : any; // no outputSchema property at all -> allow anything\n\n// --- Define the schema types locally to constrain the generic ---\n// This mirrors your `ToolOutputType` definitions for use in constraints.\n\ntype __PrimitiveOutputType =\n | 'string'\n | 'number'\n | 'date'\n | 'boolean'\n | z.ZodString\n | z.ZodNumber\n | z.ZodBoolean\n | z.ZodBigInt\n | z.ZodDate;\ntype __ImageOutputType = 'image';\ntype __AudioOutputType = 'audio';\ntype __ResourceOutputType = 'resource';\ntype __ResourceLinkOutputType = 'resource_link';\ntype __StructuredOutputType =\n | z.ZodRawShape\n | z.ZodObject<any>\n | z.ZodArray<any>\n | z.ZodUnion<[z.ZodObject<any>, ...z.ZodObject<any>[]]>\n | z.ZodDiscriminatedUnion<any, any>;\n\ntype __ToolSingleOutputType =\n | __PrimitiveOutputType\n | __ImageOutputType\n | __AudioOutputType\n | __ResourceOutputType\n | __ResourceLinkOutputType\n | __StructuredOutputType;\n\n// This is the final constraint for the `outputSchema` option\ntype __OutputSchema = __ToolSingleOutputType | __ToolSingleOutputType[];\n\nexport type ToolMetadataOptions<I extends __Shape, O extends __OutputSchema> = ToolMetadata<\n I | z.ZodObject<I>, // inputSchema can be a raw shape or ZodObject\n O // outputSchema: any of the allowed forms\n>;\n\n// ---------- ctor & reflection ----------\ntype __Ctor = (new (...a: any[]) => any) | (abstract new (...a: any[]) => any);\ntype __A<C extends __Ctor> = C extends new (...a: infer A) => any\n ? A\n : C extends abstract new (...a: infer A) => any\n ? A\n : never;\ntype __R<C extends __Ctor> = C extends new (...a: any[]) => infer R\n ? R\n : C extends abstract new (...a: any[]) => infer R\n ? R\n : never;\ntype __Param<C extends __Ctor> = __R<C> extends { execute: (arg: infer P, ...r: any) => any } ? P : never;\ntype __Return<C extends __Ctor> = __R<C> extends { execute: (...a: any) => infer R } ? R : never;\ntype __Unwrap<T> = T extends Promise<infer U> ? U : T;\ntype __IsAny<T> = 0 extends 1 & T ? true : false;\n\n// ---------- friendly branded errors (UPDATED) ----------\n\n// Must extend ToolContext (assuming ToolContext is exported by the SDK)\ntype __MustExtendCtx<C extends __Ctor> = __R<C> extends ToolContext\n ? unknown\n : { 'Tool class error': 'Class must extend ToolContext' };\n\n// execute param must exactly match In (and not be any)\ntype __MustParam<C extends __Ctor, In> =\n // 1. If 'In' (from schema) is 'any', we can't check, so allow.\n __IsAny<In> extends true\n ? unknown\n : // 2. Check if the actual param type is 'any'. This is an error.\n __IsAny<__Param<C>> extends true\n ? { 'execute() parameter error': \"Parameter type must not be 'any'.\"; expected_input_type: In }\n : // 3. Check for the exact match: Param extends In AND In extends Param\n __Param<C> extends In\n ? In extends __Param<C>\n ? unknown // OK, exact match\n : {\n 'execute() parameter error': 'Parameter type is too wide. It must exactly match the input schema.';\n expected_input_type: In;\n actual_parameter_type: __Param<C>;\n }\n : {\n 'execute() parameter error': 'Parameter type does not match the input schema.';\n expected_input_type: In;\n actual_parameter_type: __Param<C>;\n };\n\n// execute return must be Out or Promise<Out>\ntype __MustReturn<C extends __Ctor, Out> =\n // 1. If 'Out' (from schema) is 'any', no check is needed.\n __IsAny<Out> extends true\n ? unknown\n : // 2. Check if the unwrapped return type is assignable to Out.\n __Unwrap<__Return<C>> extends Out\n ? unknown // OK\n : {\n 'execute() return type error': \"The method's return type is not assignable to the expected output schema type.\";\n expected_output_type: Out;\n 'actual_return_type (unwrapped)': __Unwrap<__Return<C>>;\n };\n\n// Rewrapped constructor with updated ToolContext generic params\ntype __Rewrap<C extends __Ctor, In, Out> = C extends abstract new (...a: __A<C>) => __R<C>\n ? C & (abstract new (...a: __A<C>) => ToolContext<any, any, In, Out> & __R<C>)\n : C extends new (...a: __A<C>) => __R<C>\n ? C & (new (...a: __A<C>) => ToolContext<any, any, In, Out> & __R<C>)\n : never;\n\ndeclare module '@frontmcp/sdk' {\n // ---------- the decorator (overloads) ----------\n\n // 1) Overload: outputSchema PROVIDED → strict return typing\n // @ts-expect-error - Module augmentation requires decorator overload\n export function Tool<\n I extends __Shape,\n O extends __OutputSchema, // Use our new output schema constraint\n T extends ToolMetadataOptions<I, O> & { outputSchema: any }, // ensure present\n >(\n opts: T,\n ): <C extends __Ctor>(\n cls: C &\n __MustExtendCtx<C> &\n __MustParam<C, ToolInputOf<T>> & // <-- Will now show a rich error\n __MustReturn<C, ToolOutputOf<T>>, // <-- Will now show a rich error\n ) => __Rewrap<C, ToolInputOf<T>, ToolOutputOf<T>>;\n\n // 2) Overload: outputSchema NOT PROVIDED → execute() can return any\n // @ts-expect-error - Module augmentation requires decorator overload\n export function Tool<\n I extends __Shape,\n // Note: 'O' is omitted, 'any' is used for the generic\n T extends ToolMetadataOptions<I, any> & { outputSchema?: never }, // ensure absent\n >(\n opts: T,\n ): <C extends __Ctor>(\n cls: C &\n __MustExtendCtx<C> &\n __MustParam<C, ToolInputOf<T>> & // <-- Will now show a rich error\n __MustReturn<C, ToolOutputOf<T>>, // <-- Will now show 'any'\n ) => __Rewrap<C, ToolInputOf<T>, ToolOutputOf<T>>;\n}\n"]}
|
|
@@ -7,6 +7,7 @@ export declare abstract class ScopeEntry extends BaseEntry<ScopeRecord, ScopeInt
|
|
|
7
7
|
abstract readonly entryPath: string;
|
|
8
8
|
abstract readonly routeBase: string;
|
|
9
9
|
abstract readonly logger: FrontMcpLogger;
|
|
10
|
+
get fullPath(): string;
|
|
10
11
|
abstract get auth(): FrontMcpAuth;
|
|
11
12
|
abstract get hooks(): HookRegistryInterface;
|
|
12
13
|
abstract get authProviders(): AuthRegistryInterface;
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ScopeEntry = void 0;
|
|
4
4
|
const base_entry_1 = require("./base.entry");
|
|
5
|
+
const path_utils_1 = require("../../auth/path.utils");
|
|
5
6
|
class ScopeEntry extends base_entry_1.BaseEntry {
|
|
7
|
+
get fullPath() {
|
|
8
|
+
const prefix = (0, path_utils_1.normalizeEntryPrefix)(this.entryPath ?? '');
|
|
9
|
+
const scope = (0, path_utils_1.normalizeScopeBase)(this.routeBase ?? '');
|
|
10
|
+
return `${prefix}${scope}`;
|
|
11
|
+
}
|
|
6
12
|
}
|
|
7
13
|
exports.ScopeEntry = ScopeEntry;
|
|
8
14
|
//# sourceMappingURL=scope.entry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.entry.js","sourceRoot":"","sources":["../../../../src/common/entries/scope.entry.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;
|
|
1
|
+
{"version":3,"file":"scope.entry.js","sourceRoot":"","sources":["../../../../src/common/entries/scope.entry.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAWvC,sDAA+E;AAE/E,MAAsB,UAAW,SAAQ,sBAAqD;IAM5F,IAAI,QAAQ;QACV,MAAM,MAAM,GAAG,IAAA,iCAAoB,EAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,IAAA,+BAAkB,EAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACvD,OAAO,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;IAC7B,CAAC;CAiBF;AA3BD,gCA2BC","sourcesContent":["import {BaseEntry} from './base.entry';\nimport {ScopeRecord} from '../records';\nimport {\n ScopeInterface,\n ProviderRegistryInterface,\n AppRegistryInterface,\n AuthRegistryInterface,\n FrontMcpAuth,\n Token, FlowInputOf, FlowOutputOf, Type, FlowType, FrontMcpLogger, ToolRegistryInterface, HookRegistryInterface,\n} from '../interfaces';\nimport {FlowName, ScopeMetadata} from '../metadata';\nimport {normalizeEntryPrefix, normalizeScopeBase} from \"../../auth/path.utils\";\n\nexport abstract class ScopeEntry extends BaseEntry<ScopeRecord, ScopeInterface, ScopeMetadata> {\n abstract readonly id: string;\n abstract readonly entryPath: string;\n abstract readonly routeBase: string;\n abstract readonly logger: FrontMcpLogger;\n\n get fullPath(): string {\n const prefix = normalizeEntryPrefix(this.entryPath ?? '');\n const scope = normalizeScopeBase(this.routeBase ?? '');\n return `${prefix}${scope}`;\n }\n\n abstract get auth(): FrontMcpAuth;\n\n abstract get hooks(): HookRegistryInterface;\n\n abstract get authProviders(): AuthRegistryInterface;\n\n abstract get providers(): ProviderRegistryInterface;\n\n abstract get apps(): AppRegistryInterface;\n\n abstract get tools(): ToolRegistryInterface;\n\n abstract registryFlows(...flows: FlowType[]): Promise<void>;\n\n abstract runFlow<Name extends FlowName>(name: Name, input: FlowInputOf<Name>, additionalDeps?: Map<Token, Type>): Promise<FlowOutputOf<Name> | undefined>;\n}\n"]}
|
|
@@ -1,19 +1,62 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
1
|
import { BaseEntry, EntryOwnerRef } from './base.entry';
|
|
3
2
|
import { ToolRecord } from '../records';
|
|
4
3
|
import { ToolContext } from '../interfaces';
|
|
5
|
-
import { ToolMetadata } from '../metadata';
|
|
6
|
-
import { Request, Notification, CallToolRequest } from
|
|
7
|
-
import { RequestHandlerExtra } from
|
|
8
|
-
import { AuthInfo } from
|
|
9
|
-
|
|
4
|
+
import { ToolInputType, ToolMetadata, ToolOutputType } from '../metadata';
|
|
5
|
+
import { Request, Notification, CallToolRequest, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
+
import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
7
|
+
import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
8
|
+
import { ToolInputOf, ToolOutputOf } from '../decorators';
|
|
9
|
+
export type ToolCallArgs = CallToolRequest['params']['arguments'];
|
|
10
10
|
export type ToolCallExtra = RequestHandlerExtra<Request, Notification> & {
|
|
11
11
|
authInfo: AuthInfo;
|
|
12
12
|
};
|
|
13
|
-
export
|
|
13
|
+
export type ParsedToolResult = CallToolResult;
|
|
14
|
+
export type SafeTransformResult<T> = {
|
|
15
|
+
success: true;
|
|
16
|
+
data: T;
|
|
17
|
+
} | {
|
|
18
|
+
success: false;
|
|
19
|
+
error: Error;
|
|
20
|
+
};
|
|
21
|
+
export declare abstract class ToolEntry<InSchema extends ToolInputType = ToolInputType, OutSchema extends ToolOutputType = ToolOutputType, In = ToolInputOf<{
|
|
22
|
+
inputSchema: InSchema;
|
|
23
|
+
}>, Out = ToolOutputOf<{
|
|
24
|
+
outputSchema: OutSchema;
|
|
25
|
+
}>> extends BaseEntry<ToolRecord, ToolContext<InSchema, OutSchema, In, Out>, ToolMetadata> {
|
|
14
26
|
owner: EntryOwnerRef;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
/**
|
|
28
|
+
* The name of the tool, as declared in the metadata.
|
|
29
|
+
*/
|
|
30
|
+
name: string;
|
|
31
|
+
/**
|
|
32
|
+
* The full name of the tool, including the owner name as prefix.
|
|
33
|
+
*/
|
|
34
|
+
fullName: string;
|
|
35
|
+
inputSchema: InSchema;
|
|
36
|
+
rawInputSchema: any;
|
|
37
|
+
outputSchema?: OutSchema;
|
|
38
|
+
/**
|
|
39
|
+
* Accessor used by tools/list to expose the tool's declared outputSchema.
|
|
40
|
+
* This returns the exact value from metadata (string literal, zod schema,
|
|
41
|
+
* raw shape, or an array of those).
|
|
42
|
+
*/
|
|
43
|
+
getOutputSchema(): OutSchema | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Create a tool context (class or function wrapper).
|
|
46
|
+
*/
|
|
47
|
+
abstract create(input: ToolCallArgs, ctx: ToolCallExtra): ToolContext<InSchema, OutSchema, In, Out>;
|
|
48
|
+
/**
|
|
49
|
+
* Convert the raw tool request input into an MCP CallToolRequest-shaped object.
|
|
50
|
+
*/
|
|
51
|
+
abstract parseInput(input: CallToolRequest['params']): CallToolRequest['params']['arguments'];
|
|
52
|
+
/**
|
|
53
|
+
* Convert the raw tool return value (Out) into an MCP CallToolResult-shaped object.
|
|
54
|
+
* Concrete logic is implemented in ToolInstance.
|
|
55
|
+
*/
|
|
56
|
+
abstract parseOutput(result: Out | Partial<Out> | any): ParsedToolResult;
|
|
57
|
+
/**
|
|
58
|
+
* Convert the raw tool return value (Out) into an MCP CallToolResult-shaped object.
|
|
59
|
+
* Concrete logic is implemented in ToolInstance.
|
|
60
|
+
*/
|
|
61
|
+
abstract safeParseOutput(raw: Out | Partial<Out> | any): SafeTransformResult<ParsedToolResult>;
|
|
19
62
|
}
|
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// file: libs/sdk/src/common/entries/tool.entry.ts
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.ToolEntry = void 0;
|
|
4
5
|
const base_entry_1 = require("./base.entry");
|
|
5
6
|
class ToolEntry extends base_entry_1.BaseEntry {
|
|
6
7
|
owner;
|
|
8
|
+
/**
|
|
9
|
+
* The name of the tool, as declared in the metadata.
|
|
10
|
+
*/
|
|
11
|
+
name;
|
|
12
|
+
/**
|
|
13
|
+
* The full name of the tool, including the owner name as prefix.
|
|
14
|
+
*/
|
|
15
|
+
fullName;
|
|
7
16
|
inputSchema;
|
|
17
|
+
// This is whatever JSON-schema-ish thing you store for input; keeping type loose
|
|
8
18
|
rawInputSchema;
|
|
19
|
+
// This is your *metadata* outputSchema (literals / zod / raw shapes / arrays)
|
|
9
20
|
outputSchema;
|
|
21
|
+
/**
|
|
22
|
+
* Accessor used by tools/list to expose the tool's declared outputSchema.
|
|
23
|
+
* This returns the exact value from metadata (string literal, zod schema,
|
|
24
|
+
* raw shape, or an array of those).
|
|
25
|
+
*/
|
|
26
|
+
getOutputSchema() {
|
|
27
|
+
return this.outputSchema;
|
|
28
|
+
}
|
|
10
29
|
}
|
|
11
30
|
exports.ToolEntry = ToolEntry;
|
|
12
31
|
//# sourceMappingURL=tool.entry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.entry.js","sourceRoot":"","sources":["../../../../src/common/entries/tool.entry.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"tool.entry.js","sourceRoot":"","sources":["../../../../src/common/entries/tool.entry.ts"],"names":[],"mappings":";AAAA,kDAAkD;;;AAElD,6CAAwD;AAiBxD,MAAsB,SAKpB,SAAQ,sBAA8E;IACtF,KAAK,CAAgB;IACrB;;OAEG;IACH,IAAI,CAAS;IACb;;OAEG;IACH,QAAQ,CAAS;IAEjB,WAAW,CAAW;IACtB,iFAAiF;IACjF,cAAc,CAAM;IACpB,8EAA8E;IAC9E,YAAY,CAAa;IAEzB;;;;OAIG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CAsBF;AAnDD,8BAmDC","sourcesContent":["// file: libs/sdk/src/common/entries/tool.entry.ts\n\nimport { BaseEntry, EntryOwnerRef } from './base.entry';\nimport { ToolRecord } from '../records';\nimport { ToolContext } from '../interfaces';\nimport { ToolInputType, ToolMetadata, ToolOutputType } from '../metadata';\nimport { Request, Notification, CallToolRequest, CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';\nimport { ToolInputOf, ToolOutputOf } from '../decorators';\n\nexport type ToolCallArgs = CallToolRequest['params']['arguments'];\nexport type ToolCallExtra = RequestHandlerExtra<Request, Notification> & {\n authInfo: AuthInfo;\n};\n\nexport type ParsedToolResult = CallToolResult;\nexport type SafeTransformResult<T> = { success: true; data: T } | { success: false; error: Error };\n\nexport abstract class ToolEntry<\n InSchema extends ToolInputType = ToolInputType,\n OutSchema extends ToolOutputType = ToolOutputType,\n In = ToolInputOf<{ inputSchema: InSchema }>,\n Out = ToolOutputOf<{ outputSchema: OutSchema }>,\n> extends BaseEntry<ToolRecord, ToolContext<InSchema, OutSchema, In, Out>, ToolMetadata> {\n owner: EntryOwnerRef;\n /**\n * The name of the tool, as declared in the metadata.\n */\n name: string;\n /**\n * The full name of the tool, including the owner name as prefix.\n */\n fullName: string;\n\n inputSchema: InSchema;\n // This is whatever JSON-schema-ish thing you store for input; keeping type loose\n rawInputSchema: any;\n // This is your *metadata* outputSchema (literals / zod / raw shapes / arrays)\n outputSchema?: OutSchema;\n\n /**\n * Accessor used by tools/list to expose the tool's declared outputSchema.\n * This returns the exact value from metadata (string literal, zod schema,\n * raw shape, or an array of those).\n */\n getOutputSchema(): OutSchema | undefined {\n return this.outputSchema;\n }\n\n /**\n * Create a tool context (class or function wrapper).\n */\n abstract create(input: ToolCallArgs, ctx: ToolCallExtra): ToolContext<InSchema, OutSchema, In, Out>;\n\n /**\n * Convert the raw tool request input into an MCP CallToolRequest-shaped object.\n */\n abstract parseInput(input: CallToolRequest['params']): CallToolRequest['params']['arguments'];\n\n /**\n * Convert the raw tool return value (Out) into an MCP CallToolResult-shaped object.\n * Concrete logic is implemented in ToolInstance.\n */\n abstract parseOutput(result: Out | Partial<Out> | any): ParsedToolResult;\n /**\n * Convert the raw tool return value (Out) into an MCP CallToolResult-shaped object.\n * Concrete logic is implemented in ToolInstance.\n */\n abstract safeParseOutput(raw: Out | Partial<Out> | any): SafeTransformResult<ParsedToolResult>;\n}\n"]}
|
|
@@ -2,8 +2,8 @@ import { ScopeEntry, FlowEntry, AuthProviderEntry, AppEntry, ProviderEntry, Plug
|
|
|
2
2
|
import { Token } from '../base.interface';
|
|
3
3
|
import { FrontMcpAuth } from './primary-auth-provider.interface';
|
|
4
4
|
import { FlowName } from '../../metadata';
|
|
5
|
-
import { FlowCtxOf, FlowInputOf, FlowStagesOf } from
|
|
6
|
-
import { HookRecord } from
|
|
5
|
+
import { FlowCtxOf, FlowInputOf, FlowStagesOf } from '../flow.interface';
|
|
6
|
+
import { HookRecord } from '../../records';
|
|
7
7
|
export interface ScopeRegistryInterface {
|
|
8
8
|
getScopes(): ScopeEntry[];
|
|
9
9
|
}
|
|
@@ -30,6 +30,14 @@ export interface HookRegistryInterface {
|
|
|
30
30
|
* @param stage
|
|
31
31
|
*/
|
|
32
32
|
getFlowStageHooks<Name extends FlowName>(flow: Name, stage: FlowStagesOf<Name> | string): HookEntry<FlowInputOf<Name>, Name, FlowStagesOf<Name>, FlowCtxOf<Name>>[];
|
|
33
|
+
/**
|
|
34
|
+
* Used to pull hooks for a specific flow, optionally filtered by owner ID.
|
|
35
|
+
* Returns all hooks if no ownerId is provided, or only hooks belonging to
|
|
36
|
+
* the specified owner or global hooks (no owner) if ownerId is provided.
|
|
37
|
+
* @param flow
|
|
38
|
+
* @param ownerId
|
|
39
|
+
*/
|
|
40
|
+
getFlowHooksForOwner<Name extends FlowName>(flow: Name, ownerId?: string): HookEntry<FlowInputOf<Name>, Name, FlowStagesOf<Name>, FlowCtxOf<Name>>[];
|
|
33
41
|
registerHooks(embedded: boolean, ...records: HookRecord[]): Promise<void[]>;
|
|
34
42
|
}
|
|
35
43
|
export interface ProviderViews {
|