@agent-vm/mcp-portal 0.0.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +34 -0
- package/dist/bin/agent-vm-mcp-portal.d.ts +10 -0
- package/dist/bin/agent-vm-mcp-portal.d.ts.map +1 -0
- package/dist/bin/agent-vm-mcp-portal.js +56 -0
- package/dist/bin/agent-vm-mcp-portal.js.map +1 -0
- package/dist/bin/portal-server.d.ts +54 -0
- package/dist/bin/portal-server.d.ts.map +1 -0
- package/dist/bin/portal-server.js +277 -0
- package/dist/bin/portal-server.js.map +1 -0
- package/dist/catalog-types--gUGFPpN.d.ts +44 -0
- package/dist/catalog-types--gUGFPpN.d.ts.map +1 -0
- package/dist/index-BcI9c8sg.d.ts +42 -0
- package/dist/index-BcI9c8sg.d.ts.map +1 -0
- package/dist/index.d.ts +485 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/tool-vm/index.d.ts +2 -0
- package/dist/tool-vm/index.js +4 -0
- package/dist/tool-vm-ihnzDyjJ.js +3 -0
- package/dist/typescript-artifact-BqU8okQy.js +160 -0
- package/dist/typescript-artifact-BqU8okQy.js.map +1 -0
- package/dist/upstream-mcp-client-runtime-DiBCBsDj.js +1729 -0
- package/dist/upstream-mcp-client-runtime-DiBCBsDj.js.map +1 -0
- package/dist/zod-schema-loader-CDDtoRE1.js +90 -0
- package/dist/zod-schema-loader-CDDtoRE1.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upstream-mcp-client-runtime-DiBCBsDj.js","names":["objectPropertiesFromSchema","messageFromError"],"sources":["../src/auth/hmac-env.ts","../src/auth/hmac-token.ts","../src/mcp-server/portal-call-validation.ts","../src/portal-access-policy.ts","../src/tool-summary.ts","../src/mcp-server/portal-tools.ts","../src/mcp-server/portal-mcp-server.ts","../src/mcp-server/portal-http-server.ts","../src/mcp-server/resolve-agent-identity.ts","../src/search-index.ts","../src/tool-graph.ts","../src/portal-session.ts","../src/upstream-response-middleware.ts","../src/upstream-mcp-client-runtime.ts"],"sourcesContent":["const portalHmacKeyEnvPrefix = 'PORTAL_HMAC_KEY__';\nconst portalHmacKeyHexLength = 64;\n\nexport function portalHmacKeyEnvName(agentId: string): string {\n\treturn `${portalHmacKeyEnvPrefix}${agentId}`;\n}\n\nexport function parseHmacKeysFromEnv(\n\tenv: Readonly<Record<string, string | undefined>>,\n): ReadonlyMap<string, Buffer> {\n\tconst keysByAgent = new Map<string, Buffer>();\n\tfor (const [name, value] of Object.entries(env)) {\n\t\tif (!name.startsWith(portalHmacKeyEnvPrefix) || value === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst agentId = name.slice(portalHmacKeyEnvPrefix.length);\n\t\tif (!/^[0-9a-f]+$/u.test(value) || value.length !== portalHmacKeyHexLength) {\n\t\t\tthrow new Error(`Malformed HMAC key in env var \"${name}\".`);\n\t\t}\n\t\tkeysByAgent.set(agentId, Buffer.from(value, 'hex'));\n\t}\n\treturn keysByAgent;\n}\n","import { createHash, createHmac, timingSafeEqual } from 'node:crypto';\n\nimport { z } from 'zod';\n\nexport interface ApprovalTokenCallDigest {\n\treadonly argumentsHash: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}\n\nexport interface SignApprovalTokenProps {\n\treadonly agentId: string;\n\treadonly calls: readonly ApprovalTokenCallDigest[];\n\treadonly expiresAtMs: number;\n\treadonly key: Buffer;\n}\n\nexport interface VerifyApprovalTokenProps {\n\treadonly agentId: string;\n\treadonly calls: readonly ApprovalTokenCallDigest[];\n\treadonly key: Buffer;\n\treadonly nowMs: number;\n\treadonly token: string;\n}\n\nexport type VerifyApprovalTokenResult =\n\t| { readonly ok: true }\n\t| {\n\t\t\treadonly ok: false;\n\t\t\treadonly reason:\n\t\t\t\t| 'agent-mismatch'\n\t\t\t\t| 'call-mismatch'\n\t\t\t\t| 'expired'\n\t\t\t\t| 'malformed'\n\t\t\t\t| 'signature-mismatch';\n\t };\n\nconst approvalTokenCallDigestSchema = z\n\t.object({\n\t\targumentsHash: z.string().min(1),\n\t\tnamespace: z.string().min(1),\n\t\ttoolName: z.string().min(1),\n\t})\n\t.strict();\n\nconst approvalTokenPayloadSchema = z\n\t.object({\n\t\tagentId: z.string().min(1),\n\t\tcalls: z.array(approvalTokenCallDigestSchema),\n\t\texp: z.number().int(),\n\t})\n\t.strict();\n\ntype ApprovalTokenPayload = z.infer<typeof approvalTokenPayloadSchema>;\n\nfunction base64UrlEncode(value: Buffer | string): string {\n\tconst buffer = typeof value === 'string' ? Buffer.from(value, 'utf8') : value;\n\treturn buffer.toString('base64url');\n}\n\nfunction canonicalize(value: unknown): string {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn JSON.stringify(value ?? null);\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn `[${value.map(canonicalize).join(',')}]`;\n\t}\n\tconst entries = Object.entries(value)\n\t\t.filter((entry) => entry[1] !== undefined)\n\t\t.toSorted(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey))\n\t\t.map(([key, entryValue]) => `${JSON.stringify(key)}:${canonicalize(entryValue)}`);\n\treturn `{${entries.join(',')}}`;\n}\n\nexport function hashCallArguments(args: unknown): string {\n\treturn createHash('sha256').update(canonicalize(args)).digest('base64url');\n}\n\nexport function signApprovalToken(props: SignApprovalTokenProps): string {\n\tconst payload = {\n\t\tagentId: props.agentId,\n\t\tcalls: [...props.calls],\n\t\texp: props.expiresAtMs,\n\t} satisfies ApprovalTokenPayload;\n\tconst payloadEncoded = base64UrlEncode(canonicalize(payload));\n\tconst signature = createHmac('sha256', props.key).update(payloadEncoded).digest('base64url');\n\treturn `${payloadEncoded}.${signature}`;\n}\n\nfunction parseApprovalTokenPayload(payloadEncoded: string): ApprovalTokenPayload | null {\n\ttry {\n\t\treturn approvalTokenPayloadSchema.parse(\n\t\t\tJSON.parse(Buffer.from(payloadEncoded, 'base64url').toString('utf8')),\n\t\t);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction isApprovalTokenParts(parts: readonly string[]): parts is readonly [string, string] {\n\treturn parts.length === 2;\n}\n\nfunction callsMatch(\n\tleftCalls: readonly ApprovalTokenCallDigest[],\n\trightCalls: readonly ApprovalTokenCallDigest[],\n): boolean {\n\tif (leftCalls.length !== rightCalls.length) {\n\t\treturn false;\n\t}\n\treturn leftCalls.every((leftCall, index) => {\n\t\tconst rightCall = rightCalls[index];\n\t\treturn (\n\t\t\trightCall !== undefined &&\n\t\t\tleftCall.argumentsHash === rightCall.argumentsHash &&\n\t\t\tleftCall.namespace === rightCall.namespace &&\n\t\t\tleftCall.toolName === rightCall.toolName\n\t\t);\n\t});\n}\n\nexport function verifyApprovalToken(props: VerifyApprovalTokenProps): VerifyApprovalTokenResult {\n\tconst parts = props.token.split('.');\n\tif (!isApprovalTokenParts(parts)) {\n\t\treturn { ok: false, reason: 'malformed' };\n\t}\n\tconst [payloadEncoded, signatureEncoded] = parts;\n\tconst expectedSignature = createHmac('sha256', props.key).update(payloadEncoded).digest();\n\tconst providedSignature = Buffer.from(signatureEncoded, 'base64url');\n\tif (\n\t\tprovidedSignature.length !== expectedSignature.length ||\n\t\t!timingSafeEqual(providedSignature, expectedSignature)\n\t) {\n\t\treturn { ok: false, reason: 'signature-mismatch' };\n\t}\n\n\tconst payload = parseApprovalTokenPayload(payloadEncoded);\n\tif (payload === null) {\n\t\treturn { ok: false, reason: 'malformed' };\n\t}\n\tif (payload.exp <= props.nowMs) {\n\t\treturn { ok: false, reason: 'expired' };\n\t}\n\tif (payload.agentId !== props.agentId) {\n\t\treturn { ok: false, reason: 'agent-mismatch' };\n\t}\n\tif (!callsMatch(payload.calls, props.calls)) {\n\t\treturn { ok: false, reason: 'call-mismatch' };\n\t}\n\treturn { ok: true };\n}\n","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","const portalAgentIdentityBrand = Symbol('PortalAgentIdentity');\n\nexport type PortalAgentIdentity = {\n\treadonly agentId: string;\n\treadonly agentScopeId: string;\n\treadonly sessionId?: string;\n\treadonly [portalAgentIdentityBrand]: true;\n};\n\nexport interface PortalToolSelector {\n\treadonly namespace: string;\n\treadonly toolName: string;\n}\n\nexport type PortalDefaultPolicy = 'allow-all' | 'deny-all';\n\nexport interface PortalAccessPolicyConfig {\n\treadonly defaultPolicy?: PortalDefaultPolicy;\n\treadonly enabledNamespaces?: readonly string[];\n\treadonly enabledNamespacesByAgent: Readonly<Record<string, readonly string[]>>;\n\treadonly enabledToolsByAgent?: Readonly<Record<string, readonly PortalToolSelector[]>>;\n\treadonly hiddenToolsByAgent: Readonly<Record<string, readonly PortalToolSelector[]>>;\n}\n\nexport interface ResolvedPortalAccessPolicy {\n\treadonly allowedNamespaces: readonly string[];\n\treadonly enabledTools: readonly PortalToolSelector[];\n\treadonly hiddenTools: readonly PortalToolSelector[];\n}\n\nexport function createPortalAgentIdentity(input: {\n\treadonly agentId: string;\n\treadonly agentScopeId: string;\n\treadonly sessionId?: string;\n}): PortalAgentIdentity {\n\tvalidateIdentitySegment('agentId', input.agentId);\n\tvalidateIdentitySegment('agentScopeId', input.agentScopeId);\n\tif (input.sessionId !== undefined) {\n\t\tvalidateIdentitySegment('sessionId', input.sessionId);\n\t}\n\treturn {\n\t\tagentId: input.agentId,\n\t\tagentScopeId: input.agentScopeId,\n\t\t...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),\n\t\t[portalAgentIdentityBrand]: true,\n\t};\n}\n\nfunction validateIdentitySegment(name: string, value: string): void {\n\tif (value.length === 0) {\n\t\tthrow new Error(`MCP Portal ${name} must not be empty.`);\n\t}\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst codePoint = value.charCodeAt(index);\n\t\tif (codePoint < 32 || codePoint === 127) {\n\t\t\tthrow new Error(`MCP Portal ${name} must not contain control characters.`);\n\t\t}\n\t}\n}\n\nexport function portalAgentScopeKey(identity: PortalAgentIdentity): string {\n\treturn identity.sessionId\n\t\t? `${identity.agentScopeId}\\n${identity.sessionId}`\n\t\t: identity.agentScopeId;\n}\n\nfunction sortToolSelectors(\n\tselectors: readonly PortalToolSelector[],\n): readonly PortalToolSelector[] {\n\treturn [...selectors].toSorted((left, right) => {\n\t\tconst namespaceOrder = left.namespace.localeCompare(right.namespace);\n\t\treturn namespaceOrder === 0 ? left.toolName.localeCompare(right.toolName) : namespaceOrder;\n\t});\n}\n\nexport function resolvePortalAccessPolicy(props: {\n\treadonly config: PortalAccessPolicyConfig;\n\treadonly identity: PortalAgentIdentity;\n\treadonly upstreamNamespaces: readonly string[];\n}): ResolvedPortalAccessPolicy {\n\tconst agentNamespaces = props.config.enabledNamespacesByAgent[props.identity.agentId];\n\tconst globalNamespaces = props.config.enabledNamespaces ?? [];\n\tconst selectedNamespaces =\n\t\tagentNamespaces ??\n\t\t(globalNamespaces.length > 0\n\t\t\t? globalNamespaces\n\t\t\t: props.config.defaultPolicy === 'allow-all'\n\t\t\t\t? props.upstreamNamespaces\n\t\t\t\t: []);\n\tconst upstreamNamespaceSet = new Set(props.upstreamNamespaces);\n\n\treturn {\n\t\tallowedNamespaces: selectedNamespaces\n\t\t\t.filter((namespace) => upstreamNamespaceSet.has(namespace))\n\t\t\t.toSorted(),\n\t\tenabledTools: sortToolSelectors(\n\t\t\tprops.config.enabledToolsByAgent?.[props.identity.agentId] ?? [],\n\t\t),\n\t\thiddenTools: sortToolSelectors(props.config.hiddenToolsByAgent[props.identity.agentId] ?? []),\n\t};\n}\n","import { portalToolRecordSchema, type PortalToolRecord } from './catalog-types.js';\nimport type { JsonObject } from './json-schema.js';\nimport { encodeToolRef } from './tool-ref.js';\n\nexport interface ToolSchemaSummary {\n\treadonly optional: readonly string[];\n\treadonly propertyCount: number;\n\treadonly required: readonly string[];\n\treadonly type: string;\n}\n\nexport interface ToolSafetySummary {\n\treadonly destructiveHint?: boolean;\n\treadonly readOnlyHint?: boolean;\n}\n\nexport interface ToolSummary {\n\treadonly description?: string;\n\treadonly input: ToolSchemaSummary;\n\treadonly namespace: string;\n\treadonly output?: ToolSchemaSummary;\n\treadonly safety: ToolSafetySummary;\n\treadonly title?: string;\n\treadonly toolName: string;\n\treadonly toolRef: string;\n}\n\nfunction stringArrayFromValue(value: unknown): readonly string[] {\n\tif (!Array.isArray(value)) {\n\t\treturn [];\n\t}\n\n\treturn value.filter((entry): entry is string => typeof entry === 'string').toSorted();\n}\n\nfunction objectPropertiesFromSchema(schema: JsonObject): readonly string[] {\n\tconst properties = schema.properties;\n\tif (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {\n\t\treturn [];\n\t}\n\n\treturn Object.keys(properties).toSorted();\n}\n\nexport function summarizeJsonSchema(schema: JsonObject): ToolSchemaSummary {\n\tconst properties = objectPropertiesFromSchema(schema);\n\tconst required = stringArrayFromValue(schema.required);\n\tconst requiredSet = new Set(required);\n\tconst optional = properties.filter((propertyName) => !requiredSet.has(propertyName));\n\n\treturn {\n\t\toptional,\n\t\tpropertyCount: properties.length,\n\t\trequired,\n\t\ttype: typeof schema.type === 'string' ? schema.type : 'unknown',\n\t};\n}\n\nexport function createToolSummary(tool: PortalToolRecord): ToolSummary {\n\tconst parsed = portalToolRecordSchema.parse(tool);\n\tconst safety = {\n\t\t...(parsed.annotations?.destructiveHint !== undefined\n\t\t\t? { destructiveHint: parsed.annotations.destructiveHint }\n\t\t\t: {}),\n\t\t...(parsed.annotations?.readOnlyHint !== undefined\n\t\t\t? { readOnlyHint: parsed.annotations.readOnlyHint }\n\t\t\t: {}),\n\t};\n\n\treturn {\n\t\t...(parsed.description !== undefined ? { description: parsed.description } : {}),\n\t\tinput: summarizeJsonSchema(parsed.inputSchema),\n\t\tnamespace: parsed.namespace,\n\t\t...(parsed.outputSchema ? { output: summarizeJsonSchema(parsed.outputSchema) } : {}),\n\t\tsafety,\n\t\t...(parsed.title !== undefined ? { title: parsed.title } : {}),\n\t\ttoolName: parsed.toolName,\n\t\ttoolRef: encodeToolRef({ namespace: parsed.namespace, toolName: parsed.toolName }),\n\t};\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 type { PortalSession } from '../portal-session.js';\nimport type { ToolSearchResult } from '../search-index.js';\nimport { decodeToolRef } from '../tool-ref.js';\nimport { createToolSummary, type ToolSummary } from '../tool-summary.js';\nimport { generateTypescriptCatalogArtifact } from '../tool-vm/typescript-artifact.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 kind: string;\n\treadonly message: string;\n\treadonly namespace?: string;\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\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 toolName: string;\n}\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\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\tkind: 'upstream_discovery_failed',\n\t\tmessage: failure.message,\n\t\tnamespace: failure.namespace,\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\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\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 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) => 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;\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\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\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},\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 { readonly kind: 'allow' };\n\t\t\tconst approval =\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) ?? allowDecision);\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\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","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 { PortalAgentIdentity } from '../portal-access-policy.js';\nimport {\n\tcreatePortalToolHandlers,\n\tportalToolInputSchemas,\n\ttype PortalBatchResult,\n\ttype PortalToolRuntime,\n} from './portal-tools.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\nexport function listPortalMcpTools(): readonly Tool[] {\n\treturn [\n\t\t{\n\t\t\tdescription: 'List authorized MCP namespaces and compact tool summaries.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_list,\n\t\t\tname: 'mcp_portal_list',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\tname: 'mcp_portal_search',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\tname: 'mcp_portal_describe',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\tname: 'mcp_portal_call',\n\t\t},\n\t];\n}\n\nfunction jsonToolResult(value: PortalBatchResult): CallToolResult {\n\treturn {\n\t\tcontent: [{ text: JSON.stringify(value), type: 'text' }],\n\t\t...(value.ok ? {} : { isError: true }),\n\t};\n}\n\nexport function createPortalMcpServer(props: {\n\treadonly identity: PortalAgentIdentity;\n\treadonly runtime: PortalToolRuntime;\n}): Server {\n\tconst handlers = createPortalToolHandlers(props.runtime);\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(),\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n\t\tswitch (request.params.name) {\n\t\t\tcase 'mcp_portal_list':\n\t\t\t\treturn jsonToolResult(\n\t\t\t\t\tawait handlers.list({ identity: props.identity, input: request.params.arguments ?? {} }),\n\t\t\t\t);\n\t\t\tcase 'mcp_portal_search':\n\t\t\t\treturn jsonToolResult(\n\t\t\t\t\tawait handlers.search({\n\t\t\t\t\t\tidentity: props.identity,\n\t\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\tcase 'mcp_portal_describe':\n\t\t\t\treturn jsonToolResult(\n\t\t\t\t\tawait handlers.describe({\n\t\t\t\t\t\tidentity: props.identity,\n\t\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\tcase 'mcp_portal_call':\n\t\t\t\treturn jsonToolResult(\n\t\t\t\t\tawait handlers.call({ identity: props.identity, input: request.params.arguments ?? {} }),\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ text: `Unknown MCP Portal tool: ${request.params.name}`, type: 'text' }],\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t}\n\t});\n\n\treturn server;\n}\n","import { randomUUID, timingSafeEqual } from 'node:crypto';\n\nimport { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';\nimport { Hono } from 'hono';\n\nimport { createPortalAgentIdentity, type PortalAgentIdentity } from '../portal-access-policy.js';\nimport { createPortalMcpServer } from './portal-mcp-server.js';\nimport type { PortalToolRuntime } from './portal-tools.js';\n\nexport interface PortalHttpAgentIdentity extends PortalAgentIdentity {}\n\nexport interface PortalServerAccess {\n\treadonly expectedValue: string;\n\treadonly headerName: string;\n}\n\nexport interface PortalHttpAppOptions {\n\treadonly onSessionClosed?: (identity: PortalAgentIdentity) => Promise<void> | void;\n\treadonly registeredAgentIds?: readonly string[];\n\treadonly resolveAgentIdentity?: (agentId: string) => PortalHttpAgentIdentity | null;\n\treadonly serverAccess?: PortalServerAccess;\n\treadonly toolRuntime: PortalToolRuntime;\n}\n\nexport type PortalHttpApp = Hono & {\n\treadonly closePortalSessions: () => Promise<void>;\n};\n\nconst mcpSessionIdHeader = 'mcp-session-id';\n\ninterface ActivePortalMcpSession {\n\treadonly identity: PortalAgentIdentity;\n\treadonly server: ReturnType<typeof createPortalMcpServer>;\n\treadonly transport: WebStandardStreamableHTTPServerTransport;\n}\n\nfunction timingSafeEqualString(left: string, right: string): boolean {\n\tconst leftBuffer = Buffer.from(left);\n\tconst rightBuffer = Buffer.from(right);\n\treturn leftBuffer.length === rightBuffer.length && timingSafeEqual(leftBuffer, rightBuffer);\n}\n\nfunction activeSessionKey(scopeId: string, sessionId: string): string {\n\treturn `${scopeId}\\n${sessionId}`;\n}\n\nexport function createPortalHttpApp(options: PortalHttpAppOptions): PortalHttpApp {\n\tconst app = new Hono();\n\tconst activeSessions = new Map<string, ActivePortalMcpSession>();\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\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});\n\t\tconst transport = new WebStandardStreamableHTTPServerTransport({\n\t\t\tonsessionclosed: () => {\n\t\t\t\tvoid closeActiveSession(sessionKey, { closeTransport: false });\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\tidentity,\n\t\t\truntime: options.toolRuntime,\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\tawait Promise.all(\n\t\t\t[...activeSessions.keys()].map((sessionKey) =>\n\t\t\t\tcloseActiveSession(sessionKey, { closeTransport: true }),\n\t\t\t),\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 serverAccess = options.serverAccess;\n\t\tif (serverAccess !== undefined) {\n\t\t\tconst providedSecret = context.req.header(serverAccess.headerName);\n\t\t\tif (\n\t\t\t\tprovidedSecret === undefined ||\n\t\t\t\t!timingSafeEqualString(providedSecret, serverAccess.expectedValue)\n\t\t\t) {\n\t\t\t\treturn context.json({ error: { kind: 'unauthorized' }, ok: false }, 401);\n\t\t\t}\n\t\t}\n\n\t\tconst agentId = context.req.param('agentId');\n\t\tconst agentIdentity = options.resolveAgentIdentity?.(agentId) ?? null;\n\t\tif (agentIdentity === null) {\n\t\t\treturn context.json({ error: { kind: 'unknown_agent' }, ok: false }, 404);\n\t\t}\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.req.raw);\n\t\t}\n\n\t\tconst activeSession = await createActiveSession(agentIdentity);\n\t\treturn await activeSession.transport.handleRequest(context.req.raw);\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 { hashCallArguments, verifyApprovalToken } from '../auth/hmac-token.js';\nimport { createPortalAgentIdentity } from '../portal-access-policy.js';\nimport type { PortalApprovalCall } from './portal-tools.js';\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\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({ agentId, agentScopeId: agentId });\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 conservativeApprovalRequiredByProfile(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: PortalApprovalCall,\n): boolean {\n\treturn mcpPortalCallRequiresApproval(profile, {\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 interface ConservativeApprovalFallbackEvent {\n\treadonly agentId: string;\n\treadonly primaryReason: string;\n\treadonly strictCallCount: number;\n\treadonly conservativeCallCount: number;\n\treadonly toolRefs: readonly string[];\n}\n\nexport function createPortalApprovalVerifier(props: {\n\treadonly onConservativeApprovalFallback?: (event: ConservativeApprovalFallbackEvent) => 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\treturn (calls, agentId, token) => {\n\t\tconst record = props.records.get(agentId);\n\t\tif (record === undefined) {\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\treturn { kind: 'allow' };\n\t\t}\n\t\tif (token === undefined) {\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\tkey: record.hmacKey,\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\treturn { kind: 'allow' };\n\t\t}\n\t\tconst conservativeCallsRequiringApproval = calls.filter((call) =>\n\t\t\tconservativeApprovalRequiredByProfile(record.profile, call),\n\t\t);\n\t\tif (conservativeCallsRequiringApproval.length !== callsRequiringApproval.length) {\n\t\t\tconst conservativeVerification = verifyApprovalToken({\n\t\t\t\t...verificationProps,\n\t\t\t\tcalls: approvalTokenCallDigests(conservativeCallsRequiringApproval),\n\t\t\t});\n\t\t\tif (conservativeVerification.ok) {\n\t\t\t\tprops.onConservativeApprovalFallback?.({\n\t\t\t\t\tagentId,\n\t\t\t\t\tconservativeCallCount: conservativeCallsRequiringApproval.length,\n\t\t\t\t\tprimaryReason: verification.reason,\n\t\t\t\t\tstrictCallCount: callsRequiringApproval.length,\n\t\t\t\t\ttoolRefs: conservativeCallsRequiringApproval.map(\n\t\t\t\t\t\t(call) => `${call.namespace}/${call.toolName}`,\n\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\treturn { kind: 'allow' };\n\t\t\t}\n\t\t}\n\t\treturn { kind: 'approval_token_invalid', reason: verification.reason };\n\t};\n}\n","import { portalToolRecordSchema, type PortalToolRecord } from './catalog-types.js';\nimport type { JsonObject, JsonValue } from './json-schema.js';\nimport type { ToolGraph, ToolRelationship } from './tool-graph.js';\nimport { createToolSummary, type ToolSummary } from './tool-summary.js';\n\nexport interface SearchQuery {\n\treadonly limit: number;\n\treadonly namespaces?: readonly string[];\n\treadonly query?: string;\n}\n\nexport interface SearchResultSet {\n\treadonly results: readonly ToolSearchResult[];\n}\n\nexport interface SearchIndex {\n\treadonly search: (query: SearchQuery) => SearchResultSet;\n}\n\ninterface SearchEntry {\n\treadonly inputFields: readonly string[];\n\treadonly relationshipHints: readonly ToolRelationshipHint[];\n\treadonly searchText: string;\n\treadonly summary: ToolSearchResult;\n}\n\nexport interface ToolRelationshipHint {\n\treadonly field?: string;\n\treadonly reason: string;\n\treadonly sourceToolRef: string;\n\treadonly type: ToolRelationship['type'];\n}\n\nexport interface ToolSearchResult extends ToolSummary {\n\treadonly relationshipHints?: readonly ToolRelationshipHint[];\n\treadonly schemaFieldMatches?: readonly string[];\n}\n\nfunction collectSchemaText(value: JsonValue, parts: string[]): void {\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) {\n\t\t\tcollectSchemaText(item, parts);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (typeof value !== 'object' || value === null) {\n\t\tif (typeof value === 'string') {\n\t\t\tparts.push(value);\n\t\t}\n\t\treturn;\n\t}\n\n\tfor (const [key, childValue] of Object.entries(value)) {\n\t\tparts.push(key);\n\t\tcollectSchemaText(childValue, parts);\n\t}\n}\n\nfunction normalizeSearchText(text: string): string {\n\treturn text.toLowerCase().replace(/[_-]/g, ' ');\n}\n\nfunction buildSearchText(tool: PortalToolRecord): string {\n\tconst parts = [tool.namespace, tool.toolName, tool.title ?? '', tool.description ?? ''];\n\tcollectSchemaText(tool.inputSchema, parts);\n\tif (tool.outputSchema) {\n\t\tcollectSchemaText(tool.outputSchema, parts);\n\t}\n\n\treturn normalizeSearchText(parts.join(' '));\n}\n\nfunction propertiesFromSchema(schema: JsonObject): readonly string[] {\n\tconst properties = schema.properties;\n\tif (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {\n\t\treturn [];\n\t}\n\n\treturn Object.keys(properties).toSorted();\n}\n\nfunction createRelationshipHints(\n\ttool: PortalToolRecord,\n\trelationships: readonly ToolRelationship[],\n): readonly ToolRelationshipHint[] {\n\tconst targetToolRef = createToolSummary(tool).toolRef;\n\n\treturn relationships\n\t\t.filter((relationship) => relationship.to.toolRef === targetToolRef)\n\t\t.map((relationship) =>\n\t\t\trelationship.field === undefined\n\t\t\t\t? {\n\t\t\t\t\t\treason: relationship.reason,\n\t\t\t\t\t\tsourceToolRef: relationship.from.toolRef,\n\t\t\t\t\t\ttype: relationship.type,\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tfield: relationship.field,\n\t\t\t\t\t\treason: relationship.reason,\n\t\t\t\t\t\tsourceToolRef: relationship.from.toolRef,\n\t\t\t\t\t\ttype: relationship.type,\n\t\t\t\t\t},\n\t\t)\n\t\t.toSorted((left, right) => {\n\t\t\tconst typeOrder = left.type.localeCompare(right.type);\n\t\t\tif (typeOrder !== 0) {\n\t\t\t\treturn typeOrder;\n\t\t\t}\n\t\t\treturn left.sourceToolRef.localeCompare(right.sourceToolRef);\n\t\t});\n}\n\nfunction scopedSkillText(toolRef: string, graph?: ToolGraph): string {\n\tif (!graph) {\n\t\treturn '';\n\t}\n\n\treturn graph.skills\n\t\t.filter((skill) => skill.toolRefs.includes(toolRef))\n\t\t.map((skill) => [skill.title, skill.description ?? '', ...skill.tags].join(' '))\n\t\t.join(' ');\n}\n\nfunction scoreEntry(entry: SearchEntry, terms: readonly string[]): number {\n\tlet score = 0;\n\tfor (const term of terms) {\n\t\tif (entry.searchText.includes(term)) {\n\t\t\tscore += 1;\n\t\t}\n\t}\n\n\treturn score;\n}\n\nfunction compareSummaries(left: ToolSummary, right: ToolSummary): number {\n\tconst namespaceOrder = left.namespace.localeCompare(right.namespace);\n\tif (namespaceOrder !== 0) {\n\t\treturn namespaceOrder;\n\t}\n\n\treturn left.toolName.localeCompare(right.toolName);\n}\n\nfunction withRelationshipHints(\n\tsummary: ToolSummary,\n\trelationshipHints: readonly ToolRelationshipHint[],\n): ToolSearchResult {\n\tif (relationshipHints.length === 0) {\n\t\treturn summary;\n\t}\n\n\treturn {\n\t\t...(summary.description !== undefined ? { description: summary.description } : {}),\n\t\tinput: summary.input,\n\t\tnamespace: summary.namespace,\n\t\t...(summary.output !== undefined ? { output: summary.output } : {}),\n\t\trelationshipHints,\n\t\tsafety: summary.safety,\n\t\t...(summary.title !== undefined ? { title: summary.title } : {}),\n\t\ttoolName: summary.toolName,\n\t\ttoolRef: summary.toolRef,\n\t};\n}\n\nfunction withSchemaFieldMatches(\n\tsummary: ToolSearchResult,\n\tschemaFieldMatches: readonly string[],\n): ToolSearchResult {\n\tif (schemaFieldMatches.length === 0) {\n\t\treturn summary;\n\t}\n\n\treturn {\n\t\t...(summary.description !== undefined ? { description: summary.description } : {}),\n\t\tinput: summary.input,\n\t\tnamespace: summary.namespace,\n\t\t...(summary.output !== undefined ? { output: summary.output } : {}),\n\t\t...(summary.relationshipHints !== undefined\n\t\t\t? { relationshipHints: summary.relationshipHints }\n\t\t\t: {}),\n\t\tsafety: summary.safety,\n\t\tschemaFieldMatches,\n\t\t...(summary.title !== undefined ? { title: summary.title } : {}),\n\t\ttoolName: summary.toolName,\n\t\ttoolRef: summary.toolRef,\n\t};\n}\n\nexport function createSearchIndex(\n\ttools: readonly PortalToolRecord[],\n\tgraph?: ToolGraph,\n): SearchIndex {\n\tconst entries = tools\n\t\t.map((tool) => portalToolRecordSchema.parse(tool))\n\t\t.map((tool) => {\n\t\t\tconst summary = createToolSummary(tool);\n\t\t\tconst relationshipHints = createRelationshipHints(tool, graph?.relationships ?? []);\n\t\t\tconst inputFields = propertiesFromSchema(tool.inputSchema);\n\t\t\tconst relationText = relationshipHints\n\t\t\t\t.map((hint) => [hint.field ?? '', hint.reason, hint.sourceToolRef, hint.type].join(' '))\n\t\t\t\t.join(' ');\n\t\t\tconst skillText = scopedSkillText(summary.toolRef, graph);\n\n\t\t\treturn {\n\t\t\t\tinputFields,\n\t\t\t\trelationshipHints,\n\t\t\t\tsearchText: normalizeSearchText([buildSearchText(tool), relationText, skillText].join(' ')),\n\t\t\t\tsummary: withRelationshipHints(summary, relationshipHints),\n\t\t\t};\n\t\t})\n\t\t.toSorted((left, right) => compareSummaries(left.summary, right.summary));\n\n\treturn {\n\t\tsearch(query: SearchQuery): SearchResultSet {\n\t\t\tconst limit = Math.max(0, Math.floor(query.limit));\n\t\t\tconst namespaceFilter = new Set(query.namespaces ?? []);\n\t\t\tconst terms = normalizeSearchText(query.query ?? '')\n\t\t\t\t.split(/\\s+/)\n\t\t\t\t.map((term) => term.trim())\n\t\t\t\t.filter(Boolean);\n\t\t\tconst scoredEntries = entries\n\t\t\t\t.filter(\n\t\t\t\t\t(entry) => namespaceFilter.size === 0 || namespaceFilter.has(entry.summary.namespace),\n\t\t\t\t)\n\t\t\t\t.map((entry) => ({ entry, score: terms.length === 0 ? 1 : scoreEntry(entry, terms) }))\n\t\t\t\t.filter(({ score }) => score > 0)\n\t\t\t\t.toSorted((left, right) => {\n\t\t\t\t\tif (right.score !== left.score) {\n\t\t\t\t\t\treturn right.score - left.score;\n\t\t\t\t\t}\n\t\t\t\t\treturn compareSummaries(left.entry.summary, right.entry.summary);\n\t\t\t\t});\n\n\t\t\tconst results = scoredEntries.slice(0, limit).map(({ entry }) => {\n\t\t\t\tconst schemaFieldMatches = entry.inputFields\n\t\t\t\t\t.filter((fieldName) =>\n\t\t\t\t\t\tterms.some((term) => normalizeSearchText(fieldName).includes(term)),\n\t\t\t\t\t)\n\t\t\t\t\t.toSorted();\n\n\t\t\t\treturn withSchemaFieldMatches(entry.summary, schemaFieldMatches);\n\t\t\t});\n\n\t\t\treturn { results };\n\t\t},\n\t};\n}\n","import { portalToolRecordSchema, type PortalToolRecord } from './catalog-types.js';\nimport type { JsonObject } from './json-schema.js';\nimport { encodeToolRef, type ToolIdentity } from './tool-ref.js';\n\nexport type ToolRelationshipType = 'entity' | 'schema-field' | 'skill';\n\nexport interface ToolRelationshipEndpoint extends ToolIdentity {\n\treadonly toolRef: string;\n}\n\nexport interface ToolRelationship {\n\treadonly field?: string;\n\treadonly from: ToolRelationshipEndpoint;\n\treadonly reason: string;\n\treadonly to: ToolRelationshipEndpoint;\n\treadonly type: ToolRelationshipType;\n}\n\nexport interface SkillGraphInput {\n\treadonly description?: string;\n\treadonly tags?: readonly string[];\n\treadonly title: string;\n\treadonly toolRefs: readonly string[];\n}\n\nexport interface ScopedSkillGraphEntry {\n\treadonly description?: string;\n\treadonly tags: readonly string[];\n\treadonly title: string;\n\treadonly toolRefs: readonly string[];\n}\n\nexport interface ToolGraphInput {\n\treadonly skills?: readonly SkillGraphInput[];\n\treadonly tools: readonly PortalToolRecord[];\n}\n\nexport interface ToolGraph {\n\treadonly relationships: readonly ToolRelationship[];\n\treadonly skills: readonly ScopedSkillGraphEntry[];\n}\n\ninterface GraphTool {\n\treadonly entityNames: readonly string[];\n\treadonly inputFields: readonly string[];\n\treadonly outputFields: readonly string[];\n\treadonly record: PortalToolRecord;\n\treadonly ref: ToolRelationshipEndpoint;\n}\n\nconst genericLinkFields = new Set(['id', 'name', 'title', 'url', 'uri']);\n\nfunction compareCodePoint(left: string, right: string): number {\n\tif (left < right) {\n\t\treturn -1;\n\t}\n\tif (left > right) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nfunction objectPropertiesFromSchema(schema: JsonObject | undefined): readonly string[] {\n\tif (!schema) {\n\t\treturn [];\n\t}\n\n\tconst properties = schema.properties;\n\tif (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {\n\t\treturn [];\n\t}\n\n\treturn Object.keys(properties).toSorted();\n}\n\nfunction collectEntityNames(schema: JsonObject | undefined): readonly string[] {\n\tif (!schema) {\n\t\treturn [];\n\t}\n\n\tconst names: string[] = [];\n\tconst schemaId = schema.$id;\n\tconst title = schema.title;\n\tconst entityName = schema.entityName;\n\tif (typeof schemaId === 'string' && schemaId.length > 0) {\n\t\tnames.push(schemaId);\n\t}\n\tif (typeof title === 'string' && title.length > 0) {\n\t\tnames.push(title);\n\t}\n\tif (typeof entityName === 'string' && entityName.length > 0) {\n\t\tnames.push(entityName);\n\t}\n\n\treturn names.map((name) => name.toLowerCase()).toSorted();\n}\n\nfunction createGraphTool(tool: PortalToolRecord): GraphTool {\n\tconst record = portalToolRecordSchema.parse(tool);\n\tconst toolRef = encodeToolRef({ namespace: record.namespace, toolName: record.toolName });\n\n\treturn {\n\t\tentityNames: [\n\t\t\t...collectEntityNames(record.inputSchema),\n\t\t\t...collectEntityNames(record.outputSchema),\n\t\t].toSorted(),\n\t\tinputFields: objectPropertiesFromSchema(record.inputSchema),\n\t\toutputFields: objectPropertiesFromSchema(record.outputSchema),\n\t\trecord,\n\t\tref: {\n\t\t\tnamespace: record.namespace,\n\t\t\ttoolName: record.toolName,\n\t\t\ttoolRef,\n\t\t},\n\t};\n}\n\nfunction sharesEntity(left: GraphTool, right: GraphTool): boolean {\n\tconst rightEntities = new Set(right.entityNames);\n\treturn left.entityNames.some((entityName) => rightEntities.has(entityName));\n}\n\nfunction shouldLinkField(field: string, fromTool: GraphTool, toTool: GraphTool): boolean {\n\tif (!genericLinkFields.has(field.toLowerCase())) {\n\t\treturn true;\n\t}\n\n\treturn fromTool.record.namespace === toTool.record.namespace && sharesEntity(fromTool, toTool);\n}\n\nfunction createSchemaRelationships(tools: readonly GraphTool[]): readonly ToolRelationship[] {\n\tconst relationships: ToolRelationship[] = [];\n\n\tfor (const fromTool of tools) {\n\t\tfor (const toTool of tools) {\n\t\t\tif (fromTool.ref.toolRef === toTool.ref.toolRef) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst inputFields = new Set(toTool.inputFields);\n\t\t\tfor (const field of fromTool.outputFields) {\n\t\t\t\tif (!inputFields.has(field) || !shouldLinkField(field, fromTool, toTool)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\trelationships.push({\n\t\t\t\t\tfield,\n\t\t\t\t\tfrom: fromTool.ref,\n\t\t\t\t\treason: `Output field \"${field}\" matches input field \"${field}\".`,\n\t\t\t\t\tto: toTool.ref,\n\t\t\t\t\ttype: 'schema-field',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn relationships;\n}\n\nfunction createEntityRelationships(tools: readonly GraphTool[]): readonly ToolRelationship[] {\n\tconst relationships: ToolRelationship[] = [];\n\tfor (const fromTool of tools) {\n\t\tfor (const toTool of tools) {\n\t\t\tif (fromTool.ref.toolRef === toTool.ref.toolRef || !sharesEntity(fromTool, toTool)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\trelationships.push({\n\t\t\t\tfrom: fromTool.ref,\n\t\t\t\treason: 'Tools declare a shared schema entity through title, $id, or entityName.',\n\t\t\t\tto: toTool.ref,\n\t\t\t\ttype: 'entity',\n\t\t\t});\n\t\t}\n\t}\n\treturn relationships;\n}\n\nfunction createSkillEntries(\n\tskills: readonly SkillGraphInput[],\n\tallowedToolRefs: ReadonlySet<string>,\n): readonly ScopedSkillGraphEntry[] {\n\tconst entries: ScopedSkillGraphEntry[] = [];\n\tfor (const skill of skills) {\n\t\tconst scopedToolRefs = skill.toolRefs\n\t\t\t.filter((toolRef) => allowedToolRefs.has(toolRef))\n\t\t\t.toSorted();\n\t\tif (scopedToolRefs.length === 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tentries.push({\n\t\t\t...(skill.description !== undefined ? { description: skill.description } : {}),\n\t\t\ttags: [...(skill.tags ?? [])].toSorted(),\n\t\t\ttitle: skill.title,\n\t\t\ttoolRefs: scopedToolRefs,\n\t\t});\n\t}\n\n\treturn entries.toSorted((left, right) => left.title.localeCompare(right.title));\n}\n\nfunction createSkillRelationships(\n\tskills: readonly ScopedSkillGraphEntry[],\n\ttoolsByRef: ReadonlyMap<string, GraphTool>,\n): readonly ToolRelationship[] {\n\tconst relationships: ToolRelationship[] = [];\n\tfor (const skill of skills) {\n\t\tfor (const fromToolRef of skill.toolRefs) {\n\t\t\tfor (const toToolRef of skill.toolRefs) {\n\t\t\t\tif (fromToolRef === toToolRef) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst fromTool = toolsByRef.get(fromToolRef);\n\t\t\t\tconst toTool = toolsByRef.get(toToolRef);\n\t\t\t\tif (!fromTool || !toTool) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\trelationships.push({\n\t\t\t\t\tfrom: fromTool.ref,\n\t\t\t\t\treason: `Both tools are referenced by skill \"${skill.title}\".`,\n\t\t\t\t\tto: toTool.ref,\n\t\t\t\t\ttype: 'skill',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\treturn relationships;\n}\n\nfunction compareRelationships(left: ToolRelationship, right: ToolRelationship): number {\n\tconst typeOrder = compareCodePoint(left.type, right.type);\n\tif (typeOrder !== 0) {\n\t\treturn typeOrder;\n\t}\n\n\tconst targetOrder = compareCodePoint(left.to.toolRef, right.to.toolRef);\n\tif (targetOrder !== 0) {\n\t\treturn targetOrder;\n\t}\n\n\treturn compareCodePoint(left.from.toolRef, right.from.toolRef);\n}\n\nexport function buildToolGraph(input: ToolGraphInput): ToolGraph {\n\tconst tools = input.tools\n\t\t.map((tool) => createGraphTool(tool))\n\t\t.toSorted((left, right) => compareCodePoint(left.ref.toolRef, right.ref.toolRef));\n\tconst allowedToolRefs = new Set(tools.map((tool) => tool.ref.toolRef));\n\tconst skills = createSkillEntries(input.skills ?? [], allowedToolRefs);\n\tconst toolsByRef = new Map(tools.map((tool) => [tool.ref.toolRef, tool]));\n\n\treturn {\n\t\trelationships: [\n\t\t\t...createEntityRelationships(tools),\n\t\t\t...createSchemaRelationships(tools),\n\t\t\t...createSkillRelationships(skills, toolsByRef),\n\t\t].toSorted(compareRelationships),\n\t\tskills,\n\t};\n}\n","import { createHash } from 'node:crypto';\n\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\n\nimport { portalToolRecordSchema, type PortalToolRecord } from './catalog-types.js';\nimport {\n\tresolvePortalAccessPolicy,\n\tportalAgentScopeKey,\n\ttype PortalAccessPolicyConfig,\n\ttype PortalAgentIdentity,\n\ttype PortalToolSelector,\n} from './portal-access-policy.js';\nimport { createSearchIndex, type SearchIndex } from './search-index.js';\nimport { buildToolGraph, type SkillGraphInput, type ToolGraph } from './tool-graph.js';\n\nexport interface PortalCatalogSnapshot {\n\treadonly agentScopeId: string;\n\treadonly discoveryFailures: readonly PortalDiscoveryFailure[];\n\treadonly generatedAt: string;\n\treadonly sourceHash: string;\n\treadonly tools: readonly PortalToolRecord[];\n}\n\nexport interface PortalDiscoveryFailure {\n\treadonly message: string;\n\treadonly namespace: string;\n}\n\nexport interface PortalSession {\n\treadonly catalog: PortalCatalogSnapshot;\n\treadonly graph: ToolGraph;\n\treadonly identity: PortalAgentIdentity;\n\treadonly searchIndex: SearchIndex;\n}\n\nexport interface PortalSessionRuntime {\n\treadonly closeAgentScope: (agentScopeId: string) => Promise<void> | void;\n\treadonly closeSession?: (scopeKey: string) => Promise<void> | void;\n\treadonly listTools: (call: {\n\t\treadonly agentScopeId: string;\n\t\treadonly namespace: string;\n\t}) => Promise<readonly Tool[]>;\n}\n\nexport interface PortalSessionManagerOptions {\n\treadonly accessPolicy: PortalAccessPolicyConfig;\n\treadonly catalogTtlMs: number;\n\treadonly discoveryFailures?: readonly PortalDiscoveryFailure[];\n\treadonly now?: () => number;\n\treadonly runtime: PortalSessionRuntime;\n\treadonly skills?: readonly SkillGraphInput[];\n\treadonly upstreamNamespaces: readonly string[];\n}\n\nexport interface PortalSessionManager {\n\treadonly getSession: (identity: PortalAgentIdentity) => Promise<PortalSession>;\n\treadonly invalidateAgentScope: (agentScopeId: string) => Promise<void>;\n\treadonly invalidateSession: (identity: PortalAgentIdentity) => Promise<void>;\n}\n\ninterface CachedPortalSession {\n\treadonly expiresAt: number;\n\treadonly session: PortalSession;\n}\n\nfunction isHiddenTool(tool: PortalToolRecord, hiddenTools: readonly PortalToolSelector[]): boolean {\n\treturn hiddenTools.some(\n\t\t(hiddenTool) =>\n\t\t\thiddenTool.namespace === tool.namespace && hiddenTool.toolName === tool.toolName,\n\t);\n}\n\nfunction isEnabledTool(\n\ttool: PortalToolRecord,\n\tenabledTools: readonly PortalToolSelector[],\n): boolean {\n\tif (enabledTools.length === 0) {\n\t\treturn true;\n\t}\n\treturn enabledTools.some(\n\t\t(enabledTool) =>\n\t\t\tenabledTool.namespace === tool.namespace && enabledTool.toolName === tool.toolName,\n\t);\n}\n\nfunction portalToolFromMcpTool(namespace: string, tool: Tool): PortalToolRecord {\n\treturn portalToolRecordSchema.parse({\n\t\t...(tool.annotations !== undefined ? { annotations: tool.annotations } : {}),\n\t\t...(tool.description !== undefined ? { description: tool.description } : {}),\n\t\tinputSchema: tool.inputSchema,\n\t\tnamespace,\n\t\t...(tool.outputSchema !== undefined ? { outputSchema: tool.outputSchema } : {}),\n\t\t...(tool.title !== undefined ? { title: tool.title } : {}),\n\t\ttoolName: tool.name,\n\t});\n}\n\nfunction createSourceHash(tools: readonly PortalToolRecord[]): string {\n\treturn createHash('sha256').update(JSON.stringify(tools)).digest('hex');\n}\n\nfunction messageFromError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nexport function createPortalSessionManager(\n\toptions: PortalSessionManagerOptions,\n): PortalSessionManager {\n\tconst sessions = new Map<string, CachedPortalSession>();\n\tconst agentScopeGenerations = new Map<string, number>();\n\tconst getNow = options.now ?? (() => Date.now());\n\n\tfunction generationForAgentScope(agentScopeId: string): number {\n\t\treturn agentScopeGenerations.get(agentScopeId) ?? 0;\n\t}\n\n\tfunction incrementAgentScopeGeneration(agentScopeId: string): void {\n\t\tagentScopeGenerations.set(agentScopeId, generationForAgentScope(agentScopeId) + 1);\n\t}\n\n\tfunction generationForScope(scopeKey: string): number {\n\t\tconst agentScopeId = scopeKey.split('\\n', 1)[0] ?? scopeKey;\n\t\treturn (agentScopeGenerations.get(scopeKey) ?? 0) + generationForAgentScope(agentScopeId);\n\t}\n\n\tfunction incrementScopeGeneration(scopeKey: string): void {\n\t\tagentScopeGenerations.set(scopeKey, generationForScope(scopeKey) + 1);\n\t}\n\n\tasync function buildSession(identity: PortalAgentIdentity): Promise<PortalSession> {\n\t\tconst policy = resolvePortalAccessPolicy({\n\t\t\tconfig: options.accessPolicy,\n\t\t\tidentity,\n\t\t\tupstreamNamespaces: options.upstreamNamespaces,\n\t\t});\n\t\tconst tools: PortalToolRecord[] = [];\n\t\tconst discoveryFailures: PortalDiscoveryFailure[] = [...(options.discoveryFailures ?? [])];\n\t\tconst allowedNamespaces = policy.allowedNamespaces;\n\n\t\tconst namespaceToolGroups = await Promise.allSettled(\n\t\t\tallowedNamespaces.map(async (namespace) => ({\n\t\t\t\tmcpTools: await options.runtime.listTools({\n\t\t\t\t\tagentScopeId: portalAgentScopeKey(identity),\n\t\t\t\t\tnamespace,\n\t\t\t\t}),\n\t\t\t\tnamespace,\n\t\t\t})),\n\t\t);\n\t\tfor (const [index, namespaceToolGroup] of namespaceToolGroups.entries()) {\n\t\t\tif (namespaceToolGroup.status === 'rejected') {\n\t\t\t\tconst namespace = allowedNamespaces[index] ?? 'unknown';\n\t\t\t\tdiscoveryFailures.push({ message: messageFromError(namespaceToolGroup.reason), namespace });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst { mcpTools, namespace } = namespaceToolGroup.value;\n\t\t\tfor (const mcpTool of mcpTools) {\n\t\t\t\tconst portalTool = portalToolFromMcpTool(namespace, mcpTool);\n\t\t\t\tif (\n\t\t\t\t\tisEnabledTool(portalTool, policy.enabledTools) &&\n\t\t\t\t\t!isHiddenTool(portalTool, policy.hiddenTools)\n\t\t\t\t) {\n\t\t\t\t\ttools.push(portalTool);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst sortedTools = tools.toSorted((left, right) => {\n\t\t\tconst namespaceOrder = left.namespace.localeCompare(right.namespace);\n\t\t\treturn namespaceOrder === 0 ? left.toolName.localeCompare(right.toolName) : namespaceOrder;\n\t\t});\n\t\tconst graph = buildToolGraph({ skills: options.skills ?? [], tools: sortedTools });\n\t\tconst catalog = {\n\t\t\tagentScopeId: identity.agentScopeId,\n\t\t\tdiscoveryFailures,\n\t\t\tgeneratedAt: new Date(getNow()).toISOString(),\n\t\t\tsourceHash: createSourceHash(sortedTools),\n\t\t\ttools: sortedTools,\n\t\t};\n\n\t\treturn {\n\t\t\tcatalog,\n\t\t\tgraph,\n\t\t\tidentity,\n\t\t\tsearchIndex: createSearchIndex(sortedTools, graph),\n\t\t};\n\t}\n\n\treturn {\n\t\tasync getSession(identity: PortalAgentIdentity): Promise<PortalSession> {\n\t\t\tconst key = portalAgentScopeKey(identity);\n\t\t\tconst now = getNow();\n\t\t\tconst cached = sessions.get(key);\n\t\t\tif (cached && cached.expiresAt > now) {\n\t\t\t\treturn cached.session;\n\t\t\t}\n\n\t\t\tconst generation = generationForScope(key);\n\t\t\tconst session = await buildSession(identity);\n\t\t\tif (\n\t\t\t\tgenerationForScope(key) === generation &&\n\t\t\t\tsession.catalog.discoveryFailures.length === 0\n\t\t\t) {\n\t\t\t\tsessions.set(key, { expiresAt: now + options.catalogTtlMs, session });\n\t\t\t}\n\t\t\treturn session;\n\t\t},\n\t\tasync invalidateAgentScope(agentScopeId: string): Promise<void> {\n\t\t\tincrementAgentScopeGeneration(agentScopeId);\n\t\t\tfor (const key of sessions.keys()) {\n\t\t\t\tif (key === agentScopeId || key.startsWith(`${agentScopeId}\\n`)) {\n\t\t\t\t\tsessions.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait options.runtime.closeAgentScope(agentScopeId);\n\t\t},\n\t\tasync invalidateSession(identity: PortalAgentIdentity): Promise<void> {\n\t\t\tconst scopeKey = portalAgentScopeKey(identity);\n\t\t\tincrementScopeGeneration(scopeKey);\n\t\t\tsessions.delete(scopeKey);\n\t\t\tif (options.runtime.closeSession) {\n\t\t\t\tawait options.runtime.closeSession(scopeKey);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait options.runtime.closeAgentScope(scopeKey);\n\t\t},\n\t};\n}\n","import type { JsonValue } from './json-schema.js';\n\nconst credentialPatterns = [\n\t/\\bBearer\\s+[A-Za-z0-9._~+/=-]+/gi,\n\t/\\bBasic\\s+[A-Za-z0-9._~+/=-]+/gi,\n\t/\\b(api[_-]?key|token|password|secret)=([^&\\s]+)/gi,\n];\n\nexport interface RedactionOptions {\n\treadonly exactValues?: readonly string[];\n}\n\nexport function isCredentialConfigKey(key: string): boolean {\n\tconst normalizedKey = key.toLowerCase().replace(/[^a-z0-9]/g, '');\n\treturn (\n\t\tnormalizedKey === 'auth' ||\n\t\tnormalizedKey === 'authorization' ||\n\t\tnormalizedKey === 'apikey' ||\n\t\tnormalizedKey.endsWith('apikey') ||\n\t\tnormalizedKey.endsWith('token') ||\n\t\tnormalizedKey.endsWith('password') ||\n\t\tnormalizedKey.endsWith('secret')\n\t);\n}\n\nfunction redactExactValues(text: string, exactValues: readonly string[]): string {\n\treturn exactValues\n\t\t.filter((value) => value.length > 0)\n\t\t.reduce((currentText, value) => currentText.split(value).join('[REDACTED]'), text);\n}\n\nexport function redactExactCredentialText(text: string, options: RedactionOptions = {}): string {\n\treturn redactExactValues(text, options.exactValues ?? []);\n}\n\nexport function redactCredentialText(text: string, options: RedactionOptions = {}): string {\n\tconst patternRedactedText = credentialPatterns.reduce(\n\t\t(current, pattern) => current.replace(pattern, '[REDACTED]'),\n\t\ttext,\n\t);\n\treturn redactExactValues(patternRedactedText, options.exactValues ?? []);\n}\n\nfunction redactJsonValue(value: unknown, options: RedactionOptions, keyHint?: string): unknown {\n\tif (typeof value === 'string') {\n\t\treturn keyHint && isCredentialConfigKey(keyHint)\n\t\t\t? '[REDACTED]'\n\t\t\t: redactCredentialText(value, options);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => redactJsonValue(entry, options));\n\t}\n\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn value;\n\t}\n\n\treturn Object.fromEntries(\n\t\tObject.entries(value).map(([key, childValue]) => [\n\t\t\tkey,\n\t\t\tredactJsonValue(childValue, options, key),\n\t\t]),\n\t);\n}\n\nfunction redactExactJsonValue(value: unknown, options: RedactionOptions): unknown {\n\tif (typeof value === 'string') {\n\t\treturn redactExactCredentialText(value, options);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => redactExactJsonValue(entry, options));\n\t}\n\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn value;\n\t}\n\n\treturn Object.fromEntries(\n\t\tObject.entries(value).map(([key, childValue]) => [\n\t\t\tkey,\n\t\t\tredactExactJsonValue(childValue, options),\n\t\t]),\n\t);\n}\n\nfunction isJsonValue(value: unknown): value is JsonValue {\n\tif (\n\t\tvalue === null ||\n\t\ttypeof value === 'string' ||\n\t\ttypeof value === 'number' ||\n\t\ttypeof value === 'boolean'\n\t) {\n\t\treturn true;\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.every(isJsonValue);\n\t}\n\n\tif (typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\treturn Object.values(value).every(isJsonValue);\n}\n\nexport function redactUpstreamResponse(response: unknown, options: RedactionOptions = {}): unknown {\n\treturn redactJsonValue(response, options);\n}\n\nexport function redactUpstreamCatalogValue(\n\tresponse: unknown,\n\toptions: RedactionOptions = {},\n): unknown {\n\treturn redactExactJsonValue(response, options);\n}\n\nfunction copyRedactedErrorField(props: {\n\treadonly source: Error;\n\treadonly target: Error;\n\treadonly fieldName: string;\n\treadonly options: RedactionOptions;\n}): void {\n\tconst descriptor = Object.getOwnPropertyDescriptor(props.source, props.fieldName);\n\tif (!descriptor || !('value' in descriptor)) {\n\t\treturn;\n\t}\n\tObject.defineProperty(props.target, props.fieldName, {\n\t\t...descriptor,\n\t\tvalue: redactJsonValue(descriptor.value, props.options),\n\t});\n}\n\nexport function redactThrownError(error: unknown, options: RedactionOptions = {}): Error {\n\tconst message = error instanceof Error ? error.message : String(error);\n\tif (!(error instanceof Error)) {\n\t\treturn new Error(redactCredentialText(message, options));\n\t}\n\n\tconst redactedError = new Error(redactCredentialText(message, options), { cause: error });\n\tredactedError.name = error.name;\n\tif (error.stack) {\n\t\tredactedError.stack = redactCredentialText(error.stack, options);\n\t}\n\tcopyRedactedErrorField({ fieldName: 'code', options, source: error, target: redactedError });\n\tcopyRedactedErrorField({ fieldName: 'data', options, source: error, target: redactedError });\n\treturn redactedError;\n}\n\nexport function toRedactedJsonValue(value: unknown, options: RedactionOptions = {}): JsonValue {\n\tconst redacted = redactJsonValue(value, options);\n\tif (isJsonValue(redacted)) {\n\t\treturn redacted;\n\t}\n\n\treturn null;\n}\n","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport {\n\tSSEClientTransport,\n\ttype SSEClientTransportOptions,\n} from '@modelcontextprotocol/sdk/client/sse.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport {\n\tStreamableHTTPClientTransport,\n\ttype StreamableHTTPClientTransportOptions,\n} from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { normalizeHeaders, type Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport { ToolSchema, type Tool } from '@modelcontextprotocol/sdk/types.js';\n\nimport type { JsonObject } from './json-schema.js';\nimport {\n\tisCredentialConfigKey,\n\tredactThrownError,\n\tredactUpstreamCatalogValue,\n\tredactUpstreamResponse,\n} from './upstream-response-middleware.js';\n\nexport type UpstreamMcpTransportKind = 'auto-http' | 'sse' | 'stdio' | 'streamable-http';\n\ninterface BaseUpstreamMcpServer {\n\treadonly connectionTimeoutMs?: number;\n\treadonly namespace: string;\n\treadonly transport: UpstreamMcpTransportKind;\n}\n\nexport interface RemoteUpstreamMcpServer extends BaseUpstreamMcpServer {\n\treadonly eventSourceInit?: SSEClientTransportOptions['eventSourceInit'];\n\treadonly headers?: Readonly<Record<string, string>>;\n\treadonly requestInit?: RequestInit;\n\treadonly transport: 'auto-http' | 'sse' | 'streamable-http';\n\treadonly url: string;\n}\n\nexport interface StdioUpstreamMcpServer extends BaseUpstreamMcpServer {\n\treadonly args?: readonly string[];\n\treadonly command: string;\n\treadonly cwd?: string;\n\treadonly env?: Readonly<Record<string, string>>;\n\treadonly transport: 'stdio';\n}\n\nexport type NormalizedUpstreamMcpServer = RemoteUpstreamMcpServer | StdioUpstreamMcpServer;\n\nexport interface ListToolsCall {\n\treadonly agentScopeId: string;\n\treadonly namespace: string;\n}\n\nexport interface UpstreamToolCall {\n\treadonly arguments: JsonObject;\n\treadonly agentScopeId: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}\n\nexport interface UpstreamListToolsResult {\n\treadonly nextCursor?: string | undefined;\n\treadonly tools: readonly Tool[];\n}\n\nexport interface UpstreamMcpClientLike {\n\treadonly callTool: (params: {\n\t\treadonly arguments: JsonObject;\n\t\treadonly name: string;\n\t}) => Promise<unknown>;\n\treadonly close: () => Promise<void> | void;\n\treadonly connect: (transport: unknown) => Promise<void>;\n\treadonly listTools: (params?: { readonly cursor?: string }) => Promise<UpstreamListToolsResult>;\n}\n\nexport interface UpstreamMcpRuntimeOptions {\n\treadonly additionalRedactionValues?: readonly string[];\n\treadonly createClient?: () => UpstreamMcpClientLike;\n\treadonly createTransport?: (\n\t\tserver: NormalizedUpstreamMcpServer,\n\t\ttransport: Exclude<UpstreamMcpTransportKind, 'auto-http'>,\n\t) => unknown;\n\treadonly onCloseError?: (error: Error, context: UpstreamMcpCloseErrorContext) => void;\n\treadonly servers: readonly NormalizedUpstreamMcpServer[];\n}\n\nexport interface UpstreamMcpCloseErrorContext {\n\treadonly agentScopeId: string;\n\treadonly namespace?: string;\n}\n\nexport interface UpstreamMcpClientRuntime {\n\treadonly callTool: (call: UpstreamToolCall) => Promise<unknown>;\n\treadonly closeAgentScope: (agentScopeId: string) => Promise<void>;\n\treadonly closeSession: (scopeKey: string) => Promise<void>;\n\treadonly listTools: (call: ListToolsCall) => Promise<readonly Tool[]>;\n}\n\ninterface CachedClient {\n\treadonly client: UpstreamMcpClientLike;\n}\n\ninterface PendingClient {\n\treadonly generation: number;\n\treadonly promise: Promise<UpstreamMcpClientLike>;\n}\n\nconst defaultConnectionTimeoutMs = 30_000;\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTransport(value: unknown): value is Transport {\n\treturn (\n\t\tisObjectRecord(value) &&\n\t\ttypeof value.start === 'function' &&\n\t\ttypeof value.send === 'function' &&\n\t\ttypeof value.close === 'function'\n\t);\n}\n\nfunction createSdkClient(): UpstreamMcpClientLike {\n\tconst client = new Client({ name: 'agent-vm-mcp-portal', version: '1.0.0' });\n\n\treturn {\n\t\tcallTool: async (params) => await client.callTool(params),\n\t\tclose: async () => {\n\t\t\tawait client.close();\n\t\t},\n\t\tconnect: async (transport) => {\n\t\t\tif (!isTransport(transport)) {\n\t\t\t\tthrow new Error('SDK MCP client requires a valid MCP transport.');\n\t\t\t}\n\t\t\tawait client.connect(transport);\n\t\t},\n\t\tlistTools: async (params) => {\n\t\t\tconst result = await client.listTools(params);\n\t\t\treturn {\n\t\t\t\t...(result.nextCursor !== undefined ? { nextCursor: result.nextCursor } : {}),\n\t\t\t\ttools: result.tools,\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction withRemoteHeaders(server: RemoteUpstreamMcpServer): RemoteUpstreamMcpServer {\n\tif (!server.headers) {\n\t\treturn server;\n\t}\n\n\treturn {\n\t\t...server,\n\t\trequestInit: {\n\t\t\t...server.requestInit,\n\t\t\theaders: {\n\t\t\t\t...normalizeHeaders(server.requestInit?.headers),\n\t\t\t\t...server.headers,\n\t\t\t},\n\t\t},\n\t};\n}\n\nfunction createSdkTransport(\n\tserver: NormalizedUpstreamMcpServer,\n\ttransport: Exclude<UpstreamMcpTransportKind, 'auto-http'>,\n): unknown {\n\tif (transport === 'stdio') {\n\t\tif (server.transport !== 'stdio') {\n\t\t\tthrow new Error('Stdio transport requires stdio server config.');\n\t\t}\n\n\t\treturn new StdioClientTransport({\n\t\t\t...(server.args ? { args: [...server.args] } : {}),\n\t\t\tcommand: server.command,\n\t\t\t...(server.cwd !== undefined ? { cwd: server.cwd } : {}),\n\t\t\t...(server.env ? { env: { ...server.env } } : {}),\n\t\t});\n\t}\n\n\tif (server.transport === 'stdio') {\n\t\tthrow new Error('Remote transport requires remote server config.');\n\t}\n\n\tconst remoteServer = withRemoteHeaders(server);\n\tif (transport === 'sse') {\n\t\tconst options: SSEClientTransportOptions = {};\n\t\tif (remoteServer.eventSourceInit !== undefined) {\n\t\t\toptions.eventSourceInit = remoteServer.eventSourceInit;\n\t\t}\n\t\tif (remoteServer.requestInit !== undefined) {\n\t\t\toptions.requestInit = remoteServer.requestInit;\n\t\t}\n\t\treturn new SSEClientTransport(new URL(remoteServer.url), options);\n\t}\n\n\tconst options: StreamableHTTPClientTransportOptions = {};\n\tif (remoteServer.requestInit !== undefined) {\n\t\toptions.requestInit = remoteServer.requestInit;\n\t}\n\treturn new StreamableHTTPClientTransport(new URL(remoteServer.url), options);\n}\n\nfunction cacheKey(agentScopeId: string, namespace: string): string {\n\treturn `${agentScopeId}\\n${namespace}`;\n}\n\nfunction rootAgentScopeId(agentScopeId: string): string {\n\treturn agentScopeId.split('\\n', 1)[0] ?? agentScopeId;\n}\n\nfunction transportAttempts(\n\tserver: NormalizedUpstreamMcpServer,\n): readonly Exclude<UpstreamMcpTransportKind, 'auto-http'>[] {\n\tif (server.transport === 'auto-http') {\n\t\treturn ['streamable-http', 'sse'];\n\t}\n\n\treturn [server.transport];\n}\n\nfunction redactionValuesFromServer(server: NormalizedUpstreamMcpServer): readonly string[] {\n\tif (server.transport === 'stdio') {\n\t\treturn Object.entries(server.env ?? {})\n\t\t\t.filter(([key, value]) => isCredentialConfigKey(key) && value.length > 0)\n\t\t\t.map(([, value]) => value);\n\t}\n\n\treturn Object.entries(server.headers ?? {})\n\t\t.filter(([key, value]) => isCredentialConfigKey(key) && value.length > 0)\n\t\t.map(([, value]) => value);\n}\n\nfunction timeoutMsForServer(server: NormalizedUpstreamMcpServer): number {\n\treturn server.connectionTimeoutMs ?? defaultConnectionTimeoutMs;\n}\n\nasync function withTimeout<TResult>(\n\tpromise: Promise<TResult>,\n\tprops: {\n\t\treadonly operation: string;\n\t\treadonly timeoutMs: number;\n\t},\n): Promise<TResult> {\n\tlet timeout: NodeJS.Timeout | undefined;\n\ttry {\n\t\treturn await Promise.race([\n\t\t\tpromise,\n\t\t\tnew Promise<never>((_resolve, reject) => {\n\t\t\t\ttimeout = setTimeout(() => {\n\t\t\t\t\treject(new Error(`${props.operation} timed out after ${props.timeoutMs}ms.`));\n\t\t\t\t}, props.timeoutMs);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tif (timeout) {\n\t\t\tclearTimeout(timeout);\n\t\t}\n\t}\n}\n\nasync function listAllTools(\n\tclient: UpstreamMcpClientLike,\n\tcursor: string | undefined,\n\tcollectedTools: readonly Tool[],\n\ttimeoutMs: number,\n): Promise<readonly Tool[]> {\n\tconst result = await withTimeout(client.listTools(cursor ? { cursor } : undefined), {\n\t\toperation: 'MCP listTools',\n\t\ttimeoutMs,\n\t});\n\tconst nextTools = [...collectedTools, ...result.tools];\n\treturn result.nextCursor\n\t\t? listAllTools(client, result.nextCursor, nextTools, timeoutMs)\n\t\t: nextTools;\n}\n\nasync function closeClientAfterFailure(client: UpstreamMcpClientLike | null): Promise<void> {\n\tif (!client) {\n\t\treturn;\n\t}\n\ttry {\n\t\tawait client.close();\n\t} catch {\n\t\t// Preserve the original upstream failure; close errors are best-effort cleanup.\n\t}\n}\n\nasync function closeClientForTeardown(\n\tclient: UpstreamMcpClientLike | null,\n\tprops: {\n\t\treadonly context: UpstreamMcpCloseErrorContext;\n\t\treadonly onCloseError?:\n\t\t\t| ((error: Error, context: UpstreamMcpCloseErrorContext) => void)\n\t\t\t| undefined;\n\t},\n): Promise<void> {\n\tif (!client) {\n\t\treturn;\n\t}\n\ttry {\n\t\tawait client.close();\n\t} catch (error) {\n\t\tprops.onCloseError?.(redactThrownError(error), props.context);\n\t}\n}\n\nfunction closeErrorContextFromCacheKey(cacheKeyValue: string): UpstreamMcpCloseErrorContext {\n\tconst keyParts = cacheKeyValue.split('\\n');\n\tconst namespace = keyParts.length > 1 ? keyParts[keyParts.length - 1] : undefined;\n\tconst agentScopeId =\n\t\tnamespace !== undefined ? keyParts.slice(0, keyParts.length - 1).join('\\n') : cacheKeyValue;\n\treturn {\n\t\tagentScopeId,\n\t\t...(namespace !== undefined ? { namespace } : {}),\n\t};\n}\n\nfunction redactToolCatalog(\n\ttools: readonly Tool[],\n\toptions: { readonly exactValues: readonly string[] },\n): readonly Tool[] {\n\treturn tools.map((tool) => ToolSchema.parse(redactUpstreamCatalogValue(tool, options)));\n}\n\nexport function createUpstreamMcpClientRuntime(\n\toptions: UpstreamMcpRuntimeOptions,\n): UpstreamMcpClientRuntime {\n\tconst serversByNamespace = new Map(options.servers.map((server) => [server.namespace, server]));\n\tconst clients = new Map<string, CachedClient>();\n\tconst pendingClients = new Map<string, PendingClient>();\n\tconst agentScopeGenerations = new Map<string, number>();\n\tconst createClient = options.createClient ?? createSdkClient;\n\tconst createTransport = options.createTransport ?? createSdkTransport;\n\tconst redactionValues = [\n\t\t...(options.additionalRedactionValues ?? []),\n\t\t...options.servers.flatMap((server) => redactionValuesFromServer(server)),\n\t];\n\n\tfunction generationForAgentScope(agentScopeId: string): number {\n\t\treturn (\n\t\t\tagentScopeGenerations.get(agentScopeId) ??\n\t\t\tagentScopeGenerations.get(rootAgentScopeId(agentScopeId)) ??\n\t\t\t0\n\t\t);\n\t}\n\n\tfunction incrementAgentScopeGeneration(agentScopeId: string): void {\n\t\tconst rootAgentScope = rootAgentScopeId(agentScopeId);\n\t\tagentScopeGenerations.set(rootAgentScope, (agentScopeGenerations.get(rootAgentScope) ?? 0) + 1);\n\t}\n\n\tfunction incrementScopeGeneration(scopeKey: string): void {\n\t\tagentScopeGenerations.set(scopeKey, (agentScopeGenerations.get(scopeKey) ?? 0) + 1);\n\t}\n\n\tasync function createConnectedClient(\n\t\tserver: NormalizedUpstreamMcpServer,\n\t): Promise<UpstreamMcpClientLike> {\n\t\tconst attempts = transportAttempts(server);\n\t\tasync function tryAttempt(\n\t\t\tattemptIndex: number,\n\t\t\tlastError: Error | null,\n\t\t): Promise<UpstreamMcpClientLike> {\n\t\t\tconst transportKind = attempts[attemptIndex];\n\t\t\tif (transportKind === undefined) {\n\t\t\t\tthrow (\n\t\t\t\t\tlastError ??\n\t\t\t\t\tnew Error(`Could not connect to upstream MCP namespace \"${server.namespace}\".`)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst client = createClient();\n\t\t\tconst transportServer =\n\t\t\t\ttransportKind === 'sse' && server.transport !== 'stdio'\n\t\t\t\t\t? withRemoteHeaders(server)\n\t\t\t\t\t: server;\n\t\t\tconst transport = createTransport(transportServer, transportKind);\n\t\t\ttry {\n\t\t\t\tawait withTimeout(client.connect(transport), {\n\t\t\t\t\toperation: `MCP ${transportKind} connect for namespace \"${server.namespace}\"`,\n\t\t\t\t\ttimeoutMs: timeoutMsForServer(server),\n\t\t\t\t});\n\t\t\t\treturn client;\n\t\t\t} catch (error) {\n\t\t\t\tconst redactedError = redactThrownError(error, { exactValues: redactionValues });\n\t\t\t\tawait closeClientAfterFailure(client);\n\t\t\t\treturn tryAttempt(attemptIndex + 1, redactedError);\n\t\t\t}\n\t\t}\n\n\t\treturn tryAttempt(0, null);\n\t}\n\n\tasync function getClient(\n\t\tagentScopeId: string,\n\t\tnamespace: string,\n\t): Promise<UpstreamMcpClientLike> {\n\t\tconst key = cacheKey(agentScopeId, namespace);\n\t\tconst cachedClient = clients.get(key);\n\t\tif (cachedClient) {\n\t\t\treturn cachedClient.client;\n\t\t}\n\t\tconst pendingClient = pendingClients.get(key);\n\t\tconst generation = generationForAgentScope(agentScopeId);\n\t\tif (pendingClient && pendingClient.generation === generation) {\n\t\t\treturn pendingClient.promise;\n\t\t}\n\t\tif (pendingClient) {\n\t\t\tpendingClients.delete(key);\n\t\t\tvoid pendingClient.promise.then(closeClientAfterFailure, () => undefined);\n\t\t}\n\n\t\tconst server = serversByNamespace.get(namespace);\n\t\tif (!server) {\n\t\t\tthrow new Error(`Unknown upstream MCP namespace \"${namespace}\".`);\n\t\t}\n\n\t\tconst pending = createConnectedClient(server);\n\t\tconst pendingRecord = { generation, promise: pending } satisfies PendingClient;\n\t\tpendingClients.set(key, pendingRecord);\n\t\ttry {\n\t\t\tconst client = await pending;\n\t\t\tif (generationForAgentScope(agentScopeId) !== generation) {\n\t\t\t\tawait closeClientAfterFailure(client);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`MCP client for agent scope \"${rootAgentScopeId(agentScopeId)}\" was invalidated.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tclients.set(key, { client });\n\t\t\treturn client;\n\t\t} finally {\n\t\t\tif (pendingClients.get(key) === pendingRecord) {\n\t\t\t\tpendingClients.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tasync callTool(call: UpstreamToolCall): Promise<unknown> {\n\t\t\tconst key = cacheKey(call.agentScopeId, call.namespace);\n\t\t\tlet client: UpstreamMcpClientLike | null = null;\n\t\t\ttry {\n\t\t\t\tclient = await getClient(call.agentScopeId, call.namespace);\n\t\t\t\tconst server = serversByNamespace.get(call.namespace);\n\t\t\t\treturn redactUpstreamResponse(\n\t\t\t\t\tawait withTimeout(client.callTool({ arguments: call.arguments, name: call.toolName }), {\n\t\t\t\t\t\toperation: `MCP callTool ${call.namespace}.${call.toolName}`,\n\t\t\t\t\t\ttimeoutMs: server ? timeoutMsForServer(server) : defaultConnectionTimeoutMs,\n\t\t\t\t\t}),\n\t\t\t\t\t{ exactValues: redactionValues },\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tclients.delete(key);\n\t\t\t\tawait closeClientAfterFailure(client);\n\t\t\t\tthrow redactThrownError(error, { exactValues: redactionValues });\n\t\t\t}\n\t\t},\n\t\tasync closeAgentScope(agentScopeId: string): Promise<void> {\n\t\t\tincrementAgentScopeGeneration(agentScopeId);\n\t\t\tconst closePromises: Promise<void>[] = [];\n\t\t\tfor (const [key, cachedClient] of clients.entries()) {\n\t\t\t\tif (key !== agentScopeId && !key.startsWith(`${agentScopeId}\\n`)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tclients.delete(key);\n\t\t\t\tclosePromises.push(\n\t\t\t\t\tcloseClientForTeardown(cachedClient.client, {\n\t\t\t\t\t\tcontext: closeErrorContextFromCacheKey(key),\n\t\t\t\t\t\tonCloseError: options.onCloseError,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [key, pendingClient] of pendingClients.entries()) {\n\t\t\t\tif (key !== agentScopeId && !key.startsWith(`${agentScopeId}\\n`)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tpendingClients.delete(key);\n\t\t\t\tclosePromises.push(\n\t\t\t\t\tpendingClient.promise.then(\n\t\t\t\t\t\t(client) =>\n\t\t\t\t\t\t\tcloseClientForTeardown(client, {\n\t\t\t\t\t\t\t\tcontext: closeErrorContextFromCacheKey(key),\n\t\t\t\t\t\t\t\tonCloseError: options.onCloseError,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t() => undefined,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait Promise.all(closePromises);\n\t\t},\n\t\tasync closeSession(scopeKey: string): Promise<void> {\n\t\t\tincrementScopeGeneration(scopeKey);\n\t\t\tconst closePromises: Promise<void>[] = [];\n\t\t\tfor (const [key, cachedClient] of clients.entries()) {\n\t\t\t\tif (key !== scopeKey && !key.startsWith(`${scopeKey}\\n`)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tclients.delete(key);\n\t\t\t\tclosePromises.push(\n\t\t\t\t\tcloseClientForTeardown(cachedClient.client, {\n\t\t\t\t\t\tcontext: closeErrorContextFromCacheKey(key),\n\t\t\t\t\t\tonCloseError: options.onCloseError,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [key, pendingClient] of pendingClients.entries()) {\n\t\t\t\tif (key !== scopeKey && !key.startsWith(`${scopeKey}\\n`)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tpendingClients.delete(key);\n\t\t\t\tclosePromises.push(\n\t\t\t\t\tpendingClient.promise.then(\n\t\t\t\t\t\t(client) =>\n\t\t\t\t\t\t\tcloseClientForTeardown(client, {\n\t\t\t\t\t\t\t\tcontext: closeErrorContextFromCacheKey(key),\n\t\t\t\t\t\t\t\tonCloseError: options.onCloseError,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t() => undefined,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait Promise.all(closePromises);\n\t\t},\n\t\tasync listTools(call: ListToolsCall): Promise<readonly Tool[]> {\n\t\t\tconst key = cacheKey(call.agentScopeId, call.namespace);\n\t\t\tlet client: UpstreamMcpClientLike | null = null;\n\t\t\ttry {\n\t\t\t\tclient = await getClient(call.agentScopeId, call.namespace);\n\t\t\t\tconst server = serversByNamespace.get(call.namespace);\n\t\t\t\treturn redactToolCatalog(\n\t\t\t\t\tawait listAllTools(\n\t\t\t\t\t\tclient,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t[],\n\t\t\t\t\t\tserver ? timeoutMsForServer(server) : defaultConnectionTimeoutMs,\n\t\t\t\t\t),\n\t\t\t\t\t{ exactValues: redactionValues },\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tclients.delete(key);\n\t\t\t\tawait closeClientAfterFailure(client);\n\t\t\t\tthrow redactThrownError(error, { exactValues: redactionValues });\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/zod-schema-loader.ts
|
|
3
|
+
const unsupportedFeatures = new Set([
|
|
4
|
+
"contains",
|
|
5
|
+
"dependentSchemas",
|
|
6
|
+
"else",
|
|
7
|
+
"if",
|
|
8
|
+
"not",
|
|
9
|
+
"then",
|
|
10
|
+
"unevaluatedProperties",
|
|
11
|
+
"uniqueItems"
|
|
12
|
+
]);
|
|
13
|
+
function isJsonObject(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
function findUnsupportedFeature(value, path = []) {
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
for (const [index, childValue] of value.entries()) {
|
|
19
|
+
const childUnsupported = findUnsupportedFeature(childValue, [...path, index]);
|
|
20
|
+
if (childUnsupported) return childUnsupported;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (!isJsonObject(value)) return null;
|
|
25
|
+
for (const [key, childValue] of Object.entries(value)) {
|
|
26
|
+
if (unsupportedFeatures.has(key)) return {
|
|
27
|
+
feature: key,
|
|
28
|
+
path: [...path, key]
|
|
29
|
+
};
|
|
30
|
+
const childUnsupported = findUnsupportedFeature(childValue, [...path, key]);
|
|
31
|
+
if (childUnsupported) return childUnsupported;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function unavailableError(feature, path) {
|
|
36
|
+
return {
|
|
37
|
+
feature,
|
|
38
|
+
kind: "schema_validation_unavailable",
|
|
39
|
+
message: `JSON Schema feature "${feature}" is not supported by the portal validator.`,
|
|
40
|
+
path
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function toValidationIssue(issue) {
|
|
44
|
+
return {
|
|
45
|
+
code: issue.code,
|
|
46
|
+
message: issue.message,
|
|
47
|
+
path: issue.path.map((pathPart) => typeof pathPart === "symbol" ? String(pathPart) : pathPart)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function buildZodValidatorFromJsonSchema(jsonSchema) {
|
|
51
|
+
const unsupported = findUnsupportedFeature(jsonSchema);
|
|
52
|
+
if (unsupported) return {
|
|
53
|
+
error: unavailableError(unsupported.feature, unsupported.path),
|
|
54
|
+
ok: false
|
|
55
|
+
};
|
|
56
|
+
try {
|
|
57
|
+
const zodSchema = z.fromJSONSchema(jsonSchema);
|
|
58
|
+
return {
|
|
59
|
+
ok: true,
|
|
60
|
+
validate(value) {
|
|
61
|
+
const parsed = zodSchema.safeParse(value);
|
|
62
|
+
if (parsed.success) return {
|
|
63
|
+
ok: true,
|
|
64
|
+
value: parsed.data
|
|
65
|
+
};
|
|
66
|
+
return {
|
|
67
|
+
error: {
|
|
68
|
+
kind: "input_validation",
|
|
69
|
+
issues: parsed.error.issues.map((issue) => toValidationIssue(issue))
|
|
70
|
+
},
|
|
71
|
+
ok: false
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
} catch (error) {
|
|
76
|
+
return {
|
|
77
|
+
error: {
|
|
78
|
+
feature: "conversion_failed",
|
|
79
|
+
kind: "schema_validation_unavailable",
|
|
80
|
+
message: error instanceof Error ? error.message : String(error),
|
|
81
|
+
path: []
|
|
82
|
+
},
|
|
83
|
+
ok: false
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { buildZodValidatorFromJsonSchema as t };
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=zod-schema-loader-CDDtoRE1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-schema-loader-CDDtoRE1.js","names":[],"sources":["../src/zod-schema-loader.ts"],"sourcesContent":["import { z } from 'zod';\n\nimport type { JsonObject, JsonValue } from './json-schema.js';\n\nexport interface InputValidationIssue {\n\treadonly code: string;\n\treadonly message: string;\n\treadonly path: readonly (number | string)[];\n}\n\nexport interface InputValidationError {\n\treadonly kind: 'input_validation';\n\treadonly issues: readonly InputValidationIssue[];\n}\n\nexport interface SchemaValidationUnavailableError {\n\treadonly feature: string;\n\treadonly kind: 'schema_validation_unavailable';\n\treadonly message: string;\n\treadonly path: readonly (number | string)[];\n}\n\nexport type PortalValidationResult =\n\t| { readonly ok: true; readonly value: unknown }\n\t| { readonly error: InputValidationError; readonly ok: false };\n\nexport type BuiltZodValidator =\n\t| {\n\t\t\treadonly ok: true;\n\t\t\treadonly validate: (value: unknown) => PortalValidationResult;\n\t }\n\t| {\n\t\t\treadonly error: SchemaValidationUnavailableError;\n\t\t\treadonly ok: false;\n\t };\n\ninterface UnsupportedFeature {\n\treadonly feature: string;\n\treadonly path: readonly (number | string)[];\n}\n\nconst unsupportedFeatures = new Set([\n\t'contains',\n\t'dependentSchemas',\n\t'else',\n\t'if',\n\t'not',\n\t'then',\n\t'unevaluatedProperties',\n\t'uniqueItems',\n]);\n\nfunction isJsonObject(value: JsonValue): value is JsonObject {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction findUnsupportedFeature(\n\tvalue: JsonValue,\n\tpath: readonly (number | string)[] = [],\n): UnsupportedFeature | null {\n\tif (Array.isArray(value)) {\n\t\tfor (const [index, childValue] of value.entries()) {\n\t\t\tconst childUnsupported = findUnsupportedFeature(childValue, [...path, index]);\n\t\t\tif (childUnsupported) {\n\t\t\t\treturn childUnsupported;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tif (!isJsonObject(value)) {\n\t\treturn null;\n\t}\n\n\tfor (const [key, childValue] of Object.entries(value)) {\n\t\tif (unsupportedFeatures.has(key)) {\n\t\t\treturn { feature: key, path: [...path, key] };\n\t\t}\n\t\tconst childUnsupported = findUnsupportedFeature(childValue, [...path, key]);\n\t\tif (childUnsupported) {\n\t\t\treturn childUnsupported;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction unavailableError(\n\tfeature: string,\n\tpath: readonly (number | string)[],\n): SchemaValidationUnavailableError {\n\treturn {\n\t\tfeature,\n\t\tkind: 'schema_validation_unavailable',\n\t\tmessage: `JSON Schema feature \"${feature}\" is not supported by the portal validator.`,\n\t\tpath,\n\t};\n}\n\nfunction toValidationIssue(issue: z.core.$ZodIssue): InputValidationIssue {\n\treturn {\n\t\tcode: issue.code,\n\t\tmessage: issue.message,\n\t\tpath: issue.path.map((pathPart) =>\n\t\t\ttypeof pathPart === 'symbol' ? String(pathPart) : pathPart,\n\t\t),\n\t};\n}\n\nexport function buildZodValidatorFromJsonSchema(jsonSchema: JsonObject): BuiltZodValidator {\n\tconst unsupported = findUnsupportedFeature(jsonSchema);\n\tif (unsupported) {\n\t\treturn {\n\t\t\terror: unavailableError(unsupported.feature, unsupported.path),\n\t\t\tok: false,\n\t\t};\n\t}\n\n\ttry {\n\t\tconst zodSchema = z.fromJSONSchema(jsonSchema);\n\n\t\treturn {\n\t\t\tok: true,\n\t\t\tvalidate(value: unknown): PortalValidationResult {\n\t\t\t\tconst parsed = zodSchema.safeParse(value);\n\t\t\t\tif (parsed.success) {\n\t\t\t\t\treturn { ok: true, value: parsed.data };\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\tkind: 'input_validation',\n\t\t\t\t\t\tissues: parsed.error.issues.map((issue) => toValidationIssue(issue)),\n\t\t\t\t\t},\n\t\t\t\t\tok: false,\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\tfeature: 'conversion_failed',\n\t\t\t\tkind: 'schema_validation_unavailable',\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\tpath: [],\n\t\t\t},\n\t\t\tok: false,\n\t\t};\n\t}\n}\n"],"mappings":";;AAyCA,MAAM,sBAAsB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;AAEF,SAAS,aAAa,OAAuC;CAC5D,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,uBACR,OACA,OAAqC,EAAE,EACX;CAC5B,IAAI,MAAM,QAAQ,MAAM,EAAE;EACzB,KAAK,MAAM,CAAC,OAAO,eAAe,MAAM,SAAS,EAAE;GAClD,MAAM,mBAAmB,uBAAuB,YAAY,CAAC,GAAG,MAAM,MAAM,CAAC;GAC7E,IAAI,kBACH,OAAO;;EAGT,OAAO;;CAGR,IAAI,CAAC,aAAa,MAAM,EACvB,OAAO;CAGR,KAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,MAAM,EAAE;EACtD,IAAI,oBAAoB,IAAI,IAAI,EAC/B,OAAO;GAAE,SAAS;GAAK,MAAM,CAAC,GAAG,MAAM,IAAI;GAAE;EAE9C,MAAM,mBAAmB,uBAAuB,YAAY,CAAC,GAAG,MAAM,IAAI,CAAC;EAC3E,IAAI,kBACH,OAAO;;CAIT,OAAO;;AAGR,SAAS,iBACR,SACA,MACmC;CACnC,OAAO;EACN;EACA,MAAM;EACN,SAAS,wBAAwB,QAAQ;EACzC;EACA;;AAGF,SAAS,kBAAkB,OAA+C;CACzE,OAAO;EACN,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,MAAM,MAAM,KAAK,KAAK,aACrB,OAAO,aAAa,WAAW,OAAO,SAAS,GAAG,SAClD;EACD;;AAGF,SAAgB,gCAAgC,YAA2C;CAC1F,MAAM,cAAc,uBAAuB,WAAW;CACtD,IAAI,aACH,OAAO;EACN,OAAO,iBAAiB,YAAY,SAAS,YAAY,KAAK;EAC9D,IAAI;EACJ;CAGF,IAAI;EACH,MAAM,YAAY,EAAE,eAAe,WAAW;EAE9C,OAAO;GACN,IAAI;GACJ,SAAS,OAAwC;IAChD,MAAM,SAAS,UAAU,UAAU,MAAM;IACzC,IAAI,OAAO,SACV,OAAO;KAAE,IAAI;KAAM,OAAO,OAAO;KAAM;IAGxC,OAAO;KACN,OAAO;MACN,MAAM;MACN,QAAQ,OAAO,MAAM,OAAO,KAAK,UAAU,kBAAkB,MAAM,CAAC;MACpE;KACD,IAAI;KACJ;;GAEF;UACO,OAAO;EACf,OAAO;GACN,OAAO;IACN,SAAS;IACT,MAAM;IACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC/D,MAAM,EAAE;IACR;GACD,IAAI;GACJ"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-vm/mcp-portal",
|
|
3
|
+
"version": "0.0.59",
|
|
4
|
+
"description": "Agent-scoped MCP Portal server and TypeScript helpers for composable upstream MCP tools.",
|
|
5
|
+
"homepage": "https://github.com/ShravanSunder/agent-vm#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/ShravanSunder/agent-vm/issues"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Shravan Sunder <ShravanSunder@users.noreply.github.com>",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/ShravanSunder/agent-vm.git",
|
|
14
|
+
"directory": "packages/mcp-portal"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"agent-vm-mcp-portal": "./dist/bin/agent-vm-mcp-portal.js",
|
|
18
|
+
"agent-vm-mcp-portal-server": "./dist/bin/portal-server.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./tool-vm": {
|
|
32
|
+
"types": "./dist/tool-vm/index.d.ts",
|
|
33
|
+
"import": "./dist/tool-vm/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./auth/hmac-token": {
|
|
36
|
+
"types": "./dist/auth/hmac-token.d.ts",
|
|
37
|
+
"import": "./dist/auth/hmac-token.js"
|
|
38
|
+
},
|
|
39
|
+
"./auth/hmac-env": {
|
|
40
|
+
"types": "./dist/auth/hmac-env.d.ts",
|
|
41
|
+
"import": "./dist/auth/hmac-env.js"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@hono/node-server": "^2.0.2",
|
|
49
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
50
|
+
"hono": "^4.12.18",
|
|
51
|
+
"zod": "^4.4.3",
|
|
52
|
+
"@agent-vm/config-contracts": "0.0.59"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"vitest": "^4.1.5"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsdown",
|
|
59
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
60
|
+
"test": "pnpm test:unit",
|
|
61
|
+
"test:unit": "vitest run --root ../../ --config vitest.config.ts packages/mcp-portal/src"
|
|
62
|
+
}
|
|
63
|
+
}
|