@agent-vm/mcp-portal 0.0.70 → 0.0.71
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/README.md +1 -1
- package/dist/bin/mcp-portal.d.ts +1 -1
- package/dist/bin/mcp-portal.js +1 -1
- package/dist/bin/mcp-portal.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{serve-command-CnSMUybd.js → serve-command-D3SlETy_.js} +2 -2
- package/dist/serve-command-D3SlETy_.js.map +1 -0
- package/package.json +3 -3
- package/dist/serve-command-CnSMUybd.js.map +0 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ The portal loads two files from `--config-dir`:
|
|
|
27
27
|
- `mcp.config.jsonc`: upstream MCP provider catalog and credentials.
|
|
28
28
|
- `mcp-portal.config.jsonc`: agents, profiles, policy, and optional external proxy auth.
|
|
29
29
|
|
|
30
|
-
External `serve` resolves `source: "1password"` refs through `@agent-vm/
|
|
30
|
+
External `serve` resolves `source: "1password"` refs through `@agent-vm/secret-management`.
|
|
31
31
|
Use `AGENT_VM_MCP_PORTAL_OP_TOKEN_SOURCE=env`, `op-cli`, or `keychain` plus the
|
|
32
32
|
matching source-specific env settings when the proxy host needs 1Password
|
|
33
33
|
access. If no token source is configured, env-only configs still work. The
|
package/dist/bin/mcp-portal.d.ts
CHANGED
package/dist/bin/mcp-portal.js
CHANGED
|
@@ -5,7 +5,7 @@ import { i as resolveUpstreamServers, n as createPortalCore } from "../portal-co
|
|
|
5
5
|
import { t as generateTypescriptCatalogArtifact } from "../typescript-artifact-BVLt3Ifd.js";
|
|
6
6
|
import { n as deriveAgentBearerToken, r as formatMasterKeyFingerprint, t as decodePortalMasterKey } from "../agent-bearer-token-DCtpDPCZ.js";
|
|
7
7
|
import { i as resolveAgentHmacKeys, n as createPortalApprovalVerifier, t as createPortalAgentRuntimeRecords } from "../resolve-agent-identity-DnC_Pmnh.js";
|
|
8
|
-
import { c as resolveSecretValue, i as deriveApprovalHmacKeysFromMasterKey, n as buildProfilePolicyMaps, o as parsePortalServerCliArgs, r as createServeSecretResolver, s as startPortalServer } from "../serve-command-
|
|
8
|
+
import { c as resolveSecretValue, i as deriveApprovalHmacKeysFromMasterKey, n as buildProfilePolicyMaps, o as parsePortalServerCliArgs, r as createServeSecretResolver, s as startPortalServer } from "../serve-command-D3SlETy_.js";
|
|
9
9
|
import { t as parseHmacKeysFromEnv } from "../hmac-env-B4shpRRB.js";
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
import { loadMcpConfig, loadMcpPortalConfig } from "@agent-vm/config-contracts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-portal.js","names":[],"sources":["../../src/bin/mcp-portal.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\n\nimport {\n\tloadMcpConfig,\n\tloadMcpPortalConfig,\n\ttype McpPortalConfig,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\nimport type { SecretResolver } from '@agent-vm/secrets';\nimport { z } from 'zod';\n\nimport { portalToolRecordSchema, type PortalToolRecord } from '../catalog-types.js';\nimport {\n\tbuildProfilePolicyMaps,\n\tcreateServeSecretResolver,\n\tderiveApprovalHmacKeysFromMasterKey,\n\tparsePortalServerCliArgs,\n\tstartPortalServer,\n} from '../cli/serve-command.js';\nimport {\n\tcreatePortalCore,\n\ttype PortalCoreEvent,\n\ttype PortalCoreToolName,\n} from '../core/portal-core.js';\nimport { resolveUpstreamServers } from '../core/provider-runtime.js';\nimport {\n\tcreatePortalAgentRuntimeRecords,\n\tcreatePortalApprovalVerifier,\n\tresolveAgentHmacKeys,\n} from '../mcp-proxy/resolve-agent-identity.js';\nimport {\n\tdecodePortalMasterKey,\n\tderiveAgentBearerToken,\n\tformatMasterKeyFingerprint,\n} from '../portal-auth/agent-bearer-token.js';\nimport { parseHmacKeysFromEnv } from '../portal-auth/hmac-env.js';\nimport { generateTypescriptCatalogArtifact } from '../portal-config/typescript-artifact.js';\nimport { createUpstreamMcpClientRuntime } from '../upstream-mcp-client-runtime.js';\nimport { resolveSecretValue } from './secret-value-resolver.js';\n\nconst catalogFileSchema = z\n\t.object({\n\t\ttools: z.array(portalToolRecordSchema),\n\t})\n\t.strict();\n\nexport interface PortalCatalogFile {\n\treadonly tools: readonly PortalToolRecord[];\n}\n\nexport interface AgentVmMcpPortalRuntimeProps {\n\treadonly env?: Readonly<Record<string, string | undefined>>;\n\treadonly secretResolver?: SecretResolver;\n}\n\nasync function readCatalogFile(catalogPath: string): Promise<PortalCatalogFile> {\n\tconst rawCatalog = await readFile(catalogPath, 'utf-8');\n\tconst parsedJson = JSON.parse(rawCatalog) as unknown;\n\treturn catalogFileSchema.parse(parsedJson);\n}\n\nfunction parseOutputDirectory(args: readonly string[]): string | null {\n\tconst outputFlagIndex = args.indexOf('--out');\n\tif (outputFlagIndex === -1) {\n\t\treturn null;\n\t}\n\n\treturn args[outputFlagIndex + 1] ?? null;\n}\n\nfunction printUsage(): void {\n\tprocess.stderr.write('Usage: mcp-portal validate <catalog.json>\\n');\n\tprocess.stderr.write('Usage: mcp-portal generate-helper <catalog.json> --out <directory>\\n');\n\tprocess.stderr.write(\n\t\t'Usage: mcp-portal mcp-proxy serve --config-dir <directory> [--port <port>]\\n',\n\t);\n\tprocess.stderr.write(\n\t\t'Usage: mcp-portal call --config-dir <directory> --agent <agent-id> --input <request.json> [--tool <portal-tool-name>]\\n',\n\t);\n\tprocess.stderr.write(\n\t\t'Usage: mcp-portal mcp-proxy print-client-config --config-dir <directory> --agent <agent-id> --master-key-fingerprint <sha256:...> [--proxy-url <url>]\\n',\n\t);\n}\n\nfunction readFlag(args: readonly string[], name: string): string | null {\n\tconst index = args.indexOf(name);\n\tif (index === -1) {\n\t\treturn null;\n\t}\n\treturn args[index + 1] ?? null;\n}\n\nfunction normalizeCredentialProxyUrl(value: string): string {\n\tconst url = new URL(value);\n\tif (url.protocol !== 'http:' && url.protocol !== 'https:') {\n\t\tthrow new Error(`Invalid --proxy-url protocol \"${url.protocol}\". Expected http or https.`);\n\t}\n\treturn url.toString();\n}\n\ntype RequiredPortalRuntimeProps = Required<Pick<AgentVmMcpPortalRuntimeProps, 'env'>> &\n\tPick<AgentVmMcpPortalRuntimeProps, 'secretResolver'>;\n\nasync function createCliSecretResolver(props: RequiredPortalRuntimeProps): Promise<SecretResolver> {\n\treturn props.secretResolver ?? (await createServeSecretResolver(props.env));\n}\n\ninterface McpPortalClientConfigServer {\n\treadonly headers: Readonly<Record<string, string>>;\n\treadonly type: 'streamable-http';\n\treadonly url: string;\n}\n\ninterface McpPortalClientConfig {\n\treadonly agentId: string;\n\treadonly authorizationHeaderName: string;\n\treadonly authorizationHeaderValue: string;\n\treadonly kind: 'mcp-portal-client-config';\n\treadonly masterKeyFingerprint: string;\n\treadonly mcpServers: Readonly<Record<string, McpPortalClientConfigServer>>;\n\treadonly proxyUrl: string;\n\treadonly schemaVersion: 1;\n}\n\nfunction serverNameForClientConfig(agentId: string): string {\n\treturn `mcp-portal-${agentId.replaceAll(/[^A-Za-z0-9_-]/gu, '-')}`;\n}\n\nfunction printCredentialMaterialWarning(): void {\n\tprocess.stderr.write(\n\t\t[\n\t\t\t'WARNING: MCP Portal client config is bearer credential material.',\n\t\t\t'WARNING: Treat stdout like an API token. Do not paste it into logs, commits, or chat.',\n\t\t\t'WARNING: The token is per-agent and remains valid until credentialVersion or masterKey rotation.',\n\t\t\t'',\n\t\t].join('\\n'),\n\t);\n}\n\nfunction printDisabledCredentialWriter(): number {\n\tprocess.stderr.write(\n\t\t[\n\t\t\t'mcp-portal: mcp-proxy write-credential is disabled because it persists bearer credentials.',\n\t\t\t'Use mcp-portal mcp-proxy print-client-config and decide explicitly where stdout is stored.',\n\t\t\t'',\n\t\t].join('\\n'),\n\t);\n\treturn 1;\n}\n\nasync function printClientConfig(\n\targs: readonly string[],\n\truntimeProps: RequiredPortalRuntimeProps,\n): Promise<number> {\n\tconst configDir = readFlag(args, '--config-dir');\n\tconst agentId = readFlag(args, '--agent');\n\tconst expectedFingerprint = readFlag(args, '--master-key-fingerprint');\n\tconst proxyUrlOverride = readFlag(args, '--proxy-url');\n\tif (configDir === null || agentId === null || expectedFingerprint === null) {\n\t\tprintUsage();\n\t\treturn 1;\n\t}\n\tconst portalConfig = await loadMcpPortalConfig(join(configDir, 'mcp-portal.config.jsonc'));\n\tif (portalConfig.externalAuth === undefined) {\n\t\tthrow new Error('print-client-config requires externalAuth.masterKey.');\n\t}\n\tif (portalConfig.mcpProxy === undefined && proxyUrlOverride === null) {\n\t\tthrow new Error('print-client-config requires mcpProxy server settings or --proxy-url.');\n\t}\n\tif (portalConfig.agents[agentId] === undefined) {\n\t\tthrow new Error(`Unknown MCP Portal agent \"${agentId}\".`);\n\t}\n\tconst secretResolver = await createCliSecretResolver(runtimeProps);\n\tconst masterKey = decodePortalMasterKey(\n\t\tawait resolveSecretValue(portalConfig.externalAuth.masterKey, {\n\t\t\tenv: runtimeProps.env,\n\t\t\tsecretResolver,\n\t\t}),\n\t);\n\tconst actualFingerprint = formatMasterKeyFingerprint(masterKey);\n\tif (actualFingerprint !== expectedFingerprint) {\n\t\tthrow new Error(\n\t\t\t`Master-key fingerprint mismatch. Expected ${expectedFingerprint}; resolved ${actualFingerprint}.`,\n\t\t);\n\t}\n\tconst agentConfig = portalConfig.agents[agentId];\n\tconst bearer = deriveAgentBearerToken({\n\t\tagentId,\n\t\tcredentialVersion: agentConfig.credentialVersion,\n\t\tmasterKey,\n\t});\n\tconst proxyUrl =\n\t\tproxyUrlOverride === null\n\t\t\t? credentialProxyUrlFromConfig(requireCredentialMcpProxy(portalConfig.mcpProxy), agentId)\n\t\t\t: normalizeCredentialProxyUrl(proxyUrlOverride);\n\tconst authorizationHeaderName = portalConfig.mcpProxy?.auth.headerName ?? 'authorization';\n\tconst authorizationHeaderValue = `Bearer ${bearer}`;\n\tconst clientConfig = {\n\t\tagentId,\n\t\tauthorizationHeaderName,\n\t\tauthorizationHeaderValue,\n\t\tkind: 'mcp-portal-client-config',\n\t\tmasterKeyFingerprint: actualFingerprint,\n\t\tmcpServers: {\n\t\t\t[serverNameForClientConfig(agentId)]: {\n\t\t\t\theaders: { [authorizationHeaderName]: authorizationHeaderValue },\n\t\t\t\ttype: 'streamable-http',\n\t\t\t\turl: proxyUrl,\n\t\t\t},\n\t\t},\n\t\tproxyUrl,\n\t\tschemaVersion: 1,\n\t} satisfies McpPortalClientConfig;\n\tprintCredentialMaterialWarning();\n\tprocess.stdout.write(`${JSON.stringify(clientConfig, null, '\\t')}\\n`);\n\treturn 0;\n}\n\nfunction requireCredentialMcpProxy(\n\tmcpProxy: McpPortalConfig['mcpProxy'],\n): NonNullable<McpPortalConfig['mcpProxy']> {\n\tif (mcpProxy === undefined) {\n\t\tthrow new Error('print-client-config requires mcpProxy server settings or --proxy-url.');\n\t}\n\treturn mcpProxy;\n}\n\nfunction credentialProxyUrlFromConfig(\n\tmcpProxy: NonNullable<McpPortalConfig['mcpProxy']>,\n\tagentId: string,\n): string {\n\tconst host = mcpProxy.server.host.includes(':')\n\t\t? `[${mcpProxy.server.host.replace(/^\\[|\\]$/gu, '')}]`\n\t\t: mcpProxy.server.host;\n\treturn `http://${host}:${String(mcpProxy.server.port)}/agents/${encodeURIComponent(agentId)}/mcp`;\n}\n\nconst portalCoreToolNames = new Set<string>([\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n]);\n\ntype PortalShutdownSignal = 'SIGINT' | 'SIGTERM';\ninterface PortalSignalTarget {\n\treadonly off: (signal: PortalShutdownSignal, listener: () => void) => void;\n\treadonly once: (signal: PortalShutdownSignal, listener: () => void) => void;\n}\n\nexport interface RunningPortalServer {\n\treadonly close: () => Promise<void>;\n}\n\nfunction waitForPortalShutdownSignal(\n\tsignalTarget: PortalSignalTarget = process,\n): Promise<PortalShutdownSignal> {\n\tconst signals = ['SIGINT', 'SIGTERM'] satisfies readonly PortalShutdownSignal[];\n\treturn new Promise((resolve) => {\n\t\tconst listeners = new Map<PortalShutdownSignal, () => void>();\n\t\tfor (const signal of signals) {\n\t\t\tconst listener = (): void => {\n\t\t\t\tfor (const [registeredSignal, registeredListener] of listeners) {\n\t\t\t\t\tsignalTarget.off(registeredSignal, registeredListener);\n\t\t\t\t}\n\t\t\t\tresolve(signal);\n\t\t\t};\n\t\t\tlisteners.set(signal, listener);\n\t\t\tsignalTarget.once(signal, listener);\n\t\t}\n\t});\n}\n\nexport async function waitUntilPortalServerShutdown(props: {\n\treadonly server: RunningPortalServer;\n\treadonly signalTarget?: PortalSignalTarget;\n}): Promise<void> {\n\ttry {\n\t\tawait waitForPortalShutdownSignal(props.signalTarget);\n\t} finally {\n\t\tawait props.server.close();\n\t}\n}\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalCoreToolNames.has(value);\n}\n\nfunction parsePortalCoreToolName(value: string | null): PortalCoreToolName {\n\tconst toolName = value ?? 'mcp_portal_call';\n\tif (!isPortalCoreToolName(toolName)) {\n\t\tthrow new Error(`Unknown MCP Portal tool \"${toolName}\".`);\n\t}\n\treturn toolName;\n}\n\nfunction writePortalCoreEventToStderr(event: PortalCoreEvent): void {\n\tif (event.kind === 'progress' && event.message !== undefined) {\n\t\tprocess.stderr.write(`${event.message}\\n`);\n\t\treturn;\n\t}\n\tif (event.kind === 'partial_content') {\n\t\tconst message =\n\t\t\tevent.content.type === 'text' ? event.content.text : JSON.stringify(event.content.value);\n\t\tprocess.stderr.write(`${message}\\n`);\n\t\treturn;\n\t}\n\tif (event.kind === 'upstream_notification') {\n\t\tprocess.stderr.write(`upstream notification ${event.method}\\n`);\n\t}\n}\n\nasync function resolveCliApprovalHmacKeys(props: {\n\treadonly agentIds: readonly string[];\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly portalConfig: Awaited<ReturnType<typeof loadMcpPortalConfig>>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<ReadonlyMap<string, Buffer>> {\n\tif (props.portalConfig.externalAuth !== undefined) {\n\t\tconst masterKey = decodePortalMasterKey(\n\t\t\tawait props.resolveSecret(props.portalConfig.externalAuth.masterKey),\n\t\t);\n\t\treturn deriveApprovalHmacKeysFromMasterKey({ agentIds: props.agentIds, masterKey });\n\t}\n\treturn await resolveAgentHmacKeys({\n\t\tagents: props.portalConfig.agents,\n\t\tenvKeys: parseHmacKeysFromEnv(props.env),\n\t\tresolveSecret: props.resolveSecret,\n\t});\n}\n\nasync function runCallCommand(\n\targs: readonly string[],\n\truntimeProps: RequiredPortalRuntimeProps,\n): Promise<number> {\n\tconst configDir = readFlag(args, '--config-dir');\n\tconst agentId = readFlag(args, '--agent');\n\tconst inputPath = readFlag(args, '--input');\n\tif (configDir === null || agentId === null || inputPath === null) {\n\t\tprintUsage();\n\t\treturn 1;\n\t}\n\tconst toolName = parsePortalCoreToolName(readFlag(args, '--tool'));\n\tconst input = JSON.parse(await readFile(inputPath, 'utf8')) as unknown;\n\tconst secretResolver = await createCliSecretResolver(runtimeProps);\n\tconst resolveSecret = (secret: SecretValue): Promise<string> =>\n\t\tresolveSecretValue(secret, { env: runtimeProps.env, secretResolver });\n\tconst [mcpConfig, portalConfig] = await Promise.all([\n\t\tloadMcpConfig(join(configDir, 'mcp.config.jsonc')),\n\t\tloadMcpPortalConfig(join(configDir, 'mcp-portal.config.jsonc')),\n\t]);\n\tif (portalConfig.agents[agentId] === undefined) {\n\t\tthrow new Error(`Unknown MCP Portal agent \"${agentId}\".`);\n\t}\n\tconst hmacKeys = await resolveCliApprovalHmacKeys({\n\t\tagentIds: Object.keys(portalConfig.agents),\n\t\tenv: runtimeProps.env,\n\t\tportalConfig,\n\t\tresolveSecret,\n\t});\n\tconst agentRecords = createPortalAgentRuntimeRecords({ hmacKeys, portalConfig });\n\tconst verifyApproval = createPortalApprovalVerifier({ records: agentRecords });\n\tconst upstreamServers = await resolveUpstreamServers({ config: mcpConfig, resolveSecret });\n\tconst upstreamRuntime = createUpstreamMcpClientRuntime({ servers: upstreamServers });\n\tconst profilePolicyMaps = buildProfilePolicyMaps(portalConfig);\n\tconst core = createPortalCore({\n\t\taccessPolicy: {\n\t\t\tdefaultPolicy: 'deny-all',\n\t\t\tenabledNamespacesByAgent: profilePolicyMaps.enabledNamespacesByAgent,\n\t\t\tenabledToolsByAgent: profilePolicyMaps.enabledToolsByAgent,\n\t\t\thiddenToolsByAgent: profilePolicyMaps.hiddenToolsByAgent,\n\t\t},\n\t\tapproval: (calls, scope, approvalToken) => verifyApproval(calls, scope.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\ttry {\n\t\tconst scope = core.createAgentScope({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'cli-operator',\n\t\t});\n\t\tconst result = await core.collectPortalCoreResult(core.callStream({ input, scope, toolName }), {\n\t\t\tonEvent: writePortalCoreEventToStderr,\n\t\t});\n\t\tprocess.stdout.write(`${JSON.stringify(result, null, '\\t')}\\n`);\n\t\treturn 0;\n\t} finally {\n\t\tawait core.close();\n\t}\n}\n\nexport async function runMcpPortal(\n\targs: readonly string[],\n\tprops: AgentVmMcpPortalRuntimeProps = {},\n): Promise<number> {\n\tconst [command, catalogPath, ...restArgs] = args;\n\tconst runtimeProps = {\n\t\tenv: props.env ?? process.env,\n\t\t...(props.secretResolver !== undefined ? { secretResolver: props.secretResolver } : {}),\n\t};\n\tif (!command) {\n\t\tprintUsage();\n\t\treturn 1;\n\t}\n\n\ttry {\n\t\tif (command === 'mcp-proxy') {\n\t\t\tconst [mcpProxyCommand, ...mcpProxyArgs] = args.slice(1);\n\t\t\tif (mcpProxyCommand === 'serve') {\n\t\t\t\tconst injectedSecretResolver = runtimeProps.secretResolver;\n\t\t\t\tconst server = await startPortalServer({\n\t\t\t\t\targs: parsePortalServerCliArgs(mcpProxyArgs),\n\t\t\t\t\tenv: runtimeProps.env,\n\t\t\t\t\t...(injectedSecretResolver !== undefined\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tresolveSecret: (secret) =>\n\t\t\t\t\t\t\t\t\tresolveSecretValue(secret, {\n\t\t\t\t\t\t\t\t\t\tenv: runtimeProps.env,\n\t\t\t\t\t\t\t\t\t\tsecretResolver: injectedSecretResolver,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\tawait waitUntilPortalServerShutdown({ server });\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (mcpProxyCommand === 'write-credential') {\n\t\t\t\treturn printDisabledCredentialWriter();\n\t\t\t}\n\t\t\tif (mcpProxyCommand === 'print-client-config') {\n\t\t\t\treturn await printClientConfig(mcpProxyArgs, runtimeProps);\n\t\t\t}\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tif (command === 'serve') {\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tif (command === 'write-credential') {\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tif (command === 'call') {\n\t\t\treturn await runCallCommand(args.slice(1), runtimeProps);\n\t\t}\n\t\tif (!catalogPath) {\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tconst catalog = await readCatalogFile(catalogPath);\n\t\tswitch (command) {\n\t\t\tcase 'validate':\n\t\t\t\treturn 0;\n\t\t\tcase 'generate-helper': {\n\t\t\t\tconst outputDirectory = parseOutputDirectory(restArgs);\n\t\t\t\tif (!outputDirectory) {\n\t\t\t\t\tprintUsage();\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tawait mkdir(outputDirectory, { recursive: true });\n\t\t\t\tawait writeFile(join(outputDirectory, 'catalog.json'), JSON.stringify(catalog, null, '\\t'));\n\t\t\t\tawait writeFile(\n\t\t\t\t\tjoin(outputDirectory, 'catalog.ts'),\n\t\t\t\t\tgenerateTypescriptCatalogArtifact(catalog),\n\t\t\t\t);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tprintUsage();\n\t\t\t\treturn 1;\n\t\t}\n\t} catch (error) {\n\t\tprocess.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n\t\treturn 1;\n\t}\n}\n\n/*\n * Command-shape note: top-level `serve` and credential commands are\n * intentionally rejected. The public CLI shape is `mcp-portal mcp-proxy ...`\n * so the command mirrors the library adapter boundary.\n */\n\nexport function shouldRunMcpPortalEntrypoint(argvPath: string | undefined): boolean {\n\tconst entrypointName = argvPath === undefined ? undefined : basename(argvPath);\n\treturn (\n\t\tentrypointName === 'mcp-portal' ||\n\t\tentrypointName === 'mcp-portal.js' ||\n\t\tentrypointName === 'mcp-portal.ts'\n\t);\n}\n\nif (shouldRunMcpPortalEntrypoint(process.argv[1])) {\n\tprocess.exitCode = await runMcpPortal(process.argv.slice(2));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp-portal.js","names":[],"sources":["../../src/bin/mcp-portal.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\n\nimport {\n\tloadMcpConfig,\n\tloadMcpPortalConfig,\n\ttype McpPortalConfig,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\nimport type { SecretResolver } from '@agent-vm/secret-management';\nimport { z } from 'zod';\n\nimport { portalToolRecordSchema, type PortalToolRecord } from '../catalog-types.js';\nimport {\n\tbuildProfilePolicyMaps,\n\tcreateServeSecretResolver,\n\tderiveApprovalHmacKeysFromMasterKey,\n\tparsePortalServerCliArgs,\n\tstartPortalServer,\n} from '../cli/serve-command.js';\nimport {\n\tcreatePortalCore,\n\ttype PortalCoreEvent,\n\ttype PortalCoreToolName,\n} from '../core/portal-core.js';\nimport { resolveUpstreamServers } from '../core/provider-runtime.js';\nimport {\n\tcreatePortalAgentRuntimeRecords,\n\tcreatePortalApprovalVerifier,\n\tresolveAgentHmacKeys,\n} from '../mcp-proxy/resolve-agent-identity.js';\nimport {\n\tdecodePortalMasterKey,\n\tderiveAgentBearerToken,\n\tformatMasterKeyFingerprint,\n} from '../portal-auth/agent-bearer-token.js';\nimport { parseHmacKeysFromEnv } from '../portal-auth/hmac-env.js';\nimport { generateTypescriptCatalogArtifact } from '../portal-config/typescript-artifact.js';\nimport { createUpstreamMcpClientRuntime } from '../upstream-mcp-client-runtime.js';\nimport { resolveSecretValue } from './secret-value-resolver.js';\n\nconst catalogFileSchema = z\n\t.object({\n\t\ttools: z.array(portalToolRecordSchema),\n\t})\n\t.strict();\n\nexport interface PortalCatalogFile {\n\treadonly tools: readonly PortalToolRecord[];\n}\n\nexport interface AgentVmMcpPortalRuntimeProps {\n\treadonly env?: Readonly<Record<string, string | undefined>>;\n\treadonly secretResolver?: SecretResolver;\n}\n\nasync function readCatalogFile(catalogPath: string): Promise<PortalCatalogFile> {\n\tconst rawCatalog = await readFile(catalogPath, 'utf-8');\n\tconst parsedJson = JSON.parse(rawCatalog) as unknown;\n\treturn catalogFileSchema.parse(parsedJson);\n}\n\nfunction parseOutputDirectory(args: readonly string[]): string | null {\n\tconst outputFlagIndex = args.indexOf('--out');\n\tif (outputFlagIndex === -1) {\n\t\treturn null;\n\t}\n\n\treturn args[outputFlagIndex + 1] ?? null;\n}\n\nfunction printUsage(): void {\n\tprocess.stderr.write('Usage: mcp-portal validate <catalog.json>\\n');\n\tprocess.stderr.write('Usage: mcp-portal generate-helper <catalog.json> --out <directory>\\n');\n\tprocess.stderr.write(\n\t\t'Usage: mcp-portal mcp-proxy serve --config-dir <directory> [--port <port>]\\n',\n\t);\n\tprocess.stderr.write(\n\t\t'Usage: mcp-portal call --config-dir <directory> --agent <agent-id> --input <request.json> [--tool <portal-tool-name>]\\n',\n\t);\n\tprocess.stderr.write(\n\t\t'Usage: mcp-portal mcp-proxy print-client-config --config-dir <directory> --agent <agent-id> --master-key-fingerprint <sha256:...> [--proxy-url <url>]\\n',\n\t);\n}\n\nfunction readFlag(args: readonly string[], name: string): string | null {\n\tconst index = args.indexOf(name);\n\tif (index === -1) {\n\t\treturn null;\n\t}\n\treturn args[index + 1] ?? null;\n}\n\nfunction normalizeCredentialProxyUrl(value: string): string {\n\tconst url = new URL(value);\n\tif (url.protocol !== 'http:' && url.protocol !== 'https:') {\n\t\tthrow new Error(`Invalid --proxy-url protocol \"${url.protocol}\". Expected http or https.`);\n\t}\n\treturn url.toString();\n}\n\ntype RequiredPortalRuntimeProps = Required<Pick<AgentVmMcpPortalRuntimeProps, 'env'>> &\n\tPick<AgentVmMcpPortalRuntimeProps, 'secretResolver'>;\n\nasync function createCliSecretResolver(props: RequiredPortalRuntimeProps): Promise<SecretResolver> {\n\treturn props.secretResolver ?? (await createServeSecretResolver(props.env));\n}\n\ninterface McpPortalClientConfigServer {\n\treadonly headers: Readonly<Record<string, string>>;\n\treadonly type: 'streamable-http';\n\treadonly url: string;\n}\n\ninterface McpPortalClientConfig {\n\treadonly agentId: string;\n\treadonly authorizationHeaderName: string;\n\treadonly authorizationHeaderValue: string;\n\treadonly kind: 'mcp-portal-client-config';\n\treadonly masterKeyFingerprint: string;\n\treadonly mcpServers: Readonly<Record<string, McpPortalClientConfigServer>>;\n\treadonly proxyUrl: string;\n\treadonly schemaVersion: 1;\n}\n\nfunction serverNameForClientConfig(agentId: string): string {\n\treturn `mcp-portal-${agentId.replaceAll(/[^A-Za-z0-9_-]/gu, '-')}`;\n}\n\nfunction printCredentialMaterialWarning(): void {\n\tprocess.stderr.write(\n\t\t[\n\t\t\t'WARNING: MCP Portal client config is bearer credential material.',\n\t\t\t'WARNING: Treat stdout like an API token. Do not paste it into logs, commits, or chat.',\n\t\t\t'WARNING: The token is per-agent and remains valid until credentialVersion or masterKey rotation.',\n\t\t\t'',\n\t\t].join('\\n'),\n\t);\n}\n\nfunction printDisabledCredentialWriter(): number {\n\tprocess.stderr.write(\n\t\t[\n\t\t\t'mcp-portal: mcp-proxy write-credential is disabled because it persists bearer credentials.',\n\t\t\t'Use mcp-portal mcp-proxy print-client-config and decide explicitly where stdout is stored.',\n\t\t\t'',\n\t\t].join('\\n'),\n\t);\n\treturn 1;\n}\n\nasync function printClientConfig(\n\targs: readonly string[],\n\truntimeProps: RequiredPortalRuntimeProps,\n): Promise<number> {\n\tconst configDir = readFlag(args, '--config-dir');\n\tconst agentId = readFlag(args, '--agent');\n\tconst expectedFingerprint = readFlag(args, '--master-key-fingerprint');\n\tconst proxyUrlOverride = readFlag(args, '--proxy-url');\n\tif (configDir === null || agentId === null || expectedFingerprint === null) {\n\t\tprintUsage();\n\t\treturn 1;\n\t}\n\tconst portalConfig = await loadMcpPortalConfig(join(configDir, 'mcp-portal.config.jsonc'));\n\tif (portalConfig.externalAuth === undefined) {\n\t\tthrow new Error('print-client-config requires externalAuth.masterKey.');\n\t}\n\tif (portalConfig.mcpProxy === undefined && proxyUrlOverride === null) {\n\t\tthrow new Error('print-client-config requires mcpProxy server settings or --proxy-url.');\n\t}\n\tif (portalConfig.agents[agentId] === undefined) {\n\t\tthrow new Error(`Unknown MCP Portal agent \"${agentId}\".`);\n\t}\n\tconst secretResolver = await createCliSecretResolver(runtimeProps);\n\tconst masterKey = decodePortalMasterKey(\n\t\tawait resolveSecretValue(portalConfig.externalAuth.masterKey, {\n\t\t\tenv: runtimeProps.env,\n\t\t\tsecretResolver,\n\t\t}),\n\t);\n\tconst actualFingerprint = formatMasterKeyFingerprint(masterKey);\n\tif (actualFingerprint !== expectedFingerprint) {\n\t\tthrow new Error(\n\t\t\t`Master-key fingerprint mismatch. Expected ${expectedFingerprint}; resolved ${actualFingerprint}.`,\n\t\t);\n\t}\n\tconst agentConfig = portalConfig.agents[agentId];\n\tconst bearer = deriveAgentBearerToken({\n\t\tagentId,\n\t\tcredentialVersion: agentConfig.credentialVersion,\n\t\tmasterKey,\n\t});\n\tconst proxyUrl =\n\t\tproxyUrlOverride === null\n\t\t\t? credentialProxyUrlFromConfig(requireCredentialMcpProxy(portalConfig.mcpProxy), agentId)\n\t\t\t: normalizeCredentialProxyUrl(proxyUrlOverride);\n\tconst authorizationHeaderName = portalConfig.mcpProxy?.auth.headerName ?? 'authorization';\n\tconst authorizationHeaderValue = `Bearer ${bearer}`;\n\tconst clientConfig = {\n\t\tagentId,\n\t\tauthorizationHeaderName,\n\t\tauthorizationHeaderValue,\n\t\tkind: 'mcp-portal-client-config',\n\t\tmasterKeyFingerprint: actualFingerprint,\n\t\tmcpServers: {\n\t\t\t[serverNameForClientConfig(agentId)]: {\n\t\t\t\theaders: { [authorizationHeaderName]: authorizationHeaderValue },\n\t\t\t\ttype: 'streamable-http',\n\t\t\t\turl: proxyUrl,\n\t\t\t},\n\t\t},\n\t\tproxyUrl,\n\t\tschemaVersion: 1,\n\t} satisfies McpPortalClientConfig;\n\tprintCredentialMaterialWarning();\n\tprocess.stdout.write(`${JSON.stringify(clientConfig, null, '\\t')}\\n`);\n\treturn 0;\n}\n\nfunction requireCredentialMcpProxy(\n\tmcpProxy: McpPortalConfig['mcpProxy'],\n): NonNullable<McpPortalConfig['mcpProxy']> {\n\tif (mcpProxy === undefined) {\n\t\tthrow new Error('print-client-config requires mcpProxy server settings or --proxy-url.');\n\t}\n\treturn mcpProxy;\n}\n\nfunction credentialProxyUrlFromConfig(\n\tmcpProxy: NonNullable<McpPortalConfig['mcpProxy']>,\n\tagentId: string,\n): string {\n\tconst host = mcpProxy.server.host.includes(':')\n\t\t? `[${mcpProxy.server.host.replace(/^\\[|\\]$/gu, '')}]`\n\t\t: mcpProxy.server.host;\n\treturn `http://${host}:${String(mcpProxy.server.port)}/agents/${encodeURIComponent(agentId)}/mcp`;\n}\n\nconst portalCoreToolNames = new Set<string>([\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n]);\n\ntype PortalShutdownSignal = 'SIGINT' | 'SIGTERM';\ninterface PortalSignalTarget {\n\treadonly off: (signal: PortalShutdownSignal, listener: () => void) => void;\n\treadonly once: (signal: PortalShutdownSignal, listener: () => void) => void;\n}\n\nexport interface RunningPortalServer {\n\treadonly close: () => Promise<void>;\n}\n\nfunction waitForPortalShutdownSignal(\n\tsignalTarget: PortalSignalTarget = process,\n): Promise<PortalShutdownSignal> {\n\tconst signals = ['SIGINT', 'SIGTERM'] satisfies readonly PortalShutdownSignal[];\n\treturn new Promise((resolve) => {\n\t\tconst listeners = new Map<PortalShutdownSignal, () => void>();\n\t\tfor (const signal of signals) {\n\t\t\tconst listener = (): void => {\n\t\t\t\tfor (const [registeredSignal, registeredListener] of listeners) {\n\t\t\t\t\tsignalTarget.off(registeredSignal, registeredListener);\n\t\t\t\t}\n\t\t\t\tresolve(signal);\n\t\t\t};\n\t\t\tlisteners.set(signal, listener);\n\t\t\tsignalTarget.once(signal, listener);\n\t\t}\n\t});\n}\n\nexport async function waitUntilPortalServerShutdown(props: {\n\treadonly server: RunningPortalServer;\n\treadonly signalTarget?: PortalSignalTarget;\n}): Promise<void> {\n\ttry {\n\t\tawait waitForPortalShutdownSignal(props.signalTarget);\n\t} finally {\n\t\tawait props.server.close();\n\t}\n}\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalCoreToolNames.has(value);\n}\n\nfunction parsePortalCoreToolName(value: string | null): PortalCoreToolName {\n\tconst toolName = value ?? 'mcp_portal_call';\n\tif (!isPortalCoreToolName(toolName)) {\n\t\tthrow new Error(`Unknown MCP Portal tool \"${toolName}\".`);\n\t}\n\treturn toolName;\n}\n\nfunction writePortalCoreEventToStderr(event: PortalCoreEvent): void {\n\tif (event.kind === 'progress' && event.message !== undefined) {\n\t\tprocess.stderr.write(`${event.message}\\n`);\n\t\treturn;\n\t}\n\tif (event.kind === 'partial_content') {\n\t\tconst message =\n\t\t\tevent.content.type === 'text' ? event.content.text : JSON.stringify(event.content.value);\n\t\tprocess.stderr.write(`${message}\\n`);\n\t\treturn;\n\t}\n\tif (event.kind === 'upstream_notification') {\n\t\tprocess.stderr.write(`upstream notification ${event.method}\\n`);\n\t}\n}\n\nasync function resolveCliApprovalHmacKeys(props: {\n\treadonly agentIds: readonly string[];\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly portalConfig: Awaited<ReturnType<typeof loadMcpPortalConfig>>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<ReadonlyMap<string, Buffer>> {\n\tif (props.portalConfig.externalAuth !== undefined) {\n\t\tconst masterKey = decodePortalMasterKey(\n\t\t\tawait props.resolveSecret(props.portalConfig.externalAuth.masterKey),\n\t\t);\n\t\treturn deriveApprovalHmacKeysFromMasterKey({ agentIds: props.agentIds, masterKey });\n\t}\n\treturn await resolveAgentHmacKeys({\n\t\tagents: props.portalConfig.agents,\n\t\tenvKeys: parseHmacKeysFromEnv(props.env),\n\t\tresolveSecret: props.resolveSecret,\n\t});\n}\n\nasync function runCallCommand(\n\targs: readonly string[],\n\truntimeProps: RequiredPortalRuntimeProps,\n): Promise<number> {\n\tconst configDir = readFlag(args, '--config-dir');\n\tconst agentId = readFlag(args, '--agent');\n\tconst inputPath = readFlag(args, '--input');\n\tif (configDir === null || agentId === null || inputPath === null) {\n\t\tprintUsage();\n\t\treturn 1;\n\t}\n\tconst toolName = parsePortalCoreToolName(readFlag(args, '--tool'));\n\tconst input = JSON.parse(await readFile(inputPath, 'utf8')) as unknown;\n\tconst secretResolver = await createCliSecretResolver(runtimeProps);\n\tconst resolveSecret = (secret: SecretValue): Promise<string> =>\n\t\tresolveSecretValue(secret, { env: runtimeProps.env, secretResolver });\n\tconst [mcpConfig, portalConfig] = await Promise.all([\n\t\tloadMcpConfig(join(configDir, 'mcp.config.jsonc')),\n\t\tloadMcpPortalConfig(join(configDir, 'mcp-portal.config.jsonc')),\n\t]);\n\tif (portalConfig.agents[agentId] === undefined) {\n\t\tthrow new Error(`Unknown MCP Portal agent \"${agentId}\".`);\n\t}\n\tconst hmacKeys = await resolveCliApprovalHmacKeys({\n\t\tagentIds: Object.keys(portalConfig.agents),\n\t\tenv: runtimeProps.env,\n\t\tportalConfig,\n\t\tresolveSecret,\n\t});\n\tconst agentRecords = createPortalAgentRuntimeRecords({ hmacKeys, portalConfig });\n\tconst verifyApproval = createPortalApprovalVerifier({ records: agentRecords });\n\tconst upstreamServers = await resolveUpstreamServers({ config: mcpConfig, resolveSecret });\n\tconst upstreamRuntime = createUpstreamMcpClientRuntime({ servers: upstreamServers });\n\tconst profilePolicyMaps = buildProfilePolicyMaps(portalConfig);\n\tconst core = createPortalCore({\n\t\taccessPolicy: {\n\t\t\tdefaultPolicy: 'deny-all',\n\t\t\tenabledNamespacesByAgent: profilePolicyMaps.enabledNamespacesByAgent,\n\t\t\tenabledToolsByAgent: profilePolicyMaps.enabledToolsByAgent,\n\t\t\thiddenToolsByAgent: profilePolicyMaps.hiddenToolsByAgent,\n\t\t},\n\t\tapproval: (calls, scope, approvalToken) => verifyApproval(calls, scope.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\ttry {\n\t\tconst scope = core.createAgentScope({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'cli-operator',\n\t\t});\n\t\tconst result = await core.collectPortalCoreResult(core.callStream({ input, scope, toolName }), {\n\t\t\tonEvent: writePortalCoreEventToStderr,\n\t\t});\n\t\tprocess.stdout.write(`${JSON.stringify(result, null, '\\t')}\\n`);\n\t\treturn 0;\n\t} finally {\n\t\tawait core.close();\n\t}\n}\n\nexport async function runMcpPortal(\n\targs: readonly string[],\n\tprops: AgentVmMcpPortalRuntimeProps = {},\n): Promise<number> {\n\tconst [command, catalogPath, ...restArgs] = args;\n\tconst runtimeProps = {\n\t\tenv: props.env ?? process.env,\n\t\t...(props.secretResolver !== undefined ? { secretResolver: props.secretResolver } : {}),\n\t};\n\tif (!command) {\n\t\tprintUsage();\n\t\treturn 1;\n\t}\n\n\ttry {\n\t\tif (command === 'mcp-proxy') {\n\t\t\tconst [mcpProxyCommand, ...mcpProxyArgs] = args.slice(1);\n\t\t\tif (mcpProxyCommand === 'serve') {\n\t\t\t\tconst injectedSecretResolver = runtimeProps.secretResolver;\n\t\t\t\tconst server = await startPortalServer({\n\t\t\t\t\targs: parsePortalServerCliArgs(mcpProxyArgs),\n\t\t\t\t\tenv: runtimeProps.env,\n\t\t\t\t\t...(injectedSecretResolver !== undefined\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tresolveSecret: (secret) =>\n\t\t\t\t\t\t\t\t\tresolveSecretValue(secret, {\n\t\t\t\t\t\t\t\t\t\tenv: runtimeProps.env,\n\t\t\t\t\t\t\t\t\t\tsecretResolver: injectedSecretResolver,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\tawait waitUntilPortalServerShutdown({ server });\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (mcpProxyCommand === 'write-credential') {\n\t\t\t\treturn printDisabledCredentialWriter();\n\t\t\t}\n\t\t\tif (mcpProxyCommand === 'print-client-config') {\n\t\t\t\treturn await printClientConfig(mcpProxyArgs, runtimeProps);\n\t\t\t}\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tif (command === 'serve') {\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tif (command === 'write-credential') {\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tif (command === 'call') {\n\t\t\treturn await runCallCommand(args.slice(1), runtimeProps);\n\t\t}\n\t\tif (!catalogPath) {\n\t\t\tprintUsage();\n\t\t\treturn 1;\n\t\t}\n\t\tconst catalog = await readCatalogFile(catalogPath);\n\t\tswitch (command) {\n\t\t\tcase 'validate':\n\t\t\t\treturn 0;\n\t\t\tcase 'generate-helper': {\n\t\t\t\tconst outputDirectory = parseOutputDirectory(restArgs);\n\t\t\t\tif (!outputDirectory) {\n\t\t\t\t\tprintUsage();\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tawait mkdir(outputDirectory, { recursive: true });\n\t\t\t\tawait writeFile(join(outputDirectory, 'catalog.json'), JSON.stringify(catalog, null, '\\t'));\n\t\t\t\tawait writeFile(\n\t\t\t\t\tjoin(outputDirectory, 'catalog.ts'),\n\t\t\t\t\tgenerateTypescriptCatalogArtifact(catalog),\n\t\t\t\t);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tprintUsage();\n\t\t\t\treturn 1;\n\t\t}\n\t} catch (error) {\n\t\tprocess.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n\t\treturn 1;\n\t}\n}\n\n/*\n * Command-shape note: top-level `serve` and credential commands are\n * intentionally rejected. The public CLI shape is `mcp-portal mcp-proxy ...`\n * so the command mirrors the library adapter boundary.\n */\n\nexport function shouldRunMcpPortalEntrypoint(argvPath: string | undefined): boolean {\n\tconst entrypointName = argvPath === undefined ? undefined : basename(argvPath);\n\treturn (\n\t\tentrypointName === 'mcp-portal' ||\n\t\tentrypointName === 'mcp-portal.js' ||\n\t\tentrypointName === 'mcp-portal.ts'\n\t);\n}\n\nif (shouldRunMcpPortalEntrypoint(process.argv[1])) {\n\tprocess.exitCode = await runMcpPortal(process.argv.slice(2));\n}\n"],"mappings":"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"}
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { F as PortalToolSelector } from "../portal-session-DG2CUjIo.js";
|
|
2
2
|
import { f as PortalHttpAuditEvent, n as PortalApprovalAuditEvent } from "../resolve-agent-identity-FQL02YdW.js";
|
|
3
3
|
import { McpPortalAgentConfig, McpPortalConfig, SecretValue } from "@agent-vm/config-contracts";
|
|
4
|
-
import { SecretResolver, createSecretResolver, resolveServiceAccountToken } from "@agent-vm/
|
|
4
|
+
import { SecretResolver, createSecretResolver, resolveServiceAccountToken } from "@agent-vm/secret-management";
|
|
5
5
|
import { serve } from "@hono/node-server";
|
|
6
6
|
|
|
7
7
|
//#region src/cli/serve-command.d.ts
|
package/dist/cli/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as handlePortalServerError, i as deriveApprovalHmacKeysFromMasterKey, n as buildProfilePolicyMaps, o as parsePortalServerCliArgs, r as createServeSecretResolver, s as startPortalServer, t as applyAgentOverrides } from "../serve-command-
|
|
1
|
+
import { a as handlePortalServerError, i as deriveApprovalHmacKeysFromMasterKey, n as buildProfilePolicyMaps, o as parsePortalServerCliArgs, r as createServeSecretResolver, s as startPortalServer, t as applyAgentOverrides } from "../serve-command-D3SlETy_.js";
|
|
2
2
|
export { applyAgentOverrides, buildProfilePolicyMaps, createServeSecretResolver, deriveApprovalHmacKeysFromMasterKey, handlePortalServerError, parsePortalServerCliArgs, startPortalServer };
|
|
@@ -6,7 +6,7 @@ import { createHmac } from "node:crypto";
|
|
|
6
6
|
import { loadMcpConfig, loadMcpPortalConfig, resolveMcpPortalProfile } from "@agent-vm/config-contracts";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { parseArgs } from "node:util";
|
|
9
|
-
import { createCompositeSecretResolver, createSecretResolver, resolveServiceAccountToken } from "@agent-vm/
|
|
9
|
+
import { createCompositeSecretResolver, createSecretResolver, resolveServiceAccountToken } from "@agent-vm/secret-management";
|
|
10
10
|
import { serve } from "@hono/node-server";
|
|
11
11
|
//#region src/bin/secret-value-resolver.ts
|
|
12
12
|
function secretRefFromSecretValue(secret) {
|
|
@@ -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-D3SlETy_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve-command-D3SlETy_.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 enabledToolsByAgent: Readonly<Record<string, readonly PortalToolSelector[]>>;\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 enabledToolsByAgent: Record<string, readonly PortalToolSelector[]> = {};\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\tenabledToolsByAgent[agentId] = selectorsFromNamespaceTools(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\tenabledToolsByAgent,\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\tenabledToolsByAgent: profilePolicyMaps.enabledToolsByAgent,\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-vm/mcp-portal",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.71",
|
|
4
4
|
"description": "Agent-scoped MCP Portal server and TypeScript helpers for composable upstream MCP tools.",
|
|
5
5
|
"homepage": "https://github.com/ShravanSunder/agent-vm#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
70
70
|
"hono": "^4.12.18",
|
|
71
71
|
"zod": "^4.4.3",
|
|
72
|
-
"@agent-vm/
|
|
73
|
-
"@agent-vm/
|
|
72
|
+
"@agent-vm/config-contracts": "0.0.71",
|
|
73
|
+
"@agent-vm/secret-management": "0.0.71"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"vitest": "^4.1.5"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serve-command-CnSMUybd.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/secrets';\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/secrets';\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 enabledToolsByAgent: Readonly<Record<string, readonly PortalToolSelector[]>>;\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 enabledToolsByAgent: Record<string, readonly PortalToolSelector[]> = {};\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\tenabledToolsByAgent[agentId] = selectorsFromNamespaceTools(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\tenabledToolsByAgent,\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\tenabledToolsByAgent: profilePolicyMaps.enabledToolsByAgent,\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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"}
|