@agent-vm/mcp-portal 0.0.93 → 0.0.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/mcp-portal.js +6 -6
- package/dist/cli/index.js +1 -1
- package/dist/core/index.js +4 -4
- package/dist/index.js +3 -3
- package/dist/mcp-proxy/index.js +1 -1
- package/dist/portal-config/index.js +2 -2
- package/dist/{portal-core-B8HZPw3z.js → portal-core-CYLdSvsL.js} +5 -5
- package/dist/{portal-core-B8HZPw3z.js.map → portal-core-CYLdSvsL.js.map} +1 -1
- package/dist/{portal-tools-fFyF72Nl.js → portal-tools-BhBrxlwi.js} +4 -4
- package/dist/{portal-tools-fFyF72Nl.js.map → portal-tools-BhBrxlwi.js.map} +1 -1
- package/dist/{resolve-agent-identity-BQNGUP66.js → resolve-agent-identity-BK4WlZgd.js} +3 -3
- package/dist/{resolve-agent-identity-BQNGUP66.js.map → resolve-agent-identity-BK4WlZgd.js.map} +1 -1
- package/dist/{serve-command-4BNOH14H.js → serve-command-B101-A2V.js} +4 -4
- package/dist/{serve-command-4BNOH14H.js.map → serve-command-B101-A2V.js.map} +1 -1
- package/dist/{typescript-artifact-EQH4tZ0C.js → typescript-artifact-CXxEYME7.js} +2 -2
- package/dist/{typescript-artifact-EQH4tZ0C.js.map → typescript-artifact-CXxEYME7.js.map} +1 -1
- package/dist/{upstream-mcp-client-runtime-vu2TiTUw.js → upstream-mcp-client-runtime-Bzy0aa0o.js} +3 -3
- package/dist/{upstream-mcp-client-runtime-vu2TiTUw.js.map → upstream-mcp-client-runtime-Bzy0aa0o.js.map} +1 -1
- package/dist/{upstream-response-middleware-_dthoE1r.js → upstream-response-middleware-fcJSrSEo.js} +2 -2
- package/dist/{upstream-response-middleware-_dthoE1r.js.map → upstream-response-middleware-fcJSrSEo.js.map} +1 -1
- package/dist/zod-schema-loader-BubVafy-.d.ts.map +1 -1
- package/dist/{zod-schema-loader-C3I-MnWq.js → zod-schema-loader-DI7JliBn.js} +141 -3
- package/dist/zod-schema-loader-DI7JliBn.js.map +1 -0
- package/package.json +3 -3
- package/dist/zod-schema-loader-C3I-MnWq.js.map +0 -1
package/dist/{resolve-agent-identity-BQNGUP66.js.map → resolve-agent-identity-BK4WlZgd.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-agent-identity-BQNGUP66.js","names":["exhaustiveDecision"],"sources":["../src/mcp-proxy/portal-mcp-server.ts","../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n\tCallToolRequestSchema,\n\tListToolsRequestSchema,\n\ttype CallToolResult,\n\ttype Tool,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport type {\n\tPortalAgentScope,\n\tPortalCore,\n\tPortalCoreEvent,\n\tPortalCoreToolDescriptor,\n\tPortalCoreResult,\n\tPortalCoreToolName,\n} from '../core/portal-core.js';\nimport { portalToolInputSchemas } from '../core/portal-tools.js';\nimport { redactThrownError } from '../upstream-response-middleware.js';\n\nexport const portalMcpToolNames = [\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n] as const;\n\nexport type PortalMcpToolName = (typeof portalMcpToolNames)[number];\n\nconst portalMcpToolNameSet = new Set<string>(portalMcpToolNames);\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalMcpToolNameSet.has(value);\n}\n\nexport function listPortalMcpTools(\n\tdescriptors?: readonly PortalCoreToolDescriptor[],\n): readonly Tool[] {\n\treturn (\n\t\tdescriptors ?? [\n\t\t\t{\n\t\t\t\tdescription: 'List authorized MCP namespaces and compact tool summaries.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_list,\n\t\t\t\tname: 'mcp_portal_list',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\t\tname: 'mcp_portal_search',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\t\tname: 'mcp_portal_describe',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\t\tname: 'mcp_portal_call',\n\t\t\t},\n\t\t]\n\t);\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction coreResultIsError(value: PortalCoreResult): boolean {\n\tif (value.items.some((item) => item.status === 'failed')) {\n\t\treturn true;\n\t}\n\tif (!isObjectRecord(value.structuredContent)) {\n\t\treturn false;\n\t}\n\treturn value.structuredContent.ok === false;\n}\n\nfunction jsonToolResult(value: PortalCoreResult): CallToolResult {\n\treturn {\n\t\tcontent: [{ text: JSON.stringify(value), type: 'text' }],\n\t\t...(coreResultIsError(value) ? { isError: true } : {}),\n\t};\n}\n\nfunction errorToolResult(error: unknown): CallToolResult {\n\tconst redactedError = redactThrownError(error);\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttext: redactedError.message,\n\t\t\t\ttype: 'text',\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\nasync function sendBestEffortNotification(\n\tnotification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t},\n\tsendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tawait sendNotification(notification);\n\t} catch {\n\t\t// Progress is advisory; unsupported client notification channels must not fail the tool call.\n\t}\n}\n\nexport async function emitMcpProgress(props: {\n\treadonly event: PortalCoreEvent;\n\treadonly sendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>;\n\treadonly progressToken: number | string | undefined;\n}): Promise<void> {\n\tif (props.event.kind === 'upstream_notification') {\n\t\tif (!isObjectRecord(props.event.params)) {\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method === 'notifications/progress') {\n\t\t\tif (props.progressToken === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait sendBestEffortNotification(\n\t\t\t\t{\n\t\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\t\tparams: { ...props.event.params, progressToken: props.progressToken },\n\t\t\t\t},\n\t\t\t\tprops.sendNotification,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method !== 'notifications/message') {\n\t\t\treturn;\n\t\t}\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/message',\n\t\t\t\tparams: props.event.params,\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tif (props.event.kind !== 'progress' && props.event.kind !== 'partial_content') {\n\t\treturn;\n\t}\n\tconst message =\n\t\tprops.event.kind === 'progress'\n\t\t\t? props.event.message\n\t\t\t: props.event.content.type === 'text'\n\t\t\t\t? props.event.content.text\n\t\t\t\t: JSON.stringify(props.event.content.value);\n\tif (message === undefined || message.length === 0) {\n\t\treturn;\n\t}\n\tif (props.progressToken !== undefined) {\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\tparams: {\n\t\t\t\t\tmessage,\n\t\t\t\t\tprogress: props.event.kind === 'progress' ? (props.event.progress ?? 0) : 0,\n\t\t\t\t\tprogressToken: props.progressToken,\n\t\t\t\t\t...(props.event.kind === 'progress' && props.event.total !== undefined\n\t\t\t\t\t\t? { total: props.event.total }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tawait sendBestEffortNotification(\n\t\t{\n\t\t\tmethod: 'notifications/message',\n\t\t\tparams: {\n\t\t\t\tdata: message,\n\t\t\t\tlevel: 'info',\n\t\t\t},\n\t\t},\n\t\tprops.sendNotification,\n\t);\n}\n\nexport function createPortalMcpServer(props: {\n\treadonly core: PortalCore;\n\treadonly scope: PortalAgentScope;\n}): Server {\n\tconst server = new Server(\n\t\t{ name: 'mcp-portal', version: '1.0.0' },\n\t\t{ capabilities: { tools: { listChanged: false } } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: listPortalMcpTools(props.core.describeTools(props.scope)),\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n\t\tif (!isPortalCoreToolName(request.params.name)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ text: `Unknown MCP Portal tool: ${request.params.name}`, type: 'text' }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst result = await props.core.collectPortalCoreResult(\n\t\t\t\tprops.core.callStream({\n\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\tscope: props.scope,\n\t\t\t\t\tsignal: extra.signal,\n\t\t\t\t\ttoolName: request.params.name,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tonEvent: async (event) => {\n\t\t\t\t\t\tawait emitMcpProgress({\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\tprogressToken: extra['_meta']?.progressToken,\n\t\t\t\t\t\t\tsendNotification: extra.sendNotification,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn jsonToolResult(result);\n\t\t} catch (error) {\n\t\t\treturn errorToolResult(error);\n\t\t}\n\t});\n\n\treturn server;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport { StreamableHTTPTransport } from '@hono/mcp';\nimport { getConnInfo } from '@hono/node-server/conninfo';\nimport { Hono, type Context } from 'hono';\n\nimport type { PortalCore } from '../core/portal-core.js';\nimport { createPortalAgentIdentity, type PortalAgentIdentity } from '../portal-access-policy.js';\nimport { verifyAgentBearerAuthorization } from '../portal-auth/agent-bearer-token.js';\nimport { createPortalMcpServer } from './portal-mcp-server.js';\n\nexport interface PortalHttpAgentIdentity extends PortalAgentIdentity {}\n\nexport interface PortalAgentBearerAuth {\n\treadonly authorizationHeaderName: string;\n\treadonly credentialVersionsByAgent?: Readonly<Record<string, number>>;\n\treadonly masterKey: Buffer;\n}\n\nexport type PortalHttpAuditEvent = {\n\treadonly agentId: string;\n\treadonly clientAddress: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_proxy_auth';\n\treadonly reason?:\n\t\t| 'malformed'\n\t\t| 'missing'\n\t\t| 'rate_limited'\n\t\t| 'signature-mismatch'\n\t\t| 'unknown_agent';\n\treadonly timeMs: number;\n};\n\nexport interface PortalHttpAppOptions {\n\treadonly agentBearerAuth: PortalAgentBearerAuth;\n\treadonly auditErrorSink?: (error: Error, event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly auditSink?: (event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly authFailureLimit?: {\n\t\treadonly maxFailures: number;\n\t\treadonly windowMs: number;\n\t};\n\treadonly core: PortalCore;\n\treadonly onSessionClosed?: (identity: PortalAgentIdentity) => Promise<void> | void;\n\treadonly onSessionCloseError?: (\n\t\terror: Error,\n\t\tidentity: PortalAgentIdentity,\n\t) => Promise<void> | void;\n\treadonly registeredAgentIds?: readonly string[];\n\treadonly resolveAgentIdentity?: (agentId: string) => PortalHttpAgentIdentity | null;\n}\n\nexport type PortalHttpApp = Hono & {\n\treadonly closePortalSessions: () => Promise<void>;\n};\n\nconst mcpSessionIdHeader = 'mcp-session-id';\nconst defaultAuthFailureLimit = { maxFailures: 60, windowMs: 60_000 } as const;\nconst authFailureBucketLimit = 1_024;\nconst directClientAddress = 'direct-client';\nconst unknownAgentCredentialVersionForOpaqueAuthTiming = 1;\n\ninterface ActivePortalMcpSession {\n\treadonly identity: PortalAgentIdentity;\n\treadonly server: ReturnType<typeof createPortalMcpServer>;\n\treadonly transport: StreamableHTTPTransport;\n}\n\ninterface AuthFailureBucket {\n\treadonly resetAtMs: number;\n\tfailures: number;\n}\n\nfunction activeSessionKey(scopeId: string, sessionId: string): string {\n\treturn `${scopeId}\\n${sessionId}`;\n}\n\nfunction unauthorizedResponse(): Response {\n\treturn Response.json({ error: { kind: 'unauthorized' }, ok: false }, { status: 401 });\n}\n\nfunction rateLimitedResponse(): Response {\n\treturn Response.json({ error: { kind: 'rate_limited' }, ok: false }, { status: 429 });\n}\n\nfunction unavailableResponse(): Response {\n\treturn Response.json({ error: { kind: 'shutting_down' }, ok: false }, { status: 503 });\n}\n\nfunction errorFromUnknown(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction clientAddressFromContext(context: Context): string {\n\ttry {\n\t\tconst address = getConnInfo(context).remote.address;\n\t\treturn address && address.length > 0 ? address : directClientAddress;\n\t} catch {\n\t\treturn directClientAddress;\n\t}\n}\n\nexport function createPortalHttpApp(options: PortalHttpAppOptions): PortalHttpApp {\n\tif (options.agentBearerAuth === undefined) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth.');\n\t}\n\tif (options.agentBearerAuth.authorizationHeaderName.length === 0) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth header name.');\n\t}\n\tconst app = new Hono();\n\tconst activeSessions = new Map<string, ActivePortalMcpSession>();\n\tconst authFailureBuckets = new Map<string, AuthFailureBucket>();\n\tconst pendingNewSessionRequests = new Set<Promise<void>>();\n\tconst authFailureLimit = options.authFailureLimit ?? defaultAuthFailureLimit;\n\tlet closing = false;\n\n\tasync function auditAuth(event: Omit<PortalHttpAuditEvent, 'kind' | 'timeMs'>): Promise<void> {\n\t\tconst auditEvent = { ...event, kind: 'mcp_proxy_auth', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tawait options.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tawait options.auditErrorSink?.(errorFromUnknown(error), auditEvent);\n\t\t}\n\t}\n\n\tasync function reportSessionCloseError(\n\t\terror: unknown,\n\t\tidentity: PortalAgentIdentity,\n\t): Promise<void> {\n\t\tawait options.onSessionCloseError?.(errorFromUnknown(error), identity);\n\t}\n\n\tfunction pruneAuthFailureBuckets(nowMs: number): void {\n\t\tfor (const [key, bucket] of authFailureBuckets) {\n\t\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\t\tauthFailureBuckets.delete(key);\n\t\t\t}\n\t\t}\n\t\twhile (authFailureBuckets.size > authFailureBucketLimit) {\n\t\t\tconst firstKey = authFailureBuckets.keys().next().value;\n\t\t\tif (typeof firstKey !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthFailureBuckets.delete(firstKey);\n\t\t}\n\t}\n\n\tfunction isAuthFailureRateLimited(clientAddress: string): boolean {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket === undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\tauthFailureBuckets.delete(clientAddress);\n\t\t\treturn false;\n\t\t}\n\t\treturn bucket.failures >= authFailureLimit.maxFailures;\n\t}\n\n\tfunction recordAuthFailure(clientAddress: string): void {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket !== undefined && bucket.resetAtMs > nowMs) {\n\t\t\tbucket.failures += 1;\n\t\t\treturn;\n\t\t}\n\t\tauthFailureBuckets.set(clientAddress, {\n\t\t\tfailures: 1,\n\t\t\tresetAtMs: nowMs + authFailureLimit.windowMs,\n\t\t});\n\t\tpruneAuthFailureBuckets(nowMs);\n\t}\n\n\tfunction clearAuthFailures(clientAddress: string): void {\n\t\tauthFailureBuckets.delete(clientAddress);\n\t}\n\n\tasync function closeActiveSession(\n\t\tsessionKey: string,\n\t\tcloseOptions: { readonly closeTransport: boolean },\n\t): Promise<void> {\n\t\tconst activeSession = activeSessions.get(sessionKey);\n\t\tif (!activeSession) {\n\t\t\treturn;\n\t\t}\n\t\tactiveSessions.delete(sessionKey);\n\t\ttry {\n\t\t\tif (closeOptions.closeTransport) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t}\n\t\t} finally {\n\t\t\tawait options.onSessionClosed?.(activeSession.identity);\n\t\t}\n\t}\n\n\tfunction trackPendingNewSessionRequest(): () => void {\n\t\tlet resolvePending: (() => void) | undefined;\n\t\tconst pendingRequest = new Promise<void>((resolve) => {\n\t\t\tresolvePending = resolve;\n\t\t});\n\t\tpendingNewSessionRequests.add(pendingRequest);\n\t\treturn () => {\n\t\t\tpendingNewSessionRequests.delete(pendingRequest);\n\t\t\tresolvePending?.();\n\t\t};\n\t}\n\n\tasync function createActiveSession(\n\t\tidentityBase: PortalAgentIdentity,\n\t): Promise<ActivePortalMcpSession> {\n\t\tconst sessionId = randomUUID();\n\t\tconst sessionKey = activeSessionKey(identityBase.agentScopeId, sessionId);\n\t\tlet server: ReturnType<typeof createPortalMcpServer> | null = null;\n\t\tconst identity = createPortalAgentIdentity({\n\t\t\tagentId: identityBase.agentId,\n\t\t\tagentScopeId: identityBase.agentScopeId,\n\t\t\tsessionId,\n\t\t\tsource: identityBase.source,\n\t\t});\n\t\tconst transport = new StreamableHTTPTransport({\n\t\t\tonsessionclosed: () => {\n\t\t\t\tvoid closeActiveSession(sessionKey, { closeTransport: false }).catch((error: unknown) =>\n\t\t\t\t\treportSessionCloseError(error, identity),\n\t\t\t\t);\n\t\t\t},\n\t\t\tonsessioninitialized: (initializedSessionId) => {\n\t\t\t\tif (!server) {\n\t\t\t\t\tthrow new Error('MCP Portal session initialized before server connection.');\n\t\t\t\t}\n\t\t\t\tactiveSessions.set(activeSessionKey(identityBase.agentScopeId, initializedSessionId), {\n\t\t\t\t\tidentity,\n\t\t\t\t\tserver,\n\t\t\t\t\ttransport,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsessionIdGenerator: () => sessionId,\n\t\t});\n\t\tserver = createPortalMcpServer({\n\t\t\tcore: options.core,\n\t\t\tscope: identity,\n\t\t});\n\t\tawait server.connect(transport);\n\t\treturn { identity, server, transport };\n\t}\n\n\tasync function closePortalSessions(): Promise<void> {\n\t\tclosing = true;\n\t\tconst closeErrors: Error[] = [];\n\t\twhile (activeSessions.size > 0 || pendingNewSessionRequests.size > 0) {\n\t\t\tif (pendingNewSessionRequests.size > 0) {\n\t\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\t\tawait Promise.allSettled(pendingNewSessionRequests);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Closing may trigger callbacks that mutate activeSessions, so drain snapshots until empty.\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst closeResults = await Promise.allSettled(\n\t\t\t\t[...activeSessions.keys()].map((sessionKey) =>\n\t\t\t\t\tcloseActiveSession(sessionKey, { closeTransport: true }),\n\t\t\t\t),\n\t\t\t);\n\t\t\tcloseErrors.push(\n\t\t\t\t...closeResults\n\t\t\t\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t\t\t\t.map((result): Error => errorFromUnknown(result.reason)),\n\t\t\t);\n\t\t}\n\t\tif (closeErrors.length > 0) {\n\t\t\tthrow new AggregateError(closeErrors, 'Failed to close one or more MCP Portal sessions.');\n\t\t}\n\t}\n\n\tapp.get('/health', (context) =>\n\t\tcontext.json({ agents: [...(options.registeredAgentIds ?? [])].toSorted(), ok: true }),\n\t);\n\n\tapp.all('/agents/:agentId/mcp', async (context) => {\n\t\tconst agentId = context.req.param('agentId');\n\t\tconst clientAddress = clientAddressFromContext(context);\n\t\tif (closing) {\n\t\t\treturn unavailableResponse();\n\t\t}\n\t\tif (isAuthFailureRateLimited(clientAddress)) {\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'rate_limited',\n\t\t\t});\n\t\t\treturn rateLimitedResponse();\n\t\t}\n\t\tconst agentBearerAuth = options.agentBearerAuth;\n\t\tconst credentialVersion = agentBearerAuth.credentialVersionsByAgent?.[agentId];\n\t\tconst verification = verifyAgentBearerAuthorization({\n\t\t\tagentId,\n\t\t\tauthorizationHeader: context.req.header(agentBearerAuth.authorizationHeaderName),\n\t\t\tcredentialVersion: credentialVersion ?? unknownAgentCredentialVersionForOpaqueAuthTiming,\n\t\t\tmasterKey: agentBearerAuth.masterKey,\n\t\t});\n\t\tconst agentIdentity = options.resolveAgentIdentity?.(agentId) ?? null;\n\t\tif (agentIdentity === null) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'unknown_agent',\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tif (!verification.ok) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: verification.reason,\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tclearAuthFailures(clientAddress);\n\t\tawait auditAuth({ agentId, clientAddress, decision: 'allow' });\n\n\t\tconst mcpSessionId = context.req.header(mcpSessionIdHeader);\n\t\tif (mcpSessionId) {\n\t\t\tconst activeSession = activeSessions.get(\n\t\t\t\tactiveSessionKey(agentIdentity.agentScopeId, mcpSessionId),\n\t\t\t);\n\t\t\tif (!activeSession) {\n\t\t\t\treturn new Response('Unknown MCP portal session', { status: 404 });\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t}\n\n\t\tconst finishPendingRequest = trackPendingNewSessionRequest();\n\t\ttry {\n\t\t\tif (closing) {\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\tconst activeSession = await createActiveSession(agentIdentity);\n\t\t\tif (closing) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t} finally {\n\t\t\tfinishPendingRequest();\n\t\t}\n\t});\n\n\treturn Object.assign(app, { closePortalSessions });\n}\n","import {\n\tresolveMcpPortalProfile,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport { createPortalPolicyApprovalEvaluator } from '../core/portal-approval-evaluator.js';\nimport type {\n\tPortalApprovalCall,\n\tPortalApprovalCallDecision,\n\tPortalApprovalEvaluation,\n} from '../core/portal-tools.js';\nimport { createPortalAgentIdentity } from '../portal-access-policy.js';\n\nconst approvalTokenMaxLifetimeMs = 5 * 60_000;\nconst approvalTokenReplayCacheLimit = 4_096;\n\nexport interface ResolveAgentHmacKeysProps {\n\treadonly agents: Readonly<Record<string, McpPortalAgentConfig>>;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nexport interface PortalAgentRuntimeRecord {\n\treadonly agentId: string;\n\treadonly hmacKey: Buffer;\n\treadonly profile: ResolvedMcpPortalProfile;\n\treadonly profileName: string;\n}\n\nexport interface PortalApprovalAuditEvent {\n\treadonly agentId: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_portal_approval';\n\treadonly reason?:\n\t\t| 'approval_token_invalid'\n\t\t| 'approval_token_missing'\n\t\t| 'call_blocked'\n\t\t| 'no_approval_required'\n\t\t| 'per_call_evaluation';\n\treadonly timeMs: number;\n\treadonly verifierReason?: string;\n}\n\nasync function resolveAgentHmacKeyEntry(props: {\n\treadonly agent: McpPortalAgentConfig;\n\treadonly agentId: string;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<readonly [string, Buffer]> {\n\tconst envKey = props.envKeys.get(props.agentId);\n\tif (envKey !== undefined) {\n\t\treturn [props.agentId, envKey];\n\t}\n\tif (props.agent.hmacKey === undefined) {\n\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${props.agentId}\".`);\n\t}\n\tconst secretValue = await props.resolveSecret(props.agent.hmacKey);\n\tif (!/^[0-9a-f]+$/u.test(secretValue) || secretValue.length !== 64) {\n\t\tthrow new Error(`MCP Portal agent \"${props.agentId}\" HMAC key must be 64 hex characters.`);\n\t}\n\treturn [props.agentId, Buffer.from(secretValue, 'hex')];\n}\n\nexport async function resolveAgentHmacKeys(\n\tprops: ResolveAgentHmacKeysProps,\n): Promise<ReadonlyMap<string, Buffer>> {\n\treturn new Map(\n\t\tawait Promise.all(\n\t\t\tObject.entries(props.agents).map(([agentId, agent]) =>\n\t\t\t\tresolveAgentHmacKeyEntry({\n\t\t\t\t\tagent,\n\t\t\t\t\tagentId,\n\t\t\t\t\tenvKeys: props.envKeys,\n\t\t\t\t\tresolveSecret: props.resolveSecret,\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t);\n}\n\nexport function createPortalAgentRuntimeRecords(props: {\n\treadonly hmacKeys: ReadonlyMap<string, Buffer>;\n\treadonly portalConfig: McpPortalConfig;\n}): ReadonlyMap<string, PortalAgentRuntimeRecord> {\n\tconst records = new Map<string, PortalAgentRuntimeRecord>();\n\tfor (const [agentId, agent] of Object.entries(props.portalConfig.agents)) {\n\t\tconst hmacKey = props.hmacKeys.get(agentId);\n\t\tif (hmacKey === undefined) {\n\t\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\trecords.set(agentId, {\n\t\t\tagentId,\n\t\t\thmacKey,\n\t\t\tprofile: resolveMcpPortalProfile(props.portalConfig, agent.profile),\n\t\t\tprofileName: agent.profile,\n\t\t});\n\t}\n\treturn records;\n}\n\nexport function createPortalHttpAgentResolver(\n\trecords: ReadonlyMap<string, PortalAgentRuntimeRecord>,\n): (agentId: string) => ReturnType<typeof createPortalAgentIdentity> | null {\n\treturn (agentId) => {\n\t\tconst record = records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn createPortalAgentIdentity({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'mcp-proxy-bearer',\n\t\t});\n\t};\n}\n\nexport function createPortalApprovalVerifier(props: {\n\treadonly approvalTokenReplayCacheLimit?: number;\n\treadonly auditErrorSink?: (error: Error, event: PortalApprovalAuditEvent) => void;\n\treadonly auditSink?: (event: PortalApprovalAuditEvent) => void;\n\treadonly records: ReadonlyMap<string, PortalAgentRuntimeRecord>;\n}): (\n\tcalls: readonly PortalApprovalCall[],\n\tagentId: string,\n\ttoken: string | undefined,\n) => PortalApprovalEvaluation {\n\tfunction auditApproval(event: Omit<PortalApprovalAuditEvent, 'kind' | 'timeMs'>): void {\n\t\tconst auditEvent = { ...event, kind: 'mcp_portal_approval', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tprops.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tprops.auditErrorSink?.(error instanceof Error ? error : new Error(String(error)), auditEvent);\n\t\t}\n\t}\n\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = props.approvalTokenReplayCacheLimit ?? approvalTokenReplayCacheLimit;\n\tconst consumeTokenId = (\n\t\tagentId: string,\n\t\tjti: string,\n\t\texpiresAtMs: number,\n\t):\n\t\t| { readonly ok: true }\n\t\t| { readonly ok: false; readonly reason: 'replay-cache-full' | 'replayed' } => {\n\t\tconst nowMs = Date.now();\n\t\tfor (const [tokenKey, tokenExpiresAtMs] of consumedApprovalTokenIds) {\n\t\t\tif (tokenExpiresAtMs <= nowMs) {\n\t\t\t\tconsumedApprovalTokenIds.delete(tokenKey);\n\t\t\t}\n\t\t}\n\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t}\n\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t}\n\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\treturn { ok: true };\n\t};\n\tconst evaluateApproval = createPortalPolicyApprovalEvaluator({\n\t\tconsumeTokenId,\n\t\tmaxLifetimeMs: approvalTokenMaxLifetimeMs,\n\t\tresolveRecord: (agentId) => props.records.get(agentId),\n\t});\n\n\tfunction auditEvaluation(agentId: string, evaluation: PortalApprovalEvaluation): void {\n\t\tconst decisions = Object.values(evaluation.decisionsByCallId);\n\t\tconst firstDeny = decisions.find((decision) => decision.kind !== 'allow');\n\t\tif (firstDeny === undefined) {\n\t\t\tauditApproval({\n\t\t\t\tagentId,\n\t\t\t\tdecision: 'allow',\n\t\t\t\t...(decisions.length === 0 ? { reason: 'no_approval_required' } : {}),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tauditApproval({\n\t\t\tagentId,\n\t\t\tdecision: 'deny',\n\t\t\treason: auditReasonFromDecision(firstDeny),\n\t\t\t...(firstDeny.kind === 'approval_token_invalid' ? { verifierReason: firstDeny.reason } : {}),\n\t\t});\n\t}\n\n\treturn (calls, agentId, token) => {\n\t\tconst evaluation = evaluateApproval(calls, agentId, token);\n\t\tauditEvaluation(agentId, evaluation);\n\t\treturn evaluation;\n\t};\n}\n\nfunction auditReasonFromDecision(\n\tdecision: PortalApprovalCallDecision,\n): Exclude<PortalApprovalAuditEvent['reason'], undefined> {\n\tswitch (decision.kind) {\n\t\tcase 'allow':\n\t\t\treturn 'no_approval_required';\n\t\tcase 'approval_token_invalid':\n\t\t\treturn 'approval_token_invalid';\n\t\tcase 'approval_token_missing':\n\t\t\treturn 'approval_token_missing';\n\t\tcase 'call_blocked':\n\t\t\treturn 'call_blocked';\n\t\tcase 'approval_required':\n\t\tcase 'approval_configuration_missing':\n\t\t\treturn 'per_call_evaluation';\n\t\tdefault: {\n\t\t\tconst exhaustiveDecision: never = decision;\n\t\t\tthrow new Error(\n\t\t\t\t`Unhandled MCP Portal approval audit decision: ${JSON.stringify(exhaustiveDecision)}`,\n\t\t\t);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;AAmBA,MAAa,qBAAqB;CACjC;CACA;CACA;CACA;CACA;AAID,MAAM,uBAAuB,IAAI,IAAY,mBAAmB;AAEhE,SAAS,qBAAqB,OAA4C;CACzE,OAAO,qBAAqB,IAAI,MAAM;;AAGvC,SAAgB,mBACf,aACkB;CAClB,OACC,eAAe;EACd;GACC,aAAa;GACb,aAAa,uBAAuB;GACpC,MAAM;GACN;EACD;GACC,aAAa;GACb,aAAa,uBAAuB;GACpC,MAAM;GACN;EACD;GACC,aAAa;GACb,aAAa,uBAAuB;GACpC,MAAM;GACN;EACD;GACC,aAAa;GACb,aAAa,uBAAuB;GACpC,MAAM;GACN;EACD;;AAIH,SAAS,eAAe,OAAkD;CACzE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,kBAAkB,OAAkC;CAC5D,IAAI,MAAM,MAAM,MAAM,SAAS,KAAK,WAAW,SAAS,EACvD,OAAO;CAER,IAAI,CAAC,eAAe,MAAM,kBAAkB,EAC3C,OAAO;CAER,OAAO,MAAM,kBAAkB,OAAO;;AAGvC,SAAS,eAAe,OAAyC;CAChE,OAAO;EACN,SAAS,CAAC;GAAE,MAAM,KAAK,UAAU,MAAM;GAAE,MAAM;GAAQ,CAAC;EACxD,GAAI,kBAAkB,MAAM,GAAG,EAAE,SAAS,MAAM,GAAG,EAAE;EACrD;;AAGF,SAAS,gBAAgB,OAAgC;CAExD,OAAO;EACN,SAAS,CACR;GACC,MAJmB,kBAAkB,MAIlB,CAAC;GACpB,MAAM;GACN,CACD;EACD,SAAS;EACT;;AAGF,eAAe,2BACd,cAIA,kBAIgB;CAChB,IAAI;EACH,MAAM,iBAAiB,aAAa;SAC7B;;AAKT,eAAsB,gBAAgB,OAOpB;CACjB,IAAI,MAAM,MAAM,SAAS,yBAAyB;EACjD,IAAI,CAAC,eAAe,MAAM,MAAM,OAAO,EACtC;EAED,IAAI,MAAM,MAAM,WAAW,0BAA0B;GACpD,IAAI,MAAM,kBAAkB,KAAA,GAC3B;GAED,MAAM,2BACL;IACC,QAAQ;IACR,QAAQ;KAAE,GAAG,MAAM,MAAM;KAAQ,eAAe,MAAM;KAAe;IACrE,EACD,MAAM,iBACN;GACD;;EAED,IAAI,MAAM,MAAM,WAAW,yBAC1B;EAED,MAAM,2BACL;GACC,QAAQ;GACR,QAAQ,MAAM,MAAM;GACpB,EACD,MAAM,iBACN;EACD;;CAED,IAAI,MAAM,MAAM,SAAS,cAAc,MAAM,MAAM,SAAS,mBAC3D;CAED,MAAM,UACL,MAAM,MAAM,SAAS,aAClB,MAAM,MAAM,UACZ,MAAM,MAAM,QAAQ,SAAS,SAC5B,MAAM,MAAM,QAAQ,OACpB,KAAK,UAAU,MAAM,MAAM,QAAQ,MAAM;CAC9C,IAAI,YAAY,KAAA,KAAa,QAAQ,WAAW,GAC/C;CAED,IAAI,MAAM,kBAAkB,KAAA,GAAW;EACtC,MAAM,2BACL;GACC,QAAQ;GACR,QAAQ;IACP;IACA,UAAU,MAAM,MAAM,SAAS,aAAc,MAAM,MAAM,YAAY,IAAK;IAC1E,eAAe,MAAM;IACrB,GAAI,MAAM,MAAM,SAAS,cAAc,MAAM,MAAM,UAAU,KAAA,IAC1D,EAAE,OAAO,MAAM,MAAM,OAAO,GAC5B,EAAE;IACL;GACD,EACD,MAAM,iBACN;EACD;;CAED,MAAM,2BACL;EACC,QAAQ;EACR,QAAQ;GACP,MAAM;GACN,OAAO;GACP;EACD,EACD,MAAM,iBACN;;AAGF,SAAgB,sBAAsB,OAG3B;CACV,MAAM,SAAS,IAAI,OAClB;EAAE,MAAM;EAAc,SAAS;EAAS,EACxC,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,OAAO,EAAE,EAAE,CACnD;CAED,OAAO,kBAAkB,wBAAwB,aAAa,EAC7D,OAAO,mBAAmB,MAAM,KAAK,cAAc,MAAM,MAAM,CAAC,EAChE,EAAE;CAEH,OAAO,kBAAkB,uBAAuB,OAAO,SAAS,UAAU;EACzE,IAAI,CAAC,qBAAqB,QAAQ,OAAO,KAAK,EAC7C,OAAO;GACN,SAAS,CAAC;IAAE,MAAM,4BAA4B,QAAQ,OAAO;IAAQ,MAAM;IAAQ,CAAC;GACpF,SAAS;GACT;EAEF,IAAI;GAkBH,OAAO,eAAe,MAjBD,MAAM,KAAK,wBAC/B,MAAM,KAAK,WAAW;IACrB,OAAO,QAAQ,OAAO,aAAa,EAAE;IACrC,OAAO,MAAM;IACb,QAAQ,MAAM;IACd,UAAU,QAAQ,OAAO;IACzB,CAAC,EACF,EACC,SAAS,OAAO,UAAU;IACzB,MAAM,gBAAgB;KACrB;KACA,eAAe,MAAM,UAAU;KAC/B,kBAAkB,MAAM;KACxB,CAAC;MAEH,CACD,CAC4B;WACrB,OAAO;GACf,OAAO,gBAAgB,MAAM;;GAE7B;CAEF,OAAO;;;;ACrLR,MAAM,qBAAqB;AAC3B,MAAM,0BAA0B;CAAE,aAAa;CAAI,UAAU;CAAQ;AACrE,MAAM,yBAAyB;AAC/B,MAAM,sBAAsB;AAC5B,MAAM,mDAAmD;AAazD,SAAS,iBAAiB,SAAiB,WAA2B;CACrE,OAAO,GAAG,QAAQ,IAAI;;AAGvB,SAAS,uBAAiC;CACzC,OAAO,SAAS,KAAK;EAAE,OAAO,EAAE,MAAM,gBAAgB;EAAE,IAAI;EAAO,EAAE,EAAE,QAAQ,KAAK,CAAC;;AAGtF,SAAS,sBAAgC;CACxC,OAAO,SAAS,KAAK;EAAE,OAAO,EAAE,MAAM,gBAAgB;EAAE,IAAI;EAAO,EAAE,EAAE,QAAQ,KAAK,CAAC;;AAGtF,SAAS,sBAAgC;CACxC,OAAO,SAAS,KAAK;EAAE,OAAO,EAAE,MAAM,iBAAiB;EAAE,IAAI;EAAO,EAAE,EAAE,QAAQ,KAAK,CAAC;;AAGvF,SAAS,iBAAiB,OAAuB;CAChD,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;;AAGjE,SAAS,yBAAyB,SAA0B;CAC3D,IAAI;EACH,MAAM,UAAU,YAAY,QAAQ,CAAC,OAAO;EAC5C,OAAO,WAAW,QAAQ,SAAS,IAAI,UAAU;SAC1C;EACP,OAAO;;;AAIT,SAAgB,oBAAoB,SAA8C;CACjF,IAAI,QAAQ,oBAAoB,KAAA,GAC/B,MAAM,IAAI,MAAM,kDAAkD;CAEnE,IAAI,QAAQ,gBAAgB,wBAAwB,WAAW,GAC9D,MAAM,IAAI,MAAM,8DAA8D;CAE/E,MAAM,MAAM,IAAI,MAAM;CACtB,MAAM,iCAAiB,IAAI,KAAqC;CAChE,MAAM,qCAAqB,IAAI,KAAgC;CAC/D,MAAM,4CAA4B,IAAI,KAAoB;CAC1D,MAAM,mBAAmB,QAAQ,oBAAoB;CACrD,IAAI,UAAU;CAEd,eAAe,UAAU,OAAqE;EAC7F,MAAM,aAAa;GAAE,GAAG;GAAO,MAAM;GAAkB,QAAQ,KAAK,KAAK;GAAE;EAC3E,IAAI;GACH,MAAM,QAAQ,YAAY,WAAW;WAC7B,OAAO;GACf,MAAM,QAAQ,iBAAiB,iBAAiB,MAAM,EAAE,WAAW;;;CAIrE,eAAe,wBACd,OACA,UACgB;EAChB,MAAM,QAAQ,sBAAsB,iBAAiB,MAAM,EAAE,SAAS;;CAGvE,SAAS,wBAAwB,OAAqB;EACrD,KAAK,MAAM,CAAC,KAAK,WAAW,oBAC3B,IAAI,OAAO,aAAa,OACvB,mBAAmB,OAAO,IAAI;EAGhC,OAAO,mBAAmB,OAAO,wBAAwB;GACxD,MAAM,WAAW,mBAAmB,MAAM,CAAC,MAAM,CAAC;GAClD,IAAI,OAAO,aAAa,UACvB;GAED,mBAAmB,OAAO,SAAS;;;CAIrC,SAAS,yBAAyB,eAAgC;EACjE,MAAM,QAAQ,KAAK,KAAK;EACxB,wBAAwB,MAAM;EAC9B,MAAM,SAAS,mBAAmB,IAAI,cAAc;EACpD,IAAI,WAAW,KAAA,GACd,OAAO;EAER,IAAI,OAAO,aAAa,OAAO;GAC9B,mBAAmB,OAAO,cAAc;GACxC,OAAO;;EAER,OAAO,OAAO,YAAY,iBAAiB;;CAG5C,SAAS,kBAAkB,eAA6B;EACvD,MAAM,QAAQ,KAAK,KAAK;EACxB,wBAAwB,MAAM;EAC9B,MAAM,SAAS,mBAAmB,IAAI,cAAc;EACpD,IAAI,WAAW,KAAA,KAAa,OAAO,YAAY,OAAO;GACrD,OAAO,YAAY;GACnB;;EAED,mBAAmB,IAAI,eAAe;GACrC,UAAU;GACV,WAAW,QAAQ,iBAAiB;GACpC,CAAC;EACF,wBAAwB,MAAM;;CAG/B,SAAS,kBAAkB,eAA6B;EACvD,mBAAmB,OAAO,cAAc;;CAGzC,eAAe,mBACd,YACA,cACgB;EAChB,MAAM,gBAAgB,eAAe,IAAI,WAAW;EACpD,IAAI,CAAC,eACJ;EAED,eAAe,OAAO,WAAW;EACjC,IAAI;GACH,IAAI,aAAa,gBAChB,MAAM,cAAc,UAAU,OAAO;YAE7B;GACT,MAAM,QAAQ,kBAAkB,cAAc,SAAS;;;CAIzD,SAAS,gCAA4C;EACpD,IAAI;EACJ,MAAM,iBAAiB,IAAI,SAAe,YAAY;GACrD,iBAAiB;IAChB;EACF,0BAA0B,IAAI,eAAe;EAC7C,aAAa;GACZ,0BAA0B,OAAO,eAAe;GAChD,kBAAkB;;;CAIpB,eAAe,oBACd,cACkC;EAClC,MAAM,YAAY,YAAY;EAC9B,MAAM,aAAa,iBAAiB,aAAa,cAAc,UAAU;EACzE,IAAI,SAA0D;EAC9D,MAAM,WAAW,0BAA0B;GAC1C,SAAS,aAAa;GACtB,cAAc,aAAa;GAC3B;GACA,QAAQ,aAAa;GACrB,CAAC;EACF,MAAM,YAAY,IAAI,wBAAwB;GAC7C,uBAAuB;IACtB,mBAAwB,YAAY,EAAE,gBAAgB,OAAO,CAAC,CAAC,OAAO,UACrE,wBAAwB,OAAO,SAAS,CACxC;;GAEF,uBAAuB,yBAAyB;IAC/C,IAAI,CAAC,QACJ,MAAM,IAAI,MAAM,2DAA2D;IAE5E,eAAe,IAAI,iBAAiB,aAAa,cAAc,qBAAqB,EAAE;KACrF;KACA;KACA;KACA,CAAC;;GAEH,0BAA0B;GAC1B,CAAC;EACF,SAAS,sBAAsB;GAC9B,MAAM,QAAQ;GACd,OAAO;GACP,CAAC;EACF,MAAM,OAAO,QAAQ,UAAU;EAC/B,OAAO;GAAE;GAAU;GAAQ;GAAW;;CAGvC,eAAe,sBAAqC;EACnD,UAAU;EACV,MAAM,cAAuB,EAAE;EAC/B,OAAO,eAAe,OAAO,KAAK,0BAA0B,OAAO,GAAG;GACrE,IAAI,0BAA0B,OAAO,GAAG;IAEvC,MAAM,QAAQ,WAAW,0BAA0B;IACnD;;GAID,MAAM,eAAe,MAAM,QAAQ,WAClC,CAAC,GAAG,eAAe,MAAM,CAAC,CAAC,KAAK,eAC/B,mBAAmB,YAAY,EAAE,gBAAgB,MAAM,CAAC,CACxD,CACD;GACD,YAAY,KACX,GAAG,aACD,QAAQ,WAA4C,OAAO,WAAW,WAAW,CACjF,KAAK,WAAkB,iBAAiB,OAAO,OAAO,CAAC,CACzD;;EAEF,IAAI,YAAY,SAAS,GACxB,MAAM,IAAI,eAAe,aAAa,mDAAmD;;CAI3F,IAAI,IAAI,YAAY,YACnB,QAAQ,KAAK;EAAE,QAAQ,CAAC,GAAI,QAAQ,sBAAsB,EAAE,CAAE,CAAC,UAAU;EAAE,IAAI;EAAM,CAAC,CACtF;CAED,IAAI,IAAI,wBAAwB,OAAO,YAAY;EAClD,MAAM,UAAU,QAAQ,IAAI,MAAM,UAAU;EAC5C,MAAM,gBAAgB,yBAAyB,QAAQ;EACvD,IAAI,SACH,OAAO,qBAAqB;EAE7B,IAAI,yBAAyB,cAAc,EAAE;GAC5C,MAAM,UAAU;IACf;IACA;IACA,UAAU;IACV,QAAQ;IACR,CAAC;GACF,OAAO,qBAAqB;;EAE7B,MAAM,kBAAkB,QAAQ;EAChC,MAAM,oBAAoB,gBAAgB,4BAA4B;EACtE,MAAM,eAAe,+BAA+B;GACnD;GACA,qBAAqB,QAAQ,IAAI,OAAO,gBAAgB,wBAAwB;GAChF,mBAAmB,qBAAqB;GACxC,WAAW,gBAAgB;GAC3B,CAAC;EACF,MAAM,gBAAgB,QAAQ,uBAAuB,QAAQ,IAAI;EACjE,IAAI,kBAAkB,MAAM;GAC3B,kBAAkB,cAAc;GAChC,MAAM,UAAU;IACf;IACA;IACA,UAAU;IACV,QAAQ;IACR,CAAC;GACF,OAAO,sBAAsB;;EAE9B,IAAI,CAAC,aAAa,IAAI;GACrB,kBAAkB,cAAc;GAChC,MAAM,UAAU;IACf;IACA;IACA,UAAU;IACV,QAAQ,aAAa;IACrB,CAAC;GACF,OAAO,sBAAsB;;EAE9B,kBAAkB,cAAc;EAChC,MAAM,UAAU;GAAE;GAAS;GAAe,UAAU;GAAS,CAAC;EAE9D,MAAM,eAAe,QAAQ,IAAI,OAAO,mBAAmB;EAC3D,IAAI,cAAc;GACjB,MAAM,gBAAgB,eAAe,IACpC,iBAAiB,cAAc,cAAc,aAAa,CAC1D;GACD,IAAI,CAAC,eACJ,OAAO,IAAI,SAAS,8BAA8B,EAAE,QAAQ,KAAK,CAAC;GAEnE,OAAO,MAAM,cAAc,UAAU,cAAc,QAAQ;;EAG5D,MAAM,uBAAuB,+BAA+B;EAC5D,IAAI;GACH,IAAI,SACH,OAAO,qBAAqB;GAE7B,MAAM,gBAAgB,MAAM,oBAAoB,cAAc;GAC9D,IAAI,SAAS;IACZ,MAAM,cAAc,UAAU,OAAO;IACrC,OAAO,qBAAqB;;GAE7B,OAAO,MAAM,cAAc,UAAU,cAAc,QAAQ;YAClD;GACT,sBAAsB;;GAEtB;CAEF,OAAO,OAAO,OAAO,KAAK,EAAE,qBAAqB,CAAC;;;;AChVnD,MAAM,6BAA6B,IAAI;AACvC,MAAM,gCAAgC;AA6BtC,eAAe,yBAAyB,OAKD;CACtC,MAAM,SAAS,MAAM,QAAQ,IAAI,MAAM,QAAQ;CAC/C,IAAI,WAAW,KAAA,GACd,OAAO,CAAC,MAAM,SAAS,OAAO;CAE/B,IAAI,MAAM,MAAM,YAAY,KAAA,GAC3B,MAAM,IAAI,MAAM,0CAA0C,MAAM,QAAQ,IAAI;CAE7E,MAAM,cAAc,MAAM,MAAM,cAAc,MAAM,MAAM,QAAQ;CAClE,IAAI,CAAC,eAAe,KAAK,YAAY,IAAI,YAAY,WAAW,IAC/D,MAAM,IAAI,MAAM,qBAAqB,MAAM,QAAQ,uCAAuC;CAE3F,OAAO,CAAC,MAAM,SAAS,OAAO,KAAK,aAAa,MAAM,CAAC;;AAGxD,eAAsB,qBACrB,OACuC;CACvC,OAAO,IAAI,IACV,MAAM,QAAQ,IACb,OAAO,QAAQ,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,WAC3C,yBAAyB;EACxB;EACA;EACA,SAAS,MAAM;EACf,eAAe,MAAM;EACrB,CAAC,CACF,CACD,CACD;;AAGF,SAAgB,gCAAgC,OAGE;CACjD,MAAM,0BAAU,IAAI,KAAuC;CAC3D,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,MAAM,aAAa,OAAO,EAAE;EACzE,MAAM,UAAU,MAAM,SAAS,IAAI,QAAQ;EAC3C,IAAI,YAAY,KAAA,GACf,MAAM,IAAI,MAAM,0CAA0C,QAAQ,IAAI;EAEvE,QAAQ,IAAI,SAAS;GACpB;GACA;GACA,SAAS,wBAAwB,MAAM,cAAc,MAAM,QAAQ;GACnE,aAAa,MAAM;GACnB,CAAC;;CAEH,OAAO;;AAGR,SAAgB,8BACf,SAC2E;CAC3E,QAAQ,YAAY;EAEnB,IADe,QAAQ,IAAI,QACjB,KAAK,KAAA,GACd,OAAO;EAER,OAAO,0BAA0B;GAChC;GACA,cAAc;GACd,QAAQ;GACR,CAAC;;;AAIJ,SAAgB,6BAA6B,OASf;CAC7B,SAAS,cAAc,OAAgE;EACtF,MAAM,aAAa;GAAE,GAAG;GAAO,MAAM;GAAuB,QAAQ,KAAK,KAAK;GAAE;EAChF,IAAI;GACH,MAAM,YAAY,WAAW;WACrB,OAAO;GACf,MAAM,iBAAiB,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,EAAE,WAAW;;;CAI/F,MAAM,2CAA2B,IAAI,KAAqB;CAC1D,MAAM,mBAAmB,MAAM,iCAAiC;CAChE,MAAM,kBACL,SACA,KACA,gBAG+E;EAC/E,MAAM,QAAQ,KAAK,KAAK;EACxB,KAAK,MAAM,CAAC,UAAU,qBAAqB,0BAC1C,IAAI,oBAAoB,OACvB,yBAAyB,OAAO,SAAS;EAG3C,MAAM,WAAW,GAAG,QAAQ,IAAI;EAChC,IAAI,yBAAyB,IAAI,SAAS,EACzC,OAAO;GAAE,IAAI;GAAO,QAAQ;GAAY;EAEzC,IAAI,yBAAyB,QAAQ,kBACpC,OAAO;GAAE,IAAI;GAAO,QAAQ;GAAqB;EAElD,yBAAyB,IAAI,UAAU,YAAY;EACnD,OAAO,EAAE,IAAI,MAAM;;CAEpB,MAAM,mBAAmB,oCAAoC;EAC5D;EACA,eAAe;EACf,gBAAgB,YAAY,MAAM,QAAQ,IAAI,QAAQ;EACtD,CAAC;CAEF,SAAS,gBAAgB,SAAiB,YAA4C;EACrF,MAAM,YAAY,OAAO,OAAO,WAAW,kBAAkB;EAC7D,MAAM,YAAY,UAAU,MAAM,aAAa,SAAS,SAAS,QAAQ;EACzE,IAAI,cAAc,KAAA,GAAW;GAC5B,cAAc;IACb;IACA,UAAU;IACV,GAAI,UAAU,WAAW,IAAI,EAAE,QAAQ,wBAAwB,GAAG,EAAE;IACpE,CAAC;GACF;;EAED,cAAc;GACb;GACA,UAAU;GACV,QAAQ,wBAAwB,UAAU;GAC1C,GAAI,UAAU,SAAS,2BAA2B,EAAE,gBAAgB,UAAU,QAAQ,GAAG,EAAE;GAC3F,CAAC;;CAGH,QAAQ,OAAO,SAAS,UAAU;EACjC,MAAM,aAAa,iBAAiB,OAAO,SAAS,MAAM;EAC1D,gBAAgB,SAAS,WAAW;EACpC,OAAO;;;AAIT,SAAS,wBACR,UACyD;CACzD,QAAQ,SAAS,MAAjB;EACC,KAAK,SACJ,OAAO;EACR,KAAK,0BACJ,OAAO;EACR,KAAK,0BACJ,OAAO;EACR,KAAK,gBACJ,OAAO;EACR,KAAK;EACL,KAAK,kCACJ,OAAO;EACR,SAEC,MAAM,IAAI,MACT,iDAAiD,KAAK,UAAUA,SAAmB,GACnF"}
|
|
1
|
+
{"version":3,"file":"resolve-agent-identity-BK4WlZgd.js","names":["exhaustiveDecision"],"sources":["../src/mcp-proxy/portal-mcp-server.ts","../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n\tCallToolRequestSchema,\n\tListToolsRequestSchema,\n\ttype CallToolResult,\n\ttype Tool,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport type {\n\tPortalAgentScope,\n\tPortalCore,\n\tPortalCoreEvent,\n\tPortalCoreToolDescriptor,\n\tPortalCoreResult,\n\tPortalCoreToolName,\n} from '../core/portal-core.js';\nimport { portalToolInputSchemas } from '../core/portal-tools.js';\nimport { redactThrownError } from '../upstream-response-middleware.js';\n\nexport const portalMcpToolNames = [\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n] as const;\n\nexport type PortalMcpToolName = (typeof portalMcpToolNames)[number];\n\nconst portalMcpToolNameSet = new Set<string>(portalMcpToolNames);\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalMcpToolNameSet.has(value);\n}\n\nexport function listPortalMcpTools(\n\tdescriptors?: readonly PortalCoreToolDescriptor[],\n): readonly Tool[] {\n\treturn (\n\t\tdescriptors ?? [\n\t\t\t{\n\t\t\t\tdescription: 'List authorized MCP namespaces and compact tool summaries.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_list,\n\t\t\t\tname: 'mcp_portal_list',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\t\tname: 'mcp_portal_search',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\t\tname: 'mcp_portal_describe',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\t\tname: 'mcp_portal_call',\n\t\t\t},\n\t\t]\n\t);\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction coreResultIsError(value: PortalCoreResult): boolean {\n\tif (value.items.some((item) => item.status === 'failed')) {\n\t\treturn true;\n\t}\n\tif (!isObjectRecord(value.structuredContent)) {\n\t\treturn false;\n\t}\n\treturn value.structuredContent.ok === false;\n}\n\nfunction jsonToolResult(value: PortalCoreResult): CallToolResult {\n\treturn {\n\t\tcontent: [{ text: JSON.stringify(value), type: 'text' }],\n\t\t...(coreResultIsError(value) ? { isError: true } : {}),\n\t};\n}\n\nfunction errorToolResult(error: unknown): CallToolResult {\n\tconst redactedError = redactThrownError(error);\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttext: redactedError.message,\n\t\t\t\ttype: 'text',\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\nasync function sendBestEffortNotification(\n\tnotification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t},\n\tsendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tawait sendNotification(notification);\n\t} catch {\n\t\t// Progress is advisory; unsupported client notification channels must not fail the tool call.\n\t}\n}\n\nexport async function emitMcpProgress(props: {\n\treadonly event: PortalCoreEvent;\n\treadonly sendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>;\n\treadonly progressToken: number | string | undefined;\n}): Promise<void> {\n\tif (props.event.kind === 'upstream_notification') {\n\t\tif (!isObjectRecord(props.event.params)) {\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method === 'notifications/progress') {\n\t\t\tif (props.progressToken === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait sendBestEffortNotification(\n\t\t\t\t{\n\t\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\t\tparams: { ...props.event.params, progressToken: props.progressToken },\n\t\t\t\t},\n\t\t\t\tprops.sendNotification,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method !== 'notifications/message') {\n\t\t\treturn;\n\t\t}\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/message',\n\t\t\t\tparams: props.event.params,\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tif (props.event.kind !== 'progress' && props.event.kind !== 'partial_content') {\n\t\treturn;\n\t}\n\tconst message =\n\t\tprops.event.kind === 'progress'\n\t\t\t? props.event.message\n\t\t\t: props.event.content.type === 'text'\n\t\t\t\t? props.event.content.text\n\t\t\t\t: JSON.stringify(props.event.content.value);\n\tif (message === undefined || message.length === 0) {\n\t\treturn;\n\t}\n\tif (props.progressToken !== undefined) {\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\tparams: {\n\t\t\t\t\tmessage,\n\t\t\t\t\tprogress: props.event.kind === 'progress' ? (props.event.progress ?? 0) : 0,\n\t\t\t\t\tprogressToken: props.progressToken,\n\t\t\t\t\t...(props.event.kind === 'progress' && props.event.total !== undefined\n\t\t\t\t\t\t? { total: props.event.total }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tawait sendBestEffortNotification(\n\t\t{\n\t\t\tmethod: 'notifications/message',\n\t\t\tparams: {\n\t\t\t\tdata: message,\n\t\t\t\tlevel: 'info',\n\t\t\t},\n\t\t},\n\t\tprops.sendNotification,\n\t);\n}\n\nexport function createPortalMcpServer(props: {\n\treadonly core: PortalCore;\n\treadonly scope: PortalAgentScope;\n}): Server {\n\tconst server = new Server(\n\t\t{ name: 'mcp-portal', version: '1.0.0' },\n\t\t{ capabilities: { tools: { listChanged: false } } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: listPortalMcpTools(props.core.describeTools(props.scope)),\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n\t\tif (!isPortalCoreToolName(request.params.name)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ text: `Unknown MCP Portal tool: ${request.params.name}`, type: 'text' }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst result = await props.core.collectPortalCoreResult(\n\t\t\t\tprops.core.callStream({\n\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\tscope: props.scope,\n\t\t\t\t\tsignal: extra.signal,\n\t\t\t\t\ttoolName: request.params.name,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tonEvent: async (event) => {\n\t\t\t\t\t\tawait emitMcpProgress({\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\tprogressToken: extra['_meta']?.progressToken,\n\t\t\t\t\t\t\tsendNotification: extra.sendNotification,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn jsonToolResult(result);\n\t\t} catch (error) {\n\t\t\treturn errorToolResult(error);\n\t\t}\n\t});\n\n\treturn server;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport { StreamableHTTPTransport } from '@hono/mcp';\nimport { getConnInfo } from '@hono/node-server/conninfo';\nimport { Hono, type Context } from 'hono';\n\nimport type { PortalCore } from '../core/portal-core.js';\nimport { createPortalAgentIdentity, type PortalAgentIdentity } from '../portal-access-policy.js';\nimport { verifyAgentBearerAuthorization } from '../portal-auth/agent-bearer-token.js';\nimport { createPortalMcpServer } from './portal-mcp-server.js';\n\nexport interface PortalHttpAgentIdentity extends PortalAgentIdentity {}\n\nexport interface PortalAgentBearerAuth {\n\treadonly authorizationHeaderName: string;\n\treadonly credentialVersionsByAgent?: Readonly<Record<string, number>>;\n\treadonly masterKey: Buffer;\n}\n\nexport type PortalHttpAuditEvent = {\n\treadonly agentId: string;\n\treadonly clientAddress: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_proxy_auth';\n\treadonly reason?:\n\t\t| 'malformed'\n\t\t| 'missing'\n\t\t| 'rate_limited'\n\t\t| 'signature-mismatch'\n\t\t| 'unknown_agent';\n\treadonly timeMs: number;\n};\n\nexport interface PortalHttpAppOptions {\n\treadonly agentBearerAuth: PortalAgentBearerAuth;\n\treadonly auditErrorSink?: (error: Error, event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly auditSink?: (event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly authFailureLimit?: {\n\t\treadonly maxFailures: number;\n\t\treadonly windowMs: number;\n\t};\n\treadonly core: PortalCore;\n\treadonly onSessionClosed?: (identity: PortalAgentIdentity) => Promise<void> | void;\n\treadonly onSessionCloseError?: (\n\t\terror: Error,\n\t\tidentity: PortalAgentIdentity,\n\t) => Promise<void> | void;\n\treadonly registeredAgentIds?: readonly string[];\n\treadonly resolveAgentIdentity?: (agentId: string) => PortalHttpAgentIdentity | null;\n}\n\nexport type PortalHttpApp = Hono & {\n\treadonly closePortalSessions: () => Promise<void>;\n};\n\nconst mcpSessionIdHeader = 'mcp-session-id';\nconst defaultAuthFailureLimit = { maxFailures: 60, windowMs: 60_000 } as const;\nconst authFailureBucketLimit = 1_024;\nconst directClientAddress = 'direct-client';\nconst unknownAgentCredentialVersionForOpaqueAuthTiming = 1;\n\ninterface ActivePortalMcpSession {\n\treadonly identity: PortalAgentIdentity;\n\treadonly server: ReturnType<typeof createPortalMcpServer>;\n\treadonly transport: StreamableHTTPTransport;\n}\n\ninterface AuthFailureBucket {\n\treadonly resetAtMs: number;\n\tfailures: number;\n}\n\nfunction activeSessionKey(scopeId: string, sessionId: string): string {\n\treturn `${scopeId}\\n${sessionId}`;\n}\n\nfunction unauthorizedResponse(): Response {\n\treturn Response.json({ error: { kind: 'unauthorized' }, ok: false }, { status: 401 });\n}\n\nfunction rateLimitedResponse(): Response {\n\treturn Response.json({ error: { kind: 'rate_limited' }, ok: false }, { status: 429 });\n}\n\nfunction unavailableResponse(): Response {\n\treturn Response.json({ error: { kind: 'shutting_down' }, ok: false }, { status: 503 });\n}\n\nfunction errorFromUnknown(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction clientAddressFromContext(context: Context): string {\n\ttry {\n\t\tconst address = getConnInfo(context).remote.address;\n\t\treturn address && address.length > 0 ? address : directClientAddress;\n\t} catch {\n\t\treturn directClientAddress;\n\t}\n}\n\nexport function createPortalHttpApp(options: PortalHttpAppOptions): PortalHttpApp {\n\tif (options.agentBearerAuth === undefined) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth.');\n\t}\n\tif (options.agentBearerAuth.authorizationHeaderName.length === 0) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth header name.');\n\t}\n\tconst app = new Hono();\n\tconst activeSessions = new Map<string, ActivePortalMcpSession>();\n\tconst authFailureBuckets = new Map<string, AuthFailureBucket>();\n\tconst pendingNewSessionRequests = new Set<Promise<void>>();\n\tconst authFailureLimit = options.authFailureLimit ?? defaultAuthFailureLimit;\n\tlet closing = false;\n\n\tasync function auditAuth(event: Omit<PortalHttpAuditEvent, 'kind' | 'timeMs'>): Promise<void> {\n\t\tconst auditEvent = { ...event, kind: 'mcp_proxy_auth', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tawait options.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tawait options.auditErrorSink?.(errorFromUnknown(error), auditEvent);\n\t\t}\n\t}\n\n\tasync function reportSessionCloseError(\n\t\terror: unknown,\n\t\tidentity: PortalAgentIdentity,\n\t): Promise<void> {\n\t\tawait options.onSessionCloseError?.(errorFromUnknown(error), identity);\n\t}\n\n\tfunction pruneAuthFailureBuckets(nowMs: number): void {\n\t\tfor (const [key, bucket] of authFailureBuckets) {\n\t\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\t\tauthFailureBuckets.delete(key);\n\t\t\t}\n\t\t}\n\t\twhile (authFailureBuckets.size > authFailureBucketLimit) {\n\t\t\tconst firstKey = authFailureBuckets.keys().next().value;\n\t\t\tif (typeof firstKey !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthFailureBuckets.delete(firstKey);\n\t\t}\n\t}\n\n\tfunction isAuthFailureRateLimited(clientAddress: string): boolean {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket === undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\tauthFailureBuckets.delete(clientAddress);\n\t\t\treturn false;\n\t\t}\n\t\treturn bucket.failures >= authFailureLimit.maxFailures;\n\t}\n\n\tfunction recordAuthFailure(clientAddress: string): void {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket !== undefined && bucket.resetAtMs > nowMs) {\n\t\t\tbucket.failures += 1;\n\t\t\treturn;\n\t\t}\n\t\tauthFailureBuckets.set(clientAddress, {\n\t\t\tfailures: 1,\n\t\t\tresetAtMs: nowMs + authFailureLimit.windowMs,\n\t\t});\n\t\tpruneAuthFailureBuckets(nowMs);\n\t}\n\n\tfunction clearAuthFailures(clientAddress: string): void {\n\t\tauthFailureBuckets.delete(clientAddress);\n\t}\n\n\tasync function closeActiveSession(\n\t\tsessionKey: string,\n\t\tcloseOptions: { readonly closeTransport: boolean },\n\t): Promise<void> {\n\t\tconst activeSession = activeSessions.get(sessionKey);\n\t\tif (!activeSession) {\n\t\t\treturn;\n\t\t}\n\t\tactiveSessions.delete(sessionKey);\n\t\ttry {\n\t\t\tif (closeOptions.closeTransport) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t}\n\t\t} finally {\n\t\t\tawait options.onSessionClosed?.(activeSession.identity);\n\t\t}\n\t}\n\n\tfunction trackPendingNewSessionRequest(): () => void {\n\t\tlet resolvePending: (() => void) | undefined;\n\t\tconst pendingRequest = new Promise<void>((resolve) => {\n\t\t\tresolvePending = resolve;\n\t\t});\n\t\tpendingNewSessionRequests.add(pendingRequest);\n\t\treturn () => {\n\t\t\tpendingNewSessionRequests.delete(pendingRequest);\n\t\t\tresolvePending?.();\n\t\t};\n\t}\n\n\tasync function createActiveSession(\n\t\tidentityBase: PortalAgentIdentity,\n\t): Promise<ActivePortalMcpSession> {\n\t\tconst sessionId = randomUUID();\n\t\tconst sessionKey = activeSessionKey(identityBase.agentScopeId, sessionId);\n\t\tlet server: ReturnType<typeof createPortalMcpServer> | null = null;\n\t\tconst identity = createPortalAgentIdentity({\n\t\t\tagentId: identityBase.agentId,\n\t\t\tagentScopeId: identityBase.agentScopeId,\n\t\t\tsessionId,\n\t\t\tsource: identityBase.source,\n\t\t});\n\t\tconst transport = new StreamableHTTPTransport({\n\t\t\tonsessionclosed: () => {\n\t\t\t\tvoid closeActiveSession(sessionKey, { closeTransport: false }).catch((error: unknown) =>\n\t\t\t\t\treportSessionCloseError(error, identity),\n\t\t\t\t);\n\t\t\t},\n\t\t\tonsessioninitialized: (initializedSessionId) => {\n\t\t\t\tif (!server) {\n\t\t\t\t\tthrow new Error('MCP Portal session initialized before server connection.');\n\t\t\t\t}\n\t\t\t\tactiveSessions.set(activeSessionKey(identityBase.agentScopeId, initializedSessionId), {\n\t\t\t\t\tidentity,\n\t\t\t\t\tserver,\n\t\t\t\t\ttransport,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsessionIdGenerator: () => sessionId,\n\t\t});\n\t\tserver = createPortalMcpServer({\n\t\t\tcore: options.core,\n\t\t\tscope: identity,\n\t\t});\n\t\tawait server.connect(transport);\n\t\treturn { identity, server, transport };\n\t}\n\n\tasync function closePortalSessions(): Promise<void> {\n\t\tclosing = true;\n\t\tconst closeErrors: Error[] = [];\n\t\twhile (activeSessions.size > 0 || pendingNewSessionRequests.size > 0) {\n\t\t\tif (pendingNewSessionRequests.size > 0) {\n\t\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\t\tawait Promise.allSettled(pendingNewSessionRequests);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Closing may trigger callbacks that mutate activeSessions, so drain snapshots until empty.\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst closeResults = await Promise.allSettled(\n\t\t\t\t[...activeSessions.keys()].map((sessionKey) =>\n\t\t\t\t\tcloseActiveSession(sessionKey, { closeTransport: true }),\n\t\t\t\t),\n\t\t\t);\n\t\t\tcloseErrors.push(\n\t\t\t\t...closeResults\n\t\t\t\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t\t\t\t.map((result): Error => errorFromUnknown(result.reason)),\n\t\t\t);\n\t\t}\n\t\tif (closeErrors.length > 0) {\n\t\t\tthrow new AggregateError(closeErrors, 'Failed to close one or more MCP Portal sessions.');\n\t\t}\n\t}\n\n\tapp.get('/health', (context) =>\n\t\tcontext.json({ agents: [...(options.registeredAgentIds ?? [])].toSorted(), ok: true }),\n\t);\n\n\tapp.all('/agents/:agentId/mcp', async (context) => {\n\t\tconst agentId = context.req.param('agentId');\n\t\tconst clientAddress = clientAddressFromContext(context);\n\t\tif (closing) {\n\t\t\treturn unavailableResponse();\n\t\t}\n\t\tif (isAuthFailureRateLimited(clientAddress)) {\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'rate_limited',\n\t\t\t});\n\t\t\treturn rateLimitedResponse();\n\t\t}\n\t\tconst agentBearerAuth = options.agentBearerAuth;\n\t\tconst credentialVersion = agentBearerAuth.credentialVersionsByAgent?.[agentId];\n\t\tconst verification = verifyAgentBearerAuthorization({\n\t\t\tagentId,\n\t\t\tauthorizationHeader: context.req.header(agentBearerAuth.authorizationHeaderName),\n\t\t\tcredentialVersion: credentialVersion ?? unknownAgentCredentialVersionForOpaqueAuthTiming,\n\t\t\tmasterKey: agentBearerAuth.masterKey,\n\t\t});\n\t\tconst agentIdentity = options.resolveAgentIdentity?.(agentId) ?? null;\n\t\tif (agentIdentity === null) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'unknown_agent',\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tif (!verification.ok) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: verification.reason,\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tclearAuthFailures(clientAddress);\n\t\tawait auditAuth({ agentId, clientAddress, decision: 'allow' });\n\n\t\tconst mcpSessionId = context.req.header(mcpSessionIdHeader);\n\t\tif (mcpSessionId) {\n\t\t\tconst activeSession = activeSessions.get(\n\t\t\t\tactiveSessionKey(agentIdentity.agentScopeId, mcpSessionId),\n\t\t\t);\n\t\t\tif (!activeSession) {\n\t\t\t\treturn new Response('Unknown MCP portal session', { status: 404 });\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t}\n\n\t\tconst finishPendingRequest = trackPendingNewSessionRequest();\n\t\ttry {\n\t\t\tif (closing) {\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\tconst activeSession = await createActiveSession(agentIdentity);\n\t\t\tif (closing) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t} finally {\n\t\t\tfinishPendingRequest();\n\t\t}\n\t});\n\n\treturn Object.assign(app, { closePortalSessions });\n}\n","import {\n\tresolveMcpPortalProfile,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport { createPortalPolicyApprovalEvaluator } from '../core/portal-approval-evaluator.js';\nimport type {\n\tPortalApprovalCall,\n\tPortalApprovalCallDecision,\n\tPortalApprovalEvaluation,\n} from '../core/portal-tools.js';\nimport { createPortalAgentIdentity } from '../portal-access-policy.js';\n\nconst approvalTokenMaxLifetimeMs = 5 * 60_000;\nconst approvalTokenReplayCacheLimit = 4_096;\n\nexport interface ResolveAgentHmacKeysProps {\n\treadonly agents: Readonly<Record<string, McpPortalAgentConfig>>;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nexport interface PortalAgentRuntimeRecord {\n\treadonly agentId: string;\n\treadonly hmacKey: Buffer;\n\treadonly profile: ResolvedMcpPortalProfile;\n\treadonly profileName: string;\n}\n\nexport interface PortalApprovalAuditEvent {\n\treadonly agentId: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_portal_approval';\n\treadonly reason?:\n\t\t| 'approval_token_invalid'\n\t\t| 'approval_token_missing'\n\t\t| 'call_blocked'\n\t\t| 'no_approval_required'\n\t\t| 'per_call_evaluation';\n\treadonly timeMs: number;\n\treadonly verifierReason?: string;\n}\n\nasync function resolveAgentHmacKeyEntry(props: {\n\treadonly agent: McpPortalAgentConfig;\n\treadonly agentId: string;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<readonly [string, Buffer]> {\n\tconst envKey = props.envKeys.get(props.agentId);\n\tif (envKey !== undefined) {\n\t\treturn [props.agentId, envKey];\n\t}\n\tif (props.agent.hmacKey === undefined) {\n\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${props.agentId}\".`);\n\t}\n\tconst secretValue = await props.resolveSecret(props.agent.hmacKey);\n\tif (!/^[0-9a-f]+$/u.test(secretValue) || secretValue.length !== 64) {\n\t\tthrow new Error(`MCP Portal agent \"${props.agentId}\" HMAC key must be 64 hex characters.`);\n\t}\n\treturn [props.agentId, Buffer.from(secretValue, 'hex')];\n}\n\nexport async function resolveAgentHmacKeys(\n\tprops: ResolveAgentHmacKeysProps,\n): Promise<ReadonlyMap<string, Buffer>> {\n\treturn new Map(\n\t\tawait Promise.all(\n\t\t\tObject.entries(props.agents).map(([agentId, agent]) =>\n\t\t\t\tresolveAgentHmacKeyEntry({\n\t\t\t\t\tagent,\n\t\t\t\t\tagentId,\n\t\t\t\t\tenvKeys: props.envKeys,\n\t\t\t\t\tresolveSecret: props.resolveSecret,\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t);\n}\n\nexport function createPortalAgentRuntimeRecords(props: {\n\treadonly hmacKeys: ReadonlyMap<string, Buffer>;\n\treadonly portalConfig: McpPortalConfig;\n}): ReadonlyMap<string, PortalAgentRuntimeRecord> {\n\tconst records = new Map<string, PortalAgentRuntimeRecord>();\n\tfor (const [agentId, agent] of Object.entries(props.portalConfig.agents)) {\n\t\tconst hmacKey = props.hmacKeys.get(agentId);\n\t\tif (hmacKey === undefined) {\n\t\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\trecords.set(agentId, {\n\t\t\tagentId,\n\t\t\thmacKey,\n\t\t\tprofile: resolveMcpPortalProfile(props.portalConfig, agent.profile),\n\t\t\tprofileName: agent.profile,\n\t\t});\n\t}\n\treturn records;\n}\n\nexport function createPortalHttpAgentResolver(\n\trecords: ReadonlyMap<string, PortalAgentRuntimeRecord>,\n): (agentId: string) => ReturnType<typeof createPortalAgentIdentity> | null {\n\treturn (agentId) => {\n\t\tconst record = records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn createPortalAgentIdentity({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'mcp-proxy-bearer',\n\t\t});\n\t};\n}\n\nexport function createPortalApprovalVerifier(props: {\n\treadonly approvalTokenReplayCacheLimit?: number;\n\treadonly auditErrorSink?: (error: Error, event: PortalApprovalAuditEvent) => void;\n\treadonly auditSink?: (event: PortalApprovalAuditEvent) => void;\n\treadonly records: ReadonlyMap<string, PortalAgentRuntimeRecord>;\n}): (\n\tcalls: readonly PortalApprovalCall[],\n\tagentId: string,\n\ttoken: string | undefined,\n) => PortalApprovalEvaluation {\n\tfunction auditApproval(event: Omit<PortalApprovalAuditEvent, 'kind' | 'timeMs'>): void {\n\t\tconst auditEvent = { ...event, kind: 'mcp_portal_approval', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tprops.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tprops.auditErrorSink?.(error instanceof Error ? error : new Error(String(error)), auditEvent);\n\t\t}\n\t}\n\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = props.approvalTokenReplayCacheLimit ?? approvalTokenReplayCacheLimit;\n\tconst consumeTokenId = (\n\t\tagentId: string,\n\t\tjti: string,\n\t\texpiresAtMs: number,\n\t):\n\t\t| { readonly ok: true }\n\t\t| { readonly ok: false; readonly reason: 'replay-cache-full' | 'replayed' } => {\n\t\tconst nowMs = Date.now();\n\t\tfor (const [tokenKey, tokenExpiresAtMs] of consumedApprovalTokenIds) {\n\t\t\tif (tokenExpiresAtMs <= nowMs) {\n\t\t\t\tconsumedApprovalTokenIds.delete(tokenKey);\n\t\t\t}\n\t\t}\n\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t}\n\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t}\n\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\treturn { ok: true };\n\t};\n\tconst evaluateApproval = createPortalPolicyApprovalEvaluator({\n\t\tconsumeTokenId,\n\t\tmaxLifetimeMs: approvalTokenMaxLifetimeMs,\n\t\tresolveRecord: (agentId) => props.records.get(agentId),\n\t});\n\n\tfunction auditEvaluation(agentId: string, evaluation: PortalApprovalEvaluation): void {\n\t\tconst decisions = Object.values(evaluation.decisionsByCallId);\n\t\tconst firstDeny = decisions.find((decision) => decision.kind !== 'allow');\n\t\tif (firstDeny === undefined) {\n\t\t\tauditApproval({\n\t\t\t\tagentId,\n\t\t\t\tdecision: 'allow',\n\t\t\t\t...(decisions.length === 0 ? { reason: 'no_approval_required' } : {}),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tauditApproval({\n\t\t\tagentId,\n\t\t\tdecision: 'deny',\n\t\t\treason: auditReasonFromDecision(firstDeny),\n\t\t\t...(firstDeny.kind === 'approval_token_invalid' ? { verifierReason: firstDeny.reason } : {}),\n\t\t});\n\t}\n\n\treturn (calls, agentId, token) => {\n\t\tconst evaluation = evaluateApproval(calls, agentId, token);\n\t\tauditEvaluation(agentId, evaluation);\n\t\treturn evaluation;\n\t};\n}\n\nfunction auditReasonFromDecision(\n\tdecision: PortalApprovalCallDecision,\n): Exclude<PortalApprovalAuditEvent['reason'], undefined> {\n\tswitch (decision.kind) {\n\t\tcase 'allow':\n\t\t\treturn 'no_approval_required';\n\t\tcase 'approval_token_invalid':\n\t\t\treturn 'approval_token_invalid';\n\t\tcase 'approval_token_missing':\n\t\t\treturn 'approval_token_missing';\n\t\tcase 'call_blocked':\n\t\t\treturn 'call_blocked';\n\t\tcase 'approval_required':\n\t\tcase 'approval_configuration_missing':\n\t\t\treturn 'per_call_evaluation';\n\t\tdefault: {\n\t\t\tconst exhaustiveDecision: never = decision;\n\t\t\tthrow new Error(\n\t\t\t\t`Unhandled MCP Portal approval audit decision: ${JSON.stringify(exhaustiveDecision)}`,\n\t\t\t);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as createUpstreamMcpClientRuntime } from "./upstream-mcp-client-runtime-
|
|
2
|
-
import { i as resolveUpstreamServers, n as createPortalCore } from "./portal-core-
|
|
1
|
+
import { t as createUpstreamMcpClientRuntime } from "./upstream-mcp-client-runtime-Bzy0aa0o.js";
|
|
2
|
+
import { i as resolveUpstreamServers, n as createPortalCore } from "./portal-core-CYLdSvsL.js";
|
|
3
3
|
import { t as decodePortalMasterKey } from "./agent-bearer-token-NtEqghPk.js";
|
|
4
|
-
import { a as createPortalHttpApp, n as createPortalApprovalVerifier, r as createPortalHttpAgentResolver, t as createPortalAgentRuntimeRecords } from "./resolve-agent-identity-
|
|
4
|
+
import { a as createPortalHttpApp, n as createPortalApprovalVerifier, r as createPortalHttpAgentResolver, t as createPortalAgentRuntimeRecords } from "./resolve-agent-identity-BK4WlZgd.js";
|
|
5
5
|
import { createHmac } from "node:crypto";
|
|
6
6
|
import { loadMcpConfig, loadMcpPortalConfig, resolveMcpPortalProfile } from "@agent-vm/config-contracts";
|
|
7
7
|
import { join } from "node:path";
|
|
@@ -355,4 +355,4 @@ async function startPortalServer(props) {
|
|
|
355
355
|
//#endregion
|
|
356
356
|
export { handlePortalServerError as a, resolveSecretValue as c, deriveApprovalHmacKeysFromMasterKey as i, buildProfilePolicyMaps as n, parsePortalServerCliArgs as o, createServeSecretResolver as r, startPortalServer as s, applyAgentOverrides as t };
|
|
357
357
|
|
|
358
|
-
//# sourceMappingURL=serve-command-
|
|
358
|
+
//# sourceMappingURL=serve-command-B101-A2V.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve-command-4BNOH14H.js","names":["createOnePasswordSecretResolver"],"sources":["../src/bin/secret-value-resolver.ts","../src/cli/serve-command.ts"],"sourcesContent":["import type { SecretValue } from '@agent-vm/config-contracts';\nimport type { SecretRef, SecretResolver } from '@agent-vm/secret-management';\n\nexport interface ResolveSecretValueProps {\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly secretResolver?: SecretResolver;\n}\n\nfunction secretRefFromSecretValue(secret: SecretValue): SecretRef {\n\tif (secret.source === 'environment') {\n\t\treturn { ref: secret.name, source: 'environment' };\n\t}\n\treturn { ref: secret.ref, source: '1password' };\n}\n\nexport async function resolveSecretValue(\n\tsecret: SecretValue,\n\tprops: ResolveSecretValueProps,\n): Promise<string> {\n\tif (secret.source === 'environment') {\n\t\tconst value = props.env[secret.name];\n\t\tif (value === undefined || value.length === 0) {\n\t\t\tthrow new Error(`Missing environment secret ${secret.name}.`);\n\t\t}\n\t\treturn value;\n\t}\n\n\tif (props.secretResolver === undefined) {\n\t\tthrow new Error(\"Secret with source '1password' requires a configured secret resolver.\");\n\t}\n\treturn await props.secretResolver.resolve(secretRefFromSecretValue(secret));\n}\n","import { createHmac } from 'node:crypto';\nimport { join } from 'node:path';\nimport { parseArgs } from 'node:util';\n\nimport {\n\tloadMcpConfig,\n\tloadMcpPortalConfig,\n\tresolveMcpPortalProfile,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype McpPortalExternalAuthConfig,\n\ttype McpPortalProxyConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\nimport {\n\tcreateCompositeSecretResolver,\n\tcreateSecretResolver as createOnePasswordSecretResolver,\n\tresolveServiceAccountToken,\n\ttype SecretResolver,\n\ttype TokenSource,\n} from '@agent-vm/secret-management';\nimport { serve } from '@hono/node-server';\n\nimport { resolveSecretValue } from '../bin/secret-value-resolver.js';\nimport { createPortalCore } from '../core/portal-core.js';\nimport { resolveUpstreamServers } from '../core/provider-runtime.js';\nimport { createPortalHttpApp, type PortalHttpAuditEvent } from '../mcp-proxy/portal-http-server.js';\nimport {\n\tcreatePortalAgentRuntimeRecords,\n\tcreatePortalApprovalVerifier,\n\tcreatePortalHttpAgentResolver,\n\ttype PortalApprovalAuditEvent,\n} from '../mcp-proxy/resolve-agent-identity.js';\nimport type { PortalToolSelector } from '../portal-access-policy.js';\nimport { decodePortalMasterKey } from '../portal-auth/agent-bearer-token.js';\nimport { createUpstreamMcpClientRuntime } from '../upstream-mcp-client-runtime.js';\n\ntype PortalNodeServer = ReturnType<typeof serve>;\ntype PortalServeFunction = typeof serve;\n\nexport type PortalServerLogEvent =\n\t| {\n\t\t\treadonly event: 'server_error';\n\t\t\treadonly level: 'error';\n\t\t\treadonly message: string;\n\t\t\treadonly stack?: string;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly clientAddress: string;\n\t\t\treadonly decision: PortalHttpAuditEvent['decision'];\n\t\t\treadonly event: 'mcp_proxy_auth';\n\t\t\treadonly level: 'info' | 'warn';\n\t\t\treadonly reason?: PortalHttpAuditEvent['reason'];\n\t\t\treadonly timeMs: number;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly clientAddress: string;\n\t\t\treadonly event: 'mcp_proxy_auth_audit_error';\n\t\t\treadonly level: 'warn';\n\t\t\treadonly message: string;\n\t\t\treadonly timeMs: number;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly decision: PortalApprovalAuditEvent['decision'];\n\t\t\treadonly event: 'mcp_portal_approval';\n\t\t\treadonly level: 'info' | 'warn';\n\t\t\treadonly reason?: PortalApprovalAuditEvent['reason'];\n\t\t\treadonly timeMs: number;\n\t\t\treadonly verifierReason?: string;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly event: 'mcp_portal_approval_audit_error';\n\t\t\treadonly level: 'warn';\n\t\t\treadonly message: string;\n\t\t\treadonly timeMs: number;\n\t }\n\t| {\n\t\t\treadonly agentScopeId: string;\n\t\t\treadonly event: 'upstream_close_error';\n\t\t\treadonly level: 'warn';\n\t\t\treadonly message: string;\n\t\t\treadonly namespace?: string;\n\t };\n\nexport interface PortalServerLogger {\n\treadonly log: (event: PortalServerLogEvent) => void;\n}\n\nexport interface PortalServerCliArgs {\n\treadonly agentOverrides: readonly string[];\n\treadonly configDir: string;\n\treadonly port?: number;\n}\n\nexport interface StartPortalServerProps {\n\treadonly args: PortalServerCliArgs;\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly logger?: PortalServerLogger;\n\treadonly resolveSecret?: (secret: SecretValue) => Promise<string>;\n\treadonly serveFn?: PortalServeFunction;\n}\n\nexport interface CreateServeSecretResolverDependencies {\n\treadonly createOnePasswordSecretResolver?: typeof createOnePasswordSecretResolver;\n\treadonly resolveServiceAccountToken?: typeof resolveServiceAccountToken;\n}\n\nfunction requirePortalTokenSourceValue(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tname: string,\n\tsourceType: string,\n): string {\n\tconst value = env[name]?.trim();\n\tif (value === undefined || value.length === 0) {\n\t\tthrow new Error(`${name} is required when AGENT_VM_MCP_PORTAL_OP_TOKEN_SOURCE=${sourceType}.`);\n\t}\n\treturn value;\n}\n\nfunction readPortalOnePasswordTokenSource(\n\tenv: Readonly<Record<string, string | undefined>>,\n): TokenSource | null {\n\tconst sourceType = env.AGENT_VM_MCP_PORTAL_OP_TOKEN_SOURCE?.trim();\n\tif (sourceType === undefined || sourceType.length === 0) {\n\t\tconst configuredEnvVar = env.AGENT_VM_MCP_PORTAL_OP_TOKEN_ENV_VAR?.trim();\n\t\tconst envVar =\n\t\t\tconfiguredEnvVar === undefined || configuredEnvVar.length === 0\n\t\t\t\t? 'OP_SERVICE_ACCOUNT_TOKEN'\n\t\t\t\t: configuredEnvVar;\n\t\tconst token = env[envVar]?.trim();\n\t\treturn token === undefined || token.length === 0 ? null : { envVar, type: 'env' };\n\t}\n\n\tif (sourceType === 'env') {\n\t\treturn {\n\t\t\tenvVar: requirePortalTokenSourceValue(\n\t\t\t\tenv,\n\t\t\t\t'AGENT_VM_MCP_PORTAL_OP_TOKEN_ENV_VAR',\n\t\t\t\tsourceType,\n\t\t\t),\n\t\t\ttype: 'env',\n\t\t};\n\t}\n\tif (sourceType === 'op-cli') {\n\t\treturn {\n\t\t\tref: requirePortalTokenSourceValue(env, 'AGENT_VM_MCP_PORTAL_OP_TOKEN_REF', sourceType),\n\t\t\ttype: 'op-cli',\n\t\t};\n\t}\n\tif (sourceType === 'keychain') {\n\t\treturn {\n\t\t\taccount: requirePortalTokenSourceValue(\n\t\t\t\tenv,\n\t\t\t\t'AGENT_VM_MCP_PORTAL_OP_TOKEN_KEYCHAIN_ACCOUNT',\n\t\t\t\tsourceType,\n\t\t\t),\n\t\t\tservice: requirePortalTokenSourceValue(\n\t\t\t\tenv,\n\t\t\t\t'AGENT_VM_MCP_PORTAL_OP_TOKEN_KEYCHAIN_SERVICE',\n\t\t\t\tsourceType,\n\t\t\t),\n\t\t\ttype: 'keychain',\n\t\t};\n\t}\n\n\tthrow new Error(`Unsupported AGENT_VM_MCP_PORTAL_OP_TOKEN_SOURCE \"${sourceType}\".`);\n}\n\nasync function resolvePortalServiceAccountToken(props: {\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly resolveToken: typeof resolveServiceAccountToken;\n\treadonly tokenSource: TokenSource;\n}): Promise<string> {\n\tif (props.tokenSource.type !== 'env') {\n\t\treturn await props.resolveToken(props.tokenSource);\n\t}\n\tconst envVar = props.tokenSource.envVar ?? 'OP_SERVICE_ACCOUNT_TOKEN';\n\tconst token = props.env[envVar]?.trim();\n\tif (token === undefined || token.length === 0) {\n\t\tthrow new Error(`Environment variable ${envVar} is not set`);\n\t}\n\treturn token;\n}\n\nexport async function createServeSecretResolver(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tdependencies: CreateServeSecretResolverDependencies = {},\n): Promise<SecretResolver> {\n\tconst tokenSource = readPortalOnePasswordTokenSource(env);\n\tconst resolveToken = dependencies.resolveServiceAccountToken ?? resolveServiceAccountToken;\n\tconst createResolver =\n\t\tdependencies.createOnePasswordSecretResolver ?? createOnePasswordSecretResolver;\n\tconst onePasswordResolver =\n\t\ttokenSource === null\n\t\t\t? null\n\t\t\t: await createResolver({\n\t\t\t\t\tserviceAccountToken: await resolvePortalServiceAccountToken({\n\t\t\t\t\t\tenv,\n\t\t\t\t\t\tresolveToken,\n\t\t\t\t\t\ttokenSource,\n\t\t\t\t\t}),\n\t\t\t\t});\n\treturn createCompositeSecretResolver(onePasswordResolver, env);\n}\n\nexport interface ProfilePolicyMaps {\n\treadonly enabledNamespacesByAgent: Readonly<Record<string, readonly string[]>>;\n\treadonly enabledToolsByNamespaceByAgent: Readonly<\n\t\tRecord<string, Readonly<Record<string, readonly string[]>>>\n\t>;\n\treadonly hiddenToolsByAgent: Readonly<Record<string, readonly PortalToolSelector[]>>;\n}\n\nfunction parsePort(value: string | undefined): number | undefined {\n\tif (value === undefined) {\n\t\treturn undefined;\n\t}\n\tconst port = Number(value);\n\tif (!Number.isInteger(port) || port < 0 || port > 65_535) {\n\t\tthrow new Error(`Invalid --port value \"${value}\".`);\n\t}\n\treturn port;\n}\n\nexport function parsePortalServerCliArgs(argv: readonly string[]): PortalServerCliArgs {\n\tconst parsed = parseArgs({\n\t\targs: [...argv],\n\t\toptions: {\n\t\t\tagent: { multiple: true, type: 'string' },\n\t\t\t'config-dir': { type: 'string' },\n\t\t\tport: { short: 'p', type: 'string' },\n\t\t},\n\t\tstrict: true,\n\t});\n\tconst configDir = parsed.values['config-dir'];\n\tif (typeof configDir !== 'string' || configDir.length === 0) {\n\t\tthrow new Error('--config-dir <path> is required.');\n\t}\n\tconst rawAgentOverrides = parsed.values.agent;\n\tconst args = {\n\t\tagentOverrides: Array.isArray(rawAgentOverrides) ? rawAgentOverrides : [],\n\t\tconfigDir,\n\t};\n\tconst port = parsePort(parsed.values.port);\n\treturn port === undefined ? args : { ...args, port };\n}\n\nexport function applyAgentOverrides(\n\tagents: Readonly<Record<string, McpPortalAgentConfig>>,\n\toverrides: readonly string[],\n): Readonly<Record<string, McpPortalAgentConfig>> {\n\tconst nextAgents: Record<string, McpPortalAgentConfig> = { ...agents };\n\tfor (const override of overrides) {\n\t\tconst [agentId, profileName, extra] = override.split('=');\n\t\tif (\n\t\t\tagentId === undefined ||\n\t\t\tprofileName === undefined ||\n\t\t\textra !== undefined ||\n\t\t\tagentId.length === 0 ||\n\t\t\tprofileName.length === 0\n\t\t) {\n\t\t\tthrow new Error(`Invalid --agent override \"${override}\". Expected <agentId>=<profile>.`);\n\t\t}\n\t\tconst existingAgent = nextAgents[agentId];\n\t\tif (existingAgent === undefined) {\n\t\t\tthrow new Error(`Cannot override unknown MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\tnextAgents[agentId] = { ...existingAgent, profile: profileName };\n\t}\n\treturn nextAgents;\n}\n\nexport interface DeferredPort {\n\treadonly promise: Promise<number>;\n\treadonly reject: (error: Error) => void;\n\treadonly resolve: (port: number) => void;\n}\n\nfunction createDeferredPort(): DeferredPort {\n\tlet rejectPort: ((error: Error) => void) | undefined;\n\tlet resolvePort: ((port: number) => void) | undefined;\n\tconst promise = new Promise<number>((resolve, reject) => {\n\t\trejectPort = reject;\n\t\tresolvePort = resolve;\n\t});\n\treturn {\n\t\tpromise,\n\t\treject: (error) => {\n\t\t\tif (rejectPort === undefined) {\n\t\t\t\tthrow new Error('MCP Portal port rejector was not initialized.');\n\t\t\t}\n\t\t\trejectPort(error);\n\t\t},\n\t\tresolve: (port) => {\n\t\t\tif (resolvePort === undefined) {\n\t\t\t\tthrow new Error('MCP Portal port resolver was not initialized.');\n\t\t\t}\n\t\t\tresolvePort(port);\n\t\t},\n\t};\n}\n\nfunction defaultPortalServerLogger(): PortalServerLogger {\n\treturn {\n\t\tlog: (event) => {\n\t\t\tprocess.stderr.write(`${JSON.stringify(event)}\\n`);\n\t\t},\n\t};\n}\n\nexport function handlePortalServerError(props: {\n\treadonly error: Error;\n\treadonly hasListened: boolean;\n\treadonly listeningPort: DeferredPort;\n\treadonly logger: PortalServerLogger;\n}): void {\n\tprops.logger.log({\n\t\tevent: 'server_error',\n\t\tlevel: 'error',\n\t\tmessage: props.error.message,\n\t\t...(props.error.stack === undefined ? {} : { stack: props.error.stack }),\n\t});\n\tif (!props.hasListened) {\n\t\tprops.listeningPort.reject(props.error);\n\t}\n}\n\nfunction closeNodeServer(server: PortalNodeServer): Promise<void> {\n\treturn new Promise<void>((resolve, reject) => {\n\t\tserver.close((error) => {\n\t\t\tif (error) {\n\t\t\t\treject(error);\n\t\t\t} else {\n\t\t\t\tresolve();\n\t\t\t}\n\t\t});\n\t});\n}\n\nfunction selectorsFromNamespaceTools(\n\tnamespaceTools: Readonly<Record<string, readonly string[]>>,\n): readonly PortalToolSelector[] {\n\treturn Object.entries(namespaceTools).flatMap(([namespace, toolNames]) =>\n\t\ttoolNames.map((toolName) => ({ namespace, toolName })),\n\t);\n}\n\nexport function buildProfilePolicyMaps(\n\tportalConfig: McpPortalConfig,\n): ProfilePolicyMaps & { readonly cacheTtlMs: number } {\n\tconst enabledNamespacesByAgent: Record<string, readonly string[]> = {};\n\tconst enabledToolsByNamespaceByAgent: Record<\n\t\tstring,\n\t\tReadonly<Record<string, readonly string[]>>\n\t> = {};\n\tconst hiddenToolsByAgent: Record<string, readonly PortalToolSelector[]> = {};\n\tconst profileTtls: number[] = [];\n\n\tfor (const [agentId, agent] of Object.entries(portalConfig.agents)) {\n\t\tconst profile: ResolvedMcpPortalProfile = resolveMcpPortalProfile(portalConfig, agent.profile);\n\t\tenabledNamespacesByAgent[agentId] = profile.enabledNamespaces;\n\t\tenabledToolsByNamespaceByAgent[agentId] = profile.enabledToolsByNamespace;\n\t\thiddenToolsByAgent[agentId] = selectorsFromNamespaceTools(profile.hiddenToolsByNamespace);\n\t\tprofileTtls.push(profile.cache.catalogTtlMs);\n\t}\n\n\treturn {\n\t\tcacheTtlMs: profileTtls.length === 0 ? 60_000 : Math.min(...profileTtls),\n\t\tenabledNamespacesByAgent,\n\t\tenabledToolsByNamespaceByAgent,\n\t\thiddenToolsByAgent,\n\t};\n}\n\nfunction withAgentOverrides(\n\tportalConfig: McpPortalConfig,\n\tagentOverrides: readonly string[],\n): McpPortalConfig {\n\treturn {\n\t\t...portalConfig,\n\t\tagents: applyAgentOverrides(portalConfig.agents, agentOverrides),\n\t};\n}\n\nfunction requireProxyConfig(portalConfig: McpPortalConfig): {\n\treadonly externalAuth: McpPortalExternalAuthConfig;\n\treadonly mcpProxy: McpPortalProxyConfig;\n} {\n\tif (portalConfig.externalAuth === undefined || portalConfig.mcpProxy === undefined) {\n\t\tthrow new Error(\n\t\t\t'mcp-proxy startup requires mcp-portal.config.jsonc externalAuth.masterKey and mcpProxy settings.',\n\t\t);\n\t}\n\treturn {\n\t\texternalAuth: portalConfig.externalAuth,\n\t\tmcpProxy: portalConfig.mcpProxy,\n\t};\n}\n\nexport function deriveApprovalHmacKeysFromMasterKey(props: {\n\treadonly agentIds: readonly string[];\n\treadonly masterKey: Buffer;\n}): ReadonlyMap<string, Buffer> {\n\treturn new Map(\n\t\tprops.agentIds.map((agentId) => [\n\t\t\tagentId,\n\t\t\tcreateHmac('sha256', props.masterKey).update(`mcp-portal:approval-agent:${agentId}`).digest(),\n\t\t]),\n\t);\n}\n\nfunction credentialVersionsByAgent(\n\tportalConfig: McpPortalConfig,\n): Readonly<Record<string, number>> {\n\treturn Object.fromEntries(\n\t\tObject.entries(portalConfig.agents).map(([agentId, agent]) => [\n\t\t\tagentId,\n\t\t\tagent.credentialVersion,\n\t\t]),\n\t);\n}\n\nexport async function startPortalServer(\n\tprops: StartPortalServerProps,\n): Promise<{ readonly close: () => Promise<void>; readonly port: number }> {\n\tconst logger = props.logger ?? defaultPortalServerLogger();\n\tconst serveFn = props.serveFn ?? serve;\n\tlet defaultSecretResolverPromise: Promise<SecretResolver> | undefined;\n\tconst getDefaultSecretResolver = (): Promise<SecretResolver> => {\n\t\tdefaultSecretResolverPromise ??= createServeSecretResolver(props.env);\n\t\treturn defaultSecretResolverPromise;\n\t};\n\tconst resolveSecret =\n\t\tprops.resolveSecret ??\n\t\t(async (secret: SecretValue) =>\n\t\t\tresolveSecretValue(secret, {\n\t\t\t\tenv: props.env,\n\t\t\t\tsecretResolver: await getDefaultSecretResolver(),\n\t\t\t}));\n\tconst mcpConfig = await loadMcpConfig(join(props.args.configDir, 'mcp.config.jsonc'));\n\tconst portalConfig = withAgentOverrides(\n\t\tawait loadMcpPortalConfig(join(props.args.configDir, 'mcp-portal.config.jsonc')),\n\t\tprops.args.agentOverrides,\n\t);\n\tconst proxyStartup = requireProxyConfig(portalConfig);\n\tconst masterKey = decodePortalMasterKey(await resolveSecret(proxyStartup.externalAuth.masterKey));\n\tconst hmacKeys = deriveApprovalHmacKeysFromMasterKey({\n\t\tagentIds: Object.keys(portalConfig.agents),\n\t\tmasterKey,\n\t});\n\tconst agentRecords = createPortalAgentRuntimeRecords({ hmacKeys, portalConfig });\n\tconst upstreamServers = await resolveUpstreamServers({ config: mcpConfig, resolveSecret });\n\tconst upstreamRuntime = createUpstreamMcpClientRuntime({\n\t\tadditionalRedactionValues: [masterKey.toString('base64url')],\n\t\tonCloseError: (error, context) => {\n\t\t\tlogger.log({\n\t\t\t\tagentScopeId: context.agentScopeId,\n\t\t\t\tevent: 'upstream_close_error',\n\t\t\t\tlevel: 'warn',\n\t\t\t\tmessage: error.message,\n\t\t\t\t...(context.namespace === undefined ? {} : { namespace: context.namespace }),\n\t\t\t});\n\t\t},\n\t\tservers: upstreamServers,\n\t});\n\tconst profilePolicyMaps = buildProfilePolicyMaps(portalConfig);\n\tconst verifyApproval = createPortalApprovalVerifier({\n\t\tauditErrorSink: (error, event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tevent: 'mcp_portal_approval_audit_error',\n\t\t\t\tlevel: 'warn',\n\t\t\t\tmessage: error.message,\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t});\n\t\t},\n\t\tauditSink: (event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tdecision: event.decision,\n\t\t\t\tevent: 'mcp_portal_approval',\n\t\t\t\tlevel: event.decision === 'allow' ? 'info' : 'warn',\n\t\t\t\t...('reason' in event ? { reason: event.reason } : {}),\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t\t...('verifierReason' in event ? { verifierReason: event.verifierReason } : {}),\n\t\t\t});\n\t\t},\n\t\trecords: agentRecords,\n\t});\n\tconst core = createPortalCore({\n\t\taccessPolicy: {\n\t\t\tdefaultPolicy: 'deny-all',\n\t\t\tenabledNamespacesByAgent: profilePolicyMaps.enabledNamespacesByAgent,\n\t\t\tenabledToolsByNamespaceByAgent: profilePolicyMaps.enabledToolsByNamespaceByAgent,\n\t\t\thiddenToolsByAgent: profilePolicyMaps.hiddenToolsByAgent,\n\t\t},\n\t\tapproval: (calls, identity, approvalToken) =>\n\t\t\tverifyApproval(calls, identity.agentId, approvalToken),\n\t\tcatalogTtlMs: profilePolicyMaps.cacheTtlMs,\n\t\truntime: {\n\t\t\t...upstreamRuntime,\n\t\t\tcallUpstreamTool: upstreamRuntime.callTool,\n\t\t},\n\t\tupstreamNamespaces: upstreamServers.map((server) => server.namespace),\n\t});\n\tconst app = createPortalHttpApp({\n\t\tagentBearerAuth: {\n\t\t\tauthorizationHeaderName: proxyStartup.mcpProxy.auth.headerName,\n\t\t\tcredentialVersionsByAgent: credentialVersionsByAgent(portalConfig),\n\t\t\tmasterKey,\n\t\t},\n\t\tauditSink: (event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tclientAddress: event.clientAddress,\n\t\t\t\tdecision: event.decision,\n\t\t\t\tevent: 'mcp_proxy_auth',\n\t\t\t\tlevel: event.decision === 'allow' ? 'info' : 'warn',\n\t\t\t\t...(event.reason === undefined ? {} : { reason: event.reason }),\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t});\n\t\t},\n\t\tauditErrorSink: (error, event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tclientAddress: event.clientAddress,\n\t\t\t\tevent: 'mcp_proxy_auth_audit_error',\n\t\t\t\tlevel: 'warn',\n\t\t\t\tmessage: error.message,\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t});\n\t\t},\n\t\tcore,\n\t\tonSessionClosed: async (identity) => {\n\t\t\tawait core.invalidateSession(identity);\n\t\t},\n\t\tregisteredAgentIds: Object.keys(portalConfig.agents),\n\t\tresolveAgentIdentity: createPortalHttpAgentResolver(agentRecords),\n\t});\n\tconst listeningPort = createDeferredPort();\n\tlet hasListened = false;\n\tconst server = serveFn(\n\t\t{\n\t\t\tfetch: app.fetch,\n\t\t\thostname: proxyStartup.mcpProxy.server.host,\n\t\t\tport: props.args.port ?? proxyStartup.mcpProxy.server.port,\n\t\t},\n\t\t(info) => {\n\t\t\thasListened = true;\n\t\t\tprocess.stdout.write(`listening port=${String(info.port)}\\n`);\n\t\t\tlisteningPort.resolve(info.port);\n\t\t},\n\t);\n\tserver.on('error', (error: Error) => {\n\t\thandlePortalServerError({ error, hasListened, listeningPort, logger });\n\t});\n\tconst port = await listeningPort.promise;\n\n\treturn {\n\t\tclose: async () => {\n\t\t\tawait app.closePortalSessions();\n\t\t\tawait core.close();\n\t\t\tawait closeNodeServer(server);\n\t\t},\n\t\tport,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"serve-command-B101-A2V.js","names":["createOnePasswordSecretResolver"],"sources":["../src/bin/secret-value-resolver.ts","../src/cli/serve-command.ts"],"sourcesContent":["import type { SecretValue } from '@agent-vm/config-contracts';\nimport type { SecretRef, SecretResolver } from '@agent-vm/secret-management';\n\nexport interface ResolveSecretValueProps {\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly secretResolver?: SecretResolver;\n}\n\nfunction secretRefFromSecretValue(secret: SecretValue): SecretRef {\n\tif (secret.source === 'environment') {\n\t\treturn { ref: secret.name, source: 'environment' };\n\t}\n\treturn { ref: secret.ref, source: '1password' };\n}\n\nexport async function resolveSecretValue(\n\tsecret: SecretValue,\n\tprops: ResolveSecretValueProps,\n): Promise<string> {\n\tif (secret.source === 'environment') {\n\t\tconst value = props.env[secret.name];\n\t\tif (value === undefined || value.length === 0) {\n\t\t\tthrow new Error(`Missing environment secret ${secret.name}.`);\n\t\t}\n\t\treturn value;\n\t}\n\n\tif (props.secretResolver === undefined) {\n\t\tthrow new Error(\"Secret with source '1password' requires a configured secret resolver.\");\n\t}\n\treturn await props.secretResolver.resolve(secretRefFromSecretValue(secret));\n}\n","import { createHmac } from 'node:crypto';\nimport { join } from 'node:path';\nimport { parseArgs } from 'node:util';\n\nimport {\n\tloadMcpConfig,\n\tloadMcpPortalConfig,\n\tresolveMcpPortalProfile,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype McpPortalExternalAuthConfig,\n\ttype McpPortalProxyConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\nimport {\n\tcreateCompositeSecretResolver,\n\tcreateSecretResolver as createOnePasswordSecretResolver,\n\tresolveServiceAccountToken,\n\ttype SecretResolver,\n\ttype TokenSource,\n} from '@agent-vm/secret-management';\nimport { serve } from '@hono/node-server';\n\nimport { resolveSecretValue } from '../bin/secret-value-resolver.js';\nimport { createPortalCore } from '../core/portal-core.js';\nimport { resolveUpstreamServers } from '../core/provider-runtime.js';\nimport { createPortalHttpApp, type PortalHttpAuditEvent } from '../mcp-proxy/portal-http-server.js';\nimport {\n\tcreatePortalAgentRuntimeRecords,\n\tcreatePortalApprovalVerifier,\n\tcreatePortalHttpAgentResolver,\n\ttype PortalApprovalAuditEvent,\n} from '../mcp-proxy/resolve-agent-identity.js';\nimport type { PortalToolSelector } from '../portal-access-policy.js';\nimport { decodePortalMasterKey } from '../portal-auth/agent-bearer-token.js';\nimport { createUpstreamMcpClientRuntime } from '../upstream-mcp-client-runtime.js';\n\ntype PortalNodeServer = ReturnType<typeof serve>;\ntype PortalServeFunction = typeof serve;\n\nexport type PortalServerLogEvent =\n\t| {\n\t\t\treadonly event: 'server_error';\n\t\t\treadonly level: 'error';\n\t\t\treadonly message: string;\n\t\t\treadonly stack?: string;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly clientAddress: string;\n\t\t\treadonly decision: PortalHttpAuditEvent['decision'];\n\t\t\treadonly event: 'mcp_proxy_auth';\n\t\t\treadonly level: 'info' | 'warn';\n\t\t\treadonly reason?: PortalHttpAuditEvent['reason'];\n\t\t\treadonly timeMs: number;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly clientAddress: string;\n\t\t\treadonly event: 'mcp_proxy_auth_audit_error';\n\t\t\treadonly level: 'warn';\n\t\t\treadonly message: string;\n\t\t\treadonly timeMs: number;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly decision: PortalApprovalAuditEvent['decision'];\n\t\t\treadonly event: 'mcp_portal_approval';\n\t\t\treadonly level: 'info' | 'warn';\n\t\t\treadonly reason?: PortalApprovalAuditEvent['reason'];\n\t\t\treadonly timeMs: number;\n\t\t\treadonly verifierReason?: string;\n\t }\n\t| {\n\t\t\treadonly agentId: string;\n\t\t\treadonly event: 'mcp_portal_approval_audit_error';\n\t\t\treadonly level: 'warn';\n\t\t\treadonly message: string;\n\t\t\treadonly timeMs: number;\n\t }\n\t| {\n\t\t\treadonly agentScopeId: string;\n\t\t\treadonly event: 'upstream_close_error';\n\t\t\treadonly level: 'warn';\n\t\t\treadonly message: string;\n\t\t\treadonly namespace?: string;\n\t };\n\nexport interface PortalServerLogger {\n\treadonly log: (event: PortalServerLogEvent) => void;\n}\n\nexport interface PortalServerCliArgs {\n\treadonly agentOverrides: readonly string[];\n\treadonly configDir: string;\n\treadonly port?: number;\n}\n\nexport interface StartPortalServerProps {\n\treadonly args: PortalServerCliArgs;\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly logger?: PortalServerLogger;\n\treadonly resolveSecret?: (secret: SecretValue) => Promise<string>;\n\treadonly serveFn?: PortalServeFunction;\n}\n\nexport interface CreateServeSecretResolverDependencies {\n\treadonly createOnePasswordSecretResolver?: typeof createOnePasswordSecretResolver;\n\treadonly resolveServiceAccountToken?: typeof resolveServiceAccountToken;\n}\n\nfunction requirePortalTokenSourceValue(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tname: string,\n\tsourceType: string,\n): string {\n\tconst value = env[name]?.trim();\n\tif (value === undefined || value.length === 0) {\n\t\tthrow new Error(`${name} is required when AGENT_VM_MCP_PORTAL_OP_TOKEN_SOURCE=${sourceType}.`);\n\t}\n\treturn value;\n}\n\nfunction readPortalOnePasswordTokenSource(\n\tenv: Readonly<Record<string, string | undefined>>,\n): TokenSource | null {\n\tconst sourceType = env.AGENT_VM_MCP_PORTAL_OP_TOKEN_SOURCE?.trim();\n\tif (sourceType === undefined || sourceType.length === 0) {\n\t\tconst configuredEnvVar = env.AGENT_VM_MCP_PORTAL_OP_TOKEN_ENV_VAR?.trim();\n\t\tconst envVar =\n\t\t\tconfiguredEnvVar === undefined || configuredEnvVar.length === 0\n\t\t\t\t? 'OP_SERVICE_ACCOUNT_TOKEN'\n\t\t\t\t: configuredEnvVar;\n\t\tconst token = env[envVar]?.trim();\n\t\treturn token === undefined || token.length === 0 ? null : { envVar, type: 'env' };\n\t}\n\n\tif (sourceType === 'env') {\n\t\treturn {\n\t\t\tenvVar: requirePortalTokenSourceValue(\n\t\t\t\tenv,\n\t\t\t\t'AGENT_VM_MCP_PORTAL_OP_TOKEN_ENV_VAR',\n\t\t\t\tsourceType,\n\t\t\t),\n\t\t\ttype: 'env',\n\t\t};\n\t}\n\tif (sourceType === 'op-cli') {\n\t\treturn {\n\t\t\tref: requirePortalTokenSourceValue(env, 'AGENT_VM_MCP_PORTAL_OP_TOKEN_REF', sourceType),\n\t\t\ttype: 'op-cli',\n\t\t};\n\t}\n\tif (sourceType === 'keychain') {\n\t\treturn {\n\t\t\taccount: requirePortalTokenSourceValue(\n\t\t\t\tenv,\n\t\t\t\t'AGENT_VM_MCP_PORTAL_OP_TOKEN_KEYCHAIN_ACCOUNT',\n\t\t\t\tsourceType,\n\t\t\t),\n\t\t\tservice: requirePortalTokenSourceValue(\n\t\t\t\tenv,\n\t\t\t\t'AGENT_VM_MCP_PORTAL_OP_TOKEN_KEYCHAIN_SERVICE',\n\t\t\t\tsourceType,\n\t\t\t),\n\t\t\ttype: 'keychain',\n\t\t};\n\t}\n\n\tthrow new Error(`Unsupported AGENT_VM_MCP_PORTAL_OP_TOKEN_SOURCE \"${sourceType}\".`);\n}\n\nasync function resolvePortalServiceAccountToken(props: {\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly resolveToken: typeof resolveServiceAccountToken;\n\treadonly tokenSource: TokenSource;\n}): Promise<string> {\n\tif (props.tokenSource.type !== 'env') {\n\t\treturn await props.resolveToken(props.tokenSource);\n\t}\n\tconst envVar = props.tokenSource.envVar ?? 'OP_SERVICE_ACCOUNT_TOKEN';\n\tconst token = props.env[envVar]?.trim();\n\tif (token === undefined || token.length === 0) {\n\t\tthrow new Error(`Environment variable ${envVar} is not set`);\n\t}\n\treturn token;\n}\n\nexport async function createServeSecretResolver(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tdependencies: CreateServeSecretResolverDependencies = {},\n): Promise<SecretResolver> {\n\tconst tokenSource = readPortalOnePasswordTokenSource(env);\n\tconst resolveToken = dependencies.resolveServiceAccountToken ?? resolveServiceAccountToken;\n\tconst createResolver =\n\t\tdependencies.createOnePasswordSecretResolver ?? createOnePasswordSecretResolver;\n\tconst onePasswordResolver =\n\t\ttokenSource === null\n\t\t\t? null\n\t\t\t: await createResolver({\n\t\t\t\t\tserviceAccountToken: await resolvePortalServiceAccountToken({\n\t\t\t\t\t\tenv,\n\t\t\t\t\t\tresolveToken,\n\t\t\t\t\t\ttokenSource,\n\t\t\t\t\t}),\n\t\t\t\t});\n\treturn createCompositeSecretResolver(onePasswordResolver, env);\n}\n\nexport interface ProfilePolicyMaps {\n\treadonly enabledNamespacesByAgent: Readonly<Record<string, readonly string[]>>;\n\treadonly enabledToolsByNamespaceByAgent: Readonly<\n\t\tRecord<string, Readonly<Record<string, readonly string[]>>>\n\t>;\n\treadonly hiddenToolsByAgent: Readonly<Record<string, readonly PortalToolSelector[]>>;\n}\n\nfunction parsePort(value: string | undefined): number | undefined {\n\tif (value === undefined) {\n\t\treturn undefined;\n\t}\n\tconst port = Number(value);\n\tif (!Number.isInteger(port) || port < 0 || port > 65_535) {\n\t\tthrow new Error(`Invalid --port value \"${value}\".`);\n\t}\n\treturn port;\n}\n\nexport function parsePortalServerCliArgs(argv: readonly string[]): PortalServerCliArgs {\n\tconst parsed = parseArgs({\n\t\targs: [...argv],\n\t\toptions: {\n\t\t\tagent: { multiple: true, type: 'string' },\n\t\t\t'config-dir': { type: 'string' },\n\t\t\tport: { short: 'p', type: 'string' },\n\t\t},\n\t\tstrict: true,\n\t});\n\tconst configDir = parsed.values['config-dir'];\n\tif (typeof configDir !== 'string' || configDir.length === 0) {\n\t\tthrow new Error('--config-dir <path> is required.');\n\t}\n\tconst rawAgentOverrides = parsed.values.agent;\n\tconst args = {\n\t\tagentOverrides: Array.isArray(rawAgentOverrides) ? rawAgentOverrides : [],\n\t\tconfigDir,\n\t};\n\tconst port = parsePort(parsed.values.port);\n\treturn port === undefined ? args : { ...args, port };\n}\n\nexport function applyAgentOverrides(\n\tagents: Readonly<Record<string, McpPortalAgentConfig>>,\n\toverrides: readonly string[],\n): Readonly<Record<string, McpPortalAgentConfig>> {\n\tconst nextAgents: Record<string, McpPortalAgentConfig> = { ...agents };\n\tfor (const override of overrides) {\n\t\tconst [agentId, profileName, extra] = override.split('=');\n\t\tif (\n\t\t\tagentId === undefined ||\n\t\t\tprofileName === undefined ||\n\t\t\textra !== undefined ||\n\t\t\tagentId.length === 0 ||\n\t\t\tprofileName.length === 0\n\t\t) {\n\t\t\tthrow new Error(`Invalid --agent override \"${override}\". Expected <agentId>=<profile>.`);\n\t\t}\n\t\tconst existingAgent = nextAgents[agentId];\n\t\tif (existingAgent === undefined) {\n\t\t\tthrow new Error(`Cannot override unknown MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\tnextAgents[agentId] = { ...existingAgent, profile: profileName };\n\t}\n\treturn nextAgents;\n}\n\nexport interface DeferredPort {\n\treadonly promise: Promise<number>;\n\treadonly reject: (error: Error) => void;\n\treadonly resolve: (port: number) => void;\n}\n\nfunction createDeferredPort(): DeferredPort {\n\tlet rejectPort: ((error: Error) => void) | undefined;\n\tlet resolvePort: ((port: number) => void) | undefined;\n\tconst promise = new Promise<number>((resolve, reject) => {\n\t\trejectPort = reject;\n\t\tresolvePort = resolve;\n\t});\n\treturn {\n\t\tpromise,\n\t\treject: (error) => {\n\t\t\tif (rejectPort === undefined) {\n\t\t\t\tthrow new Error('MCP Portal port rejector was not initialized.');\n\t\t\t}\n\t\t\trejectPort(error);\n\t\t},\n\t\tresolve: (port) => {\n\t\t\tif (resolvePort === undefined) {\n\t\t\t\tthrow new Error('MCP Portal port resolver was not initialized.');\n\t\t\t}\n\t\t\tresolvePort(port);\n\t\t},\n\t};\n}\n\nfunction defaultPortalServerLogger(): PortalServerLogger {\n\treturn {\n\t\tlog: (event) => {\n\t\t\tprocess.stderr.write(`${JSON.stringify(event)}\\n`);\n\t\t},\n\t};\n}\n\nexport function handlePortalServerError(props: {\n\treadonly error: Error;\n\treadonly hasListened: boolean;\n\treadonly listeningPort: DeferredPort;\n\treadonly logger: PortalServerLogger;\n}): void {\n\tprops.logger.log({\n\t\tevent: 'server_error',\n\t\tlevel: 'error',\n\t\tmessage: props.error.message,\n\t\t...(props.error.stack === undefined ? {} : { stack: props.error.stack }),\n\t});\n\tif (!props.hasListened) {\n\t\tprops.listeningPort.reject(props.error);\n\t}\n}\n\nfunction closeNodeServer(server: PortalNodeServer): Promise<void> {\n\treturn new Promise<void>((resolve, reject) => {\n\t\tserver.close((error) => {\n\t\t\tif (error) {\n\t\t\t\treject(error);\n\t\t\t} else {\n\t\t\t\tresolve();\n\t\t\t}\n\t\t});\n\t});\n}\n\nfunction selectorsFromNamespaceTools(\n\tnamespaceTools: Readonly<Record<string, readonly string[]>>,\n): readonly PortalToolSelector[] {\n\treturn Object.entries(namespaceTools).flatMap(([namespace, toolNames]) =>\n\t\ttoolNames.map((toolName) => ({ namespace, toolName })),\n\t);\n}\n\nexport function buildProfilePolicyMaps(\n\tportalConfig: McpPortalConfig,\n): ProfilePolicyMaps & { readonly cacheTtlMs: number } {\n\tconst enabledNamespacesByAgent: Record<string, readonly string[]> = {};\n\tconst enabledToolsByNamespaceByAgent: Record<\n\t\tstring,\n\t\tReadonly<Record<string, readonly string[]>>\n\t> = {};\n\tconst hiddenToolsByAgent: Record<string, readonly PortalToolSelector[]> = {};\n\tconst profileTtls: number[] = [];\n\n\tfor (const [agentId, agent] of Object.entries(portalConfig.agents)) {\n\t\tconst profile: ResolvedMcpPortalProfile = resolveMcpPortalProfile(portalConfig, agent.profile);\n\t\tenabledNamespacesByAgent[agentId] = profile.enabledNamespaces;\n\t\tenabledToolsByNamespaceByAgent[agentId] = profile.enabledToolsByNamespace;\n\t\thiddenToolsByAgent[agentId] = selectorsFromNamespaceTools(profile.hiddenToolsByNamespace);\n\t\tprofileTtls.push(profile.cache.catalogTtlMs);\n\t}\n\n\treturn {\n\t\tcacheTtlMs: profileTtls.length === 0 ? 60_000 : Math.min(...profileTtls),\n\t\tenabledNamespacesByAgent,\n\t\tenabledToolsByNamespaceByAgent,\n\t\thiddenToolsByAgent,\n\t};\n}\n\nfunction withAgentOverrides(\n\tportalConfig: McpPortalConfig,\n\tagentOverrides: readonly string[],\n): McpPortalConfig {\n\treturn {\n\t\t...portalConfig,\n\t\tagents: applyAgentOverrides(portalConfig.agents, agentOverrides),\n\t};\n}\n\nfunction requireProxyConfig(portalConfig: McpPortalConfig): {\n\treadonly externalAuth: McpPortalExternalAuthConfig;\n\treadonly mcpProxy: McpPortalProxyConfig;\n} {\n\tif (portalConfig.externalAuth === undefined || portalConfig.mcpProxy === undefined) {\n\t\tthrow new Error(\n\t\t\t'mcp-proxy startup requires mcp-portal.config.jsonc externalAuth.masterKey and mcpProxy settings.',\n\t\t);\n\t}\n\treturn {\n\t\texternalAuth: portalConfig.externalAuth,\n\t\tmcpProxy: portalConfig.mcpProxy,\n\t};\n}\n\nexport function deriveApprovalHmacKeysFromMasterKey(props: {\n\treadonly agentIds: readonly string[];\n\treadonly masterKey: Buffer;\n}): ReadonlyMap<string, Buffer> {\n\treturn new Map(\n\t\tprops.agentIds.map((agentId) => [\n\t\t\tagentId,\n\t\t\tcreateHmac('sha256', props.masterKey).update(`mcp-portal:approval-agent:${agentId}`).digest(),\n\t\t]),\n\t);\n}\n\nfunction credentialVersionsByAgent(\n\tportalConfig: McpPortalConfig,\n): Readonly<Record<string, number>> {\n\treturn Object.fromEntries(\n\t\tObject.entries(portalConfig.agents).map(([agentId, agent]) => [\n\t\t\tagentId,\n\t\t\tagent.credentialVersion,\n\t\t]),\n\t);\n}\n\nexport async function startPortalServer(\n\tprops: StartPortalServerProps,\n): Promise<{ readonly close: () => Promise<void>; readonly port: number }> {\n\tconst logger = props.logger ?? defaultPortalServerLogger();\n\tconst serveFn = props.serveFn ?? serve;\n\tlet defaultSecretResolverPromise: Promise<SecretResolver> | undefined;\n\tconst getDefaultSecretResolver = (): Promise<SecretResolver> => {\n\t\tdefaultSecretResolverPromise ??= createServeSecretResolver(props.env);\n\t\treturn defaultSecretResolverPromise;\n\t};\n\tconst resolveSecret =\n\t\tprops.resolveSecret ??\n\t\t(async (secret: SecretValue) =>\n\t\t\tresolveSecretValue(secret, {\n\t\t\t\tenv: props.env,\n\t\t\t\tsecretResolver: await getDefaultSecretResolver(),\n\t\t\t}));\n\tconst mcpConfig = await loadMcpConfig(join(props.args.configDir, 'mcp.config.jsonc'));\n\tconst portalConfig = withAgentOverrides(\n\t\tawait loadMcpPortalConfig(join(props.args.configDir, 'mcp-portal.config.jsonc')),\n\t\tprops.args.agentOverrides,\n\t);\n\tconst proxyStartup = requireProxyConfig(portalConfig);\n\tconst masterKey = decodePortalMasterKey(await resolveSecret(proxyStartup.externalAuth.masterKey));\n\tconst hmacKeys = deriveApprovalHmacKeysFromMasterKey({\n\t\tagentIds: Object.keys(portalConfig.agents),\n\t\tmasterKey,\n\t});\n\tconst agentRecords = createPortalAgentRuntimeRecords({ hmacKeys, portalConfig });\n\tconst upstreamServers = await resolveUpstreamServers({ config: mcpConfig, resolveSecret });\n\tconst upstreamRuntime = createUpstreamMcpClientRuntime({\n\t\tadditionalRedactionValues: [masterKey.toString('base64url')],\n\t\tonCloseError: (error, context) => {\n\t\t\tlogger.log({\n\t\t\t\tagentScopeId: context.agentScopeId,\n\t\t\t\tevent: 'upstream_close_error',\n\t\t\t\tlevel: 'warn',\n\t\t\t\tmessage: error.message,\n\t\t\t\t...(context.namespace === undefined ? {} : { namespace: context.namespace }),\n\t\t\t});\n\t\t},\n\t\tservers: upstreamServers,\n\t});\n\tconst profilePolicyMaps = buildProfilePolicyMaps(portalConfig);\n\tconst verifyApproval = createPortalApprovalVerifier({\n\t\tauditErrorSink: (error, event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tevent: 'mcp_portal_approval_audit_error',\n\t\t\t\tlevel: 'warn',\n\t\t\t\tmessage: error.message,\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t});\n\t\t},\n\t\tauditSink: (event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tdecision: event.decision,\n\t\t\t\tevent: 'mcp_portal_approval',\n\t\t\t\tlevel: event.decision === 'allow' ? 'info' : 'warn',\n\t\t\t\t...('reason' in event ? { reason: event.reason } : {}),\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t\t...('verifierReason' in event ? { verifierReason: event.verifierReason } : {}),\n\t\t\t});\n\t\t},\n\t\trecords: agentRecords,\n\t});\n\tconst core = createPortalCore({\n\t\taccessPolicy: {\n\t\t\tdefaultPolicy: 'deny-all',\n\t\t\tenabledNamespacesByAgent: profilePolicyMaps.enabledNamespacesByAgent,\n\t\t\tenabledToolsByNamespaceByAgent: profilePolicyMaps.enabledToolsByNamespaceByAgent,\n\t\t\thiddenToolsByAgent: profilePolicyMaps.hiddenToolsByAgent,\n\t\t},\n\t\tapproval: (calls, identity, approvalToken) =>\n\t\t\tverifyApproval(calls, identity.agentId, approvalToken),\n\t\tcatalogTtlMs: profilePolicyMaps.cacheTtlMs,\n\t\truntime: {\n\t\t\t...upstreamRuntime,\n\t\t\tcallUpstreamTool: upstreamRuntime.callTool,\n\t\t},\n\t\tupstreamNamespaces: upstreamServers.map((server) => server.namespace),\n\t});\n\tconst app = createPortalHttpApp({\n\t\tagentBearerAuth: {\n\t\t\tauthorizationHeaderName: proxyStartup.mcpProxy.auth.headerName,\n\t\t\tcredentialVersionsByAgent: credentialVersionsByAgent(portalConfig),\n\t\t\tmasterKey,\n\t\t},\n\t\tauditSink: (event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tclientAddress: event.clientAddress,\n\t\t\t\tdecision: event.decision,\n\t\t\t\tevent: 'mcp_proxy_auth',\n\t\t\t\tlevel: event.decision === 'allow' ? 'info' : 'warn',\n\t\t\t\t...(event.reason === undefined ? {} : { reason: event.reason }),\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t});\n\t\t},\n\t\tauditErrorSink: (error, event) => {\n\t\t\tlogger.log({\n\t\t\t\tagentId: event.agentId,\n\t\t\t\tclientAddress: event.clientAddress,\n\t\t\t\tevent: 'mcp_proxy_auth_audit_error',\n\t\t\t\tlevel: 'warn',\n\t\t\t\tmessage: error.message,\n\t\t\t\ttimeMs: event.timeMs,\n\t\t\t});\n\t\t},\n\t\tcore,\n\t\tonSessionClosed: async (identity) => {\n\t\t\tawait core.invalidateSession(identity);\n\t\t},\n\t\tregisteredAgentIds: Object.keys(portalConfig.agents),\n\t\tresolveAgentIdentity: createPortalHttpAgentResolver(agentRecords),\n\t});\n\tconst listeningPort = createDeferredPort();\n\tlet hasListened = false;\n\tconst server = serveFn(\n\t\t{\n\t\t\tfetch: app.fetch,\n\t\t\thostname: proxyStartup.mcpProxy.server.host,\n\t\t\tport: props.args.port ?? proxyStartup.mcpProxy.server.port,\n\t\t},\n\t\t(info) => {\n\t\t\thasListened = true;\n\t\t\tprocess.stdout.write(`listening port=${String(info.port)}\\n`);\n\t\t\tlisteningPort.resolve(info.port);\n\t\t},\n\t);\n\tserver.on('error', (error: Error) => {\n\t\thandlePortalServerError({ error, hasListened, listeningPort, logger });\n\t});\n\tconst port = await listeningPort.promise;\n\n\treturn {\n\t\tclose: async () => {\n\t\t\tawait app.closePortalSessions();\n\t\t\tawait core.close();\n\t\t\tawait closeNodeServer(server);\n\t\t},\n\t\tport,\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as portalToolRecordSchema, r as encodeToolRef } from "./zod-schema-loader-
|
|
1
|
+
import { a as portalToolRecordSchema, r as encodeToolRef } from "./zod-schema-loader-DI7JliBn.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
//#region src/portal-config/typescript-artifact.ts
|
|
4
4
|
function toIdentifierPart(value) {
|
|
@@ -57,4 +57,4 @@ function generateTypescriptCatalogArtifact(input) {
|
|
|
57
57
|
//#endregion
|
|
58
58
|
export { generateTypescriptCatalogArtifact as t };
|
|
59
59
|
|
|
60
|
-
//# sourceMappingURL=typescript-artifact-
|
|
60
|
+
//# sourceMappingURL=typescript-artifact-CXxEYME7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript-artifact-
|
|
1
|
+
{"version":3,"file":"typescript-artifact-CXxEYME7.js","names":[],"sources":["../src/portal-config/typescript-artifact.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\nimport { portalToolRecordSchema, type PortalToolRecord } from '../catalog-types.js';\nimport { encodeToolRef } from '../tool-ref.js';\n\nexport interface CatalogArtifactInput {\n\treadonly tools: readonly PortalToolRecord[];\n}\n\nfunction toIdentifierPart(value: string): string {\n\tconst words = value.split(/[^A-Za-z0-9]+/).filter(Boolean);\n\tif (words.length === 0) {\n\t\treturn 'tool';\n\t}\n\n\treturn words.map((word) => word.slice(0, 1).toUpperCase() + word.slice(1)).join('');\n}\n\nfunction shortToolRefHash(toolRef: string): string {\n\treturn createHash('sha256').update(toolRef).digest('hex').slice(0, 8);\n}\n\nfunction toToolConstantName(tool: PortalToolRecord & { readonly toolRef: string }): string {\n\tconst namespacePart = toIdentifierPart(tool.namespace);\n\tconst toolNamePart = toIdentifierPart(tool.toolName);\n\tconst identifier = `${namespacePart}${toolNamePart}${shortToolRefHash(tool.toolRef)}Tool`;\n\n\treturn identifier.slice(0, 1).toLowerCase() + identifier.slice(1);\n}\n\nexport function generateTypescriptCatalogArtifact(input: CatalogArtifactInput): string {\n\tconst tools = input.tools\n\t\t.map((tool) => portalToolRecordSchema.parse(tool))\n\t\t.toSorted((left, right) => {\n\t\t\tconst leftRef = encodeToolRef({ namespace: left.namespace, toolName: left.toolName });\n\t\t\tconst rightRef = encodeToolRef({ namespace: right.namespace, toolName: right.toolName });\n\t\t\treturn leftRef.localeCompare(rightRef);\n\t\t});\n\n\tconst catalogEntries = tools.map((tool) =>\n\t\tObject.assign({}, tool, {\n\t\t\ttoolRef: encodeToolRef({ namespace: tool.namespace, toolName: tool.toolName }),\n\t\t}),\n\t);\n\tconst constants = catalogEntries\n\t\t.map((tool) => {\n\t\t\tconst constantName = toToolConstantName(tool);\n\t\t\treturn `export const ${constantName} = requireCatalogTool(${JSON.stringify(tool.toolRef)});`;\n\t\t})\n\t\t.join('\\n');\n\n\treturn [\n\t\t'// Generated by mcp-portal. JSON Schema is canonical; Zod is derived for runtime validation.',\n\t\t\"import * as z from 'zod';\",\n\t\t'',\n\t\t`export const portalCatalog = ${JSON.stringify({ tools: catalogEntries }, null, '\\t')} as const;`,\n\t\t'',\n\t\tconstants,\n\t\t'',\n\t\t'function requireCatalogTool(toolRef: string): (typeof portalCatalog.tools)[number] {',\n\t\t'\\tconst tool = portalCatalog.tools.find((catalogTool) => catalogTool.toolRef === toolRef);',\n\t\t'\\tif (!tool) {',\n\t\t'\\t\\tthrow new Error(`Unknown MCP portal toolRef: ${toolRef}`);',\n\t\t'\\t}',\n\t\t'\\treturn tool;',\n\t\t'}',\n\t\t'',\n\t\t'export function createInputValidator(toolRef: string): z.ZodType {',\n\t\t'\\tconst tool = requireCatalogTool(toolRef);',\n\t\t'\\treturn z.fromJSONSchema(tool.inputSchema);',\n\t\t'}',\n\t\t'',\n\t].join('\\n');\n}\n"],"mappings":";;;AASA,SAAS,iBAAiB,OAAuB;CAChD,MAAM,QAAQ,MAAM,MAAM,gBAAgB,CAAC,OAAO,QAAQ;CAC1D,IAAI,MAAM,WAAW,GACpB,OAAO;CAGR,OAAO,MAAM,KAAK,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC,KAAK,GAAG;;AAGpF,SAAS,iBAAiB,SAAyB;CAClD,OAAO,WAAW,SAAS,CAAC,OAAO,QAAQ,CAAC,OAAO,MAAM,CAAC,MAAM,GAAG,EAAE;;AAGtE,SAAS,mBAAmB,MAA+D;CAG1F,MAAM,aAAa,GAFG,iBAAiB,KAAK,UAET,GADd,iBAAiB,KAAK,SACO,GAAG,iBAAiB,KAAK,QAAQ,CAAC;CAEpF,OAAO,WAAW,MAAM,GAAG,EAAE,CAAC,aAAa,GAAG,WAAW,MAAM,EAAE;;AAGlE,SAAgB,kCAAkC,OAAqC;CAStF,MAAM,iBARQ,MAAM,MAClB,KAAK,SAAS,uBAAuB,MAAM,KAAK,CAAC,CACjD,UAAU,MAAM,UAAU;EAC1B,MAAM,UAAU,cAAc;GAAE,WAAW,KAAK;GAAW,UAAU,KAAK;GAAU,CAAC;EACrF,MAAM,WAAW,cAAc;GAAE,WAAW,MAAM;GAAW,UAAU,MAAM;GAAU,CAAC;EACxF,OAAO,QAAQ,cAAc,SAAS;GAGZ,CAAC,KAAK,SACjC,OAAO,OAAO,EAAE,EAAE,MAAM,EACvB,SAAS,cAAc;EAAE,WAAW,KAAK;EAAW,UAAU,KAAK;EAAU,CAAC,EAC9E,CAAC,CACF;CACD,MAAM,YAAY,eAChB,KAAK,SAAS;EAEd,OAAO,gBADc,mBAAmB,KACL,CAAC,wBAAwB,KAAK,UAAU,KAAK,QAAQ,CAAC;GACxF,CACD,KAAK,KAAK;CAEZ,OAAO;EACN;EACA;EACA;EACA,gCAAgC,KAAK,UAAU,EAAE,OAAO,gBAAgB,EAAE,MAAM,IAAK,CAAC;EACtF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,KAAK,KAAK"}
|
package/dist/{upstream-mcp-client-runtime-vu2TiTUw.js → upstream-mcp-client-runtime-Bzy0aa0o.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as portalToolRecordSchema, r as encodeToolRef } from "./zod-schema-loader-
|
|
2
|
-
import { a as redactUpstreamCatalogValue, d as isUpstreamMcpError, f as messageFromUnknownError, h as createToolSummary, i as redactThrownError, l as createUpstreamMcpError, m as upstreamMcpFailureDetailsFromUnknown, o as redactUpstreamResponse, p as transportSummaryFromServer, u as formatUpstreamMcpFailureMessage, v as portalAgentScopeKey, y as resolvePortalAccessPolicy } from "./upstream-response-middleware-
|
|
1
|
+
import { a as portalToolRecordSchema, r as encodeToolRef } from "./zod-schema-loader-DI7JliBn.js";
|
|
2
|
+
import { a as redactUpstreamCatalogValue, d as isUpstreamMcpError, f as messageFromUnknownError, h as createToolSummary, i as redactThrownError, l as createUpstreamMcpError, m as upstreamMcpFailureDetailsFromUnknown, o as redactUpstreamResponse, p as transportSummaryFromServer, u as formatUpstreamMcpFailureMessage, v as portalAgentScopeKey, y as resolvePortalAccessPolicy } from "./upstream-response-middleware-fcJSrSEo.js";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
5
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
@@ -831,4 +831,4 @@ function createUpstreamMcpClientRuntime(options) {
|
|
|
831
831
|
//#endregion
|
|
832
832
|
export { createSearchIndex as i, createPortalSessionManager as n, buildToolGraph as r, createUpstreamMcpClientRuntime as t };
|
|
833
833
|
|
|
834
|
-
//# sourceMappingURL=upstream-mcp-client-runtime-
|
|
834
|
+
//# sourceMappingURL=upstream-mcp-client-runtime-Bzy0aa0o.js.map
|