@agent-vm/mcp-portal 0.0.76 → 0.0.78

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 (39) hide show
  1. package/dist/bin/mcp-portal.js +5 -5
  2. package/dist/bin/mcp-portal.js.map +1 -1
  3. package/dist/cli/index.d.ts +3 -3
  4. package/dist/cli/index.d.ts.map +1 -1
  5. package/dist/cli/index.js +1 -1
  6. package/dist/core/index.d.ts +2 -2
  7. package/dist/core/index.js +4 -4
  8. package/dist/index.d.ts +39 -2
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +3 -3
  11. package/dist/mcp-proxy/index.d.ts +2 -2
  12. package/dist/mcp-proxy/index.js +1 -1
  13. package/dist/{portal-core-BPSvDGvi.js → portal-core-B5cRpZMG.js} +26 -17
  14. package/dist/portal-core-B5cRpZMG.js.map +1 -0
  15. package/dist/{portal-core-CZQI7Ob6.d.ts → portal-core-Ckq-Mrzb.d.ts} +19 -2
  16. package/dist/portal-core-Ckq-Mrzb.d.ts.map +1 -0
  17. package/dist/{portal-session-DG2CUjIo.d.ts → portal-session-5ksK1G9Z.d.ts} +19 -4
  18. package/dist/portal-session-5ksK1G9Z.d.ts.map +1 -0
  19. package/dist/{portal-tools-DKci1szO.js → portal-tools-DA7j2pyv.js} +25 -8
  20. package/dist/portal-tools-DA7j2pyv.js.map +1 -0
  21. package/dist/{resolve-agent-identity-FQL02YdW.d.ts → resolve-agent-identity-C9Jc2NhJ.d.ts} +3 -3
  22. package/dist/{resolve-agent-identity-FQL02YdW.d.ts.map → resolve-agent-identity-C9Jc2NhJ.d.ts.map} +1 -1
  23. package/dist/{resolve-agent-identity-DnC_Pmnh.js → resolve-agent-identity-ZMMY2Wqm.js} +3 -3
  24. package/dist/{resolve-agent-identity-DnC_Pmnh.js.map → resolve-agent-identity-ZMMY2Wqm.js.map} +1 -1
  25. package/dist/{serve-command-CV1s-Eln.js → serve-command-Dz6nvnzQ.js} +8 -8
  26. package/dist/serve-command-Dz6nvnzQ.js.map +1 -0
  27. package/dist/{upstream-mcp-client-runtime-DbPkS6Rk.js → upstream-mcp-client-runtime-Be_cw6pV.js} +64 -15
  28. package/dist/upstream-mcp-client-runtime-Be_cw6pV.js.map +1 -0
  29. package/dist/upstream-response-middleware-1MZnAD9C.d.ts.map +1 -1
  30. package/dist/{upstream-response-middleware-BjUWZ2G8.js → upstream-response-middleware-Cd1MxA6A.js} +57 -3
  31. package/dist/upstream-response-middleware-Cd1MxA6A.js.map +1 -0
  32. package/package.json +3 -3
  33. package/dist/portal-core-BPSvDGvi.js.map +0 -1
  34. package/dist/portal-core-CZQI7Ob6.d.ts.map +0 -1
  35. package/dist/portal-session-DG2CUjIo.d.ts.map +0 -1
  36. package/dist/portal-tools-DKci1szO.js.map +0 -1
  37. package/dist/serve-command-CV1s-Eln.js.map +0 -1
  38. package/dist/upstream-mcp-client-runtime-DbPkS6Rk.js.map +0 -1
  39. package/dist/upstream-response-middleware-BjUWZ2G8.js.map +0 -1
@@ -23,12 +23,12 @@ interface PortalAccessPolicyConfig {
23
23
  readonly defaultPolicy?: PortalDefaultPolicy;
24
24
  readonly enabledNamespaces?: readonly string[];
25
25
  readonly enabledNamespacesByAgent: Readonly<Record<string, readonly string[]>>;
26
- readonly enabledToolsByAgent?: Readonly<Record<string, readonly PortalToolSelector[]>>;
26
+ readonly enabledToolsByNamespaceByAgent?: Readonly<Record<string, Readonly<Record<string, readonly string[]>>>>;
27
27
  readonly hiddenToolsByAgent: Readonly<Record<string, readonly PortalToolSelector[]>>;
28
28
  }
29
29
  interface ResolvedPortalAccessPolicy {
30
30
  readonly allowedNamespaces: readonly string[];
31
- readonly enabledTools: readonly PortalToolSelector[];
31
+ readonly enabledToolsByNamespace: Readonly<Record<string, readonly string[]>>;
32
32
  readonly hiddenTools: readonly PortalToolSelector[];
33
33
  }
34
34
  declare function createPortalAgentIdentity(input: {
@@ -101,12 +101,18 @@ interface ToolSafetySummary {
101
101
  readonly destructiveHint?: boolean;
102
102
  readonly readOnlyHint?: boolean;
103
103
  }
104
+ type ToolSchemaHintNext = 'call_ready' | 'describe_before_call';
105
+ interface ToolSchemaHint {
106
+ readonly message: string;
107
+ readonly next: ToolSchemaHintNext;
108
+ }
104
109
  interface ToolSummary {
105
110
  readonly description?: string;
106
111
  readonly input: ToolSchemaSummary;
107
112
  readonly namespace: string;
108
113
  readonly output?: ToolSchemaSummary;
109
114
  readonly safety: ToolSafetySummary;
115
+ readonly schemaHint?: ToolSchemaHint;
110
116
  readonly title?: string;
111
117
  readonly toolName: string;
112
118
  readonly toolRef: string;
@@ -147,8 +153,17 @@ interface PortalCatalogSnapshot {
147
153
  readonly tools: readonly PortalToolRecord[];
148
154
  }
149
155
  interface PortalDiscoveryFailure {
156
+ readonly causeMessage?: string;
157
+ readonly elapsedMs?: number;
158
+ readonly hint?: string;
159
+ readonly kind: string;
150
160
  readonly message: string;
151
161
  readonly namespace: string;
162
+ readonly operation?: string;
163
+ readonly phase?: string;
164
+ readonly timeoutMs?: number;
165
+ readonly toolName?: string;
166
+ readonly transport?: unknown;
152
167
  }
153
168
  interface PortalSession {
154
169
  readonly catalog: PortalCatalogSnapshot;
@@ -180,5 +195,5 @@ interface PortalSessionManager {
180
195
  }
181
196
  declare function createPortalSessionManager(options: PortalSessionManagerOptions): PortalSessionManager;
182
197
  //#endregion
183
- export { encodeToolRef as A, ToolRelationship as C, ToolIdentity as D, buildToolGraph as E, PortalToolSelector as F, ResolvedPortalAccessPolicy as I, createPortalAgentIdentity as L, PortalAgentIdentity as M, PortalAgentScopeSource as N, ToolRef as O, PortalDefaultPolicy as P, portalAgentScopeKey as R, ToolGraphInput as S, ToolRelationshipType as T, createToolSummary as _, PortalSessionManagerOptions as a, SkillGraphInput as b, SearchIndex as c, ToolRelationshipHint as d, ToolSearchResult as f, ToolSummary as g, ToolSchemaSummary as h, PortalSessionManager as i, PortalAccessPolicyConfig as j, decodeToolRef as k, SearchQuery as l, ToolSafetySummary as m, PortalDiscoveryFailure as n, PortalSessionRuntime as o, createSearchIndex as p, PortalSession as r, createPortalSessionManager as s, PortalCatalogSnapshot as t, SearchResultSet as u, summarizeJsonSchema as v, ToolRelationshipEndpoint as w, ToolGraph as x, ScopedSkillGraphEntry as y, resolvePortalAccessPolicy as z };
184
- //# sourceMappingURL=portal-session-DG2CUjIo.d.ts.map
198
+ export { ToolRef as A, portalAgentScopeKey as B, ToolGraph as C, ToolRelationshipType as D, ToolRelationshipEndpoint as E, PortalAgentScopeSource as F, PortalDefaultPolicy as I, PortalToolSelector as L, encodeToolRef as M, PortalAccessPolicyConfig as N, buildToolGraph as O, PortalAgentIdentity as P, ResolvedPortalAccessPolicy as R, SkillGraphInput as S, ToolRelationship as T, resolvePortalAccessPolicy as V, ToolSchemaSummary as _, PortalSessionManagerOptions as a, summarizeJsonSchema as b, SearchIndex as c, ToolRelationshipHint as d, ToolSearchResult as f, ToolSchemaHintNext as g, ToolSchemaHint as h, PortalSessionManager as i, decodeToolRef as j, ToolIdentity as k, SearchQuery as l, ToolSafetySummary as m, PortalDiscoveryFailure as n, PortalSessionRuntime as o, createSearchIndex as p, PortalSession as r, createPortalSessionManager as s, PortalCatalogSnapshot as t, SearchResultSet as u, ToolSummary as v, ToolGraphInput as w, ScopedSkillGraphEntry as x, createToolSummary as y, createPortalAgentIdentity as z };
199
+ //# sourceMappingURL=portal-session-5ksK1G9Z.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-session-5ksK1G9Z.d.ts","names":[],"sources":["../src/portal-access-policy.ts","../src/tool-ref.ts","../src/tool-graph.ts","../src/tool-summary.ts","../src/search-index.ts","../src/portal-session.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { l as jsonObjectSchema, n as decodeToolRef, t as buildZodValidatorFromJsonSchema } from "./zod-schema-loader-yNekKNpm.js";
2
- import { c as createToolSummary, d as portalAgentScopeKey } from "./upstream-response-middleware-BjUWZ2G8.js";
2
+ import { h as createToolSummary, m as upstreamMcpFailureDetailsFromUnknown, v as portalAgentScopeKey } from "./upstream-response-middleware-Cd1MxA6A.js";
3
3
  import { t as generateTypescriptCatalogArtifact } from "./typescript-artifact-BVLt3Ifd.js";
4
4
  import { z } from "zod";
5
5
  //#region src/core/portal-call-validation.ts
@@ -79,6 +79,14 @@ const callExecutionInputSchema = z.object({
79
79
  calls: z.array(callRequestSchema).min(1),
80
80
  portalApprovalToken: z.string().min(1).optional()
81
81
  }).strict();
82
+ const describeBeforeCallSchemaHint = {
83
+ message: "Use mcp_portal_describe for exact input schema before calling.",
84
+ next: "describe_before_call"
85
+ };
86
+ const callReadySchemaHint = {
87
+ message: "Full input schema included.",
88
+ next: "call_ready"
89
+ };
82
90
  function isToolSchemaProperties(value) {
83
91
  return typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry));
84
92
  }
@@ -133,9 +141,8 @@ function itemOutput(props) {
133
141
  }
134
142
  function discoveryDiagnostics(session) {
135
143
  return session.catalog.discoveryFailures.map((failure) => ({
136
- kind: "upstream_discovery_failed",
137
- message: failure.message,
138
- namespace: failure.namespace
144
+ ...failure,
145
+ kind: failure.kind === "upstream_mcp_failed" ? "upstream_mcp_failed" : "upstream_discovery_failed"
139
146
  }));
140
147
  }
141
148
  function portalBatchResult(results, diagnostics = []) {
@@ -233,6 +240,7 @@ function describeToolOutput(props) {
233
240
  annotations: props.tool.annotations ?? {},
234
241
  namespace: props.tool.namespace,
235
242
  related: props.includeRelated ? props.session.graph.relationships.filter((relationship) => relationship.from.toolRef === toolSummary.toolRef || relationship.to.toolRef === toolSummary.toolRef) : [],
243
+ schemaHint: callReadySchemaHint,
236
244
  toolName: props.tool.toolName,
237
245
  toolRef: toolSummary.toolRef
238
246
  };
@@ -253,6 +261,7 @@ function searchOutputWithFullSchema(session, summary) {
253
261
  input: summary.input,
254
262
  namespace: summary.namespace,
255
263
  safety: summary.safety,
264
+ schemaHint: callReadySchemaHint,
256
265
  toolName: summary.toolName,
257
266
  toolRef: summary.toolRef
258
267
  };
@@ -267,6 +276,12 @@ function searchOutputWithFullSchema(session, summary) {
267
276
  }
268
277
  return result;
269
278
  }
279
+ function toolSummaryWithSchemaHint(summary) {
280
+ return Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });
281
+ }
282
+ function toolSearchResultWithSchemaHint(summary) {
283
+ return Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });
284
+ }
270
285
  function listRequestResult(session, request) {
271
286
  const filteredTools = applyExactFilters(session.catalog.tools, {
272
287
  ...request.namespaces !== void 0 ? { namespaces: request.namespaces } : {},
@@ -277,7 +292,7 @@ function listRequestResult(session, request) {
277
292
  error: filteredTools.error,
278
293
  input: request
279
294
  });
280
- const page = paginate(filteredTools.tools.map((tool) => createToolSummary(tool)), request.limit, request.cursor);
295
+ const page = paginate(filteredTools.tools.map((tool) => toolSummaryWithSchemaHint(createToolSummary(tool))), request.limit, request.cursor);
281
296
  return itemOutput({
282
297
  input: request,
283
298
  output: {
@@ -295,7 +310,7 @@ function searchRequestResult(session, request) {
295
310
  });
296
311
  return itemOutput({
297
312
  input: request,
298
- output: { tools: request.schemaDetail === "full" ? result.results.map((summary) => searchOutputWithFullSchema(session, summary)) : result.results }
313
+ output: { tools: request.schemaDetail === "full" ? result.results.map((summary) => searchOutputWithFullSchema(session, summary)) : result.results.map((summary) => toolSearchResultWithSchemaHint(summary)) }
299
314
  });
300
315
  }
301
316
  function describeRequestResult(session, request) {
@@ -377,12 +392,14 @@ async function executePreparedPortalCall(call, identity, runtime) {
377
392
  }
378
393
  });
379
394
  } catch (error) {
395
+ const upstream = upstreamMcpFailureDetailsFromUnknown(error);
380
396
  return itemError({
381
397
  error: {
382
398
  kind: "upstream_call_failed",
383
399
  message: messageFromError(error),
384
400
  namespace: call.tool.namespace,
385
- toolName: call.tool.toolName
401
+ toolName: call.tool.toolName,
402
+ ...upstream === null ? {} : { upstream }
386
403
  },
387
404
  input
388
405
  });
@@ -525,4 +542,4 @@ function createPortalToolHandlers(runtime) {
525
542
  //#endregion
526
543
  export { portalToolInputSchemas as n, validatePortalToolArguments as r, createPortalToolHandlers as t };
527
544
 
528
- //# sourceMappingURL=portal-tools-DKci1szO.js.map
545
+ //# sourceMappingURL=portal-tools-DA7j2pyv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-tools-DA7j2pyv.js","names":[],"sources":["../src/core/portal-call-validation.ts","../src/core/portal-tools.ts"],"sourcesContent":["import type { PortalToolRecord } from '../catalog-types.js';\nimport type { JsonObject } from '../json-schema.js';\nimport { buildZodValidatorFromJsonSchema } from '../zod-schema-loader.js';\n\nexport function validatePortalToolArguments(\n\ttool: PortalToolRecord,\n\targumentsValue: JsonObject,\n):\n\t| { readonly ok: true; readonly value: unknown }\n\t| {\n\t\t\treadonly error:\n\t\t\t\t| {\n\t\t\t\t\t\treadonly issues: readonly {\n\t\t\t\t\t\t\treadonly code: string;\n\t\t\t\t\t\t\treadonly message: string;\n\t\t\t\t\t\t\treadonly path: readonly (number | string)[];\n\t\t\t\t\t\t}[];\n\t\t\t\t\t\treadonly kind: 'input_validation';\n\t\t\t\t\t\treadonly namespace: string;\n\t\t\t\t\t\treadonly toolName: string;\n\t\t\t\t }\n\t\t\t\t| {\n\t\t\t\t\t\treadonly feature: string;\n\t\t\t\t\t\treadonly kind: 'schema_validation_unavailable';\n\t\t\t\t\t\treadonly message: string;\n\t\t\t\t\t\treadonly namespace: string;\n\t\t\t\t\t\treadonly path: readonly (number | string)[];\n\t\t\t\t\t\treadonly toolName: string;\n\t\t\t\t };\n\t\t\treadonly ok: false;\n\t } {\n\tconst validator = buildZodValidatorFromJsonSchema(tool.inputSchema);\n\tif (!validator.ok) {\n\t\treturn {\n\t\t\terror: { ...validator.error, namespace: tool.namespace, toolName: tool.toolName },\n\t\t\tok: false,\n\t\t};\n\t}\n\n\tconst result = validator.validate(argumentsValue);\n\tif (!result.ok) {\n\t\treturn {\n\t\t\terror: { ...result.error, namespace: tool.namespace, toolName: tool.toolName },\n\t\t\tok: false,\n\t\t};\n\t}\n\n\treturn result;\n}\n","import type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\n\nimport type { PortalToolRecord } from '../catalog-types.js';\nimport { jsonObjectSchema, type JsonObject } from '../json-schema.js';\nimport {\n\tportalAgentScopeKey,\n\ttype PortalAgentIdentity,\n\ttype PortalToolSelector,\n} from '../portal-access-policy.js';\nimport { generateTypescriptCatalogArtifact } from '../portal-config/typescript-artifact.js';\nimport type { PortalSession } from '../portal-session.js';\nimport type { ToolSearchResult } from '../search-index.js';\nimport { decodeToolRef } from '../tool-ref.js';\nimport { createToolSummary, type ToolSchemaHint, type ToolSummary } from '../tool-summary.js';\nimport { upstreamMcpFailureDetailsFromUnknown } from '../upstream-mcp-errors.js';\nimport { validatePortalToolArguments } from './portal-call-validation.js';\n\nexport interface PortalToolSuccess {\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly ok: true;\n\treadonly output: Readonly<Record<string, unknown>>;\n}\n\nexport interface PortalToolFailure {\n\treadonly error: unknown;\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly ok: false;\n}\n\nexport type PortalToolResult = PortalToolFailure | PortalToolSuccess;\nexport type PortalToolResultMap = Readonly<Record<string, PortalToolResult>>;\n\nexport interface PortalBatchError {\n\treadonly id?: string;\n\treadonly kind: string;\n\treadonly message: string;\n}\n\nexport interface PortalBatchDiagnostic {\n\treadonly causeMessage?: string;\n\treadonly elapsedMs?: number;\n\treadonly hint?: string;\n\treadonly kind: string;\n\treadonly message: string;\n\treadonly namespace?: string;\n\treadonly operation?: string;\n\treadonly phase?: string;\n\treadonly timeoutMs?: number;\n\treadonly toolName?: string;\n\treadonly transport?: unknown;\n}\n\nexport interface PortalBatchResult {\n\treadonly diagnostics: readonly PortalBatchDiagnostic[];\n\treadonly errors: readonly PortalBatchError[];\n\treadonly ok: boolean;\n\treadonly results: PortalToolResultMap;\n}\n\nexport interface PortalApprovalCall {\n\treadonly arguments: JsonObject;\n\treadonly id: string;\n\treadonly namespace: string;\n\treadonly tool: PortalToolRecord;\n\treadonly toolName: string;\n}\n\ntype SelectorInputResult =\n\t| { readonly error: PortalBatchError; readonly ok: false }\n\t| { readonly ok: true; readonly selectors: readonly PortalToolSelector[] };\ntype ExactFilterResult =\n\t| { readonly error: PortalBatchError; readonly ok: false }\n\t| { readonly ok: true; readonly tools: readonly PortalToolRecord[] };\n\nconst requestIdSchema = z.string().min(1);\nconst reservedRequestIds = new Set(['__proto__', 'constructor', 'prototype']);\nconst safeRequestIdSchema = requestIdSchema.refine((id) => !reservedRequestIds.has(id), {\n\tmessage: 'Portal request id uses a reserved object property name.',\n});\nconst namespaceToolSelectorSchema = z\n\t.object({ namespace: z.string().min(1), toolName: z.string().min(1) })\n\t.strict();\nconst listRequestSchema = z\n\t.object({\n\t\tcursor: z.string().regex(/^\\d+$/u).optional(),\n\t\tid: safeRequestIdSchema,\n\t\tlimit: z.number().int().positive().max(100).default(20),\n\t\tnamespaces: z.array(z.string()).optional(),\n\t\trefs: z.array(z.string()).optional(),\n\t\ttools: z.array(namespaceToolSelectorSchema).optional(),\n\t})\n\t.strict();\nconst searchRequestSchema = z\n\t.object({\n\t\tid: safeRequestIdSchema,\n\t\tlimit: z.number().int().positive().max(50).default(10),\n\t\tnamespaces: z.array(z.string()).optional(),\n\t\tquery: z.string().optional(),\n\t\tschemaDetail: z.enum(['none', 'summary', 'full']).default('summary'),\n\t})\n\t.strict();\nconst describeRequestSchema = z\n\t.object({\n\t\tid: safeRequestIdSchema,\n\t\tincludeJsonSchema: z.boolean().default(true),\n\t\tincludeRelated: z.boolean().default(true),\n\t\tincludeTypescriptHelper: z.boolean().default(false),\n\t\tincludeZod: z.boolean().default(false),\n\t\trefs: z.array(z.string()).optional(),\n\t\ttools: z.array(namespaceToolSelectorSchema).optional(),\n\t})\n\t.strict();\nconst callRequestSchema = z\n\t.object({\n\t\targuments: jsonObjectSchema,\n\t\tid: safeRequestIdSchema,\n\t\tnamespace: z.string().min(1),\n\t\ttoolName: z.string().min(1),\n\t})\n\t.strict();\nconst listInputSchema = z.object({ requests: z.array(listRequestSchema).min(1) }).strict();\nconst searchInputSchema = z.object({ requests: z.array(searchRequestSchema).min(1) }).strict();\nconst describeInputSchema = z.object({ requests: z.array(describeRequestSchema).min(1) }).strict();\nconst callInputSchema = z.object({ calls: z.array(callRequestSchema).min(1) }).strict();\nconst callExecutionInputSchema = z\n\t.object({\n\t\tcalls: z.array(callRequestSchema).min(1),\n\t\tportalApprovalToken: z.string().min(1).optional(),\n\t})\n\t.strict();\n\ntype ListRequest = z.infer<typeof listRequestSchema>;\ntype SearchRequest = z.infer<typeof searchRequestSchema>;\ntype DescribeRequest = z.infer<typeof describeRequestSchema>;\ntype CallRequest = z.infer<typeof callRequestSchema>;\n\ninterface PreparedPortalCall {\n\treadonly input: CallRequest;\n\treadonly validatedArguments: JsonObject;\n\treadonly tool: PortalToolRecord;\n}\n\nconst describeBeforeCallSchemaHint = {\n\tmessage: 'Use mcp_portal_describe for exact input schema before calling.',\n\tnext: 'describe_before_call',\n} as const satisfies ToolSchemaHint;\n\nconst callReadySchemaHint = {\n\tmessage: 'Full input schema included.',\n\tnext: 'call_ready',\n} as const satisfies ToolSchemaHint;\n\nfunction isToolSchemaProperties(value: unknown): value is Record<string, object> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t!Array.isArray(value) &&\n\t\tObject.values(value).every(\n\t\t\t(entry) => typeof entry === 'object' && entry !== null && !Array.isArray(entry),\n\t\t)\n\t);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\nfunction toPortalInputJsonSchema(schema: z.ZodType): Tool['inputSchema'] {\n\tconst jsonSchema = jsonObjectSchema.parse(z.toJSONSchema(schema, { io: 'input' }));\n\tif (jsonSchema.type !== 'object') {\n\t\tthrow new Error('MCP Portal tool input schemas must be JSON Schema objects.');\n\t}\n\tconst properties = isToolSchemaProperties(jsonSchema.properties)\n\t\t? jsonSchema.properties\n\t\t: undefined;\n\tconst required = isStringArray(jsonSchema.required) ? jsonSchema.required : undefined;\n\n\treturn {\n\t\t...jsonSchema,\n\t\t...(properties !== undefined ? { properties } : {}),\n\t\t...(required !== undefined ? { required } : {}),\n\t\ttype: 'object',\n\t};\n}\n\nexport const portalToolInputSchemas = {\n\tmcp_portal_call: toPortalInputJsonSchema(callInputSchema),\n\tmcp_portal_describe: toPortalInputJsonSchema(describeInputSchema),\n\tmcp_portal_list: toPortalInputJsonSchema(listInputSchema),\n\tmcp_portal_search: toPortalInputJsonSchema(searchInputSchema),\n} as const;\n\nexport interface PortalToolHandlerCall {\n\treadonly identity: PortalAgentIdentity;\n\treadonly input: unknown;\n}\n\nexport interface PortalCallUpstreamTool {\n\treadonly arguments: JsonObject;\n\treadonly agentScopeId: string;\n\treadonly namespace: string;\n\treadonly onEvent?: (event: PortalUpstreamEvent) => Promise<void> | void;\n\treadonly requestId: string;\n\treadonly signal?: AbortSignal;\n\treadonly toolName: string;\n}\n\nexport type PortalUpstreamEvent =\n\t| {\n\t\t\treadonly kind: 'progress';\n\t\t\treadonly message?: string;\n\t\t\treadonly progress?: number;\n\t\t\treadonly total?: number;\n\t }\n\t| {\n\t\t\treadonly kind: 'upstream_notification';\n\t\t\treadonly method: string;\n\t\t\treadonly params: unknown;\n\t }\n\t| {\n\t\t\treadonly content:\n\t\t\t\t| { readonly text: string; readonly type: 'text' }\n\t\t\t\t| { readonly type: 'json'; readonly value: unknown };\n\t\t\treadonly kind: 'partial_content';\n\t };\n\nexport interface PortalToolRuntime {\n\treadonly approval?: (\n\t\tcalls: readonly PortalApprovalCall[],\n\t\tidentity: PortalAgentIdentity,\n\t\tapprovalToken: string | undefined,\n\t) =>\n\t\t| { readonly kind: 'allow' }\n\t\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t\t| { readonly kind: 'approval_token_missing' }\n\t\t| { readonly kind: 'approval_required'; readonly level: 'critical' | 'standard' };\n\treadonly callUpstreamTool: (call: PortalCallUpstreamTool) => Promise<unknown>;\n\treadonly getSession: (identity: PortalAgentIdentity) => Promise<PortalSession>;\n}\n\ntype PortalApprovalDecision =\n\t| { readonly kind: 'allow' }\n\t| { readonly kind: 'approval_configuration_missing' }\n\t| { readonly kind: 'approval_required'; readonly level: 'critical' | 'standard' }\n\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t| { readonly kind: 'approval_token_missing' };\n\nexport interface PortalToolHandlers {\n\treadonly call: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly describe: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly list: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly search: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n}\n\nfunction messageFromError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction invalidPortalInput(error: unknown): PortalBatchResult {\n\treturn {\n\t\tdiagnostics: [],\n\t\terrors: [{ kind: 'invalid_portal_input', message: messageFromError(error) }],\n\t\tok: false,\n\t\tresults: {},\n\t};\n}\n\nfunction itemError(props: {\n\treadonly error: unknown;\n\treadonly input: Readonly<Record<string, unknown>>;\n}): PortalToolResult {\n\treturn {\n\t\terror: props.error,\n\t\tinput: props.input,\n\t\tok: false,\n\t};\n}\n\nfunction itemOutput(props: {\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly output: Readonly<Record<string, unknown>>;\n}): PortalToolResult {\n\treturn {\n\t\tinput: props.input,\n\t\tok: true,\n\t\toutput: props.output,\n\t};\n}\n\nfunction discoveryDiagnostics(session: PortalSession): readonly PortalBatchDiagnostic[] {\n\treturn session.catalog.discoveryFailures.map((failure) => ({\n\t\t...failure,\n\t\tkind:\n\t\t\tfailure.kind === 'upstream_mcp_failed' ? 'upstream_mcp_failed' : 'upstream_discovery_failed',\n\t}));\n}\n\nfunction portalBatchResult(\n\tresults: PortalToolResultMap,\n\tdiagnostics: readonly PortalBatchDiagnostic[] = [],\n): PortalBatchResult {\n\tconst allItemsOk = Object.values(results).every((result) => result.ok);\n\treturn { diagnostics, errors: [], ok: allItemsOk, results };\n}\n\nfunction duplicateIdErrors(items: readonly { readonly id: string }[]): readonly PortalBatchError[] {\n\tconst seenIds = new Set<string>();\n\tconst duplicateIds = new Set<string>();\n\tfor (const item of items) {\n\t\tif (seenIds.has(item.id)) {\n\t\t\tduplicateIds.add(item.id);\n\t\t}\n\t\tseenIds.add(item.id);\n\t}\n\n\treturn [...duplicateIds].toSorted().map((id) => ({\n\t\tid,\n\t\tkind: 'duplicate_id',\n\t\tmessage: `Duplicate portal request id \"${id}\". Each request id must be unique.`,\n\t}));\n}\n\nfunction duplicateIdResult(items: readonly { readonly id: string }[]): PortalBatchResult | null {\n\tconst errors = duplicateIdErrors(items);\n\treturn errors.length > 0 ? { diagnostics: [], errors, ok: false, results: {} } : null;\n}\n\nfunction findTool(session: PortalSession, selector: PortalToolSelector): PortalToolRecord | null {\n\treturn (\n\t\tsession.catalog.tools.find(\n\t\t\t(tool) => tool.namespace === selector.namespace && tool.toolName === selector.toolName,\n\t\t) ?? null\n\t);\n}\n\nfunction selectorsFromInput(\n\ttools?: readonly PortalToolSelector[],\n\trefs?: readonly string[],\n): SelectorInputResult {\n\tconst selectors: PortalToolSelector[] = [...(tools ?? [])];\n\tfor (const toolRef of refs ?? []) {\n\t\ttry {\n\t\t\tselectors.push(decodeToolRef(toolRef));\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\terror: { kind: 'invalid_portal_input', message: messageFromError(error) },\n\t\t\t\tok: false,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { ok: true, selectors };\n}\n\nfunction applyExactFilters(\n\ttools: readonly PortalToolRecord[],\n\tfilters: {\n\t\treadonly namespaces?: readonly string[];\n\t\treadonly refs?: readonly string[];\n\t\treadonly tools?: readonly PortalToolSelector[];\n\t},\n): ExactFilterResult {\n\tconst namespaceFilter = new Set(filters.namespaces ?? []);\n\tconst selectorResult = selectorsFromInput(filters.tools, filters.refs);\n\tif (!selectorResult.ok) {\n\t\treturn selectorResult;\n\t}\n\tconst exactSelectors = selectorResult.selectors;\n\tif (exactSelectors.length === 0) {\n\t\treturn {\n\t\t\tok: true,\n\t\t\ttools: tools.filter(\n\t\t\t\t(tool) => namespaceFilter.size === 0 || namespaceFilter.has(tool.namespace),\n\t\t\t),\n\t\t};\n\t}\n\n\treturn {\n\t\tok: true,\n\t\ttools: tools.filter(\n\t\t\t(tool) =>\n\t\t\t\t(namespaceFilter.size === 0 || namespaceFilter.has(tool.namespace)) &&\n\t\t\t\texactSelectors.some(\n\t\t\t\t\t(selector) =>\n\t\t\t\t\t\tselector.namespace === tool.namespace && selector.toolName === tool.toolName,\n\t\t\t\t),\n\t\t),\n\t};\n}\n\nfunction selectorKey(selector: PortalToolSelector): string {\n\treturn `${selector.namespace}\\n${selector.toolName}`;\n}\n\nfunction missingSelectorError(\n\trequestedSelectors: readonly PortalToolSelector[],\n\tselectedTools: readonly PortalToolRecord[],\n): PortalBatchError | null {\n\tconst foundKeys = new Set(\n\t\tselectedTools.map((tool) =>\n\t\t\tselectorKey({ namespace: tool.namespace, toolName: tool.toolName }),\n\t\t),\n\t);\n\tconst missingSelectors = requestedSelectors.filter(\n\t\t(selector) => !foundKeys.has(selectorKey(selector)),\n\t);\n\tif (missingSelectors.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: 'unknown_or_denied_tool',\n\t\tmessage: 'One or more requested tools are unknown or denied for this portal agent scope.',\n\t};\n}\n\nfunction paginate<TItem>(\n\titems: readonly TItem[],\n\tlimit: number,\n\tcursor?: string,\n): { readonly items: readonly TItem[]; readonly nextCursor?: string } {\n\tconst offset = cursor ? Number.parseInt(cursor, 10) : 0;\n\tconst safeOffset = Number.isFinite(offset) && offset > 0 ? offset : 0;\n\tconst page = items.slice(safeOffset, safeOffset + limit);\n\tconst nextOffset = safeOffset + page.length;\n\n\treturn {\n\t\titems: page,\n\t\t...(nextOffset < items.length ? { nextCursor: String(nextOffset) } : {}),\n\t};\n}\n\nfunction describeToolOutput(props: {\n\treadonly includeJsonSchema: boolean;\n\treadonly includeRelated: boolean;\n\treadonly includeTypescriptHelper: boolean;\n\treadonly includeZod: boolean;\n\treadonly session: PortalSession;\n\treadonly tool: PortalToolRecord;\n}): Readonly<Record<string, unknown>> {\n\tconst toolSummary = createToolSummary(props.tool);\n\tconst result: Record<string, unknown> = {\n\t\tannotations: props.tool.annotations ?? {},\n\t\tnamespace: props.tool.namespace,\n\t\trelated: props.includeRelated\n\t\t\t? props.session.graph.relationships.filter(\n\t\t\t\t\t(relationship) =>\n\t\t\t\t\t\trelationship.from.toolRef === toolSummary.toolRef ||\n\t\t\t\t\t\trelationship.to.toolRef === toolSummary.toolRef,\n\t\t\t\t)\n\t\t\t: [],\n\t\tschemaHint: callReadySchemaHint,\n\t\ttoolName: props.tool.toolName,\n\t\ttoolRef: toolSummary.toolRef,\n\t};\n\n\tif (props.includeJsonSchema) {\n\t\tresult.inputSchema = props.tool.inputSchema;\n\t\tresult.outputSchema = props.tool.outputSchema;\n\t}\n\tif (props.includeZod) {\n\t\tresult.zod = { experimental: true, source: 'z.fromJSONSchema(inputSchema)' };\n\t}\n\tif (props.includeTypescriptHelper) {\n\t\tresult.typescriptHelper = generateTypescriptCatalogArtifact({ tools: [props.tool] });\n\t}\n\n\treturn result;\n}\n\nfunction searchOutputWithFullSchema(\n\tsession: PortalSession,\n\tsummary: ToolSearchResult,\n): Readonly<Record<string, unknown>> {\n\tconst tool = findTool(session, summary);\n\tconst result: Record<string, unknown> = {\n\t\tinput: summary.input,\n\t\tnamespace: summary.namespace,\n\t\tsafety: summary.safety,\n\t\tschemaHint: callReadySchemaHint,\n\t\ttoolName: summary.toolName,\n\t\ttoolRef: summary.toolRef,\n\t};\n\n\tif (summary.description !== undefined) {\n\t\tresult.description = summary.description;\n\t}\n\tif (summary.output !== undefined) {\n\t\tresult.output = summary.output;\n\t}\n\tif (summary.relationshipHints !== undefined) {\n\t\tresult.relationshipHints = summary.relationshipHints;\n\t}\n\tif (summary.schemaFieldMatches !== undefined) {\n\t\tresult.schemaFieldMatches = summary.schemaFieldMatches;\n\t}\n\tif (summary.title !== undefined) {\n\t\tresult.title = summary.title;\n\t}\n\n\tif (tool) {\n\t\tresult.inputSchema = tool.inputSchema;\n\t\tresult.outputSchema = tool.outputSchema;\n\t}\n\n\treturn result;\n}\n\nfunction toolSummaryWithSchemaHint(summary: ToolSummary): ToolSummary {\n\treturn Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });\n}\n\nfunction toolSearchResultWithSchemaHint(\n\tsummary: ToolSearchResult,\n): ToolSearchResult & { readonly schemaHint: ToolSchemaHint } {\n\treturn Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });\n}\n\nfunction listRequestResult(session: PortalSession, request: ListRequest): PortalToolResult {\n\tconst filteredTools = applyExactFilters(session.catalog.tools, {\n\t\t...(request.namespaces !== undefined ? { namespaces: request.namespaces } : {}),\n\t\t...(request.refs !== undefined ? { refs: request.refs } : {}),\n\t\t...(request.tools !== undefined ? { tools: request.tools } : {}),\n\t});\n\tif (!filteredTools.ok) {\n\t\treturn itemError({ error: filteredTools.error, input: request });\n\t}\n\tconst page = paginate(\n\t\tfilteredTools.tools.map((tool) => toolSummaryWithSchemaHint(createToolSummary(tool))),\n\t\trequest.limit,\n\t\trequest.cursor,\n\t);\n\tconst output = {\n\t\tnamespaces: [...new Set(filteredTools.tools.map((tool) => tool.namespace))].toSorted(),\n\t\t...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}),\n\t\ttools: page.items,\n\t} satisfies {\n\t\treadonly namespaces: readonly string[];\n\t\treadonly nextCursor?: string;\n\t\treadonly tools: readonly ToolSummary[];\n\t};\n\n\treturn itemOutput({ input: request, output });\n}\n\nfunction searchRequestResult(session: PortalSession, request: SearchRequest): PortalToolResult {\n\tconst result = session.searchIndex.search({\n\t\tlimit: request.limit,\n\t\t...(request.namespaces ? { namespaces: request.namespaces } : {}),\n\t\t...(request.query !== undefined ? { query: request.query } : {}),\n\t});\n\tconst tools =\n\t\trequest.schemaDetail === 'full'\n\t\t\t? result.results.map((summary) => searchOutputWithFullSchema(session, summary))\n\t\t\t: result.results.map((summary) => toolSearchResultWithSchemaHint(summary));\n\n\treturn itemOutput({ input: request, output: { tools } });\n}\n\nfunction describeRequestResult(session: PortalSession, request: DescribeRequest): PortalToolResult {\n\tconst selectorResult = selectorsFromInput(request.tools, request.refs);\n\tif (!selectorResult.ok) {\n\t\treturn itemError({ error: selectorResult.error, input: request });\n\t}\n\tconst selectors = selectorResult.selectors;\n\tconst selectedTools = selectors\n\t\t.map((selector) => findTool(session, selector))\n\t\t.filter((tool): tool is PortalToolRecord => tool !== null);\n\tconst missingError = missingSelectorError(selectors, selectedTools);\n\tif (missingError) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\t...missingError,\n\t\t\t\ttools: selectors.filter((selector) => findTool(session, selector) === null),\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\tconst tools = selectedTools.map((tool) =>\n\t\tdescribeToolOutput({\n\t\t\tincludeJsonSchema: request.includeJsonSchema,\n\t\t\tincludeRelated: request.includeRelated,\n\t\t\tincludeTypescriptHelper: request.includeTypescriptHelper,\n\t\t\tincludeZod: request.includeZod,\n\t\t\tsession,\n\t\t\ttool,\n\t\t}),\n\t);\n\treturn itemOutput({ input: request, output: { tools } });\n}\n\nfunction preparePortalCall(\n\tsession: PortalSession,\n\trequest: CallRequest,\n): PreparedPortalCall | PortalToolResult {\n\tconst tool = findTool(session, request);\n\tif (!tool) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'unknown_or_denied_tool',\n\t\t\t\tmessage: 'The requested tool is unknown or denied for this portal agent scope.',\n\t\t\t\tnamespace: request.namespace,\n\t\t\t\ttoolName: request.toolName,\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\tconst validation = validatePortalToolArguments(tool, request.arguments);\n\tif (!validation.ok) {\n\t\treturn itemError({ error: validation.error, input: request });\n\t}\n\tconst validatedArgumentsResult = jsonObjectSchema.safeParse(validation.value);\n\tif (!validatedArgumentsResult.success) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'invalid_portal_input',\n\t\t\t\tmessage: validatedArgumentsResult.error.message,\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\treturn { input: request, tool, validatedArguments: validatedArgumentsResult.data };\n}\n\nasync function executePreparedPortalCall(\n\tcall: PreparedPortalCall,\n\tidentity: PortalAgentIdentity,\n\truntime: PortalToolRuntime,\n): Promise<PortalToolResult> {\n\tconst input = { ...call.input, arguments: call.validatedArguments };\n\ttry {\n\t\treturn itemOutput({\n\t\t\tinput,\n\t\t\toutput: {\n\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\tresult: await runtime.callUpstreamTool({\n\t\t\t\t\targuments: call.validatedArguments,\n\t\t\t\t\tagentScopeId: portalAgentScopeKey(identity),\n\t\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\t\trequestId: call.input.id,\n\t\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t\t}),\n\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tconst upstream = upstreamMcpFailureDetailsFromUnknown(error);\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'upstream_call_failed',\n\t\t\t\tmessage: messageFromError(error),\n\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t\t...(upstream === null ? {} : { upstream }),\n\t\t\t},\n\t\t\tinput,\n\t\t});\n\t}\n}\n\nfunction isPreparedPortalCall(\n\tvalue: PreparedPortalCall | PortalToolResult,\n): value is PreparedPortalCall {\n\treturn 'validatedArguments' in value;\n}\n\nasync function addExecutableCallResults(props: {\n\treadonly identity: PortalAgentIdentity;\n\treadonly preparedCalls: readonly PreparedPortalCall[];\n\treadonly results: Record<string, PortalToolResult>;\n\treadonly runtime: PortalToolRuntime;\n}): Promise<void> {\n\tawait Promise.all(\n\t\tprops.preparedCalls.map(async (preparedCall): Promise<void> => {\n\t\t\tprops.results[preparedCall.input.id] = await executePreparedPortalCall(\n\t\t\t\tpreparedCall,\n\t\t\t\tprops.identity,\n\t\t\t\tprops.runtime,\n\t\t\t);\n\t\t}),\n\t);\n}\n\nexport function createPortalToolHandlers(runtime: PortalToolRuntime): PortalToolHandlers {\n\treturn {\n\t\tasync call(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = callExecutionInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.calls);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\tconst preparedResults = parsedInput.data.calls.map((request) =>\n\t\t\t\tpreparePortalCall(session, request),\n\t\t\t);\n\t\t\tconst executableCalls = preparedResults.filter(isPreparedPortalCall);\n\t\t\tconst approvalCalls = executableCalls.map(\n\t\t\t\t(executableCall) =>\n\t\t\t\t\t({\n\t\t\t\t\t\targuments: executableCall.validatedArguments,\n\t\t\t\t\t\tid: executableCall.input.id,\n\t\t\t\t\t\tnamespace: executableCall.tool.namespace,\n\t\t\t\t\t\ttool: executableCall.tool,\n\t\t\t\t\t\ttoolName: executableCall.tool.toolName,\n\t\t\t\t\t}) satisfies PortalApprovalCall,\n\t\t\t);\n\t\t\tconst allowDecision = { kind: 'allow' } satisfies PortalApprovalDecision;\n\t\t\tconst approval: PortalApprovalDecision =\n\t\t\t\tapprovalCalls.length === 0\n\t\t\t\t\t? allowDecision\n\t\t\t\t\t: (runtime.approval?.(\n\t\t\t\t\t\t\tapprovalCalls,\n\t\t\t\t\t\t\tcall.identity,\n\t\t\t\t\t\t\tparsedInput.data.portalApprovalToken,\n\t\t\t\t\t\t) ?? { kind: 'approval_configuration_missing' });\n\n\t\t\tconst results: Record<string, PortalToolResult> = {};\n\t\t\tconst callsToExecute: PreparedPortalCall[] = [];\n\t\t\tfor (const preparedResult of preparedResults) {\n\t\t\t\tif (!isPreparedPortalCall(preparedResult)) {\n\t\t\t\t\tconst input = preparedResult.input;\n\t\t\t\t\tif (typeof input === 'object' && input !== null && 'id' in input) {\n\t\t\t\t\t\tconst id = input.id;\n\t\t\t\t\t\tif (typeof id === 'string') {\n\t\t\t\t\t\t\tresults[id] = preparedResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (approval.kind === 'approval_required') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_required',\n\t\t\t\t\t\t\tlevel: approval.level,\n\t\t\t\t\t\t\tmessage: 'Operator approval is required before this batch can run.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_token_missing') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_token_missing',\n\t\t\t\t\t\t\tmessage: 'An MCP Portal approval token is required before this batch can run.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_token_invalid') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_token_invalid',\n\t\t\t\t\t\t\tmessage: `MCP Portal approval token is invalid: ${approval.reason}.`,\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\treason: approval.reason,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_configuration_missing') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_configuration_missing',\n\t\t\t\t\t\t\tmessage: 'MCP Portal approval evaluation is not configured.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcallsToExecute.push(preparedResult);\n\t\t\t}\n\t\t\tawait addExecutableCallResults({\n\t\t\t\tidentity: call.identity,\n\t\t\t\tpreparedCalls: callsToExecute,\n\t\t\t\tresults,\n\t\t\t\truntime,\n\t\t\t});\n\n\t\t\treturn portalBatchResult(results, discoveryDiagnostics(session));\n\t\t},\n\t\tasync describe(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = describeInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tdescribeRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t\tasync list(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = listInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tlistRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t\tasync search(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = searchInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tsearchRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { L as createPortalAgentIdentity, M as PortalAgentIdentity } from "./portal-session-DG2CUjIo.js";
2
- import { a as PortalCore, y as PortalApprovalCall } from "./portal-core-CZQI7Ob6.js";
1
+ import { P as PortalAgentIdentity, z as createPortalAgentIdentity } from "./portal-session-5ksK1G9Z.js";
2
+ import { a as PortalCore, y as PortalApprovalCall } from "./portal-core-Ckq-Mrzb.js";
3
3
  import { McpPortalAgentConfig, McpPortalConfig, ResolvedMcpPortalProfile, SecretValue } from "@agent-vm/config-contracts";
4
4
  import { Hono } from "hono";
5
5
 
@@ -78,4 +78,4 @@ declare function createPortalApprovalVerifier(props: {
78
78
  };
79
79
  //#endregion
80
80
  export { createPortalApprovalVerifier as a, PortalAgentBearerAuth as c, PortalHttpAppOptions as d, PortalHttpAuditEvent as f, createPortalAgentRuntimeRecords as i, PortalHttpAgentIdentity as l, PortalApprovalAuditEvent as n, createPortalHttpAgentResolver as o, createPortalHttpApp as p, ResolveAgentHmacKeysProps as r, resolveAgentHmacKeys as s, PortalAgentRuntimeRecord as t, PortalHttpApp as u };
81
- //# sourceMappingURL=resolve-agent-identity-FQL02YdW.d.ts.map
81
+ //# sourceMappingURL=resolve-agent-identity-C9Jc2NhJ.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-agent-identity-FQL02YdW.d.ts","names":[],"sources":["../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"mappings":";;;;;;UAWiB,uBAAA,SAAgC,mBAAA;AAAA,UAEhC,qBAAA;EAAA,SACP,uBAAA;EAAA,SACA,yBAAA,GAA4B,QAAA,CAAS,MAAA;EAAA,SACrC,SAAA,EAAW,MAAA;AAAA;AAAA,KAGT,oBAAA;EAAA,SACF,OAAA;EAAA,SACA,aAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SAMA,MAAA;AAAA;AAAA,UAGO,oBAAA;EAAA,SACP,eAAA,EAAiB,qBAAA;EAAA,SACjB,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAChE,SAAA,IAAa,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAC7C,gBAAA;IAAA,SACC,WAAA;IAAA,SACA,QAAA;EAAA;EAAA,SAED,IAAA,EAAM,UAAA;EAAA,SACN,eAAA,IAAmB,QAAA,EAAU,mBAAA,KAAwB,OAAA;EAAA,SACrD,mBAAA,IACR,KAAA,EAAO,KAAA,EACP,QAAA,EAAU,mBAAA,KACN,OAAA;EAAA,SACI,kBAAA;EAAA,SACA,oBAAA,IAAwB,OAAA,aAAoB,uBAAA;AAAA;AAAA,KAG1C,aAAA,GAAgB,IAAA;EAAA,SAClB,mBAAA,QAA2B,OAAA;AAAA;AAAA,iBAiDrB,mBAAA,CAAoB,OAAA,EAAS,oBAAA,GAAuB,aAAA;;;UCrFnD,yBAAA;EAAA,SACP,MAAA,EAAQ,QAAA,CAAS,MAAA,SAAe,oBAAA;EAAA,SAChC,OAAA,EAAS,WAAA,SAAoB,MAAA;EAAA,SAC7B,aAAA,GAAgB,MAAA,EAAQ,WAAA,KAAgB,OAAA;AAAA;AAAA,UAGjC,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,OAAA,EAAS,MAAA;EAAA,SACT,OAAA,EAAS,wBAAA;EAAA,SACT,WAAA;AAAA;AAAA,UAGO,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;EAAA,SACA,cAAA;AAAA;AAAA,iBAuBY,oBAAA,CACrB,KAAA,EAAO,yBAAA,GACL,OAAA,CAAQ,WAAA,SAAoB,MAAA;AAAA,iBAef,+BAAA,CAAgC,KAAA;EAAA,SACtC,QAAA,EAAU,WAAA,SAAoB,MAAA;EAAA,SAC9B,YAAA,EAAc,eAAA;AAAA,IACpB,WAAA,SAAoB,wBAAA;AAAA,iBAiBR,6BAAA,CACf,OAAA,EAAS,WAAA,SAAoB,wBAAA,KAC1B,OAAA,aAAoB,UAAA,QAAkB,yBAAA;AAAA,iBAsC1B,4BAAA,CAA6B,KAAA;EAAA,SACnC,6BAAA;EAAA,SACA,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,wBAAA;EAAA,SACvC,SAAA,IAAa,KAAA,EAAO,wBAAA;EAAA,SACpB,OAAA,EAAS,WAAA,SAAoB,wBAAA;AAAA,KAEtC,KAAA,WAAgB,kBAAA,IAChB,OAAA,UACA,KAAA;EAAA,SAEa,IAAA;AAAA;EAAA,SACA,IAAA;EAAA,SAAyC,MAAA;AAAA;EAAA,SACzC,IAAA;AAAA"}
1
+ {"version":3,"file":"resolve-agent-identity-C9Jc2NhJ.d.ts","names":[],"sources":["../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"mappings":";;;;;;UAWiB,uBAAA,SAAgC,mBAAA;AAAA,UAEhC,qBAAA;EAAA,SACP,uBAAA;EAAA,SACA,yBAAA,GAA4B,QAAA,CAAS,MAAA;EAAA,SACrC,SAAA,EAAW,MAAA;AAAA;AAAA,KAGT,oBAAA;EAAA,SACF,OAAA;EAAA,SACA,aAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SAMA,MAAA;AAAA;AAAA,UAGO,oBAAA;EAAA,SACP,eAAA,EAAiB,qBAAA;EAAA,SACjB,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAChE,SAAA,IAAa,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAC7C,gBAAA;IAAA,SACC,WAAA;IAAA,SACA,QAAA;EAAA;EAAA,SAED,IAAA,EAAM,UAAA;EAAA,SACN,eAAA,IAAmB,QAAA,EAAU,mBAAA,KAAwB,OAAA;EAAA,SACrD,mBAAA,IACR,KAAA,EAAO,KAAA,EACP,QAAA,EAAU,mBAAA,KACN,OAAA;EAAA,SACI,kBAAA;EAAA,SACA,oBAAA,IAAwB,OAAA,aAAoB,uBAAA;AAAA;AAAA,KAG1C,aAAA,GAAgB,IAAA;EAAA,SAClB,mBAAA,QAA2B,OAAA;AAAA;AAAA,iBAiDrB,mBAAA,CAAoB,OAAA,EAAS,oBAAA,GAAuB,aAAA;;;UCrFnD,yBAAA;EAAA,SACP,MAAA,EAAQ,QAAA,CAAS,MAAA,SAAe,oBAAA;EAAA,SAChC,OAAA,EAAS,WAAA,SAAoB,MAAA;EAAA,SAC7B,aAAA,GAAgB,MAAA,EAAQ,WAAA,KAAgB,OAAA;AAAA;AAAA,UAGjC,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,OAAA,EAAS,MAAA;EAAA,SACT,OAAA,EAAS,wBAAA;EAAA,SACT,WAAA;AAAA;AAAA,UAGO,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;EAAA,SACA,cAAA;AAAA;AAAA,iBAuBY,oBAAA,CACrB,KAAA,EAAO,yBAAA,GACL,OAAA,CAAQ,WAAA,SAAoB,MAAA;AAAA,iBAef,+BAAA,CAAgC,KAAA;EAAA,SACtC,QAAA,EAAU,WAAA,SAAoB,MAAA;EAAA,SAC9B,YAAA,EAAc,eAAA;AAAA,IACpB,WAAA,SAAoB,wBAAA;AAAA,iBAiBR,6BAAA,CACf,OAAA,EAAS,WAAA,SAAoB,wBAAA,KAC1B,OAAA,aAAoB,UAAA,QAAkB,yBAAA;AAAA,iBAsC1B,4BAAA,CAA6B,KAAA;EAAA,SACnC,6BAAA;EAAA,SACA,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,wBAAA;EAAA,SACvC,SAAA,IAAa,KAAA,EAAO,wBAAA;EAAA,SACpB,OAAA,EAAS,WAAA,SAAoB,wBAAA;AAAA,KAEtC,KAAA,WAAgB,kBAAA,IAChB,OAAA,UACA,KAAA;EAAA,SAEa,IAAA;AAAA;EAAA,SACA,IAAA;EAAA,SAAyC,MAAA;AAAA;EAAA,SACzC,IAAA;AAAA"}
@@ -1,5 +1,5 @@
1
- import { i as redactThrownError, u as createPortalAgentIdentity } from "./upstream-response-middleware-BjUWZ2G8.js";
2
- import { n as portalToolInputSchemas } from "./portal-tools-DKci1szO.js";
1
+ import { _ as createPortalAgentIdentity, i as redactThrownError } from "./upstream-response-middleware-Cd1MxA6A.js";
2
+ import { n as portalToolInputSchemas } from "./portal-tools-DA7j2pyv.js";
3
3
  import { i as verifyAgentBearerAuthorization } from "./agent-bearer-token-DCtpDPCZ.js";
4
4
  import { r as verifyApprovalToken, t as hashCallArguments } from "./hmac-token-DBqWY3-w.js";
5
5
  import { randomUUID } from "node:crypto";
@@ -547,4 +547,4 @@ function createPortalApprovalVerifier(props) {
547
547
  //#endregion
548
548
  export { createPortalHttpApp as a, listPortalMcpTools as c, resolveAgentHmacKeys as i, portalMcpToolNames as l, createPortalApprovalVerifier as n, createPortalMcpServer as o, createPortalHttpAgentResolver as r, emitMcpProgress as s, createPortalAgentRuntimeRecords as t };
549
549
 
550
- //# sourceMappingURL=resolve-agent-identity-DnC_Pmnh.js.map
550
+ //# sourceMappingURL=resolve-agent-identity-ZMMY2Wqm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-agent-identity-DnC_Pmnh.js","names":[],"sources":["../src/mcp-proxy/portal-mcp-server.ts","../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n\tCallToolRequestSchema,\n\tListToolsRequestSchema,\n\ttype CallToolResult,\n\ttype Tool,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport type {\n\tPortalAgentScope,\n\tPortalCore,\n\tPortalCoreEvent,\n\tPortalCoreToolDescriptor,\n\tPortalCoreResult,\n\tPortalCoreToolName,\n} from '../core/portal-core.js';\nimport { portalToolInputSchemas } from '../core/portal-tools.js';\nimport { redactThrownError } from '../upstream-response-middleware.js';\n\nexport const portalMcpToolNames = [\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n] as const;\n\nexport type PortalMcpToolName = (typeof portalMcpToolNames)[number];\n\nconst portalMcpToolNameSet = new Set<string>(portalMcpToolNames);\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalMcpToolNameSet.has(value);\n}\n\nexport function listPortalMcpTools(\n\tdescriptors?: readonly PortalCoreToolDescriptor[],\n): readonly Tool[] {\n\treturn (\n\t\tdescriptors ?? [\n\t\t\t{\n\t\t\t\tdescription: 'List authorized MCP namespaces and compact tool summaries.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_list,\n\t\t\t\tname: 'mcp_portal_list',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\t\tname: 'mcp_portal_search',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\t\tname: 'mcp_portal_describe',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\t\tname: 'mcp_portal_call',\n\t\t\t},\n\t\t]\n\t);\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction coreResultIsError(value: PortalCoreResult): boolean {\n\tif (value.items.some((item) => item.status === 'failed')) {\n\t\treturn true;\n\t}\n\tif (!isObjectRecord(value.structuredContent)) {\n\t\treturn false;\n\t}\n\treturn value.structuredContent.ok === false;\n}\n\nfunction jsonToolResult(value: PortalCoreResult): CallToolResult {\n\treturn {\n\t\tcontent: [{ text: JSON.stringify(value), type: 'text' }],\n\t\t...(coreResultIsError(value) ? { isError: true } : {}),\n\t};\n}\n\nfunction errorToolResult(error: unknown): CallToolResult {\n\tconst redactedError = redactThrownError(error);\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttext: redactedError.message,\n\t\t\t\ttype: 'text',\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\nasync function sendBestEffortNotification(\n\tnotification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t},\n\tsendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tawait sendNotification(notification);\n\t} catch {\n\t\t// Progress is advisory; unsupported client notification channels must not fail the tool call.\n\t}\n}\n\nexport async function emitMcpProgress(props: {\n\treadonly event: PortalCoreEvent;\n\treadonly sendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>;\n\treadonly progressToken: number | string | undefined;\n}): Promise<void> {\n\tif (props.event.kind === 'upstream_notification') {\n\t\tif (!isObjectRecord(props.event.params)) {\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method === 'notifications/progress') {\n\t\t\tif (props.progressToken === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait sendBestEffortNotification(\n\t\t\t\t{\n\t\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\t\tparams: { ...props.event.params, progressToken: props.progressToken },\n\t\t\t\t},\n\t\t\t\tprops.sendNotification,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method !== 'notifications/message') {\n\t\t\treturn;\n\t\t}\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/message',\n\t\t\t\tparams: props.event.params,\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tif (props.event.kind !== 'progress' && props.event.kind !== 'partial_content') {\n\t\treturn;\n\t}\n\tconst message =\n\t\tprops.event.kind === 'progress'\n\t\t\t? props.event.message\n\t\t\t: props.event.content.type === 'text'\n\t\t\t\t? props.event.content.text\n\t\t\t\t: JSON.stringify(props.event.content.value);\n\tif (message === undefined || message.length === 0) {\n\t\treturn;\n\t}\n\tif (props.progressToken !== undefined) {\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\tparams: {\n\t\t\t\t\tmessage,\n\t\t\t\t\tprogress: props.event.kind === 'progress' ? (props.event.progress ?? 0) : 0,\n\t\t\t\t\tprogressToken: props.progressToken,\n\t\t\t\t\t...(props.event.kind === 'progress' && props.event.total !== undefined\n\t\t\t\t\t\t? { total: props.event.total }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tawait sendBestEffortNotification(\n\t\t{\n\t\t\tmethod: 'notifications/message',\n\t\t\tparams: {\n\t\t\t\tdata: message,\n\t\t\t\tlevel: 'info',\n\t\t\t},\n\t\t},\n\t\tprops.sendNotification,\n\t);\n}\n\nexport function createPortalMcpServer(props: {\n\treadonly core: PortalCore;\n\treadonly scope: PortalAgentScope;\n}): Server {\n\tconst server = new Server(\n\t\t{ name: 'mcp-portal', version: '1.0.0' },\n\t\t{ capabilities: { tools: { listChanged: false } } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: listPortalMcpTools(props.core.describeTools(props.scope)),\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n\t\tif (!isPortalCoreToolName(request.params.name)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ text: `Unknown MCP Portal tool: ${request.params.name}`, type: 'text' }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst result = await props.core.collectPortalCoreResult(\n\t\t\t\tprops.core.callStream({\n\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\tscope: props.scope,\n\t\t\t\t\tsignal: extra.signal,\n\t\t\t\t\ttoolName: request.params.name,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tonEvent: async (event) => {\n\t\t\t\t\t\tawait emitMcpProgress({\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\tprogressToken: extra['_meta']?.progressToken,\n\t\t\t\t\t\t\tsendNotification: extra.sendNotification,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn jsonToolResult(result);\n\t\t} catch (error) {\n\t\t\treturn errorToolResult(error);\n\t\t}\n\t});\n\n\treturn server;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport { StreamableHTTPTransport } from '@hono/mcp';\nimport { getConnInfo } from '@hono/node-server/conninfo';\nimport { Hono, type Context } from 'hono';\n\nimport type { PortalCore } from '../core/portal-core.js';\nimport { createPortalAgentIdentity, type PortalAgentIdentity } from '../portal-access-policy.js';\nimport { verifyAgentBearerAuthorization } from '../portal-auth/agent-bearer-token.js';\nimport { createPortalMcpServer } from './portal-mcp-server.js';\n\nexport interface PortalHttpAgentIdentity extends PortalAgentIdentity {}\n\nexport interface PortalAgentBearerAuth {\n\treadonly authorizationHeaderName: string;\n\treadonly credentialVersionsByAgent?: Readonly<Record<string, number>>;\n\treadonly masterKey: Buffer;\n}\n\nexport type PortalHttpAuditEvent = {\n\treadonly agentId: string;\n\treadonly clientAddress: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_proxy_auth';\n\treadonly reason?:\n\t\t| 'malformed'\n\t\t| 'missing'\n\t\t| 'rate_limited'\n\t\t| 'signature-mismatch'\n\t\t| 'unknown_agent';\n\treadonly timeMs: number;\n};\n\nexport interface PortalHttpAppOptions {\n\treadonly agentBearerAuth: PortalAgentBearerAuth;\n\treadonly auditErrorSink?: (error: Error, event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly auditSink?: (event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly authFailureLimit?: {\n\t\treadonly maxFailures: number;\n\t\treadonly windowMs: number;\n\t};\n\treadonly core: PortalCore;\n\treadonly onSessionClosed?: (identity: PortalAgentIdentity) => Promise<void> | void;\n\treadonly onSessionCloseError?: (\n\t\terror: Error,\n\t\tidentity: PortalAgentIdentity,\n\t) => Promise<void> | void;\n\treadonly registeredAgentIds?: readonly string[];\n\treadonly resolveAgentIdentity?: (agentId: string) => PortalHttpAgentIdentity | null;\n}\n\nexport type PortalHttpApp = Hono & {\n\treadonly closePortalSessions: () => Promise<void>;\n};\n\nconst mcpSessionIdHeader = 'mcp-session-id';\nconst defaultAuthFailureLimit = { maxFailures: 60, windowMs: 60_000 } as const;\nconst authFailureBucketLimit = 1_024;\nconst directClientAddress = 'direct-client';\nconst unknownAgentCredentialVersionForOpaqueAuthTiming = 1;\n\ninterface ActivePortalMcpSession {\n\treadonly identity: PortalAgentIdentity;\n\treadonly server: ReturnType<typeof createPortalMcpServer>;\n\treadonly transport: StreamableHTTPTransport;\n}\n\ninterface AuthFailureBucket {\n\treadonly resetAtMs: number;\n\tfailures: number;\n}\n\nfunction activeSessionKey(scopeId: string, sessionId: string): string {\n\treturn `${scopeId}\\n${sessionId}`;\n}\n\nfunction unauthorizedResponse(): Response {\n\treturn Response.json({ error: { kind: 'unauthorized' }, ok: false }, { status: 401 });\n}\n\nfunction rateLimitedResponse(): Response {\n\treturn Response.json({ error: { kind: 'rate_limited' }, ok: false }, { status: 429 });\n}\n\nfunction unavailableResponse(): Response {\n\treturn Response.json({ error: { kind: 'shutting_down' }, ok: false }, { status: 503 });\n}\n\nfunction errorFromUnknown(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction clientAddressFromContext(context: Context): string {\n\ttry {\n\t\tconst address = getConnInfo(context).remote.address;\n\t\treturn address && address.length > 0 ? address : directClientAddress;\n\t} catch {\n\t\treturn directClientAddress;\n\t}\n}\n\nexport function createPortalHttpApp(options: PortalHttpAppOptions): PortalHttpApp {\n\tif (options.agentBearerAuth === undefined) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth.');\n\t}\n\tif (options.agentBearerAuth.authorizationHeaderName.length === 0) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth header name.');\n\t}\n\tconst app = new Hono();\n\tconst activeSessions = new Map<string, ActivePortalMcpSession>();\n\tconst authFailureBuckets = new Map<string, AuthFailureBucket>();\n\tconst pendingNewSessionRequests = new Set<Promise<void>>();\n\tconst authFailureLimit = options.authFailureLimit ?? defaultAuthFailureLimit;\n\tlet closing = false;\n\n\tasync function auditAuth(event: Omit<PortalHttpAuditEvent, 'kind' | 'timeMs'>): Promise<void> {\n\t\tconst auditEvent = { ...event, kind: 'mcp_proxy_auth', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tawait options.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tawait options.auditErrorSink?.(errorFromUnknown(error), auditEvent);\n\t\t}\n\t}\n\n\tasync function reportSessionCloseError(\n\t\terror: unknown,\n\t\tidentity: PortalAgentIdentity,\n\t): Promise<void> {\n\t\tawait options.onSessionCloseError?.(errorFromUnknown(error), identity);\n\t}\n\n\tfunction pruneAuthFailureBuckets(nowMs: number): void {\n\t\tfor (const [key, bucket] of authFailureBuckets) {\n\t\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\t\tauthFailureBuckets.delete(key);\n\t\t\t}\n\t\t}\n\t\twhile (authFailureBuckets.size > authFailureBucketLimit) {\n\t\t\tconst firstKey = authFailureBuckets.keys().next().value;\n\t\t\tif (typeof firstKey !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthFailureBuckets.delete(firstKey);\n\t\t}\n\t}\n\n\tfunction isAuthFailureRateLimited(clientAddress: string): boolean {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket === undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\tauthFailureBuckets.delete(clientAddress);\n\t\t\treturn false;\n\t\t}\n\t\treturn bucket.failures >= authFailureLimit.maxFailures;\n\t}\n\n\tfunction recordAuthFailure(clientAddress: string): void {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket !== undefined && bucket.resetAtMs > nowMs) {\n\t\t\tbucket.failures += 1;\n\t\t\treturn;\n\t\t}\n\t\tauthFailureBuckets.set(clientAddress, {\n\t\t\tfailures: 1,\n\t\t\tresetAtMs: nowMs + authFailureLimit.windowMs,\n\t\t});\n\t\tpruneAuthFailureBuckets(nowMs);\n\t}\n\n\tfunction clearAuthFailures(clientAddress: string): void {\n\t\tauthFailureBuckets.delete(clientAddress);\n\t}\n\n\tasync function closeActiveSession(\n\t\tsessionKey: string,\n\t\tcloseOptions: { readonly closeTransport: boolean },\n\t): Promise<void> {\n\t\tconst activeSession = activeSessions.get(sessionKey);\n\t\tif (!activeSession) {\n\t\t\treturn;\n\t\t}\n\t\tactiveSessions.delete(sessionKey);\n\t\ttry {\n\t\t\tif (closeOptions.closeTransport) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t}\n\t\t} finally {\n\t\t\tawait options.onSessionClosed?.(activeSession.identity);\n\t\t}\n\t}\n\n\tfunction trackPendingNewSessionRequest(): () => void {\n\t\tlet resolvePending: (() => void) | undefined;\n\t\tconst pendingRequest = new Promise<void>((resolve) => {\n\t\t\tresolvePending = resolve;\n\t\t});\n\t\tpendingNewSessionRequests.add(pendingRequest);\n\t\treturn () => {\n\t\t\tpendingNewSessionRequests.delete(pendingRequest);\n\t\t\tresolvePending?.();\n\t\t};\n\t}\n\n\tasync function createActiveSession(\n\t\tidentityBase: PortalAgentIdentity,\n\t): Promise<ActivePortalMcpSession> {\n\t\tconst sessionId = randomUUID();\n\t\tconst sessionKey = activeSessionKey(identityBase.agentScopeId, sessionId);\n\t\tlet server: ReturnType<typeof createPortalMcpServer> | null = null;\n\t\tconst identity = createPortalAgentIdentity({\n\t\t\tagentId: identityBase.agentId,\n\t\t\tagentScopeId: identityBase.agentScopeId,\n\t\t\tsessionId,\n\t\t\tsource: identityBase.source,\n\t\t});\n\t\tconst transport = new StreamableHTTPTransport({\n\t\t\tonsessionclosed: () => {\n\t\t\t\tvoid closeActiveSession(sessionKey, { closeTransport: false }).catch((error: unknown) =>\n\t\t\t\t\treportSessionCloseError(error, identity),\n\t\t\t\t);\n\t\t\t},\n\t\t\tonsessioninitialized: (initializedSessionId) => {\n\t\t\t\tif (!server) {\n\t\t\t\t\tthrow new Error('MCP Portal session initialized before server connection.');\n\t\t\t\t}\n\t\t\t\tactiveSessions.set(activeSessionKey(identityBase.agentScopeId, initializedSessionId), {\n\t\t\t\t\tidentity,\n\t\t\t\t\tserver,\n\t\t\t\t\ttransport,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsessionIdGenerator: () => sessionId,\n\t\t});\n\t\tserver = createPortalMcpServer({\n\t\t\tcore: options.core,\n\t\t\tscope: identity,\n\t\t});\n\t\tawait server.connect(transport);\n\t\treturn { identity, server, transport };\n\t}\n\n\tasync function closePortalSessions(): Promise<void> {\n\t\tclosing = true;\n\t\tconst closeErrors: Error[] = [];\n\t\twhile (activeSessions.size > 0 || pendingNewSessionRequests.size > 0) {\n\t\t\tif (pendingNewSessionRequests.size > 0) {\n\t\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\t\tawait Promise.allSettled(pendingNewSessionRequests);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Closing may trigger callbacks that mutate activeSessions, so drain snapshots until empty.\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst closeResults = await Promise.allSettled(\n\t\t\t\t[...activeSessions.keys()].map((sessionKey) =>\n\t\t\t\t\tcloseActiveSession(sessionKey, { closeTransport: true }),\n\t\t\t\t),\n\t\t\t);\n\t\t\tcloseErrors.push(\n\t\t\t\t...closeResults\n\t\t\t\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t\t\t\t.map((result): Error => errorFromUnknown(result.reason)),\n\t\t\t);\n\t\t}\n\t\tif (closeErrors.length > 0) {\n\t\t\tthrow new AggregateError(closeErrors, 'Failed to close one or more MCP Portal sessions.');\n\t\t}\n\t}\n\n\tapp.get('/health', (context) =>\n\t\tcontext.json({ agents: [...(options.registeredAgentIds ?? [])].toSorted(), ok: true }),\n\t);\n\n\tapp.all('/agents/:agentId/mcp', async (context) => {\n\t\tconst agentId = context.req.param('agentId');\n\t\tconst clientAddress = clientAddressFromContext(context);\n\t\tif (closing) {\n\t\t\treturn unavailableResponse();\n\t\t}\n\t\tif (isAuthFailureRateLimited(clientAddress)) {\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'rate_limited',\n\t\t\t});\n\t\t\treturn rateLimitedResponse();\n\t\t}\n\t\tconst agentBearerAuth = options.agentBearerAuth;\n\t\tconst credentialVersion = agentBearerAuth.credentialVersionsByAgent?.[agentId];\n\t\tconst verification = verifyAgentBearerAuthorization({\n\t\t\tagentId,\n\t\t\tauthorizationHeader: context.req.header(agentBearerAuth.authorizationHeaderName),\n\t\t\tcredentialVersion: credentialVersion ?? unknownAgentCredentialVersionForOpaqueAuthTiming,\n\t\t\tmasterKey: agentBearerAuth.masterKey,\n\t\t});\n\t\tconst agentIdentity = options.resolveAgentIdentity?.(agentId) ?? null;\n\t\tif (agentIdentity === null) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'unknown_agent',\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tif (!verification.ok) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: verification.reason,\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tclearAuthFailures(clientAddress);\n\t\tawait auditAuth({ agentId, clientAddress, decision: 'allow' });\n\n\t\tconst mcpSessionId = context.req.header(mcpSessionIdHeader);\n\t\tif (mcpSessionId) {\n\t\t\tconst activeSession = activeSessions.get(\n\t\t\t\tactiveSessionKey(agentIdentity.agentScopeId, mcpSessionId),\n\t\t\t);\n\t\t\tif (!activeSession) {\n\t\t\t\treturn new Response('Unknown MCP portal session', { status: 404 });\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t}\n\n\t\tconst finishPendingRequest = trackPendingNewSessionRequest();\n\t\ttry {\n\t\t\tif (closing) {\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\tconst activeSession = await createActiveSession(agentIdentity);\n\t\t\tif (closing) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t} finally {\n\t\t\tfinishPendingRequest();\n\t\t}\n\t});\n\n\treturn Object.assign(app, { closePortalSessions });\n}\n","import {\n\tresolveMcpPortalProfile,\n\tmcpPortalCallRequiresApproval,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport type { PortalApprovalCall } from '../core/portal-tools.js';\nimport { createPortalAgentIdentity } from '../portal-access-policy.js';\nimport { hashCallArguments, verifyApprovalToken } from '../portal-auth/hmac-token.js';\n\nconst approvalTokenMaxLifetimeMs = 5 * 60_000;\nconst approvalTokenReplayCacheLimit = 4_096;\n\nexport interface ResolveAgentHmacKeysProps {\n\treadonly agents: Readonly<Record<string, McpPortalAgentConfig>>;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nexport interface PortalAgentRuntimeRecord {\n\treadonly agentId: string;\n\treadonly hmacKey: Buffer;\n\treadonly profile: ResolvedMcpPortalProfile;\n\treadonly profileName: string;\n}\n\nexport interface PortalApprovalAuditEvent {\n\treadonly agentId: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_portal_approval';\n\treadonly reason?: 'approval_token_invalid' | 'approval_token_missing' | 'no_approval_required';\n\treadonly timeMs: number;\n\treadonly verifierReason?: string;\n}\n\nasync function resolveAgentHmacKeyEntry(props: {\n\treadonly agent: McpPortalAgentConfig;\n\treadonly agentId: string;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<readonly [string, Buffer]> {\n\tconst envKey = props.envKeys.get(props.agentId);\n\tif (envKey !== undefined) {\n\t\treturn [props.agentId, envKey];\n\t}\n\tif (props.agent.hmacKey === undefined) {\n\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${props.agentId}\".`);\n\t}\n\tconst secretValue = await props.resolveSecret(props.agent.hmacKey);\n\tif (!/^[0-9a-f]+$/u.test(secretValue) || secretValue.length !== 64) {\n\t\tthrow new Error(`MCP Portal agent \"${props.agentId}\" HMAC key must be 64 hex characters.`);\n\t}\n\treturn [props.agentId, Buffer.from(secretValue, 'hex')];\n}\n\nexport async function resolveAgentHmacKeys(\n\tprops: ResolveAgentHmacKeysProps,\n): Promise<ReadonlyMap<string, Buffer>> {\n\treturn new Map(\n\t\tawait Promise.all(\n\t\t\tObject.entries(props.agents).map(([agentId, agent]) =>\n\t\t\t\tresolveAgentHmacKeyEntry({\n\t\t\t\t\tagent,\n\t\t\t\t\tagentId,\n\t\t\t\t\tenvKeys: props.envKeys,\n\t\t\t\t\tresolveSecret: props.resolveSecret,\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t);\n}\n\nexport function createPortalAgentRuntimeRecords(props: {\n\treadonly hmacKeys: ReadonlyMap<string, Buffer>;\n\treadonly portalConfig: McpPortalConfig;\n}): ReadonlyMap<string, PortalAgentRuntimeRecord> {\n\tconst records = new Map<string, PortalAgentRuntimeRecord>();\n\tfor (const [agentId, agent] of Object.entries(props.portalConfig.agents)) {\n\t\tconst hmacKey = props.hmacKeys.get(agentId);\n\t\tif (hmacKey === undefined) {\n\t\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\trecords.set(agentId, {\n\t\t\tagentId,\n\t\t\thmacKey,\n\t\t\tprofile: resolveMcpPortalProfile(props.portalConfig, agent.profile),\n\t\t\tprofileName: agent.profile,\n\t\t});\n\t}\n\treturn records;\n}\n\nexport function createPortalHttpAgentResolver(\n\trecords: ReadonlyMap<string, PortalAgentRuntimeRecord>,\n): (agentId: string) => ReturnType<typeof createPortalAgentIdentity> | null {\n\treturn (agentId) => {\n\t\tconst record = records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn createPortalAgentIdentity({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'mcp-proxy-bearer',\n\t\t});\n\t};\n}\n\nfunction approvalRequiredByProfile(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: PortalApprovalCall,\n): boolean {\n\tconst annotations = call.tool.annotations;\n\treturn mcpPortalCallRequiresApproval(profile, {\n\t\t...(annotations === undefined ? {} : { annotations }),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t});\n}\n\nfunction approvalTokenCallDigests(calls: readonly PortalApprovalCall[]): readonly {\n\treadonly argumentsHash: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}[] {\n\treturn calls.map((call) => ({\n\t\targumentsHash: hashCallArguments(call.arguments),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t}));\n}\n\nexport function createPortalApprovalVerifier(props: {\n\treadonly approvalTokenReplayCacheLimit?: number;\n\treadonly auditErrorSink?: (error: Error, event: PortalApprovalAuditEvent) => void;\n\treadonly auditSink?: (event: PortalApprovalAuditEvent) => void;\n\treadonly records: ReadonlyMap<string, PortalAgentRuntimeRecord>;\n}): (\n\tcalls: readonly PortalApprovalCall[],\n\tagentId: string,\n\ttoken: string | undefined,\n) =>\n\t| { readonly kind: 'allow' }\n\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t| { readonly kind: 'approval_token_missing' } {\n\tfunction auditApproval(event: Omit<PortalApprovalAuditEvent, 'kind' | 'timeMs'>): void {\n\t\tconst auditEvent = { ...event, kind: 'mcp_portal_approval', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tprops.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tprops.auditErrorSink?.(error instanceof Error ? error : new Error(String(error)), auditEvent);\n\t\t}\n\t}\n\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = props.approvalTokenReplayCacheLimit ?? approvalTokenReplayCacheLimit;\n\tconst consumeTokenId = (\n\t\tagentId: string,\n\t\tjti: string,\n\t\texpiresAtMs: number,\n\t):\n\t\t| { readonly ok: true }\n\t\t| { readonly ok: false; readonly reason: 'replay-cache-full' | 'replayed' } => {\n\t\tconst nowMs = Date.now();\n\t\tfor (const [tokenKey, tokenExpiresAtMs] of consumedApprovalTokenIds) {\n\t\t\tif (tokenExpiresAtMs <= nowMs) {\n\t\t\t\tconsumedApprovalTokenIds.delete(tokenKey);\n\t\t\t}\n\t\t}\n\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t}\n\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t}\n\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\treturn { ok: true };\n\t};\n\treturn (calls, agentId, token) => {\n\t\tconst record = props.records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\tauditApproval({\n\t\t\t\tagentId,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'approval_token_invalid',\n\t\t\t\tverifierReason: 'unknown-agent',\n\t\t\t});\n\t\t\treturn { kind: 'approval_token_invalid', reason: 'unknown-agent' };\n\t\t}\n\t\tconst callsRequiringApproval = calls.filter((call) =>\n\t\t\tapprovalRequiredByProfile(record.profile, call),\n\t\t);\n\t\tif (callsRequiringApproval.length === 0) {\n\t\t\tauditApproval({ agentId, decision: 'allow', reason: 'no_approval_required' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tif (token === undefined) {\n\t\t\tauditApproval({ agentId, decision: 'deny', reason: 'approval_token_missing' });\n\t\t\treturn { kind: 'approval_token_missing' };\n\t\t}\n\t\tconst verificationProps = {\n\t\t\tagentId,\n\t\t\tcalls: approvalTokenCallDigests(callsRequiringApproval),\n\t\t\tconsumeTokenId: (jti: string, expiresAtMs: number) =>\n\t\t\t\tconsumeTokenId(agentId, jti, expiresAtMs),\n\t\t\tkey: record.hmacKey,\n\t\t\tmaxLifetimeMs: approvalTokenMaxLifetimeMs,\n\t\t\tnowMs: Date.now(),\n\t\t\ttoken,\n\t\t};\n\t\tconst verification = verifyApprovalToken(verificationProps);\n\t\tif (verification.ok) {\n\t\t\tauditApproval({ agentId, decision: 'allow' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tauditApproval({\n\t\t\tagentId,\n\t\t\tdecision: 'deny',\n\t\t\treason: 'approval_token_invalid',\n\t\t\tverifierReason: verification.reason,\n\t\t});\n\t\treturn { kind: 'approval_token_invalid', reason: verification.reason };\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resolve-agent-identity-ZMMY2Wqm.js","names":[],"sources":["../src/mcp-proxy/portal-mcp-server.ts","../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n\tCallToolRequestSchema,\n\tListToolsRequestSchema,\n\ttype CallToolResult,\n\ttype Tool,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport type {\n\tPortalAgentScope,\n\tPortalCore,\n\tPortalCoreEvent,\n\tPortalCoreToolDescriptor,\n\tPortalCoreResult,\n\tPortalCoreToolName,\n} from '../core/portal-core.js';\nimport { portalToolInputSchemas } from '../core/portal-tools.js';\nimport { redactThrownError } from '../upstream-response-middleware.js';\n\nexport const portalMcpToolNames = [\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n] as const;\n\nexport type PortalMcpToolName = (typeof portalMcpToolNames)[number];\n\nconst portalMcpToolNameSet = new Set<string>(portalMcpToolNames);\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalMcpToolNameSet.has(value);\n}\n\nexport function listPortalMcpTools(\n\tdescriptors?: readonly PortalCoreToolDescriptor[],\n): readonly Tool[] {\n\treturn (\n\t\tdescriptors ?? [\n\t\t\t{\n\t\t\t\tdescription: 'List authorized MCP namespaces and compact tool summaries.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_list,\n\t\t\t\tname: 'mcp_portal_list',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\t\tname: 'mcp_portal_search',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\t\tname: 'mcp_portal_describe',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\t\tname: 'mcp_portal_call',\n\t\t\t},\n\t\t]\n\t);\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction coreResultIsError(value: PortalCoreResult): boolean {\n\tif (value.items.some((item) => item.status === 'failed')) {\n\t\treturn true;\n\t}\n\tif (!isObjectRecord(value.structuredContent)) {\n\t\treturn false;\n\t}\n\treturn value.structuredContent.ok === false;\n}\n\nfunction jsonToolResult(value: PortalCoreResult): CallToolResult {\n\treturn {\n\t\tcontent: [{ text: JSON.stringify(value), type: 'text' }],\n\t\t...(coreResultIsError(value) ? { isError: true } : {}),\n\t};\n}\n\nfunction errorToolResult(error: unknown): CallToolResult {\n\tconst redactedError = redactThrownError(error);\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttext: redactedError.message,\n\t\t\t\ttype: 'text',\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\nasync function sendBestEffortNotification(\n\tnotification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t},\n\tsendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tawait sendNotification(notification);\n\t} catch {\n\t\t// Progress is advisory; unsupported client notification channels must not fail the tool call.\n\t}\n}\n\nexport async function emitMcpProgress(props: {\n\treadonly event: PortalCoreEvent;\n\treadonly sendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>;\n\treadonly progressToken: number | string | undefined;\n}): Promise<void> {\n\tif (props.event.kind === 'upstream_notification') {\n\t\tif (!isObjectRecord(props.event.params)) {\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method === 'notifications/progress') {\n\t\t\tif (props.progressToken === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait sendBestEffortNotification(\n\t\t\t\t{\n\t\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\t\tparams: { ...props.event.params, progressToken: props.progressToken },\n\t\t\t\t},\n\t\t\t\tprops.sendNotification,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method !== 'notifications/message') {\n\t\t\treturn;\n\t\t}\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/message',\n\t\t\t\tparams: props.event.params,\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tif (props.event.kind !== 'progress' && props.event.kind !== 'partial_content') {\n\t\treturn;\n\t}\n\tconst message =\n\t\tprops.event.kind === 'progress'\n\t\t\t? props.event.message\n\t\t\t: props.event.content.type === 'text'\n\t\t\t\t? props.event.content.text\n\t\t\t\t: JSON.stringify(props.event.content.value);\n\tif (message === undefined || message.length === 0) {\n\t\treturn;\n\t}\n\tif (props.progressToken !== undefined) {\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\tparams: {\n\t\t\t\t\tmessage,\n\t\t\t\t\tprogress: props.event.kind === 'progress' ? (props.event.progress ?? 0) : 0,\n\t\t\t\t\tprogressToken: props.progressToken,\n\t\t\t\t\t...(props.event.kind === 'progress' && props.event.total !== undefined\n\t\t\t\t\t\t? { total: props.event.total }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tawait sendBestEffortNotification(\n\t\t{\n\t\t\tmethod: 'notifications/message',\n\t\t\tparams: {\n\t\t\t\tdata: message,\n\t\t\t\tlevel: 'info',\n\t\t\t},\n\t\t},\n\t\tprops.sendNotification,\n\t);\n}\n\nexport function createPortalMcpServer(props: {\n\treadonly core: PortalCore;\n\treadonly scope: PortalAgentScope;\n}): Server {\n\tconst server = new Server(\n\t\t{ name: 'mcp-portal', version: '1.0.0' },\n\t\t{ capabilities: { tools: { listChanged: false } } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: listPortalMcpTools(props.core.describeTools(props.scope)),\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n\t\tif (!isPortalCoreToolName(request.params.name)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ text: `Unknown MCP Portal tool: ${request.params.name}`, type: 'text' }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst result = await props.core.collectPortalCoreResult(\n\t\t\t\tprops.core.callStream({\n\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\tscope: props.scope,\n\t\t\t\t\tsignal: extra.signal,\n\t\t\t\t\ttoolName: request.params.name,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tonEvent: async (event) => {\n\t\t\t\t\t\tawait emitMcpProgress({\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\tprogressToken: extra['_meta']?.progressToken,\n\t\t\t\t\t\t\tsendNotification: extra.sendNotification,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn jsonToolResult(result);\n\t\t} catch (error) {\n\t\t\treturn errorToolResult(error);\n\t\t}\n\t});\n\n\treturn server;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport { StreamableHTTPTransport } from '@hono/mcp';\nimport { getConnInfo } from '@hono/node-server/conninfo';\nimport { Hono, type Context } from 'hono';\n\nimport type { PortalCore } from '../core/portal-core.js';\nimport { createPortalAgentIdentity, type PortalAgentIdentity } from '../portal-access-policy.js';\nimport { verifyAgentBearerAuthorization } from '../portal-auth/agent-bearer-token.js';\nimport { createPortalMcpServer } from './portal-mcp-server.js';\n\nexport interface PortalHttpAgentIdentity extends PortalAgentIdentity {}\n\nexport interface PortalAgentBearerAuth {\n\treadonly authorizationHeaderName: string;\n\treadonly credentialVersionsByAgent?: Readonly<Record<string, number>>;\n\treadonly masterKey: Buffer;\n}\n\nexport type PortalHttpAuditEvent = {\n\treadonly agentId: string;\n\treadonly clientAddress: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_proxy_auth';\n\treadonly reason?:\n\t\t| 'malformed'\n\t\t| 'missing'\n\t\t| 'rate_limited'\n\t\t| 'signature-mismatch'\n\t\t| 'unknown_agent';\n\treadonly timeMs: number;\n};\n\nexport interface PortalHttpAppOptions {\n\treadonly agentBearerAuth: PortalAgentBearerAuth;\n\treadonly auditErrorSink?: (error: Error, event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly auditSink?: (event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly authFailureLimit?: {\n\t\treadonly maxFailures: number;\n\t\treadonly windowMs: number;\n\t};\n\treadonly core: PortalCore;\n\treadonly onSessionClosed?: (identity: PortalAgentIdentity) => Promise<void> | void;\n\treadonly onSessionCloseError?: (\n\t\terror: Error,\n\t\tidentity: PortalAgentIdentity,\n\t) => Promise<void> | void;\n\treadonly registeredAgentIds?: readonly string[];\n\treadonly resolveAgentIdentity?: (agentId: string) => PortalHttpAgentIdentity | null;\n}\n\nexport type PortalHttpApp = Hono & {\n\treadonly closePortalSessions: () => Promise<void>;\n};\n\nconst mcpSessionIdHeader = 'mcp-session-id';\nconst defaultAuthFailureLimit = { maxFailures: 60, windowMs: 60_000 } as const;\nconst authFailureBucketLimit = 1_024;\nconst directClientAddress = 'direct-client';\nconst unknownAgentCredentialVersionForOpaqueAuthTiming = 1;\n\ninterface ActivePortalMcpSession {\n\treadonly identity: PortalAgentIdentity;\n\treadonly server: ReturnType<typeof createPortalMcpServer>;\n\treadonly transport: StreamableHTTPTransport;\n}\n\ninterface AuthFailureBucket {\n\treadonly resetAtMs: number;\n\tfailures: number;\n}\n\nfunction activeSessionKey(scopeId: string, sessionId: string): string {\n\treturn `${scopeId}\\n${sessionId}`;\n}\n\nfunction unauthorizedResponse(): Response {\n\treturn Response.json({ error: { kind: 'unauthorized' }, ok: false }, { status: 401 });\n}\n\nfunction rateLimitedResponse(): Response {\n\treturn Response.json({ error: { kind: 'rate_limited' }, ok: false }, { status: 429 });\n}\n\nfunction unavailableResponse(): Response {\n\treturn Response.json({ error: { kind: 'shutting_down' }, ok: false }, { status: 503 });\n}\n\nfunction errorFromUnknown(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction clientAddressFromContext(context: Context): string {\n\ttry {\n\t\tconst address = getConnInfo(context).remote.address;\n\t\treturn address && address.length > 0 ? address : directClientAddress;\n\t} catch {\n\t\treturn directClientAddress;\n\t}\n}\n\nexport function createPortalHttpApp(options: PortalHttpAppOptions): PortalHttpApp {\n\tif (options.agentBearerAuth === undefined) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth.');\n\t}\n\tif (options.agentBearerAuth.authorizationHeaderName.length === 0) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth header name.');\n\t}\n\tconst app = new Hono();\n\tconst activeSessions = new Map<string, ActivePortalMcpSession>();\n\tconst authFailureBuckets = new Map<string, AuthFailureBucket>();\n\tconst pendingNewSessionRequests = new Set<Promise<void>>();\n\tconst authFailureLimit = options.authFailureLimit ?? defaultAuthFailureLimit;\n\tlet closing = false;\n\n\tasync function auditAuth(event: Omit<PortalHttpAuditEvent, 'kind' | 'timeMs'>): Promise<void> {\n\t\tconst auditEvent = { ...event, kind: 'mcp_proxy_auth', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tawait options.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tawait options.auditErrorSink?.(errorFromUnknown(error), auditEvent);\n\t\t}\n\t}\n\n\tasync function reportSessionCloseError(\n\t\terror: unknown,\n\t\tidentity: PortalAgentIdentity,\n\t): Promise<void> {\n\t\tawait options.onSessionCloseError?.(errorFromUnknown(error), identity);\n\t}\n\n\tfunction pruneAuthFailureBuckets(nowMs: number): void {\n\t\tfor (const [key, bucket] of authFailureBuckets) {\n\t\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\t\tauthFailureBuckets.delete(key);\n\t\t\t}\n\t\t}\n\t\twhile (authFailureBuckets.size > authFailureBucketLimit) {\n\t\t\tconst firstKey = authFailureBuckets.keys().next().value;\n\t\t\tif (typeof firstKey !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthFailureBuckets.delete(firstKey);\n\t\t}\n\t}\n\n\tfunction isAuthFailureRateLimited(clientAddress: string): boolean {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket === undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\tauthFailureBuckets.delete(clientAddress);\n\t\t\treturn false;\n\t\t}\n\t\treturn bucket.failures >= authFailureLimit.maxFailures;\n\t}\n\n\tfunction recordAuthFailure(clientAddress: string): void {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket !== undefined && bucket.resetAtMs > nowMs) {\n\t\t\tbucket.failures += 1;\n\t\t\treturn;\n\t\t}\n\t\tauthFailureBuckets.set(clientAddress, {\n\t\t\tfailures: 1,\n\t\t\tresetAtMs: nowMs + authFailureLimit.windowMs,\n\t\t});\n\t\tpruneAuthFailureBuckets(nowMs);\n\t}\n\n\tfunction clearAuthFailures(clientAddress: string): void {\n\t\tauthFailureBuckets.delete(clientAddress);\n\t}\n\n\tasync function closeActiveSession(\n\t\tsessionKey: string,\n\t\tcloseOptions: { readonly closeTransport: boolean },\n\t): Promise<void> {\n\t\tconst activeSession = activeSessions.get(sessionKey);\n\t\tif (!activeSession) {\n\t\t\treturn;\n\t\t}\n\t\tactiveSessions.delete(sessionKey);\n\t\ttry {\n\t\t\tif (closeOptions.closeTransport) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t}\n\t\t} finally {\n\t\t\tawait options.onSessionClosed?.(activeSession.identity);\n\t\t}\n\t}\n\n\tfunction trackPendingNewSessionRequest(): () => void {\n\t\tlet resolvePending: (() => void) | undefined;\n\t\tconst pendingRequest = new Promise<void>((resolve) => {\n\t\t\tresolvePending = resolve;\n\t\t});\n\t\tpendingNewSessionRequests.add(pendingRequest);\n\t\treturn () => {\n\t\t\tpendingNewSessionRequests.delete(pendingRequest);\n\t\t\tresolvePending?.();\n\t\t};\n\t}\n\n\tasync function createActiveSession(\n\t\tidentityBase: PortalAgentIdentity,\n\t): Promise<ActivePortalMcpSession> {\n\t\tconst sessionId = randomUUID();\n\t\tconst sessionKey = activeSessionKey(identityBase.agentScopeId, sessionId);\n\t\tlet server: ReturnType<typeof createPortalMcpServer> | null = null;\n\t\tconst identity = createPortalAgentIdentity({\n\t\t\tagentId: identityBase.agentId,\n\t\t\tagentScopeId: identityBase.agentScopeId,\n\t\t\tsessionId,\n\t\t\tsource: identityBase.source,\n\t\t});\n\t\tconst transport = new StreamableHTTPTransport({\n\t\t\tonsessionclosed: () => {\n\t\t\t\tvoid closeActiveSession(sessionKey, { closeTransport: false }).catch((error: unknown) =>\n\t\t\t\t\treportSessionCloseError(error, identity),\n\t\t\t\t);\n\t\t\t},\n\t\t\tonsessioninitialized: (initializedSessionId) => {\n\t\t\t\tif (!server) {\n\t\t\t\t\tthrow new Error('MCP Portal session initialized before server connection.');\n\t\t\t\t}\n\t\t\t\tactiveSessions.set(activeSessionKey(identityBase.agentScopeId, initializedSessionId), {\n\t\t\t\t\tidentity,\n\t\t\t\t\tserver,\n\t\t\t\t\ttransport,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsessionIdGenerator: () => sessionId,\n\t\t});\n\t\tserver = createPortalMcpServer({\n\t\t\tcore: options.core,\n\t\t\tscope: identity,\n\t\t});\n\t\tawait server.connect(transport);\n\t\treturn { identity, server, transport };\n\t}\n\n\tasync function closePortalSessions(): Promise<void> {\n\t\tclosing = true;\n\t\tconst closeErrors: Error[] = [];\n\t\twhile (activeSessions.size > 0 || pendingNewSessionRequests.size > 0) {\n\t\t\tif (pendingNewSessionRequests.size > 0) {\n\t\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\t\tawait Promise.allSettled(pendingNewSessionRequests);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Closing may trigger callbacks that mutate activeSessions, so drain snapshots until empty.\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst closeResults = await Promise.allSettled(\n\t\t\t\t[...activeSessions.keys()].map((sessionKey) =>\n\t\t\t\t\tcloseActiveSession(sessionKey, { closeTransport: true }),\n\t\t\t\t),\n\t\t\t);\n\t\t\tcloseErrors.push(\n\t\t\t\t...closeResults\n\t\t\t\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t\t\t\t.map((result): Error => errorFromUnknown(result.reason)),\n\t\t\t);\n\t\t}\n\t\tif (closeErrors.length > 0) {\n\t\t\tthrow new AggregateError(closeErrors, 'Failed to close one or more MCP Portal sessions.');\n\t\t}\n\t}\n\n\tapp.get('/health', (context) =>\n\t\tcontext.json({ agents: [...(options.registeredAgentIds ?? [])].toSorted(), ok: true }),\n\t);\n\n\tapp.all('/agents/:agentId/mcp', async (context) => {\n\t\tconst agentId = context.req.param('agentId');\n\t\tconst clientAddress = clientAddressFromContext(context);\n\t\tif (closing) {\n\t\t\treturn unavailableResponse();\n\t\t}\n\t\tif (isAuthFailureRateLimited(clientAddress)) {\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'rate_limited',\n\t\t\t});\n\t\t\treturn rateLimitedResponse();\n\t\t}\n\t\tconst agentBearerAuth = options.agentBearerAuth;\n\t\tconst credentialVersion = agentBearerAuth.credentialVersionsByAgent?.[agentId];\n\t\tconst verification = verifyAgentBearerAuthorization({\n\t\t\tagentId,\n\t\t\tauthorizationHeader: context.req.header(agentBearerAuth.authorizationHeaderName),\n\t\t\tcredentialVersion: credentialVersion ?? unknownAgentCredentialVersionForOpaqueAuthTiming,\n\t\t\tmasterKey: agentBearerAuth.masterKey,\n\t\t});\n\t\tconst agentIdentity = options.resolveAgentIdentity?.(agentId) ?? null;\n\t\tif (agentIdentity === null) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'unknown_agent',\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tif (!verification.ok) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: verification.reason,\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tclearAuthFailures(clientAddress);\n\t\tawait auditAuth({ agentId, clientAddress, decision: 'allow' });\n\n\t\tconst mcpSessionId = context.req.header(mcpSessionIdHeader);\n\t\tif (mcpSessionId) {\n\t\t\tconst activeSession = activeSessions.get(\n\t\t\t\tactiveSessionKey(agentIdentity.agentScopeId, mcpSessionId),\n\t\t\t);\n\t\t\tif (!activeSession) {\n\t\t\t\treturn new Response('Unknown MCP portal session', { status: 404 });\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t}\n\n\t\tconst finishPendingRequest = trackPendingNewSessionRequest();\n\t\ttry {\n\t\t\tif (closing) {\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\tconst activeSession = await createActiveSession(agentIdentity);\n\t\t\tif (closing) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t} finally {\n\t\t\tfinishPendingRequest();\n\t\t}\n\t});\n\n\treturn Object.assign(app, { closePortalSessions });\n}\n","import {\n\tresolveMcpPortalProfile,\n\tmcpPortalCallRequiresApproval,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport type { PortalApprovalCall } from '../core/portal-tools.js';\nimport { createPortalAgentIdentity } from '../portal-access-policy.js';\nimport { hashCallArguments, verifyApprovalToken } from '../portal-auth/hmac-token.js';\n\nconst approvalTokenMaxLifetimeMs = 5 * 60_000;\nconst approvalTokenReplayCacheLimit = 4_096;\n\nexport interface ResolveAgentHmacKeysProps {\n\treadonly agents: Readonly<Record<string, McpPortalAgentConfig>>;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nexport interface PortalAgentRuntimeRecord {\n\treadonly agentId: string;\n\treadonly hmacKey: Buffer;\n\treadonly profile: ResolvedMcpPortalProfile;\n\treadonly profileName: string;\n}\n\nexport interface PortalApprovalAuditEvent {\n\treadonly agentId: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_portal_approval';\n\treadonly reason?: 'approval_token_invalid' | 'approval_token_missing' | 'no_approval_required';\n\treadonly timeMs: number;\n\treadonly verifierReason?: string;\n}\n\nasync function resolveAgentHmacKeyEntry(props: {\n\treadonly agent: McpPortalAgentConfig;\n\treadonly agentId: string;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<readonly [string, Buffer]> {\n\tconst envKey = props.envKeys.get(props.agentId);\n\tif (envKey !== undefined) {\n\t\treturn [props.agentId, envKey];\n\t}\n\tif (props.agent.hmacKey === undefined) {\n\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${props.agentId}\".`);\n\t}\n\tconst secretValue = await props.resolveSecret(props.agent.hmacKey);\n\tif (!/^[0-9a-f]+$/u.test(secretValue) || secretValue.length !== 64) {\n\t\tthrow new Error(`MCP Portal agent \"${props.agentId}\" HMAC key must be 64 hex characters.`);\n\t}\n\treturn [props.agentId, Buffer.from(secretValue, 'hex')];\n}\n\nexport async function resolveAgentHmacKeys(\n\tprops: ResolveAgentHmacKeysProps,\n): Promise<ReadonlyMap<string, Buffer>> {\n\treturn new Map(\n\t\tawait Promise.all(\n\t\t\tObject.entries(props.agents).map(([agentId, agent]) =>\n\t\t\t\tresolveAgentHmacKeyEntry({\n\t\t\t\t\tagent,\n\t\t\t\t\tagentId,\n\t\t\t\t\tenvKeys: props.envKeys,\n\t\t\t\t\tresolveSecret: props.resolveSecret,\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t);\n}\n\nexport function createPortalAgentRuntimeRecords(props: {\n\treadonly hmacKeys: ReadonlyMap<string, Buffer>;\n\treadonly portalConfig: McpPortalConfig;\n}): ReadonlyMap<string, PortalAgentRuntimeRecord> {\n\tconst records = new Map<string, PortalAgentRuntimeRecord>();\n\tfor (const [agentId, agent] of Object.entries(props.portalConfig.agents)) {\n\t\tconst hmacKey = props.hmacKeys.get(agentId);\n\t\tif (hmacKey === undefined) {\n\t\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\trecords.set(agentId, {\n\t\t\tagentId,\n\t\t\thmacKey,\n\t\t\tprofile: resolveMcpPortalProfile(props.portalConfig, agent.profile),\n\t\t\tprofileName: agent.profile,\n\t\t});\n\t}\n\treturn records;\n}\n\nexport function createPortalHttpAgentResolver(\n\trecords: ReadonlyMap<string, PortalAgentRuntimeRecord>,\n): (agentId: string) => ReturnType<typeof createPortalAgentIdentity> | null {\n\treturn (agentId) => {\n\t\tconst record = records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn createPortalAgentIdentity({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'mcp-proxy-bearer',\n\t\t});\n\t};\n}\n\nfunction approvalRequiredByProfile(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: PortalApprovalCall,\n): boolean {\n\tconst annotations = call.tool.annotations;\n\treturn mcpPortalCallRequiresApproval(profile, {\n\t\t...(annotations === undefined ? {} : { annotations }),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t});\n}\n\nfunction approvalTokenCallDigests(calls: readonly PortalApprovalCall[]): readonly {\n\treadonly argumentsHash: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}[] {\n\treturn calls.map((call) => ({\n\t\targumentsHash: hashCallArguments(call.arguments),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t}));\n}\n\nexport function createPortalApprovalVerifier(props: {\n\treadonly approvalTokenReplayCacheLimit?: number;\n\treadonly auditErrorSink?: (error: Error, event: PortalApprovalAuditEvent) => void;\n\treadonly auditSink?: (event: PortalApprovalAuditEvent) => void;\n\treadonly records: ReadonlyMap<string, PortalAgentRuntimeRecord>;\n}): (\n\tcalls: readonly PortalApprovalCall[],\n\tagentId: string,\n\ttoken: string | undefined,\n) =>\n\t| { readonly kind: 'allow' }\n\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t| { readonly kind: 'approval_token_missing' } {\n\tfunction auditApproval(event: Omit<PortalApprovalAuditEvent, 'kind' | 'timeMs'>): void {\n\t\tconst auditEvent = { ...event, kind: 'mcp_portal_approval', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tprops.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tprops.auditErrorSink?.(error instanceof Error ? error : new Error(String(error)), auditEvent);\n\t\t}\n\t}\n\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = props.approvalTokenReplayCacheLimit ?? approvalTokenReplayCacheLimit;\n\tconst consumeTokenId = (\n\t\tagentId: string,\n\t\tjti: string,\n\t\texpiresAtMs: number,\n\t):\n\t\t| { readonly ok: true }\n\t\t| { readonly ok: false; readonly reason: 'replay-cache-full' | 'replayed' } => {\n\t\tconst nowMs = Date.now();\n\t\tfor (const [tokenKey, tokenExpiresAtMs] of consumedApprovalTokenIds) {\n\t\t\tif (tokenExpiresAtMs <= nowMs) {\n\t\t\t\tconsumedApprovalTokenIds.delete(tokenKey);\n\t\t\t}\n\t\t}\n\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t}\n\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t}\n\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\treturn { ok: true };\n\t};\n\treturn (calls, agentId, token) => {\n\t\tconst record = props.records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\tauditApproval({\n\t\t\t\tagentId,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'approval_token_invalid',\n\t\t\t\tverifierReason: 'unknown-agent',\n\t\t\t});\n\t\t\treturn { kind: 'approval_token_invalid', reason: 'unknown-agent' };\n\t\t}\n\t\tconst callsRequiringApproval = calls.filter((call) =>\n\t\t\tapprovalRequiredByProfile(record.profile, call),\n\t\t);\n\t\tif (callsRequiringApproval.length === 0) {\n\t\t\tauditApproval({ agentId, decision: 'allow', reason: 'no_approval_required' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tif (token === undefined) {\n\t\t\tauditApproval({ agentId, decision: 'deny', reason: 'approval_token_missing' });\n\t\t\treturn { kind: 'approval_token_missing' };\n\t\t}\n\t\tconst verificationProps = {\n\t\t\tagentId,\n\t\t\tcalls: approvalTokenCallDigests(callsRequiringApproval),\n\t\t\tconsumeTokenId: (jti: string, expiresAtMs: number) =>\n\t\t\t\tconsumeTokenId(agentId, jti, expiresAtMs),\n\t\t\tkey: record.hmacKey,\n\t\t\tmaxLifetimeMs: approvalTokenMaxLifetimeMs,\n\t\t\tnowMs: Date.now(),\n\t\t\ttoken,\n\t\t};\n\t\tconst verification = verifyApprovalToken(verificationProps);\n\t\tif (verification.ok) {\n\t\t\tauditApproval({ agentId, decision: 'allow' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tauditApproval({\n\t\t\tagentId,\n\t\t\tdecision: 'deny',\n\t\t\treason: 'approval_token_invalid',\n\t\t\tverifierReason: verification.reason,\n\t\t});\n\t\treturn { kind: 'approval_token_invalid', reason: verification.reason };\n\t};\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { t as createUpstreamMcpClientRuntime } from "./upstream-mcp-client-runtime-DbPkS6Rk.js";
2
- import { i as resolveUpstreamServers, n as createPortalCore } from "./portal-core-BPSvDGvi.js";
1
+ import { t as createUpstreamMcpClientRuntime } from "./upstream-mcp-client-runtime-Be_cw6pV.js";
2
+ import { i as resolveUpstreamServers, n as createPortalCore } from "./portal-core-B5cRpZMG.js";
3
3
  import { t as decodePortalMasterKey } from "./agent-bearer-token-DCtpDPCZ.js";
4
- import { a as createPortalHttpApp, n as createPortalApprovalVerifier, r as createPortalHttpAgentResolver, t as createPortalAgentRuntimeRecords } from "./resolve-agent-identity-DnC_Pmnh.js";
4
+ import { a as createPortalHttpApp, n as createPortalApprovalVerifier, r as createPortalHttpAgentResolver, t as createPortalAgentRuntimeRecords } from "./resolve-agent-identity-ZMMY2Wqm.js";
5
5
  import { createHmac } from "node:crypto";
6
6
  import { loadMcpConfig, loadMcpPortalConfig, resolveMcpPortalProfile } from "@agent-vm/config-contracts";
7
7
  import { join } from "node:path";
@@ -175,20 +175,20 @@ function selectorsFromNamespaceTools(namespaceTools) {
175
175
  }
176
176
  function buildProfilePolicyMaps(portalConfig) {
177
177
  const enabledNamespacesByAgent = {};
178
- const enabledToolsByAgent = {};
178
+ const enabledToolsByNamespaceByAgent = {};
179
179
  const hiddenToolsByAgent = {};
180
180
  const profileTtls = [];
181
181
  for (const [agentId, agent] of Object.entries(portalConfig.agents)) {
182
182
  const profile = resolveMcpPortalProfile(portalConfig, agent.profile);
183
183
  enabledNamespacesByAgent[agentId] = profile.enabledNamespaces;
184
- enabledToolsByAgent[agentId] = selectorsFromNamespaceTools(profile.enabledToolsByNamespace);
184
+ enabledToolsByNamespaceByAgent[agentId] = profile.enabledToolsByNamespace;
185
185
  hiddenToolsByAgent[agentId] = selectorsFromNamespaceTools(profile.hiddenToolsByNamespace);
186
186
  profileTtls.push(profile.cache.catalogTtlMs);
187
187
  }
188
188
  return {
189
189
  cacheTtlMs: profileTtls.length === 0 ? 6e4 : Math.min(...profileTtls),
190
190
  enabledNamespacesByAgent,
191
- enabledToolsByAgent,
191
+ enabledToolsByNamespaceByAgent,
192
192
  hiddenToolsByAgent
193
193
  };
194
194
  }
@@ -279,7 +279,7 @@ async function startPortalServer(props) {
279
279
  accessPolicy: {
280
280
  defaultPolicy: "deny-all",
281
281
  enabledNamespacesByAgent: profilePolicyMaps.enabledNamespacesByAgent,
282
- enabledToolsByAgent: profilePolicyMaps.enabledToolsByAgent,
282
+ enabledToolsByNamespaceByAgent: profilePolicyMaps.enabledToolsByNamespaceByAgent,
283
283
  hiddenToolsByAgent: profilePolicyMaps.hiddenToolsByAgent
284
284
  },
285
285
  approval: (calls, identity, approvalToken) => verifyApproval(calls, identity.agentId, approvalToken),
@@ -355,4 +355,4 @@ async function startPortalServer(props) {
355
355
  //#endregion
356
356
  export { handlePortalServerError as a, resolveSecretValue as c, deriveApprovalHmacKeysFromMasterKey as i, buildProfilePolicyMaps as n, parsePortalServerCliArgs as o, createServeSecretResolver as r, startPortalServer as s, applyAgentOverrides as t };
357
357
 
358
- //# sourceMappingURL=serve-command-CV1s-Eln.js.map
358
+ //# sourceMappingURL=serve-command-Dz6nvnzQ.js.map