@heddleagent/execution-host-client 6.4.0 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +47 -1
  2. package/dist/host/errors.d.ts +23 -0
  3. package/dist/host/errors.d.ts.map +1 -0
  4. package/dist/host/errors.js +32 -0
  5. package/dist/host/errors.js.map +1 -0
  6. package/dist/host/index.d.ts +7 -0
  7. package/dist/host/index.d.ts.map +1 -0
  8. package/dist/host/index.js +6 -0
  9. package/dist/host/index.js.map +1 -0
  10. package/dist/host/jwt-execution-host-mcp-capability-verifier.d.ts +8 -0
  11. package/dist/host/jwt-execution-host-mcp-capability-verifier.d.ts.map +1 -0
  12. package/dist/host/jwt-execution-host-mcp-capability-verifier.js +86 -0
  13. package/dist/host/jwt-execution-host-mcp-capability-verifier.js.map +1 -0
  14. package/dist/host/jwt-execution-identity-verifier.d.ts +8 -0
  15. package/dist/host/jwt-execution-identity-verifier.d.ts.map +1 -0
  16. package/dist/host/jwt-execution-identity-verifier.js +76 -0
  17. package/dist/host/jwt-execution-identity-verifier.js.map +1 -0
  18. package/dist/host/schemas.d.ts +37 -0
  19. package/dist/host/schemas.d.ts.map +1 -0
  20. package/dist/host/schemas.js +24 -0
  21. package/dist/host/schemas.js.map +1 -0
  22. package/dist/host/types.d.ts +62 -0
  23. package/dist/host/types.d.ts.map +1 -0
  24. package/dist/host/types.js +7 -0
  25. package/dist/host/types.js.map +1 -0
  26. package/dist/internal/jwt-verification.d.ts +5 -0
  27. package/dist/internal/jwt-verification.d.ts.map +1 -0
  28. package/dist/internal/jwt-verification.js +25 -0
  29. package/dist/internal/jwt-verification.js.map +1 -0
  30. package/dist/mcp/jwt-capability-verifier.d.ts.map +1 -1
  31. package/dist/mcp/jwt-capability-verifier.js +6 -25
  32. package/dist/mcp/jwt-capability-verifier.js.map +1 -1
  33. package/package.json +5 -1
package/README.md CHANGED
@@ -5,7 +5,8 @@ products that invoke a separately deployed Heddle Execution Host. It lets an
5
5
  adopter keep its own language stack, authentication, database, product policy,
6
6
  MCP tools, and UI while reusing the security-sensitive v1 contract machinery.
7
7
 
8
- > **Current availability:** stable version `6.4.0`. The former
8
+ > **Current availability:** `6.5.0` is the next manual release from this
9
+ > repository; `6.4.0` remains the latest published version until then. The former
9
10
  > `@roackb2/heddle-adopter@5.13.0` coordinate is deprecated and remains
10
11
  > installable only for existing consumers. Heddle does not currently distribute
11
12
  > the compatible Execution Host implementation or offer a hosted service. The
@@ -37,6 +38,7 @@ modular AWS SDK for its AgentCore transport and the official MCP SDK, plus
37
38
  | `@heddleagent/execution-host-client/mcp/node` | Stateless official-SDK Streamable HTTP lifecycle around adopter-defined toolsets |
38
39
  | `@heddleagent/execution-host-client/http-sse` | Transport-neutral conversation and heartbeat ports plus the strict direct-development HTTP/SSE client |
39
40
  | `@heddleagent/execution-host-client/agentcore` | Official AWS AgentCore/SigV4 implementation of the same conversation and heartbeat ports |
41
+ | `@heddleagent/execution-host-client/host` | Invocation-bound execution-identity and MCP-capability verification shared by compatible Execution Host implementations |
40
42
  | `@heddleagent/execution-host-client/testing` | Node-only loopback v1 fixture plus durable-turn store conformance for real adapters |
41
43
  | `@heddleagent/execution-host-client/node` | Optional Node JWKS/conversation HTTP edge plus safe local signing-key helpers |
42
44
 
@@ -230,6 +232,50 @@ const productMcp = new NodeStreamableHttpMcpService({
230
232
  Use the lower-level `NodeMcpToolset` interface only when a tool needs custom MCP
231
233
  content or lifecycle semantics.
232
234
 
235
+ ## Verify authority inside a compatible Execution Host
236
+
237
+ The host must independently verify the adopter's execution assertion before it
238
+ trusts product scope, then bind any optional MCP capability to that same
239
+ verified invocation. Compatible host implementations can reuse that generic
240
+ security boundary instead of maintaining their own JOSE logic:
241
+
242
+ ```ts
243
+ import {
244
+ JwtExecutionHostMcpCapabilityVerifier,
245
+ JwtExecutionIdentityVerifier,
246
+ } from '@heddleagent/execution-host-client/host'
247
+
248
+ const identity = await new JwtExecutionIdentityVerifier({
249
+ executionIssuer: 'https://api.example.com',
250
+ executionAudience: 'heddle-execution-host',
251
+ executionJwksUrl: new URL('https://api.example.com/.well-known/jwks.json'),
252
+ executionJwtAlgorithms: ['ES256'],
253
+ trustedAdopterId: 'example-product',
254
+ maxAssertionAgeSeconds: 300,
255
+ assertionClockToleranceSeconds: 5,
256
+ }).verify({
257
+ assertion: executionAssertion,
258
+ runtimeSessionId,
259
+ invocationId,
260
+ workflow: 'conversation-turn',
261
+ })
262
+
263
+ const capability = await new JwtExecutionHostMcpCapabilityVerifier({
264
+ issuer: 'https://api.example.com',
265
+ audience: 'example-product-mcp',
266
+ jwksUrl: new URL('https://api.example.com/.well-known/jwks.json'),
267
+ jwtAlgorithms: ['ES256'],
268
+ trustedAdopterId: 'example-product',
269
+ serverId: 'product_capabilities',
270
+ maxCapabilityAgeSeconds: 900,
271
+ clockToleranceSeconds: 5,
272
+ }).verify({ assertion: mcpCapability, identity })
273
+ ```
274
+
275
+ This surface owns credential verification and exact scope binding. It does not
276
+ own HTTP ingress, Runtime-session isolation, model credentials, streaming,
277
+ provider bootstrap, or deployment.
278
+
233
279
  ## Invoke an Execution Host
234
280
 
235
281
  Use the official AgentCore client for a Runtime deployed in the adopter's AWS
@@ -0,0 +1,23 @@
1
+ import type { JwtVerificationUnavailableCategory } from '../internal/jwt-verification.js';
2
+ export declare class ExecutionIdentityVerificationError extends Error {
3
+ readonly name = "ExecutionIdentityVerificationError";
4
+ constructor(options?: ErrorOptions);
5
+ }
6
+ export declare class ExecutionIdentityUnavailableError extends Error {
7
+ readonly category: JwtVerificationUnavailableCategory;
8
+ readonly name = "ExecutionIdentityUnavailableError";
9
+ constructor(category: JwtVerificationUnavailableCategory, options?: ErrorOptions);
10
+ }
11
+ export declare class ExecutionHostMcpCapabilityVerificationError extends Error {
12
+ readonly name = "ExecutionHostMcpCapabilityVerificationError";
13
+ constructor(options?: ErrorOptions);
14
+ }
15
+ export declare class ExecutionHostMcpCapabilityUnavailableError extends Error {
16
+ readonly category: JwtVerificationUnavailableCategory;
17
+ readonly name = "ExecutionHostMcpCapabilityUnavailableError";
18
+ constructor(category: JwtVerificationUnavailableCategory, options?: ErrorOptions);
19
+ }
20
+ export declare class UnexpectedExecutionHostMcpCapabilityError extends Error {
21
+ readonly name = "UnexpectedExecutionHostMcpCapabilityError";
22
+ }
23
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/host/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,iCAAiC,CAAC;AAE1F,qBAAa,kCAAmC,SAAQ,KAAK;IAC3D,QAAQ,CAAC,IAAI,wCAAwC;gBAEzC,OAAO,CAAC,EAAE,YAAY;CAGnC;AAED,qBAAa,iCAAkC,SAAQ,KAAK;IAIxD,QAAQ,CAAC,QAAQ,EAAE,kCAAkC;IAHvD,QAAQ,CAAC,IAAI,uCAAuC;gBAGzC,QAAQ,EAAE,kCAAkC,EACrD,OAAO,CAAC,EAAE,YAAY;CAIzB;AAED,qBAAa,2CAA4C,SAAQ,KAAK;IACpE,QAAQ,CAAC,IAAI,iDAAiD;gBAElD,OAAO,CAAC,EAAE,YAAY;CAGnC;AAED,qBAAa,0CAA2C,SAAQ,KAAK;IAIjE,QAAQ,CAAC,QAAQ,EAAE,kCAAkC;IAHvD,QAAQ,CAAC,IAAI,gDAAgD;gBAGlD,QAAQ,EAAE,kCAAkC,EACrD,OAAO,CAAC,EAAE,YAAY;CAIzB;AAED,qBAAa,yCAA0C,SAAQ,KAAK;IAClE,QAAQ,CAAC,IAAI,+CAA+C;CAC7D"}
@@ -0,0 +1,32 @@
1
+ export class ExecutionIdentityVerificationError extends Error {
2
+ name = 'ExecutionIdentityVerificationError';
3
+ constructor(options) {
4
+ super('Execution identity verification failed.', options);
5
+ }
6
+ }
7
+ export class ExecutionIdentityUnavailableError extends Error {
8
+ category;
9
+ name = 'ExecutionIdentityUnavailableError';
10
+ constructor(category, options) {
11
+ super('Execution identity verification is temporarily unavailable.', options);
12
+ this.category = category;
13
+ }
14
+ }
15
+ export class ExecutionHostMcpCapabilityVerificationError extends Error {
16
+ name = 'ExecutionHostMcpCapabilityVerificationError';
17
+ constructor(options) {
18
+ super('MCP capability verification failed.', options);
19
+ }
20
+ }
21
+ export class ExecutionHostMcpCapabilityUnavailableError extends Error {
22
+ category;
23
+ name = 'ExecutionHostMcpCapabilityUnavailableError';
24
+ constructor(category, options) {
25
+ super('MCP capability verification is temporarily unavailable.', options);
26
+ this.category = category;
27
+ }
28
+ }
29
+ export class UnexpectedExecutionHostMcpCapabilityError extends Error {
30
+ name = 'UnexpectedExecutionHostMcpCapabilityError';
31
+ }
32
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/host/errors.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,kCAAmC,SAAQ,KAAK;IAClD,IAAI,GAAG,oCAAoC,CAAC;IAErD,YAAY,OAAsB;QAChC,KAAK,CAAC,yCAAyC,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;CACF;AAED,MAAM,OAAO,iCAAkC,SAAQ,KAAK;IAI/C;IAHF,IAAI,GAAG,mCAAmC,CAAC;IAEpD,YACW,QAA4C,EACrD,OAAsB;QAEtB,KAAK,CAAC,6DAA6D,EAAE,OAAO,CAAC,CAAC;QAHrE,aAAQ,GAAR,QAAQ,CAAoC;IAIvD,CAAC;CACF;AAED,MAAM,OAAO,2CAA4C,SAAQ,KAAK;IAC3D,IAAI,GAAG,6CAA6C,CAAC;IAE9D,YAAY,OAAsB;QAChC,KAAK,CAAC,qCAAqC,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;CACF;AAED,MAAM,OAAO,0CAA2C,SAAQ,KAAK;IAIxD;IAHF,IAAI,GAAG,4CAA4C,CAAC;IAE7D,YACW,QAA4C,EACrD,OAAsB;QAEtB,KAAK,CAAC,yDAAyD,EAAE,OAAO,CAAC,CAAC;QAHjE,aAAQ,GAAR,QAAQ,CAAoC;IAIvD,CAAC;CACF;AAED,MAAM,OAAO,yCAA0C,SAAQ,KAAK;IACzD,IAAI,GAAG,2CAA2C,CAAC;CAC7D","sourcesContent":["import type { JwtVerificationUnavailableCategory } from '../internal/jwt-verification.js';\n\nexport class ExecutionIdentityVerificationError extends Error {\n readonly name = 'ExecutionIdentityVerificationError';\n\n constructor(options?: ErrorOptions) {\n super('Execution identity verification failed.', options);\n }\n}\n\nexport class ExecutionIdentityUnavailableError extends Error {\n readonly name = 'ExecutionIdentityUnavailableError';\n\n constructor(\n readonly category: JwtVerificationUnavailableCategory,\n options?: ErrorOptions,\n ) {\n super('Execution identity verification is temporarily unavailable.', options);\n }\n}\n\nexport class ExecutionHostMcpCapabilityVerificationError extends Error {\n readonly name = 'ExecutionHostMcpCapabilityVerificationError';\n\n constructor(options?: ErrorOptions) {\n super('MCP capability verification failed.', options);\n }\n}\n\nexport class ExecutionHostMcpCapabilityUnavailableError extends Error {\n readonly name = 'ExecutionHostMcpCapabilityUnavailableError';\n\n constructor(\n readonly category: JwtVerificationUnavailableCategory,\n options?: ErrorOptions,\n ) {\n super('MCP capability verification is temporarily unavailable.', options);\n }\n}\n\nexport class UnexpectedExecutionHostMcpCapabilityError extends Error {\n readonly name = 'UnexpectedExecutionHostMcpCapabilityError';\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export { ExecutionHostMcpCapabilityUnavailableError, ExecutionHostMcpCapabilityVerificationError, ExecutionIdentityUnavailableError, ExecutionIdentityVerificationError, UnexpectedExecutionHostMcpCapabilityError, } from './errors.js';
2
+ export { JwtExecutionIdentityVerifier } from './jwt-execution-identity-verifier.js';
3
+ export { JwtExecutionHostMcpCapabilityVerifier } from './jwt-execution-host-mcp-capability-verifier.js';
4
+ export { ExecutionHostJwtAlgorithmsSchema, JwtExecutionHostMcpCapabilityVerifierConfigSchema, JwtExecutionIdentityVerifierConfigSchema, } from './schemas.js';
5
+ export { EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS, } from './types.js';
6
+ export type { ExecutionHostJwtAlgorithm, ExecutionHostJwtVerifierOptions, ExecutionHostMcpCapabilityVerificationRequest, ExecutionHostMcpCapabilityVerifier, ExecutionIdentityVerificationRequest, ExecutionIdentityVerifier, JwtExecutionHostMcpCapabilityVerifierConfig, JwtExecutionIdentityVerifierConfig, VerifiedExecutionHostMcpCapability, VerifiedExecutionIdentity, } from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0CAA0C,EAC1C,2CAA2C,EAC3C,iCAAiC,EACjC,kCAAkC,EAClC,yCAAyC,GAC1C,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,qCAAqC,EAAE,MAAM,iDAAiD,CAAC;AACxG,OAAO,EACL,gCAAgC,EAChC,iDAAiD,EACjD,wCAAwC,GACzC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uCAAuC,GACxC,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,yBAAyB,EACzB,+BAA+B,EAC/B,6CAA6C,EAC7C,kCAAkC,EAClC,oCAAoC,EACpC,yBAAyB,EACzB,2CAA2C,EAC3C,kCAAkC,EAClC,kCAAkC,EAClC,yBAAyB,GAC1B,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { ExecutionHostMcpCapabilityUnavailableError, ExecutionHostMcpCapabilityVerificationError, ExecutionIdentityUnavailableError, ExecutionIdentityVerificationError, UnexpectedExecutionHostMcpCapabilityError, } from './errors.js';
2
+ export { JwtExecutionIdentityVerifier } from './jwt-execution-identity-verifier.js';
3
+ export { JwtExecutionHostMcpCapabilityVerifier } from './jwt-execution-host-mcp-capability-verifier.js';
4
+ export { ExecutionHostJwtAlgorithmsSchema, JwtExecutionHostMcpCapabilityVerifierConfigSchema, JwtExecutionIdentityVerifierConfigSchema, } from './schemas.js';
5
+ export { EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS, } from './types.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0CAA0C,EAC1C,2CAA2C,EAC3C,iCAAiC,EACjC,kCAAkC,EAClC,yCAAyC,GAC1C,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,qCAAqC,EAAE,MAAM,iDAAiD,CAAC;AACxG,OAAO,EACL,gCAAgC,EAChC,iDAAiD,EACjD,wCAAwC,GACzC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uCAAuC,GACxC,MAAM,YAAY,CAAC","sourcesContent":["export {\n ExecutionHostMcpCapabilityUnavailableError,\n ExecutionHostMcpCapabilityVerificationError,\n ExecutionIdentityUnavailableError,\n ExecutionIdentityVerificationError,\n UnexpectedExecutionHostMcpCapabilityError,\n} from './errors.js';\nexport { JwtExecutionIdentityVerifier } from './jwt-execution-identity-verifier.js';\nexport { JwtExecutionHostMcpCapabilityVerifier } from './jwt-execution-host-mcp-capability-verifier.js';\nexport {\n ExecutionHostJwtAlgorithmsSchema,\n JwtExecutionHostMcpCapabilityVerifierConfigSchema,\n JwtExecutionIdentityVerifierConfigSchema,\n} from './schemas.js';\nexport {\n EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS,\n} from './types.js';\nexport type {\n ExecutionHostJwtAlgorithm,\n ExecutionHostJwtVerifierOptions,\n ExecutionHostMcpCapabilityVerificationRequest,\n ExecutionHostMcpCapabilityVerifier,\n ExecutionIdentityVerificationRequest,\n ExecutionIdentityVerifier,\n JwtExecutionHostMcpCapabilityVerifierConfig,\n JwtExecutionIdentityVerifierConfig,\n VerifiedExecutionHostMcpCapability,\n VerifiedExecutionIdentity,\n} from './types.js';\n"]}
@@ -0,0 +1,8 @@
1
+ import type { ExecutionHostJwtVerifierOptions, ExecutionHostMcpCapabilityVerificationRequest, ExecutionHostMcpCapabilityVerifier, JwtExecutionHostMcpCapabilityVerifierConfig, VerifiedExecutionHostMcpCapability } from './types.js';
2
+ /** Verifies MCP authority against an independently verified host invocation. */
3
+ export declare class JwtExecutionHostMcpCapabilityVerifier implements ExecutionHostMcpCapabilityVerifier {
4
+ #private;
5
+ constructor(config: JwtExecutionHostMcpCapabilityVerifierConfig, options?: ExecutionHostJwtVerifierOptions);
6
+ verify(rawRequest: ExecutionHostMcpCapabilityVerificationRequest): Promise<VerifiedExecutionHostMcpCapability>;
7
+ }
8
+ //# sourceMappingURL=jwt-execution-host-mcp-capability-verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-execution-host-mcp-capability-verifier.d.ts","sourceRoot":"","sources":["../../src/host/jwt-execution-host-mcp-capability-verifier.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,+BAA+B,EAC/B,6CAA6C,EAC7C,kCAAkC,EAClC,2CAA2C,EAC3C,kCAAkC,EACnC,MAAM,YAAY,CAAC;AAOpB,gFAAgF;AAChF,qBAAa,qCACb,YAAW,kCAAkC;;gBAMzC,MAAM,EAAE,2CAA2C,EACnD,OAAO,GAAE,+BAAoC;IAczC,MAAM,CACV,UAAU,EAAE,6CAA6C,GACxD,OAAO,CAAC,kCAAkC,CAAC;CAkF/C"}
@@ -0,0 +1,86 @@
1
+ import { jwtVerify } from 'jose';
2
+ import { z } from 'zod';
3
+ import { MCP_CAPABILITY_TYPE, McpCapabilityClaimsSchema, } from '../contracts/index.js';
4
+ import { createJwtKeyResolver, resolveJwtVerificationUnavailableCategory, } from '../internal/jwt-verification.js';
5
+ import { ExecutionHostMcpCapabilityUnavailableError, ExecutionHostMcpCapabilityVerificationError, } from './errors.js';
6
+ import { JwtExecutionHostMcpCapabilityVerifierConfigSchema } from './schemas.js';
7
+ const AssertionSchema = z.string().trim().min(32).max(4_096);
8
+ /** Verifies MCP authority against an independently verified host invocation. */
9
+ export class JwtExecutionHostMcpCapabilityVerifier {
10
+ #config;
11
+ #keyResolver;
12
+ #now;
13
+ constructor(config, options = {}) {
14
+ const parsed = JwtExecutionHostMcpCapabilityVerifierConfigSchema.parse(config);
15
+ this.#config = Object.freeze({
16
+ ...parsed,
17
+ jwksUrl: new URL(parsed.jwksUrl),
18
+ });
19
+ this.#keyResolver = options.keyResolver
20
+ ?? createJwtKeyResolver(this.#config.jwksUrl);
21
+ this.#now = options.now ?? (() => new Date());
22
+ }
23
+ async verify(rawRequest) {
24
+ try {
25
+ const request = Object.freeze({
26
+ ...rawRequest,
27
+ assertion: AssertionSchema.parse(rawRequest.assertion),
28
+ });
29
+ const { payload } = await jwtVerify(request.assertion, this.#keyResolver, {
30
+ algorithms: [...this.#config.jwtAlgorithms],
31
+ audience: this.#config.audience,
32
+ clockTolerance: this.#config.clockToleranceSeconds,
33
+ currentDate: this.#now(),
34
+ issuer: this.#config.issuer,
35
+ maxTokenAge: this.#config.maxCapabilityAgeSeconds,
36
+ requiredClaims: ['exp', 'iat', 'jti', 'sub'],
37
+ typ: MCP_CAPABILITY_TYPE,
38
+ });
39
+ const claims = McpCapabilityClaimsSchema.parse(payload);
40
+ this.#assertInvocationBinding(claims, request);
41
+ this.#assertBoundedLifetime(claims);
42
+ return Object.freeze({
43
+ assertion: request.assertion,
44
+ capabilityId: claims.jti,
45
+ serverId: claims.serverId,
46
+ allowedTools: Object.freeze([...claims.allowedTools]),
47
+ issuedAt: new Date(claims.iat * 1_000).toISOString(),
48
+ expiresAt: new Date(claims.exp * 1_000).toISOString(),
49
+ });
50
+ }
51
+ catch (error) {
52
+ if (error instanceof ExecutionHostMcpCapabilityVerificationError
53
+ || error instanceof ExecutionHostMcpCapabilityUnavailableError) {
54
+ throw error;
55
+ }
56
+ const category = resolveJwtVerificationUnavailableCategory(error);
57
+ if (category) {
58
+ throw new ExecutionHostMcpCapabilityUnavailableError(category, { cause: error });
59
+ }
60
+ throw new ExecutionHostMcpCapabilityVerificationError({ cause: error });
61
+ }
62
+ }
63
+ #assertInvocationBinding(claims, request) {
64
+ const { identity } = request;
65
+ if (claims.adopterId !== this.#config.trustedAdopterId
66
+ || claims.adopterId !== identity.scope.adopterId
67
+ || claims.tenantId !== identity.scope.tenantId
68
+ || claims.sub !== identity.scope.subjectId
69
+ || claims.productSessionId !== identity.scope.productSessionId
70
+ || claims.runtimeSessionId !== identity.runtimeSessionId
71
+ || claims.invocationId !== identity.invocationId
72
+ || claims.workflow !== identity.workflow
73
+ || claims.serverId !== this.#config.serverId
74
+ || claims.jti === identity.invocationId) {
75
+ throw new ExecutionHostMcpCapabilityVerificationError();
76
+ }
77
+ }
78
+ #assertBoundedLifetime(claims) {
79
+ const lifetimeSeconds = claims.exp - claims.iat;
80
+ if (lifetimeSeconds <= 0
81
+ || lifetimeSeconds > this.#config.maxCapabilityAgeSeconds) {
82
+ throw new ExecutionHostMcpCapabilityVerificationError();
83
+ }
84
+ }
85
+ }
86
+ //# sourceMappingURL=jwt-execution-host-mcp-capability-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-execution-host-mcp-capability-verifier.js","sourceRoot":"","sources":["../../src/host/jwt-execution-host-mcp-capability-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import { jwtVerify } from 'jose';\nimport { z } from 'zod';\nimport {\n MCP_CAPABILITY_TYPE,\n McpCapabilityClaimsSchema,\n} from '../contracts/index.js';\nimport {\n createJwtKeyResolver,\n resolveJwtVerificationUnavailableCategory,\n} from '../internal/jwt-verification.js';\nimport {\n ExecutionHostMcpCapabilityUnavailableError,\n ExecutionHostMcpCapabilityVerificationError,\n} from './errors.js';\nimport { JwtExecutionHostMcpCapabilityVerifierConfigSchema } from './schemas.js';\nimport type {\n ExecutionHostJwtVerifierOptions,\n ExecutionHostMcpCapabilityVerificationRequest,\n ExecutionHostMcpCapabilityVerifier,\n JwtExecutionHostMcpCapabilityVerifierConfig,\n VerifiedExecutionHostMcpCapability,\n} from './types.js';\n\nconst AssertionSchema = z.string().trim().min(32).max(4_096);\ntype ParsedConfig = z.infer<\n typeof JwtExecutionHostMcpCapabilityVerifierConfigSchema\n>;\n\n/** Verifies MCP authority against an independently verified host invocation. */\nexport class JwtExecutionHostMcpCapabilityVerifier\nimplements ExecutionHostMcpCapabilityVerifier {\n readonly #config: Readonly<ParsedConfig>;\n readonly #keyResolver: NonNullable<ExecutionHostJwtVerifierOptions['keyResolver']>;\n readonly #now: () => Date;\n\n constructor(\n config: JwtExecutionHostMcpCapabilityVerifierConfig,\n options: ExecutionHostJwtVerifierOptions = {},\n ) {\n const parsed = JwtExecutionHostMcpCapabilityVerifierConfigSchema.parse(\n config,\n );\n this.#config = Object.freeze({\n ...parsed,\n jwksUrl: new URL(parsed.jwksUrl),\n });\n this.#keyResolver = options.keyResolver\n ?? createJwtKeyResolver(this.#config.jwksUrl);\n this.#now = options.now ?? (() => new Date());\n }\n\n async verify(\n rawRequest: ExecutionHostMcpCapabilityVerificationRequest,\n ): Promise<VerifiedExecutionHostMcpCapability> {\n try {\n const request = Object.freeze({\n ...rawRequest,\n assertion: AssertionSchema.parse(rawRequest.assertion),\n });\n const { payload } = await jwtVerify(\n request.assertion,\n this.#keyResolver,\n {\n algorithms: [...this.#config.jwtAlgorithms],\n audience: this.#config.audience,\n clockTolerance: this.#config.clockToleranceSeconds,\n currentDate: this.#now(),\n issuer: this.#config.issuer,\n maxTokenAge: this.#config.maxCapabilityAgeSeconds,\n requiredClaims: ['exp', 'iat', 'jti', 'sub'],\n typ: MCP_CAPABILITY_TYPE,\n },\n );\n const claims = McpCapabilityClaimsSchema.parse(payload);\n this.#assertInvocationBinding(claims, request);\n this.#assertBoundedLifetime(claims);\n\n return Object.freeze({\n assertion: request.assertion,\n capabilityId: claims.jti,\n serverId: claims.serverId,\n allowedTools: Object.freeze([...claims.allowedTools]),\n issuedAt: new Date(claims.iat * 1_000).toISOString(),\n expiresAt: new Date(claims.exp * 1_000).toISOString(),\n });\n } catch (error) {\n if (\n error instanceof ExecutionHostMcpCapabilityVerificationError\n || error instanceof ExecutionHostMcpCapabilityUnavailableError\n ) {\n throw error;\n }\n const category = resolveJwtVerificationUnavailableCategory(error);\n if (category) {\n throw new ExecutionHostMcpCapabilityUnavailableError(\n category,\n { cause: error },\n );\n }\n throw new ExecutionHostMcpCapabilityVerificationError({ cause: error });\n }\n }\n\n #assertInvocationBinding(\n claims: z.infer<typeof McpCapabilityClaimsSchema>,\n request: ExecutionHostMcpCapabilityVerificationRequest,\n ): void {\n const { identity } = request;\n if (\n claims.adopterId !== this.#config.trustedAdopterId\n || claims.adopterId !== identity.scope.adopterId\n || claims.tenantId !== identity.scope.tenantId\n || claims.sub !== identity.scope.subjectId\n || claims.productSessionId !== identity.scope.productSessionId\n || claims.runtimeSessionId !== identity.runtimeSessionId\n || claims.invocationId !== identity.invocationId\n || claims.workflow !== identity.workflow\n || claims.serverId !== this.#config.serverId\n || claims.jti === identity.invocationId\n ) {\n throw new ExecutionHostMcpCapabilityVerificationError();\n }\n }\n\n #assertBoundedLifetime(\n claims: z.infer<typeof McpCapabilityClaimsSchema>,\n ): void {\n const lifetimeSeconds = claims.exp - claims.iat;\n if (\n lifetimeSeconds <= 0\n || lifetimeSeconds > this.#config.maxCapabilityAgeSeconds\n ) {\n throw new ExecutionHostMcpCapabilityVerificationError();\n }\n }\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { ExecutionIdentityVerificationRequest, ExecutionIdentityVerifier, ExecutionHostJwtVerifierOptions, JwtExecutionIdentityVerifierConfig, VerifiedExecutionIdentity } from './types.js';
2
+ /** Verifies adopter authority and binds it to one exact host invocation. */
3
+ export declare class JwtExecutionIdentityVerifier implements ExecutionIdentityVerifier {
4
+ #private;
5
+ constructor(config: JwtExecutionIdentityVerifierConfig, options?: ExecutionHostJwtVerifierOptions);
6
+ verify(rawRequest: ExecutionIdentityVerificationRequest): Promise<VerifiedExecutionIdentity>;
7
+ }
8
+ //# sourceMappingURL=jwt-execution-identity-verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-execution-identity-verifier.d.ts","sourceRoot":"","sources":["../../src/host/jwt-execution-identity-verifier.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,oCAAoC,EACpC,yBAAyB,EACzB,+BAA+B,EAC/B,kCAAkC,EAClC,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAKpB,4EAA4E;AAC5E,qBAAa,4BAA6B,YAAW,yBAAyB;;gBAM1E,MAAM,EAAE,kCAAkC,EAC1C,OAAO,GAAE,+BAAoC;IAYzC,MAAM,CACV,UAAU,EAAE,oCAAoC,GAC/C,OAAO,CAAC,yBAAyB,CAAC;CAgEtC"}
@@ -0,0 +1,76 @@
1
+ import { jwtVerify } from 'jose';
2
+ import { z } from 'zod';
3
+ import { EXECUTION_ASSERTION_TYPE, ExecutionAssertionClaimsSchema, } from '../contracts/index.js';
4
+ import { createJwtKeyResolver, resolveJwtVerificationUnavailableCategory, } from '../internal/jwt-verification.js';
5
+ import { ExecutionIdentityUnavailableError, ExecutionIdentityVerificationError, } from './errors.js';
6
+ import { JwtExecutionIdentityVerifierConfigSchema } from './schemas.js';
7
+ const AssertionSchema = z.string().trim().min(32).max(4_096);
8
+ /** Verifies adopter authority and binds it to one exact host invocation. */
9
+ export class JwtExecutionIdentityVerifier {
10
+ #config;
11
+ #keyResolver;
12
+ #now;
13
+ constructor(config, options = {}) {
14
+ const parsed = JwtExecutionIdentityVerifierConfigSchema.parse(config);
15
+ this.#config = Object.freeze({
16
+ ...parsed,
17
+ executionJwksUrl: new URL(parsed.executionJwksUrl),
18
+ });
19
+ this.#keyResolver = options.keyResolver
20
+ ?? createJwtKeyResolver(this.#config.executionJwksUrl);
21
+ this.#now = options.now ?? (() => new Date());
22
+ }
23
+ async verify(rawRequest) {
24
+ try {
25
+ const request = Object.freeze({
26
+ ...rawRequest,
27
+ assertion: AssertionSchema.parse(rawRequest.assertion),
28
+ });
29
+ const { payload } = await jwtVerify(request.assertion, this.#keyResolver, {
30
+ algorithms: [...this.#config.executionJwtAlgorithms],
31
+ audience: this.#config.executionAudience,
32
+ clockTolerance: this.#config.assertionClockToleranceSeconds,
33
+ currentDate: this.#now(),
34
+ issuer: this.#config.executionIssuer,
35
+ maxTokenAge: this.#config.maxAssertionAgeSeconds,
36
+ requiredClaims: ['exp', 'iat', 'jti', 'sub'],
37
+ typ: EXECUTION_ASSERTION_TYPE,
38
+ });
39
+ const claims = ExecutionAssertionClaimsSchema.parse(payload);
40
+ this.#assertRequestBinding(claims, request);
41
+ return Object.freeze({
42
+ scope: Object.freeze({
43
+ adopterId: claims.adopterId,
44
+ tenantId: claims.tenantId,
45
+ subjectId: claims.sub,
46
+ productSessionId: claims.productSessionId,
47
+ }),
48
+ runtimeSessionId: claims.runtimeSessionId,
49
+ invocationId: claims.jti,
50
+ workflow: claims.workflow,
51
+ issuedAt: new Date(claims.iat * 1_000).toISOString(),
52
+ expiresAt: new Date(claims.exp * 1_000).toISOString(),
53
+ });
54
+ }
55
+ catch (error) {
56
+ if (error instanceof ExecutionIdentityVerificationError
57
+ || error instanceof ExecutionIdentityUnavailableError) {
58
+ throw error;
59
+ }
60
+ const category = resolveJwtVerificationUnavailableCategory(error);
61
+ if (category) {
62
+ throw new ExecutionIdentityUnavailableError(category, { cause: error });
63
+ }
64
+ throw new ExecutionIdentityVerificationError({ cause: error });
65
+ }
66
+ }
67
+ #assertRequestBinding(claims, request) {
68
+ if (claims.adopterId !== this.#config.trustedAdopterId
69
+ || claims.runtimeSessionId !== request.runtimeSessionId
70
+ || claims.jti !== request.invocationId
71
+ || claims.workflow !== request.workflow) {
72
+ throw new ExecutionIdentityVerificationError();
73
+ }
74
+ }
75
+ }
76
+ //# sourceMappingURL=jwt-execution-identity-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-execution-identity-verifier.js","sourceRoot":"","sources":["../../src/host/jwt-execution-identity-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import { jwtVerify } from 'jose';\nimport { z } from 'zod';\nimport {\n EXECUTION_ASSERTION_TYPE,\n ExecutionAssertionClaimsSchema,\n} from '../contracts/index.js';\nimport {\n createJwtKeyResolver,\n resolveJwtVerificationUnavailableCategory,\n} from '../internal/jwt-verification.js';\nimport {\n ExecutionIdentityUnavailableError,\n ExecutionIdentityVerificationError,\n} from './errors.js';\nimport { JwtExecutionIdentityVerifierConfigSchema } from './schemas.js';\nimport type {\n ExecutionIdentityVerificationRequest,\n ExecutionIdentityVerifier,\n ExecutionHostJwtVerifierOptions,\n JwtExecutionIdentityVerifierConfig,\n VerifiedExecutionIdentity,\n} from './types.js';\n\nconst AssertionSchema = z.string().trim().min(32).max(4_096);\ntype ParsedConfig = z.infer<typeof JwtExecutionIdentityVerifierConfigSchema>;\n\n/** Verifies adopter authority and binds it to one exact host invocation. */\nexport class JwtExecutionIdentityVerifier implements ExecutionIdentityVerifier {\n readonly #config: Readonly<ParsedConfig>;\n readonly #keyResolver: NonNullable<ExecutionHostJwtVerifierOptions['keyResolver']>;\n readonly #now: () => Date;\n\n constructor(\n config: JwtExecutionIdentityVerifierConfig,\n options: ExecutionHostJwtVerifierOptions = {},\n ) {\n const parsed = JwtExecutionIdentityVerifierConfigSchema.parse(config);\n this.#config = Object.freeze({\n ...parsed,\n executionJwksUrl: new URL(parsed.executionJwksUrl),\n });\n this.#keyResolver = options.keyResolver\n ?? createJwtKeyResolver(this.#config.executionJwksUrl);\n this.#now = options.now ?? (() => new Date());\n }\n\n async verify(\n rawRequest: ExecutionIdentityVerificationRequest,\n ): Promise<VerifiedExecutionIdentity> {\n try {\n const request = Object.freeze({\n ...rawRequest,\n assertion: AssertionSchema.parse(rawRequest.assertion),\n });\n const { payload } = await jwtVerify(\n request.assertion,\n this.#keyResolver,\n {\n algorithms: [...this.#config.executionJwtAlgorithms],\n audience: this.#config.executionAudience,\n clockTolerance: this.#config.assertionClockToleranceSeconds,\n currentDate: this.#now(),\n issuer: this.#config.executionIssuer,\n maxTokenAge: this.#config.maxAssertionAgeSeconds,\n requiredClaims: ['exp', 'iat', 'jti', 'sub'],\n typ: EXECUTION_ASSERTION_TYPE,\n },\n );\n const claims = ExecutionAssertionClaimsSchema.parse(payload);\n this.#assertRequestBinding(claims, request);\n\n return Object.freeze({\n scope: Object.freeze({\n adopterId: claims.adopterId,\n tenantId: claims.tenantId,\n subjectId: claims.sub,\n productSessionId: claims.productSessionId,\n }),\n runtimeSessionId: claims.runtimeSessionId,\n invocationId: claims.jti,\n workflow: claims.workflow,\n issuedAt: new Date(claims.iat * 1_000).toISOString(),\n expiresAt: new Date(claims.exp * 1_000).toISOString(),\n });\n } catch (error) {\n if (\n error instanceof ExecutionIdentityVerificationError\n || error instanceof ExecutionIdentityUnavailableError\n ) {\n throw error;\n }\n const category = resolveJwtVerificationUnavailableCategory(error);\n if (category) {\n throw new ExecutionIdentityUnavailableError(category, { cause: error });\n }\n throw new ExecutionIdentityVerificationError({ cause: error });\n }\n }\n\n #assertRequestBinding(\n claims: z.infer<typeof ExecutionAssertionClaimsSchema>,\n request: ExecutionIdentityVerificationRequest,\n ): void {\n if (\n claims.adopterId !== this.#config.trustedAdopterId\n || claims.runtimeSessionId !== request.runtimeSessionId\n || claims.jti !== request.invocationId\n || claims.workflow !== request.workflow\n ) {\n throw new ExecutionIdentityVerificationError();\n }\n }\n}\n"]}
@@ -0,0 +1,37 @@
1
+ import { z } from 'zod';
2
+ export declare const ExecutionHostJwtAlgorithmsSchema: z.ZodPipe<z.ZodArray<z.ZodEnum<{
3
+ ES256: "ES256";
4
+ RS256: "RS256";
5
+ PS256: "PS256";
6
+ EdDSA: "EdDSA";
7
+ }>>, z.ZodTransform<readonly ("ES256" | "RS256" | "PS256" | "EdDSA")[], ("ES256" | "RS256" | "PS256" | "EdDSA")[]>>;
8
+ export declare const JwtExecutionIdentityVerifierConfigSchema: z.ZodObject<{
9
+ executionIssuer: z.ZodURL;
10
+ executionAudience: z.ZodString;
11
+ executionJwksUrl: z.ZodCustom<URL, URL>;
12
+ executionJwtAlgorithms: z.ZodPipe<z.ZodArray<z.ZodEnum<{
13
+ ES256: "ES256";
14
+ RS256: "RS256";
15
+ PS256: "PS256";
16
+ EdDSA: "EdDSA";
17
+ }>>, z.ZodTransform<readonly ("ES256" | "RS256" | "PS256" | "EdDSA")[], ("ES256" | "RS256" | "PS256" | "EdDSA")[]>>;
18
+ trustedAdopterId: z.ZodString;
19
+ maxAssertionAgeSeconds: z.ZodNumber;
20
+ assertionClockToleranceSeconds: z.ZodNumber;
21
+ }, z.core.$strict>;
22
+ export declare const JwtExecutionHostMcpCapabilityVerifierConfigSchema: z.ZodObject<{
23
+ issuer: z.ZodURL;
24
+ audience: z.ZodString;
25
+ jwksUrl: z.ZodCustom<URL, URL>;
26
+ jwtAlgorithms: z.ZodPipe<z.ZodArray<z.ZodEnum<{
27
+ ES256: "ES256";
28
+ RS256: "RS256";
29
+ PS256: "PS256";
30
+ EdDSA: "EdDSA";
31
+ }>>, z.ZodTransform<readonly ("ES256" | "RS256" | "PS256" | "EdDSA")[], ("ES256" | "RS256" | "PS256" | "EdDSA")[]>>;
32
+ trustedAdopterId: z.ZodString;
33
+ serverId: z.ZodString;
34
+ maxCapabilityAgeSeconds: z.ZodNumber;
35
+ clockToleranceSeconds: z.ZodNumber;
36
+ }, z.core.$strict>;
37
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/host/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,gCAAgC;;;;;mHAI5C,CAAC;AAEF,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;kBAW1C,CAAC;AAEZ,eAAO,MAAM,iDAAiD;;;;;;;;;;;;;;kBAYnD,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ import { JwtAudienceSchema, JwtIssuerSchema, McpServerIdSchema, OpaqueIdSchema, isSafeWebUrl, } from '../contracts/index.js';
3
+ import { EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS } from './types.js';
4
+ export const ExecutionHostJwtAlgorithmsSchema = z.array(z.enum(EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS)).min(1).max(EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS.length).transform((algorithms) => Object.freeze([...new Set(algorithms)]));
5
+ export const JwtExecutionIdentityVerifierConfigSchema = z.object({
6
+ executionIssuer: JwtIssuerSchema,
7
+ executionAudience: JwtAudienceSchema,
8
+ executionJwksUrl: z.instanceof(URL).refine(isSafeWebUrl, 'must use HTTPS or loopback HTTP and contain no credentials, query, or fragment'),
9
+ executionJwtAlgorithms: ExecutionHostJwtAlgorithmsSchema,
10
+ trustedAdopterId: OpaqueIdSchema,
11
+ maxAssertionAgeSeconds: z.number().int().min(1).max(15 * 60),
12
+ assertionClockToleranceSeconds: z.number().int().min(0).max(60),
13
+ }).strict();
14
+ export const JwtExecutionHostMcpCapabilityVerifierConfigSchema = z.object({
15
+ issuer: JwtIssuerSchema,
16
+ audience: JwtAudienceSchema,
17
+ jwksUrl: z.instanceof(URL).refine(isSafeWebUrl, 'must use HTTPS or loopback HTTP and contain no credentials, query, or fragment'),
18
+ jwtAlgorithms: ExecutionHostJwtAlgorithmsSchema,
19
+ trustedAdopterId: OpaqueIdSchema,
20
+ serverId: McpServerIdSchema,
21
+ maxCapabilityAgeSeconds: z.number().int().min(1).max(15 * 60),
22
+ clockToleranceSeconds: z.number().int().min(0).max(60),
23
+ }).strict();
24
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/host/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uCAAuC,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,KAAK,CACrD,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAChD,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,uCAAuC,CAAC,MAAM,CAAC,CAAC,SAAS,CACpE,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CACxD,CAAC;AAEF,MAAM,CAAC,MAAM,wCAAwC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/D,eAAe,EAAE,eAAe;IAChC,iBAAiB,EAAE,iBAAiB;IACpC,gBAAgB,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CACxC,YAAY,EACZ,gFAAgF,CACjF;IACD,sBAAsB,EAAE,gCAAgC;IACxD,gBAAgB,EAAE,cAAc;IAChC,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IAC5D,8BAA8B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CAChE,CAAC,CAAC,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,iDAAiD,GAAG,CAAC,CAAC,MAAM,CAAC;IACxE,MAAM,EAAE,eAAe;IACvB,QAAQ,EAAE,iBAAiB;IAC3B,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAC/B,YAAY,EACZ,gFAAgF,CACjF;IACD,aAAa,EAAE,gCAAgC;IAC/C,gBAAgB,EAAE,cAAc;IAChC,QAAQ,EAAE,iBAAiB;IAC3B,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IAC7D,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CACvD,CAAC,CAAC,MAAM,EAAE,CAAC","sourcesContent":["import { z } from 'zod';\nimport {\n JwtAudienceSchema,\n JwtIssuerSchema,\n McpServerIdSchema,\n OpaqueIdSchema,\n isSafeWebUrl,\n} from '../contracts/index.js';\nimport { EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS } from './types.js';\n\nexport const ExecutionHostJwtAlgorithmsSchema = z.array(\n z.enum(EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS),\n).min(1).max(EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS.length).transform(\n (algorithms) => Object.freeze([...new Set(algorithms)]),\n);\n\nexport const JwtExecutionIdentityVerifierConfigSchema = z.object({\n executionIssuer: JwtIssuerSchema,\n executionAudience: JwtAudienceSchema,\n executionJwksUrl: z.instanceof(URL).refine(\n isSafeWebUrl,\n 'must use HTTPS or loopback HTTP and contain no credentials, query, or fragment',\n ),\n executionJwtAlgorithms: ExecutionHostJwtAlgorithmsSchema,\n trustedAdopterId: OpaqueIdSchema,\n maxAssertionAgeSeconds: z.number().int().min(1).max(15 * 60),\n assertionClockToleranceSeconds: z.number().int().min(0).max(60),\n}).strict();\n\nexport const JwtExecutionHostMcpCapabilityVerifierConfigSchema = z.object({\n issuer: JwtIssuerSchema,\n audience: JwtAudienceSchema,\n jwksUrl: z.instanceof(URL).refine(\n isSafeWebUrl,\n 'must use HTTPS or loopback HTTP and contain no credentials, query, or fragment',\n ),\n jwtAlgorithms: ExecutionHostJwtAlgorithmsSchema,\n trustedAdopterId: OpaqueIdSchema,\n serverId: McpServerIdSchema,\n maxCapabilityAgeSeconds: z.number().int().min(1).max(15 * 60),\n clockToleranceSeconds: z.number().int().min(0).max(60),\n}).strict();\n"]}
@@ -0,0 +1,62 @@
1
+ import type { JWTVerifyGetKey } from 'jose';
2
+ import type { ExecutionScope, HostedExecutionWorkflow } from '../contracts/index.js';
3
+ export declare const EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS: readonly ["RS256", "PS256", "ES256", "EdDSA"];
4
+ export type ExecutionHostJwtAlgorithm = typeof EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS[number];
5
+ /** Authority established from one signed assertion and its request binding. */
6
+ export type VerifiedExecutionIdentity = Readonly<{
7
+ scope: Readonly<ExecutionScope>;
8
+ runtimeSessionId: string;
9
+ invocationId: string;
10
+ workflow: HostedExecutionWorkflow;
11
+ issuedAt: string;
12
+ expiresAt: string;
13
+ }>;
14
+ export type ExecutionIdentityVerificationRequest = Readonly<{
15
+ assertion: string;
16
+ runtimeSessionId: string;
17
+ invocationId: string;
18
+ workflow: HostedExecutionWorkflow;
19
+ }>;
20
+ export interface ExecutionIdentityVerifier {
21
+ verify(request: ExecutionIdentityVerificationRequest): Promise<VerifiedExecutionIdentity>;
22
+ }
23
+ export type JwtExecutionIdentityVerifierConfig = Readonly<{
24
+ executionIssuer: string;
25
+ executionAudience: string;
26
+ executionJwksUrl: URL;
27
+ executionJwtAlgorithms: readonly ExecutionHostJwtAlgorithm[];
28
+ trustedAdopterId: string;
29
+ maxAssertionAgeSeconds: number;
30
+ assertionClockToleranceSeconds: number;
31
+ }>;
32
+ /** Opaque MCP bearer whose claims match the independently verified execution. */
33
+ export type VerifiedExecutionHostMcpCapability = Readonly<{
34
+ assertion: string;
35
+ capabilityId: string;
36
+ serverId: string;
37
+ allowedTools: readonly string[];
38
+ issuedAt: string;
39
+ expiresAt: string;
40
+ }>;
41
+ export type ExecutionHostMcpCapabilityVerificationRequest = Readonly<{
42
+ assertion: string;
43
+ identity: VerifiedExecutionIdentity;
44
+ }>;
45
+ export interface ExecutionHostMcpCapabilityVerifier {
46
+ verify(request: ExecutionHostMcpCapabilityVerificationRequest): Promise<VerifiedExecutionHostMcpCapability>;
47
+ }
48
+ export type JwtExecutionHostMcpCapabilityVerifierConfig = Readonly<{
49
+ issuer: string;
50
+ audience: string;
51
+ jwksUrl: URL;
52
+ jwtAlgorithms: readonly ExecutionHostJwtAlgorithm[];
53
+ trustedAdopterId: string;
54
+ serverId: string;
55
+ maxCapabilityAgeSeconds: number;
56
+ clockToleranceSeconds: number;
57
+ }>;
58
+ export type ExecutionHostJwtVerifierOptions = Readonly<{
59
+ keyResolver?: JWTVerifyGetKey;
60
+ now?: () => Date;
61
+ }>;
62
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/host/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,KAAK,EACV,cAAc,EACd,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,uCAAuC,+CAK1C,CAAC;AAEX,MAAM,MAAM,yBAAyB,GACnC,OAAO,uCAAuC,CAAC,MAAM,CAAC,CAAC;AAEzD,+EAA+E;AAC/E,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAAC;AAEH,MAAM,MAAM,oCAAoC,GAAG,QAAQ,CAAC;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,uBAAuB,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,WAAW,yBAAyB;IACxC,MAAM,CACJ,OAAO,EAAE,oCAAoC,GAC5C,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,kCAAkC,GAAG,QAAQ,CAAC;IACxD,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,GAAG,CAAC;IACtB,sBAAsB,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC7D,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,8BAA8B,EAAE,MAAM,CAAC;CACxC,CAAC,CAAC;AAEH,iFAAiF;AACjF,MAAM,MAAM,kCAAkC,GAAG,QAAQ,CAAC;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAAC;AAEH,MAAM,MAAM,6CAA6C,GAAG,QAAQ,CAAC;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,yBAAyB,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,WAAW,kCAAkC;IACjD,MAAM,CACJ,OAAO,EAAE,6CAA6C,GACrD,OAAO,CAAC,kCAAkC,CAAC,CAAC;CAChD;AAED,MAAM,MAAM,2CAA2C,GAAG,QAAQ,CAAC;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC;IACb,aAAa,EAAE,SAAS,yBAAyB,EAAE,CAAC;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG,QAAQ,CAAC;IACrD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export const EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS = [
2
+ 'RS256',
3
+ 'PS256',
4
+ 'ES256',
5
+ 'EdDSA',
6
+ ];
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/host/types.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,uCAAuC,GAAG;IACrD,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;CACC,CAAC","sourcesContent":["import type { JWTVerifyGetKey } from 'jose';\nimport type {\n ExecutionScope,\n HostedExecutionWorkflow,\n} from '../contracts/index.js';\n\nexport const EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS = [\n 'RS256',\n 'PS256',\n 'ES256',\n 'EdDSA',\n] as const;\n\nexport type ExecutionHostJwtAlgorithm =\n typeof EXECUTION_HOST_SUPPORTED_JWT_ALGORITHMS[number];\n\n/** Authority established from one signed assertion and its request binding. */\nexport type VerifiedExecutionIdentity = Readonly<{\n scope: Readonly<ExecutionScope>;\n runtimeSessionId: string;\n invocationId: string;\n workflow: HostedExecutionWorkflow;\n issuedAt: string;\n expiresAt: string;\n}>;\n\nexport type ExecutionIdentityVerificationRequest = Readonly<{\n assertion: string;\n runtimeSessionId: string;\n invocationId: string;\n workflow: HostedExecutionWorkflow;\n}>;\n\nexport interface ExecutionIdentityVerifier {\n verify(\n request: ExecutionIdentityVerificationRequest,\n ): Promise<VerifiedExecutionIdentity>;\n}\n\nexport type JwtExecutionIdentityVerifierConfig = Readonly<{\n executionIssuer: string;\n executionAudience: string;\n executionJwksUrl: URL;\n executionJwtAlgorithms: readonly ExecutionHostJwtAlgorithm[];\n trustedAdopterId: string;\n maxAssertionAgeSeconds: number;\n assertionClockToleranceSeconds: number;\n}>;\n\n/** Opaque MCP bearer whose claims match the independently verified execution. */\nexport type VerifiedExecutionHostMcpCapability = Readonly<{\n assertion: string;\n capabilityId: string;\n serverId: string;\n allowedTools: readonly string[];\n issuedAt: string;\n expiresAt: string;\n}>;\n\nexport type ExecutionHostMcpCapabilityVerificationRequest = Readonly<{\n assertion: string;\n identity: VerifiedExecutionIdentity;\n}>;\n\nexport interface ExecutionHostMcpCapabilityVerifier {\n verify(\n request: ExecutionHostMcpCapabilityVerificationRequest,\n ): Promise<VerifiedExecutionHostMcpCapability>;\n}\n\nexport type JwtExecutionHostMcpCapabilityVerifierConfig = Readonly<{\n issuer: string;\n audience: string;\n jwksUrl: URL;\n jwtAlgorithms: readonly ExecutionHostJwtAlgorithm[];\n trustedAdopterId: string;\n serverId: string;\n maxCapabilityAgeSeconds: number;\n clockToleranceSeconds: number;\n}>;\n\nexport type ExecutionHostJwtVerifierOptions = Readonly<{\n keyResolver?: JWTVerifyGetKey;\n now?: () => Date;\n}>;\n"]}
@@ -0,0 +1,5 @@
1
+ import { type JWTVerifyGetKey } from 'jose';
2
+ export type JwtVerificationUnavailableCategory = 'network' | 'jwks_response' | 'jwks_timeout';
3
+ export declare function createJwtKeyResolver(jwksUrl: URL): JWTVerifyGetKey;
4
+ export declare function resolveJwtVerificationUnavailableCategory(error: unknown): JwtVerificationUnavailableCategory | undefined;
5
+ //# sourceMappingURL=jwt-verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-verification.d.ts","sourceRoot":"","sources":["../../src/internal/jwt-verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,MAAM,CAAC;AAgBd,MAAM,MAAM,kCAAkC,GAC1C,SAAS,GACT,eAAe,GACf,cAAc,CAAC;AAEnB,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,GAAG,GAAG,eAAe,CAElE;AAED,wBAAgB,yCAAyC,CACvD,KAAK,EAAE,OAAO,GACb,kCAAkC,GAAG,SAAS,CAOhD"}
@@ -0,0 +1,25 @@
1
+ import { createRemoteJWKSet, errors, } from 'jose';
2
+ const REMOTE_JWKS_OPTIONS = Object.freeze({
3
+ cacheMaxAge: 10 * 60_000,
4
+ cooldownDuration: 30_000,
5
+ timeoutDuration: 3_000,
6
+ });
7
+ const UNAVAILABLE_JOSE_CATEGORIES = new Map([
8
+ ['ERR_JOSE_GENERIC', 'jwks_response'],
9
+ ['ERR_JWK_INVALID', 'jwks_response'],
10
+ ['ERR_JWKS_INVALID', 'jwks_response'],
11
+ ['ERR_JWKS_MULTIPLE_MATCHING_KEYS', 'jwks_response'],
12
+ ['ERR_JWKS_TIMEOUT', 'jwks_timeout'],
13
+ ]);
14
+ export function createJwtKeyResolver(jwksUrl) {
15
+ return createRemoteJWKSet(jwksUrl, REMOTE_JWKS_OPTIONS);
16
+ }
17
+ export function resolveJwtVerificationUnavailableCategory(error) {
18
+ if (error instanceof TypeError) {
19
+ return 'network';
20
+ }
21
+ return error instanceof errors.JOSEError
22
+ ? UNAVAILABLE_JOSE_CATEGORIES.get(error.code)
23
+ : undefined;
24
+ }
25
+ //# sourceMappingURL=jwt-verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-verification.js","sourceRoot":"","sources":["../../src/internal/jwt-verification.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,MAAM,GAEP,MAAM,MAAM,CAAC;AAEd,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,EAAE,GAAG,MAAM;IACxB,gBAAgB,EAAE,MAAM;IACxB,eAAe,EAAE,KAAK;CACvB,CAAC,CAAC;AAEH,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAA6C;IACtF,CAAC,kBAAkB,EAAE,eAAe,CAAC;IACrC,CAAC,iBAAiB,EAAE,eAAe,CAAC;IACpC,CAAC,kBAAkB,EAAE,eAAe,CAAC;IACrC,CAAC,iCAAiC,EAAE,eAAe,CAAC;IACpD,CAAC,kBAAkB,EAAE,cAAc,CAAC;CACrC,CAAC,CAAC;AAOH,MAAM,UAAU,oBAAoB,CAAC,OAAY;IAC/C,OAAO,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,yCAAyC,CACvD,KAAc;IAEd,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,YAAY,MAAM,CAAC,SAAS;QACtC,CAAC,CAAC,2BAA2B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;QAC7C,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC","sourcesContent":["import {\n createRemoteJWKSet,\n errors,\n type JWTVerifyGetKey,\n} from 'jose';\n\nconst REMOTE_JWKS_OPTIONS = Object.freeze({\n cacheMaxAge: 10 * 60_000,\n cooldownDuration: 30_000,\n timeoutDuration: 3_000,\n});\n\nconst UNAVAILABLE_JOSE_CATEGORIES = new Map<string, JwtVerificationUnavailableCategory>([\n ['ERR_JOSE_GENERIC', 'jwks_response'],\n ['ERR_JWK_INVALID', 'jwks_response'],\n ['ERR_JWKS_INVALID', 'jwks_response'],\n ['ERR_JWKS_MULTIPLE_MATCHING_KEYS', 'jwks_response'],\n ['ERR_JWKS_TIMEOUT', 'jwks_timeout'],\n]);\n\nexport type JwtVerificationUnavailableCategory =\n | 'network'\n | 'jwks_response'\n | 'jwks_timeout';\n\nexport function createJwtKeyResolver(jwksUrl: URL): JWTVerifyGetKey {\n return createRemoteJWKSet(jwksUrl, REMOTE_JWKS_OPTIONS);\n}\n\nexport function resolveJwtVerificationUnavailableCategory(\n error: unknown,\n): JwtVerificationUnavailableCategory | undefined {\n if (error instanceof TypeError) {\n return 'network';\n }\n return error instanceof errors.JOSEError\n ? UNAVAILABLE_JOSE_CATEGORIES.get(error.code)\n : undefined;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-capability-verifier.d.ts","sourceRoot":"","sources":["../../src/mcp/jwt-capability-verifier.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,8BAA8B,EAC9B,+BAA+B,EAC/B,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAqBpB;;;GAGG;AACH,qBAAa,wBAAwB,CAAC,SAAS,SAAS,MAAM,CAC9D,YAAW,qBAAqB,CAAC,SAAS,CAAC;;gBAOvC,MAAM,EAAE,8BAA8B,CAAC,SAAS,CAAC,EACjD,OAAO,GAAE,+BAAoC;IAoBzC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;CA8E3E;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,qBAAqB,EACjC,GAAG,OAAa,GACf,IAAI,CAKN"}
1
+ {"version":3,"file":"jwt-capability-verifier.d.ts","sourceRoot":"","sources":["../../src/mcp/jwt-capability-verifier.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,8BAA8B,EAC9B,+BAA+B,EAC/B,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAqBpB;;;GAGG;AACH,qBAAa,wBAAwB,CAAC,SAAS,SAAS,MAAM,CAC9D,YAAW,qBAAqB,CAAC,SAAS,CAAC;;gBAOvC,MAAM,EAAE,8BAA8B,CAAC,SAAS,CAAC,EACjD,OAAO,GAAE,+BAAoC;IAczC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;CAkF3E;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,qBAAqB,EACjC,GAAG,OAAa,GACf,IAAI,CAKN"}
@@ -1,7 +1,8 @@
1
- import { createRemoteJWKSet, errors, jwtVerify, } from 'jose';
1
+ import { jwtVerify } from 'jose';
2
2
  import { z } from 'zod';
3
3
  import { JwtAudienceSchema, JwtIssuerSchema, MCP_CAPABILITY_TYPE, McpAllowedToolsSchema, McpCapabilityClaimsSchema, McpServerIdSchema, OpaqueIdSchema, isSafeWebUrl, } from '../contracts/index.js';
4
4
  import { McpCapabilityUnavailableError, McpCapabilityVerificationError, } from './errors.js';
5
+ import { createJwtKeyResolver, resolveJwtVerificationUnavailableCategory, } from '../internal/jwt-verification.js';
5
6
  const CapabilityAssertionSchema = z.string().min(32).max(4_096);
6
7
  const ConfigSchema = z.object({
7
8
  issuer: JwtIssuerSchema,
@@ -30,11 +31,8 @@ export class JwtMcpCapabilityVerifier {
30
31
  supportedTools: Object.freeze([...parsed.supportedTools]),
31
32
  });
32
33
  this.#supportedTools = new Set(this.#config.supportedTools);
33
- this.#keyResolver = options.keyResolver ?? createRemoteJWKSet(this.#config.jwksUrl, {
34
- cacheMaxAge: 10 * 60_000,
35
- cooldownDuration: 30_000,
36
- timeoutDuration: 3_000,
37
- });
34
+ this.#keyResolver = options.keyResolver
35
+ ?? createJwtKeyResolver(this.#config.jwksUrl);
38
36
  this.#now = options.now ?? (() => new Date());
39
37
  }
40
38
  async verify(assertion) {
@@ -76,9 +74,9 @@ export class JwtMcpCapabilityVerifier {
76
74
  || error instanceof McpCapabilityUnavailableError) {
77
75
  throw error;
78
76
  }
79
- const unavailableCategory = resolveUnavailableCategory(error);
77
+ const unavailableCategory = resolveJwtVerificationUnavailableCategory(error);
80
78
  if (unavailableCategory) {
81
- throw new McpCapabilityUnavailableError(unavailableCategory);
79
+ throw new McpCapabilityUnavailableError(unavailableCategory === 'network' ? 'network' : 'jwks');
82
80
  }
83
81
  throw new McpCapabilityVerificationError();
84
82
  }
@@ -116,21 +114,4 @@ function freezeVerifiedCapability(capability) {
116
114
  scope: Object.freeze({ ...capability.scope }),
117
115
  });
118
116
  }
119
- const UNAVAILABLE_JOSE_CODES = new Set([
120
- 'ERR_JOSE_GENERIC',
121
- 'ERR_JWK_INVALID',
122
- 'ERR_JWKS_INVALID',
123
- 'ERR_JWKS_MULTIPLE_MATCHING_KEYS',
124
- 'ERR_JWKS_TIMEOUT',
125
- ]);
126
- function resolveUnavailableCategory(error) {
127
- if (error instanceof TypeError) {
128
- return 'network';
129
- }
130
- if (error instanceof errors.JOSEError
131
- && UNAVAILABLE_JOSE_CODES.has(error.code)) {
132
- return 'jwks';
133
- }
134
- return undefined;
135
- }
136
117
  //# sourceMappingURL=jwt-capability-verifier.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-capability-verifier.js","sourceRoot":"","sources":["../../src/mcp/jwt-capability-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createRemoteJWKSet,\n errors,\n jwtVerify,\n} from 'jose';\nimport { z } from 'zod';\nimport {\n JwtAudienceSchema,\n JwtIssuerSchema,\n MCP_CAPABILITY_TYPE,\n McpAllowedToolsSchema,\n McpCapabilityClaimsSchema,\n McpServerIdSchema,\n OpaqueIdSchema,\n isSafeWebUrl,\n} from '../contracts/index.js';\nimport {\n McpCapabilityUnavailableError,\n McpCapabilityVerificationError,\n} from './errors.js';\nimport type {\n JwtMcpCapabilityVerifierConfig,\n JwtMcpCapabilityVerifierOptions,\n McpCapabilityVerifier,\n VerifiedMcpCapability,\n} from './types.js';\n\nconst CapabilityAssertionSchema = z.string().min(32).max(4_096);\nconst ConfigSchema = z.object({\n issuer: JwtIssuerSchema,\n audience: JwtAudienceSchema,\n jwksUrl: z.instanceof(URL).refine(\n isSafeWebUrl,\n 'must use HTTPS or loopback HTTP and contain no credentials, query, or fragment',\n ),\n trustedAdopterId: OpaqueIdSchema,\n serverId: McpServerIdSchema,\n supportedTools: McpAllowedToolsSchema,\n maxCapabilityAgeSeconds: z.number().int().min(1).max(15 * 60),\n clockToleranceSeconds: z.number().int().min(0).max(60).default(5),\n}).strict();\n\ntype ParsedConfig = Omit<z.infer<typeof ConfigSchema>, 'supportedTools'> & {\n supportedTools: readonly string[];\n};\n\n/**\n * Independently verifies an adopter-signed capability at the adopter's MCP\n * edge. Execution Host verification is defense in depth, not forwarded trust.\n */\nexport class JwtMcpCapabilityVerifier<TToolName extends string>\nimplements McpCapabilityVerifier<TToolName> {\n readonly #config: Readonly<ParsedConfig>;\n readonly #supportedTools: ReadonlySet<string>;\n readonly #keyResolver: NonNullable<JwtMcpCapabilityVerifierOptions['keyResolver']>;\n readonly #now: () => Date;\n\n constructor(\n config: JwtMcpCapabilityVerifierConfig<TToolName>,\n options: JwtMcpCapabilityVerifierOptions = {},\n ) {\n const parsed = ConfigSchema.parse(config);\n this.#config = Object.freeze({\n ...parsed,\n jwksUrl: new URL(parsed.jwksUrl),\n supportedTools: Object.freeze([...parsed.supportedTools]),\n });\n this.#supportedTools = new Set(this.#config.supportedTools);\n this.#keyResolver = options.keyResolver ?? createRemoteJWKSet(\n this.#config.jwksUrl,\n {\n cacheMaxAge: 10 * 60_000,\n cooldownDuration: 30_000,\n timeoutDuration: 3_000,\n },\n );\n this.#now = options.now ?? (() => new Date());\n }\n\n async verify(assertion: string): Promise<VerifiedMcpCapability<TToolName>> {\n try {\n const compactJwt = CapabilityAssertionSchema.parse(assertion);\n const { payload } = await jwtVerify(compactJwt, this.#keyResolver, {\n algorithms: ['ES256'],\n audience: this.#config.audience,\n clockTolerance: this.#config.clockToleranceSeconds,\n currentDate: this.#now(),\n issuer: this.#config.issuer,\n maxTokenAge: this.#config.maxCapabilityAgeSeconds,\n requiredClaims: ['exp', 'iat', 'jti', 'sub'],\n typ: MCP_CAPABILITY_TYPE,\n });\n const claims = McpCapabilityClaimsSchema.parse(payload);\n this.#assertDeploymentBinding(claims);\n this.#assertBoundedLifetime(claims);\n this.#assertSupportedTools(claims.allowedTools);\n\n return freezeVerifiedCapability({\n capabilityId: claims.jti,\n serverId: claims.serverId,\n allowedTools: claims.allowedTools as TToolName[],\n scope: {\n adopterId: claims.adopterId,\n tenantId: claims.tenantId,\n subjectId: claims.sub,\n productSessionId: claims.productSessionId,\n runtimeSessionId: claims.runtimeSessionId,\n invocationId: claims.invocationId,\n workflow: claims.workflow,\n },\n issuedAt: new Date(claims.iat * 1_000).toISOString(),\n expiresAt: new Date(claims.exp * 1_000).toISOString(),\n });\n } catch (error) {\n if (\n error instanceof McpCapabilityVerificationError\n || error instanceof McpCapabilityUnavailableError\n ) {\n throw error;\n }\n const unavailableCategory = resolveUnavailableCategory(error);\n if (unavailableCategory) {\n throw new McpCapabilityUnavailableError(unavailableCategory);\n }\n throw new McpCapabilityVerificationError();\n }\n }\n\n #assertDeploymentBinding(\n claims: z.infer<typeof McpCapabilityClaimsSchema>,\n ): void {\n if (\n claims.adopterId !== this.#config.trustedAdopterId\n || claims.serverId !== this.#config.serverId\n || claims.jti === claims.invocationId\n ) {\n throw new McpCapabilityVerificationError();\n }\n }\n\n #assertBoundedLifetime(\n claims: z.infer<typeof McpCapabilityClaimsSchema>,\n ): void {\n const lifetimeSeconds = claims.exp - claims.iat;\n if (\n lifetimeSeconds <= 0\n || lifetimeSeconds > this.#config.maxCapabilityAgeSeconds\n ) {\n throw new McpCapabilityVerificationError();\n }\n }\n\n #assertSupportedTools(tools: readonly string[]): void {\n if (!tools.every((tool) => this.#supportedTools.has(tool))) {\n throw new McpCapabilityVerificationError();\n }\n }\n}\n\nexport function assertMcpCapabilityActive(\n capability: VerifiedMcpCapability,\n now = new Date(),\n): void {\n const expiresAt = Date.parse(capability.expiresAt);\n if (!Number.isFinite(expiresAt) || now.getTime() >= expiresAt) {\n throw new McpCapabilityVerificationError();\n }\n}\n\nfunction freezeVerifiedCapability<TToolName extends string>(\n capability: VerifiedMcpCapability<TToolName>,\n): VerifiedMcpCapability<TToolName> {\n return Object.freeze({\n ...capability,\n allowedTools: Object.freeze([...capability.allowedTools]),\n scope: Object.freeze({ ...capability.scope }),\n });\n}\n\nconst UNAVAILABLE_JOSE_CODES = new Set([\n 'ERR_JOSE_GENERIC',\n 'ERR_JWK_INVALID',\n 'ERR_JWKS_INVALID',\n 'ERR_JWKS_MULTIPLE_MATCHING_KEYS',\n 'ERR_JWKS_TIMEOUT',\n]);\n\nfunction resolveUnavailableCategory(\n error: unknown,\n): 'network' | 'jwks' | undefined {\n if (error instanceof TypeError) {\n return 'network';\n }\n if (\n error instanceof errors.JOSEError\n && UNAVAILABLE_JOSE_CODES.has(error.code)\n ) {\n return 'jwks';\n }\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"jwt-capability-verifier.js","sourceRoot":"","sources":["../../src/mcp/jwt-capability-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACd,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,GAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,yCAAyC,GAC1C,MAAM,iCAAiC,CAAC;AAQzC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAChE,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,MAAM,EAAE,eAAe;IACvB,QAAQ,EAAE,iBAAiB;IAC3B,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAC/B,YAAY,EACZ,gFAAgF,CACjF;IACD,gBAAgB,EAAE,cAAc;IAChC,QAAQ,EAAE,iBAAiB;IAC3B,cAAc,EAAE,qBAAqB;IACrC,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IAC7D,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;CAClE,CAAC,CAAC,MAAM,EAAE,CAAC;AAMZ;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAE1B,OAAO,CAAyB;IAChC,eAAe,CAAsB;IACrC,YAAY,CAA8D;IAC1E,IAAI,CAAa;IAE1B,YACE,MAAiD,EACjD,UAA2C,EAAE;QAE7C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;YAC3B,GAAG,MAAM;YACT,OAAO,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;YAChC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;SAC1D,CAAC,CAAC;QACH,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC5D,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW;eAClC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB;QAC5B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,yBAAyB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC9D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE;gBACjE,UAAU,EAAE,CAAC,OAAO,CAAC;gBACrB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;gBAC/B,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,qBAAqB;gBAClD,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE;gBACxB,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;gBAC3B,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,uBAAuB;gBACjD,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;gBAC5C,GAAG,EAAE,mBAAmB;aACzB,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACxD,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAEhD,OAAO,wBAAwB,CAAC;gBAC9B,YAAY,EAAE,MAAM,CAAC,GAAG;gBACxB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,YAAY,EAAE,MAAM,CAAC,YAA2B;gBAChD,KAAK,EAAE;oBACL,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,SAAS,EAAE,MAAM,CAAC,GAAG;oBACrB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;oBACzC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;oBACzC,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,QAAQ,EAAE,MAAM,CAAC,QAAQ;iBAC1B;gBACD,QAAQ,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE;gBACpD,SAAS,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE;aACtD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IACE,KAAK,YAAY,8BAA8B;mBAC5C,KAAK,YAAY,6BAA6B,EACjD,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,mBAAmB,GAAG,yCAAyC,CACnE,KAAK,CACN,CAAC;YACF,IAAI,mBAAmB,EAAE,CAAC;gBACxB,MAAM,IAAI,6BAA6B,CACrC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CACvD,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,8BAA8B,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,wBAAwB,CACtB,MAAiD;QAEjD,IACE,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,OAAO,CAAC,gBAAgB;eAC/C,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ;eACzC,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,YAAY,EACrC,CAAC;YACD,MAAM,IAAI,8BAA8B,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,sBAAsB,CACpB,MAAiD;QAEjD,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QAChD,IACE,eAAe,IAAI,CAAC;eACjB,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,EACzD,CAAC;YACD,MAAM,IAAI,8BAA8B,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,qBAAqB,CAAC,KAAwB;QAC5C,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,8BAA8B,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,yBAAyB,CACvC,UAAiC,EACjC,GAAG,GAAG,IAAI,IAAI,EAAE;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI,SAAS,EAAE,CAAC;QAC9D,MAAM,IAAI,8BAA8B,EAAE,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAC/B,UAA4C;IAE5C,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,GAAG,UAAU;QACb,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACzD,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC;KAC9C,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { jwtVerify } from 'jose';\nimport { z } from 'zod';\nimport {\n JwtAudienceSchema,\n JwtIssuerSchema,\n MCP_CAPABILITY_TYPE,\n McpAllowedToolsSchema,\n McpCapabilityClaimsSchema,\n McpServerIdSchema,\n OpaqueIdSchema,\n isSafeWebUrl,\n} from '../contracts/index.js';\nimport {\n McpCapabilityUnavailableError,\n McpCapabilityVerificationError,\n} from './errors.js';\nimport {\n createJwtKeyResolver,\n resolveJwtVerificationUnavailableCategory,\n} from '../internal/jwt-verification.js';\nimport type {\n JwtMcpCapabilityVerifierConfig,\n JwtMcpCapabilityVerifierOptions,\n McpCapabilityVerifier,\n VerifiedMcpCapability,\n} from './types.js';\n\nconst CapabilityAssertionSchema = z.string().min(32).max(4_096);\nconst ConfigSchema = z.object({\n issuer: JwtIssuerSchema,\n audience: JwtAudienceSchema,\n jwksUrl: z.instanceof(URL).refine(\n isSafeWebUrl,\n 'must use HTTPS or loopback HTTP and contain no credentials, query, or fragment',\n ),\n trustedAdopterId: OpaqueIdSchema,\n serverId: McpServerIdSchema,\n supportedTools: McpAllowedToolsSchema,\n maxCapabilityAgeSeconds: z.number().int().min(1).max(15 * 60),\n clockToleranceSeconds: z.number().int().min(0).max(60).default(5),\n}).strict();\n\ntype ParsedConfig = Omit<z.infer<typeof ConfigSchema>, 'supportedTools'> & {\n supportedTools: readonly string[];\n};\n\n/**\n * Independently verifies an adopter-signed capability at the adopter's MCP\n * edge. Execution Host verification is defense in depth, not forwarded trust.\n */\nexport class JwtMcpCapabilityVerifier<TToolName extends string>\nimplements McpCapabilityVerifier<TToolName> {\n readonly #config: Readonly<ParsedConfig>;\n readonly #supportedTools: ReadonlySet<string>;\n readonly #keyResolver: NonNullable<JwtMcpCapabilityVerifierOptions['keyResolver']>;\n readonly #now: () => Date;\n\n constructor(\n config: JwtMcpCapabilityVerifierConfig<TToolName>,\n options: JwtMcpCapabilityVerifierOptions = {},\n ) {\n const parsed = ConfigSchema.parse(config);\n this.#config = Object.freeze({\n ...parsed,\n jwksUrl: new URL(parsed.jwksUrl),\n supportedTools: Object.freeze([...parsed.supportedTools]),\n });\n this.#supportedTools = new Set(this.#config.supportedTools);\n this.#keyResolver = options.keyResolver\n ?? createJwtKeyResolver(this.#config.jwksUrl);\n this.#now = options.now ?? (() => new Date());\n }\n\n async verify(assertion: string): Promise<VerifiedMcpCapability<TToolName>> {\n try {\n const compactJwt = CapabilityAssertionSchema.parse(assertion);\n const { payload } = await jwtVerify(compactJwt, this.#keyResolver, {\n algorithms: ['ES256'],\n audience: this.#config.audience,\n clockTolerance: this.#config.clockToleranceSeconds,\n currentDate: this.#now(),\n issuer: this.#config.issuer,\n maxTokenAge: this.#config.maxCapabilityAgeSeconds,\n requiredClaims: ['exp', 'iat', 'jti', 'sub'],\n typ: MCP_CAPABILITY_TYPE,\n });\n const claims = McpCapabilityClaimsSchema.parse(payload);\n this.#assertDeploymentBinding(claims);\n this.#assertBoundedLifetime(claims);\n this.#assertSupportedTools(claims.allowedTools);\n\n return freezeVerifiedCapability({\n capabilityId: claims.jti,\n serverId: claims.serverId,\n allowedTools: claims.allowedTools as TToolName[],\n scope: {\n adopterId: claims.adopterId,\n tenantId: claims.tenantId,\n subjectId: claims.sub,\n productSessionId: claims.productSessionId,\n runtimeSessionId: claims.runtimeSessionId,\n invocationId: claims.invocationId,\n workflow: claims.workflow,\n },\n issuedAt: new Date(claims.iat * 1_000).toISOString(),\n expiresAt: new Date(claims.exp * 1_000).toISOString(),\n });\n } catch (error) {\n if (\n error instanceof McpCapabilityVerificationError\n || error instanceof McpCapabilityUnavailableError\n ) {\n throw error;\n }\n const unavailableCategory = resolveJwtVerificationUnavailableCategory(\n error,\n );\n if (unavailableCategory) {\n throw new McpCapabilityUnavailableError(\n unavailableCategory === 'network' ? 'network' : 'jwks',\n );\n }\n throw new McpCapabilityVerificationError();\n }\n }\n\n #assertDeploymentBinding(\n claims: z.infer<typeof McpCapabilityClaimsSchema>,\n ): void {\n if (\n claims.adopterId !== this.#config.trustedAdopterId\n || claims.serverId !== this.#config.serverId\n || claims.jti === claims.invocationId\n ) {\n throw new McpCapabilityVerificationError();\n }\n }\n\n #assertBoundedLifetime(\n claims: z.infer<typeof McpCapabilityClaimsSchema>,\n ): void {\n const lifetimeSeconds = claims.exp - claims.iat;\n if (\n lifetimeSeconds <= 0\n || lifetimeSeconds > this.#config.maxCapabilityAgeSeconds\n ) {\n throw new McpCapabilityVerificationError();\n }\n }\n\n #assertSupportedTools(tools: readonly string[]): void {\n if (!tools.every((tool) => this.#supportedTools.has(tool))) {\n throw new McpCapabilityVerificationError();\n }\n }\n}\n\nexport function assertMcpCapabilityActive(\n capability: VerifiedMcpCapability,\n now = new Date(),\n): void {\n const expiresAt = Date.parse(capability.expiresAt);\n if (!Number.isFinite(expiresAt) || now.getTime() >= expiresAt) {\n throw new McpCapabilityVerificationError();\n }\n}\n\nfunction freezeVerifiedCapability<TToolName extends string>(\n capability: VerifiedMcpCapability<TToolName>,\n): VerifiedMcpCapability<TToolName> {\n return Object.freeze({\n ...capability,\n allowedTools: Object.freeze([...capability.allowedTools]),\n scope: Object.freeze({ ...capability.scope }),\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heddleagent/execution-host-client",
3
- "version": "6.4.0",
3
+ "version": "6.5.0",
4
4
  "description": "Backend contracts, execution authority, lifecycle services, and clients for compatible Heddle Execution Hosts",
5
5
  "author": "Jay / Fienna Liang <roackb2@gmail.com>",
6
6
  "license": "MIT",
@@ -70,6 +70,10 @@
70
70
  "types": "./dist/agentcore/index.d.ts",
71
71
  "import": "./dist/agentcore/index.js"
72
72
  },
73
+ "./host": {
74
+ "types": "./dist/host/index.d.ts",
75
+ "import": "./dist/host/index.js"
76
+ },
73
77
  "./testing": {
74
78
  "types": "./dist/testing/index.d.ts",
75
79
  "import": "./dist/testing/index.js"