@agent-vm/mcp-portal 0.0.79 → 0.0.80

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.
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { a as portalToolRecordSchema } from "../zod-schema-loader-yNekKNpm.js";
3
3
  import { t as createUpstreamMcpClientRuntime } from "../upstream-mcp-client-runtime-Be_cw6pV.js";
4
- import { i as resolveUpstreamServers, n as createPortalCore } from "../portal-core-B5cRpZMG.js";
4
+ import { i as resolveUpstreamServers, n as createPortalCore } from "../portal-core-e-qajblz.js";
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
- import { i as resolveAgentHmacKeys, n as createPortalApprovalVerifier, t as createPortalAgentRuntimeRecords } from "../resolve-agent-identity-ZMMY2Wqm.js";
8
- import { c as resolveSecretValue, i as deriveApprovalHmacKeysFromMasterKey, n as buildProfilePolicyMaps, o as parsePortalServerCliArgs, r as createServeSecretResolver, s as startPortalServer } from "../serve-command-Dz6nvnzQ.js";
7
+ import { i as resolveAgentHmacKeys, n as createPortalApprovalVerifier, t as createPortalAgentRuntimeRecords } from "../resolve-agent-identity-Dnqv2hAW.js";
8
+ import { c as resolveSecretValue, i as deriveApprovalHmacKeysFromMasterKey, n as buildProfilePolicyMaps, o as parsePortalServerCliArgs, r as createServeSecretResolver, s as startPortalServer } from "../serve-command-DHkYmO6n.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,5 +1,5 @@
1
1
  import { L as PortalToolSelector } from "../portal-session-5ksK1G9Z.js";
2
- import { f as PortalHttpAuditEvent, n as PortalApprovalAuditEvent } from "../resolve-agent-identity-C9Jc2NhJ.js";
2
+ import { f as PortalHttpAuditEvent, n as PortalApprovalAuditEvent } from "../resolve-agent-identity-C1xp9_2R.js";
3
3
  import { McpPortalAgentConfig, McpPortalConfig, SecretValue } from "@agent-vm/config-contracts";
4
4
  import { SecretResolver, createSecretResolver, resolveServiceAccountToken } from "@agent-vm/secret-management";
5
5
  import { serve } from "@hono/node-server";
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-Dz6nvnzQ.js";
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-DHkYmO6n.js";
2
2
  export { applyAgentOverrides, buildProfilePolicyMaps, createServeSecretResolver, deriveApprovalHmacKeysFromMasterKey, handlePortalServerError, parsePortalServerCliArgs, startPortalServer };
@@ -1,6 +1,6 @@
1
1
  import { n as PortalToolRecord, s as JsonObject } from "../catalog-types-BVuB4Ynx.js";
2
2
  import { L as PortalToolSelector } from "../portal-session-5ksK1G9Z.js";
3
- import { A as PortalToolSuccess, C as PortalCallUpstreamTool, D as PortalToolResult, E as PortalToolHandlers, M as createPortalToolHandlers, N as portalToolInputSchemas, O as PortalToolResultMap, S as PortalBatchResult, T as PortalToolHandlerCall, _ as createPortalCore, a as PortalCore, b as PortalBatchDiagnostic, c as PortalCoreEvent, d as PortalCoreResult, f as PortalCoreRuntime, g as collectPortalCoreResult, h as PortalCoreToolName, i as PortalAuditEvent, j as PortalUpstreamEvent, k as PortalToolRuntime, l as PortalCoreItemError, m as PortalCoreToolDescriptor, n as PortalAgentScope, o as PortalCoreCollectOptions, p as PortalCoreStreamCall, r as PortalApprovalEvaluator, s as PortalCoreContentBlock, t as CreatePortalCoreProps, u as PortalCoreItemResult, v as listPortalCoreToolDescriptors, w as PortalToolFailure, x as PortalBatchError, y as PortalApprovalCall } from "../portal-core-Ckq-Mrzb.js";
3
+ import { A as PortalToolSuccess, C as PortalCallUpstreamTool, D as PortalToolResult, E as PortalToolHandlers, M as createPortalToolHandlers, N as portalToolInputSchemas, O as PortalToolResultMap, S as PortalBatchResult, T as PortalToolHandlerCall, _ as createPortalCore, a as PortalCore, b as PortalBatchDiagnostic, c as PortalCoreEvent, d as PortalCoreResult, f as PortalCoreRuntime, g as collectPortalCoreResult, h as PortalCoreToolName, i as PortalAuditEvent, j as PortalUpstreamEvent, k as PortalToolRuntime, l as PortalCoreItemError, m as PortalCoreToolDescriptor, n as PortalAgentScope, o as PortalCoreCollectOptions, p as PortalCoreStreamCall, r as PortalApprovalEvaluator, s as PortalCoreContentBlock, t as CreatePortalCoreProps, u as PortalCoreItemResult, v as listPortalCoreToolDescriptors, w as PortalToolFailure, x as PortalBatchError, y as PortalApprovalCall } from "../portal-core-CatZlNq_.js";
4
4
  import { S as createUpstreamMcpClientRuntime, r as redactCredentialText, u as NormalizedUpstreamMcpServer } from "../upstream-response-middleware-1MZnAD9C.js";
5
5
  import { McpConfig, SecretValue } from "@agent-vm/config-contracts";
6
6
 
@@ -1,5 +1,5 @@
1
1
  import { n as redactCredentialText } from "../upstream-response-middleware-Cd1MxA6A.js";
2
2
  import { t as createUpstreamMcpClientRuntime } from "../upstream-mcp-client-runtime-Be_cw6pV.js";
3
- import { i as resolveUpstreamServers, n as createPortalCore, r as listPortalCoreToolDescriptors, t as collectPortalCoreResult } from "../portal-core-B5cRpZMG.js";
4
- import { n as portalToolInputSchemas, r as validatePortalToolArguments, t as createPortalToolHandlers } from "../portal-tools-DA7j2pyv.js";
3
+ import { i as resolveUpstreamServers, n as createPortalCore, r as listPortalCoreToolDescriptors, t as collectPortalCoreResult } from "../portal-core-e-qajblz.js";
4
+ import { n as portalToolInputSchemas, r as validatePortalToolArguments, t as createPortalToolHandlers } from "../portal-tools-Ct2GuFSc.js";
5
5
  export { collectPortalCoreResult, createPortalCore, createPortalToolHandlers, createUpstreamMcpClientRuntime, listPortalCoreToolDescriptors, portalToolInputSchemas, redactCredentialText, resolveUpstreamServers, validatePortalToolArguments };
@@ -1,5 +1,5 @@
1
- import { a as PortalCore, c as PortalCoreEvent, m as PortalCoreToolDescriptor, n as PortalAgentScope } from "../portal-core-Ckq-Mrzb.js";
2
- import { a as createPortalApprovalVerifier, c as PortalAgentBearerAuth, d as PortalHttpAppOptions, f as PortalHttpAuditEvent, i as createPortalAgentRuntimeRecords, l as PortalHttpAgentIdentity, n as PortalApprovalAuditEvent, o as createPortalHttpAgentResolver, p as createPortalHttpApp, r as ResolveAgentHmacKeysProps, s as resolveAgentHmacKeys, t as PortalAgentRuntimeRecord, u as PortalHttpApp } from "../resolve-agent-identity-C9Jc2NhJ.js";
1
+ import { a as PortalCore, c as PortalCoreEvent, m as PortalCoreToolDescriptor, n as PortalAgentScope } from "../portal-core-CatZlNq_.js";
2
+ import { a as createPortalApprovalVerifier, c as PortalAgentBearerAuth, d as PortalHttpAppOptions, f as PortalHttpAuditEvent, i as createPortalAgentRuntimeRecords, l as PortalHttpAgentIdentity, n as PortalApprovalAuditEvent, o as createPortalHttpAgentResolver, p as createPortalHttpApp, r as ResolveAgentHmacKeysProps, s as resolveAgentHmacKeys, t as PortalAgentRuntimeRecord, u as PortalHttpApp } from "../resolve-agent-identity-C1xp9_2R.js";
3
3
  import { Tool } from "@modelcontextprotocol/sdk/types.js";
4
4
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
5
 
@@ -1,2 +1,2 @@
1
- import { a as createPortalHttpApp, c as listPortalMcpTools, i as resolveAgentHmacKeys, l as portalMcpToolNames, n as createPortalApprovalVerifier, o as createPortalMcpServer, r as createPortalHttpAgentResolver, s as emitMcpProgress, t as createPortalAgentRuntimeRecords } from "../resolve-agent-identity-ZMMY2Wqm.js";
1
+ import { a as createPortalHttpApp, c as listPortalMcpTools, i as resolveAgentHmacKeys, l as portalMcpToolNames, n as createPortalApprovalVerifier, o as createPortalMcpServer, r as createPortalHttpAgentResolver, s as emitMcpProgress, t as createPortalAgentRuntimeRecords } from "../resolve-agent-identity-Dnqv2hAW.js";
2
2
  export { createPortalAgentRuntimeRecords, createPortalApprovalVerifier, createPortalHttpAgentResolver, createPortalHttpApp, createPortalMcpServer, emitMcpProgress, listPortalMcpTools, portalMcpToolNames, resolveAgentHmacKeys };
@@ -115,6 +115,8 @@ type PortalUpstreamEvent = {
115
115
  interface PortalToolRuntime {
116
116
  readonly approval?: (calls: readonly PortalApprovalCall[], identity: PortalAgentIdentity, approvalToken: string | undefined) => {
117
117
  readonly kind: 'allow';
118
+ } | {
119
+ readonly kind: 'call_blocked';
118
120
  } | {
119
121
  readonly kind: 'approval_token_invalid';
120
122
  readonly reason: string;
@@ -278,4 +280,4 @@ declare function collectPortalCoreResult(events: AsyncIterable<PortalCoreEvent>,
278
280
  declare function createPortalCore(props: CreatePortalCoreProps): PortalCore;
279
281
  //#endregion
280
282
  export { PortalToolSuccess as A, PortalCallUpstreamTool as C, PortalToolResult as D, PortalToolHandlers as E, createPortalToolHandlers as M, portalToolInputSchemas as N, PortalToolResultMap as O, PortalBatchResult as S, PortalToolHandlerCall as T, createPortalCore as _, PortalCore as a, PortalBatchDiagnostic as b, PortalCoreEvent as c, PortalCoreResult as d, PortalCoreRuntime as f, collectPortalCoreResult as g, PortalCoreToolName as h, PortalAuditEvent as i, PortalUpstreamEvent as j, PortalToolRuntime as k, PortalCoreItemError as l, PortalCoreToolDescriptor as m, PortalAgentScope as n, PortalCoreCollectOptions as o, PortalCoreStreamCall as p, PortalApprovalEvaluator as r, PortalCoreContentBlock as s, CreatePortalCoreProps as t, PortalCoreItemResult as u, listPortalCoreToolDescriptors as v, PortalToolFailure as w, PortalBatchError as x, PortalApprovalCall as y };
281
- //# sourceMappingURL=portal-core-Ckq-Mrzb.d.ts.map
283
+ //# sourceMappingURL=portal-core-CatZlNq_.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-core-CatZlNq_.d.ts","names":[],"sources":["../src/core/portal-tools.ts","../src/core/portal-core.ts"],"mappings":";;;;;UAkBiB,iBAAA;EAAA,SACP,KAAA,EAAO,QAAA,CAAS,MAAA;EAAA,SAChB,EAAA;EAAA,SACA,MAAA,EAAQ,QAAA,CAAS,MAAA;AAAA;AAAA,UAGV,iBAAA;EAAA,SACP,KAAA;EAAA,SACA,KAAA,EAAO,QAAA,CAAS,MAAA;EAAA,SAChB,EAAA;AAAA;AAAA,KAGE,gBAAA,GAAmB,iBAAA,GAAoB,iBAAA;AAAA,KACvC,mBAAA,GAAsB,QAAA,CAAS,MAAA,SAAe,gBAAA;AAAA,UAEzC,gBAAA;EAAA,SACP,EAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGO,qBAAA;EAAA,SACP,YAAA;EAAA,SACA,SAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA;EAAA,SACA,SAAA;EAAA,SACA,QAAA;EAAA,SACA,SAAA;AAAA;AAAA,UAGO,iBAAA;EAAA,SACP,WAAA,WAAsB,qBAAA;EAAA,SACtB,MAAA,WAAiB,gBAAA;EAAA,SACjB,EAAA;EAAA,SACA,OAAA,EAAS,mBAAA;AAAA;AAAA,UAGF,kBAAA;EAAA,SACP,SAAA,EAAW,UAAA;EAAA,SACX,EAAA;EAAA,SACA,SAAA;EAAA,SACA,IAAA,EAAM,gBAAA;EAAA,SACN,QAAA;AAAA;AAAA,cAyHG,sBAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAOI,qBAAA;EAAA,SACP,QAAA,EAAU,mBAAA;EAAA,SACV,KAAA;AAAA;AAAA,UAGO,sBAAA;EAAA,SACP,SAAA,EAAW,UAAA;EAAA,SACX,YAAA;EAAA,SACA,SAAA;EAAA,SACA,OAAA,IAAW,KAAA,EAAO,mBAAA,KAAwB,OAAA;EAAA,SAC1C,SAAA;EAAA,SACA,MAAA,GAAS,WAAA;EAAA,SACT,QAAA;AAAA;AAAA,KAGE,mBAAA;EAAA,SAEA,IAAA;EAAA,SACA,OAAA;EAAA,SACA,QAAA;EAAA,SACA,KAAA;AAAA;EAAA,SAGA,IAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;AAAA;EAAA,SAGA,OAAA;IAAA,SACK,IAAA;IAAA,SAAuB,IAAA;EAAA;IAAA,SACvB,IAAA;IAAA,SAAuB,KAAA;EAAA;EAAA,SAC5B,IAAA;AAAA;AAAA,UAGK,iBAAA;EAAA,SACP,QAAA,IACR,KAAA,WAAgB,kBAAA,IAChB,QAAA,EAAU,mBAAA,EACV,aAAA;IAAA,SAEa,IAAA;EAAA;IAAA,SACA,IAAA;EAAA;IAAA,SACA,IAAA;IAAA,SAAyC,MAAA;EAAA;IAAA,SACzC,IAAA;EAAA;IAAA,SACA,IAAA;IAAA,SAAoC,KAAA;EAAA;EAAA,SACzC,gBAAA,GAAmB,IAAA,EAAM,sBAAA,KAA2B,OAAA;EAAA,SACpD,UAAA,GAAa,QAAA,EAAU,mBAAA,KAAwB,OAAA,CAAQ,aAAA;AAAA;AAAA,UAWhD,kBAAA;EAAA,SACP,IAAA,GAAO,IAAA,EAAM,qBAAA,KAA0B,OAAA,CAAQ,iBAAA;EAAA,SAC/C,QAAA,GAAW,IAAA,EAAM,qBAAA,KAA0B,OAAA,CAAQ,iBAAA;EAAA,SACnD,IAAA,GAAO,IAAA,EAAM,qBAAA,KAA0B,OAAA,CAAQ,iBAAA;EAAA,SAC/C,MAAA,GAAS,IAAA,EAAM,qBAAA,KAA0B,OAAA,CAAQ,iBAAA;AAAA;AAAA,iBAmb3C,wBAAA,CAAyB,OAAA,EAAS,iBAAA,GAAoB,kBAAA;;;KCtpB1D,gBAAA,GAAmB,mBAAA;AAAA,KAEnB,kBAAA;AAAA,UAMK,gBAAA;EAAA,SACP,YAAA;EAAA,SACA,SAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA;EAAA,SACA,SAAA;EAAA,SACA,QAAA;EAAA,SACA,SAAA;AAAA;AAAA,UAGO,gBAAA;EAAA,SACP,WAAA,YAAuB,gBAAA;EAAA,SACvB,OAAA,WAAkB,sBAAA;EAAA,SAClB,KAAA,WAAgB,oBAAA;EAAA,SAChB,iBAAA;AAAA;AAAA,KAGE,oBAAA;EAAA,SAEA,OAAA,WAAkB,sBAAA;EAAA,SAClB,SAAA;EAAA,SACA,MAAA;EAAA,SACA,iBAAA;AAAA;EAAA,SAGA,KAAA,EAAO,mBAAA;EAAA,SACP,SAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAGK,mBAAA;EAAA,SACP,IAAA;EAAA,SACA,OAAA;EAAA,SACA,SAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;AAAA;AAAA,KAGE,sBAAA;EAAA,SACE,IAAA;EAAA,SAAuB,IAAA;AAAA;EAAA,SACvB,IAAA;EAAA,SAAuB,KAAA;AAAA;AAAA,KAEzB,eAAA;EAAA,SAEA,IAAA;EAAA,SACA,QAAA,EAAU,kBAAA;AAAA;EAAA,SAGV,IAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;EAAA,SACA,QAAA;AAAA;EAAA,SAGA,IAAA;EAAA,SACA,OAAA;EAAA,SACA,QAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA;AAAA;EAAA,SAGA,IAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;EAAA,SACA,SAAA;AAAA;EAAA,SAGA,OAAA,EAAS,sBAAA;EAAA,SACT,IAAA;EAAA,SACA,SAAA;AAAA;EAAA,SAGA,IAAA;EAAA,SACA,SAAA;EAAA,SACA,MAAA,EAAQ,OAAA,CAAQ,oBAAA;IAAA,SAAiC,MAAA;EAAA;AAAA;EAAA,SAGjD,KAAA,EAAO,mBAAA;EAAA,SACP,IAAA;EAAA,SACA,SAAA;AAAA;EAAA,SAGA,IAAA;EAAA,SACA,MAAA,EAAQ,gBAAA;AAAA;EAAA,SAGR,KAAA;EAAA,SACA,IAAA;AAAA;AAAA,UAGK,oBAAA;EAAA,SACP,KAAA;EAAA,SACA,KAAA,EAAO,gBAAA;EAAA,SACP,MAAA,GAAS,WAAA;EAAA,SACT,QAAA,EAAU,kBAAA;AAAA;AAAA,UAMH,wBAAA;EAAA,SACP,OAAA,IAAW,KAAA,EAAO,eAAA,KAAoB,OAAA;AAAA;AAAA,UAG/B,iBAAA,SAA0B,oBAAA;EAAA,SACjC,gBAAA,EAAkB,iBAAA;AAAA;AAAA,KAGhB,uBAAA,GAA0B,WAAA,CAAY,iBAAA;AAAA,UAExC,yBAAA;EAAA,SACA,YAAA,EAAc,wBAAA;EAAA,SACd,YAAA;EAAA,SACA,OAAA,EAAS,iBAAA;EAAA,SACT,MAAA,YAAkB,eAAA;EAAA,SAClB,kBAAA;AAAA;AAAA,KAGE,qBAAA,IACR,yBAAA;EAAA,SACQ,QAAA,EAAU,uBAAA;EAAA,SACV,qBAAA;AAAA,MAER,yBAAA;EAAA,SACQ,QAAA;EAAA,SACA,qBAAA;AAAA;AAAA,UAGK,UAAA;EAAA,SACP,QAAA;IAAA,SACC,aAAA,GACR,KAAA,WAAgB,kBAAA,IAChB,KAAA,EAAO,gBAAA,EACP,aAAA,yBACI,UAAA,CAAW,uBAAA;EAAA;EAAA,SAER,UAAA,GAAa,IAAA,EAAM,oBAAA,KAAyB,aAAA,CAAc,eAAA;EAAA,SAC1D,KAAA,QAAa,OAAA;EAAA,SACb,uBAAA,SAAgC,uBAAA;EAAA,SAChC,gBAAA,GAAmB,KAAA;IAAA,SAClB,OAAA;IAAA,SACA,YAAA;IAAA,SACA,WAAA;IAAA,SACA,SAAA;IAAA,SACA,UAAA;IAAA,SACA,MAAA,EAAQ,sBAAA;EAAA,MACZ,gBAAA;EAAA,SACG,aAAA,GAAgB,KAAA,EAAO,gBAAA,cAA8B,wBAAA;EAAA,SACrD,oBAAA,GAAuB,YAAA,aAAyB,OAAA;EAAA,SAChD,iBAAA,GAAoB,KAAA,EAAO,gBAAA,KAAqB,OAAA;EAAA,SAChD,kBAAA;AAAA;AAAA,UAGO,wBAAA;EAAA,SACP,WAAA;EAAA,SACA,WAAA,EAAa,IAAA;EAAA,SACb,IAAA,EAAM,kBAAA;AAAA;AAAA,iBA+LA,6BAAA,CACf,UAAA,gCACW,wBAAA;AAAA,iBA6BU,uBAAA,CACrB,MAAA,EAAQ,aAAA,CAAc,eAAA,GACtB,OAAA,GAAS,wBAAA,GACP,OAAA,CAAQ,gBAAA;AAAA,iBA8KK,gBAAA,CAAiB,KAAA,EAAO,qBAAA,GAAwB,UAAA"}
@@ -1,7 +1,7 @@
1
1
  import { l as jsonObjectSchema } from "./zod-schema-loader-yNekKNpm.js";
2
2
  import { _ as createPortalAgentIdentity, y as resolvePortalAccessPolicy } from "./upstream-response-middleware-Cd1MxA6A.js";
3
3
  import { n as createPortalSessionManager } from "./upstream-mcp-client-runtime-Be_cw6pV.js";
4
- import { n as portalToolInputSchemas, t as createPortalToolHandlers } from "./portal-tools-DA7j2pyv.js";
4
+ import { n as portalToolInputSchemas, t as createPortalToolHandlers } from "./portal-tools-Ct2GuFSc.js";
5
5
  import { z } from "zod";
6
6
  import { mcpConfigToResolvedProviders } from "@agent-vm/config-contracts";
7
7
  //#region src/core/provider-runtime.ts
@@ -422,4 +422,4 @@ function createPortalCore(props) {
422
422
  //#endregion
423
423
  export { resolveUpstreamServers as i, createPortalCore as n, listPortalCoreToolDescriptors as r, collectPortalCoreResult as t };
424
424
 
425
- //# sourceMappingURL=portal-core-B5cRpZMG.js.map
425
+ //# sourceMappingURL=portal-core-e-qajblz.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"portal-core-B5cRpZMG.js","names":[],"sources":["../src/core/provider-runtime.ts","../src/core/portal-core.ts"],"sourcesContent":["import {\n\tmcpConfigToResolvedProviders,\n\ttype McpConfig,\n\ttype ResolvedMcpProvider,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport type { NormalizedUpstreamMcpServer } from '../upstream-mcp-client-runtime.js';\n\nexport interface ResolveUpstreamServersProps {\n\treadonly config: McpConfig;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nasync function resolveProviderSecretRecord(\n\tsecrets: Readonly<Record<string, SecretValue>>,\n\tresolveSecret: (secret: SecretValue) => Promise<string>,\n): Promise<Readonly<Record<string, string>>> {\n\tconst resolvedEntries = await Promise.all(\n\t\tObject.entries(secrets).map(\n\t\t\tasync ([name, secret]) => [name, await resolveSecret(secret)] as const,\n\t\t),\n\t);\n\treturn Object.fromEntries(resolvedEntries);\n}\n\nasync function resolveUpstreamServer(\n\tprovider: ResolvedMcpProvider,\n\tresolveSecret: (secret: SecretValue) => Promise<string>,\n): Promise<NormalizedUpstreamMcpServer> {\n\tif (provider.transport === 'stdio') {\n\t\treturn {\n\t\t\targs: provider.args,\n\t\t\tcommand: provider.command,\n\t\t\t...(provider.cwd === undefined ? {} : { cwd: provider.cwd }),\n\t\t\tenv: await resolveProviderSecretRecord(provider.env, resolveSecret),\n\t\t\tnamespace: provider.namespace,\n\t\t\ttransport: 'stdio',\n\t\t};\n\t}\n\n\treturn {\n\t\theaders: await resolveProviderSecretRecord(provider.headers, resolveSecret),\n\t\tnamespace: provider.namespace,\n\t\ttransport: provider.transport,\n\t\turl: provider.url,\n\t};\n}\n\nexport async function resolveUpstreamServers(\n\tprops: ResolveUpstreamServersProps,\n): Promise<readonly NormalizedUpstreamMcpServer[]> {\n\treturn await Promise.all(\n\t\tmcpConfigToResolvedProviders(props.config).map(async (provider) =>\n\t\t\tresolveUpstreamServer(provider, props.resolveSecret),\n\t\t),\n\t);\n}\n","import type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\n\nimport { jsonObjectSchema } from '../json-schema.js';\nimport {\n\tcreatePortalAgentIdentity,\n\tresolvePortalAccessPolicy,\n\ttype PortalAccessPolicyConfig,\n\ttype PortalAgentIdentity,\n\ttype PortalAgentScopeSource,\n} from '../portal-access-policy.js';\nimport {\n\tcreatePortalSessionManager,\n\ttype PortalSessionManager,\n\ttype PortalSessionRuntime,\n} from '../portal-session.js';\nimport type { SkillGraphInput } from '../tool-graph.js';\nimport {\n\tcreatePortalToolHandlers,\n\tportalToolInputSchemas,\n\ttype PortalApprovalCall,\n\ttype PortalBatchDiagnostic,\n\ttype PortalBatchResult,\n\ttype PortalToolResult,\n\ttype PortalToolRuntime,\n} from './portal-tools.js';\n\nexport type PortalAgentScope = PortalAgentIdentity;\n\nexport type PortalCoreToolName =\n\t| 'mcp_portal_list'\n\t| 'mcp_portal_search'\n\t| 'mcp_portal_describe'\n\t| 'mcp_portal_call';\n\nexport interface PortalAuditEvent {\n\treadonly causeMessage?: string;\n\treadonly elapsedMs?: number;\n\treadonly hint?: string;\n\treadonly kind: string;\n\treadonly message: string;\n\treadonly namespace?: string;\n\treadonly operation?: string;\n\treadonly phase?: string;\n\treadonly timeoutMs?: number;\n\treadonly toolName?: string;\n\treadonly transport?: unknown;\n}\n\nexport interface PortalCoreResult {\n\treadonly auditEvents?: readonly PortalAuditEvent[];\n\treadonly content: readonly PortalCoreContentBlock[];\n\treadonly items: readonly PortalCoreItemResult[];\n\treadonly structuredContent?: unknown;\n}\n\nexport type PortalCoreItemResult =\n\t| {\n\t\t\treadonly content: readonly PortalCoreContentBlock[];\n\t\t\treadonly requestId: string;\n\t\t\treadonly status: 'success';\n\t\t\treadonly structuredContent?: unknown;\n\t }\n\t| {\n\t\t\treadonly error: PortalCoreItemError;\n\t\t\treadonly requestId: string;\n\t\t\treadonly status: 'failed';\n\t };\n\nexport interface PortalCoreItemError {\n\treadonly code: string;\n\treadonly message: string;\n\treadonly namespace?: string;\n\treadonly toolName?: string;\n\treadonly upstream?: unknown;\n}\n\nexport type PortalCoreContentBlock =\n\t| { readonly text: string; readonly type: 'text' }\n\t| { readonly type: 'json'; readonly value: unknown };\n\nexport type PortalCoreEvent =\n\t| {\n\t\t\treadonly kind: 'started';\n\t\t\treadonly toolName: PortalCoreToolName;\n\t }\n\t| {\n\t\t\treadonly kind: 'item_started';\n\t\t\treadonly namespace?: string;\n\t\t\treadonly requestId: string;\n\t\t\treadonly toolName?: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'progress';\n\t\t\treadonly message?: string;\n\t\t\treadonly progress?: number;\n\t\t\treadonly requestId?: string;\n\t\t\treadonly total?: number;\n\t }\n\t| {\n\t\t\treadonly kind: 'upstream_notification';\n\t\t\treadonly method: string;\n\t\t\treadonly params: unknown;\n\t\t\treadonly requestId?: string;\n\t }\n\t| {\n\t\t\treadonly content: PortalCoreContentBlock;\n\t\t\treadonly kind: 'partial_content';\n\t\t\treadonly requestId?: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'item_completed';\n\t\t\treadonly requestId: string;\n\t\t\treadonly result: Extract<PortalCoreItemResult, { readonly status: 'success' }>;\n\t }\n\t| {\n\t\t\treadonly error: PortalCoreItemError;\n\t\t\treadonly kind: 'item_failed';\n\t\t\treadonly requestId: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'completed';\n\t\t\treadonly result: PortalCoreResult;\n\t }\n\t| {\n\t\t\treadonly error: unknown;\n\t\t\treadonly kind: 'failed';\n\t };\n\nexport interface PortalCoreStreamCall {\n\treadonly input: unknown;\n\treadonly scope: PortalAgentScope;\n\treadonly signal?: AbortSignal;\n\treadonly toolName: PortalCoreToolName;\n}\n\nconst maxQueuedPortalCoreEvents = 1_024;\nconst maxPortalCoreEventBytes = 256 * 1_024;\n\nexport interface PortalCoreCollectOptions {\n\treadonly onEvent?: (event: PortalCoreEvent) => Promise<void> | void;\n}\n\nexport interface PortalCoreRuntime extends PortalSessionRuntime {\n\treadonly callUpstreamTool: PortalToolRuntime['callUpstreamTool'];\n}\n\nexport type PortalApprovalEvaluator = NonNullable<PortalToolRuntime['approval']>;\n\ninterface CreatePortalCoreBaseProps {\n\treadonly accessPolicy: PortalAccessPolicyConfig;\n\treadonly catalogTtlMs: number;\n\treadonly runtime: PortalCoreRuntime;\n\treadonly skills?: readonly SkillGraphInput[];\n\treadonly upstreamNamespaces: readonly string[];\n}\n\nexport type CreatePortalCoreProps =\n\t| (CreatePortalCoreBaseProps & {\n\t\t\treadonly approval: PortalApprovalEvaluator;\n\t\t\treadonly approvalTrustBoundary?: never;\n\t })\n\t| (CreatePortalCoreBaseProps & {\n\t\t\treadonly approval?: never;\n\t\t\treadonly approvalTrustBoundary: 'openclaw-before-tool-call-hook';\n\t });\n\nexport interface PortalCore {\n\treadonly approval: {\n\t\treadonly evaluateCalls: (\n\t\t\tcalls: readonly PortalApprovalCall[],\n\t\t\tscope: PortalAgentScope,\n\t\t\tapprovalToken: string | undefined,\n\t\t) => ReturnType<PortalApprovalEvaluator>;\n\t};\n\treadonly callStream: (call: PortalCoreStreamCall) => AsyncIterable<PortalCoreEvent>;\n\treadonly close: () => Promise<void>;\n\treadonly collectPortalCoreResult: typeof collectPortalCoreResult;\n\treadonly createAgentScope: (input: {\n\t\treadonly agentId: string;\n\t\treadonly agentScopeId: string;\n\t\treadonly authSubject?: string;\n\t\treadonly sessionId?: string;\n\t\treadonly sessionKey?: string;\n\t\treadonly source: PortalAgentScopeSource;\n\t}) => PortalAgentScope;\n\treadonly describeTools: (scope: PortalAgentScope) => readonly PortalCoreToolDescriptor[];\n\treadonly invalidateAgentScope: (agentScopeId: string) => Promise<void>;\n\treadonly invalidateSession: (scope: PortalAgentScope) => Promise<void>;\n\treadonly upstreamNamespaces: readonly string[];\n}\n\nexport interface PortalCoreToolDescriptor {\n\treadonly description: string;\n\treadonly inputSchema: Tool['inputSchema'];\n\treadonly name: PortalCoreToolName;\n}\n\nconst portalCallRequestSchema = z\n\t.object({\n\t\targuments: jsonObjectSchema,\n\t\tid: z.string().min(1),\n\t\tnamespace: z.string().min(1),\n\t\ttoolName: z.string().min(1),\n\t})\n\t.strict();\nconst portalCallInputSchema = z\n\t.object({\n\t\tcalls: z.array(portalCallRequestSchema).min(1),\n\t\tportalApprovalToken: z.string().min(1).optional(),\n\t})\n\t.strict();\n\nfunction diagnosticsToAuditEvents(\n\tdiagnostics: readonly PortalBatchDiagnostic[],\n): readonly PortalAuditEvent[] {\n\treturn diagnostics.map((diagnostic) => ({ ...diagnostic }));\n}\n\nfunction isUnknownRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction errorRecordFromUnknown(error: unknown): Record<string, unknown> {\n\treturn isUnknownRecord(error) ? error : {};\n}\n\nfunction messageFromUnknown(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\tconst record = errorRecordFromUnknown(error);\n\tconst message = record.message;\n\treturn typeof message === 'string' ? message : String(error);\n}\n\nfunction errorFromAbortSignal(signal: AbortSignal): Error {\n\tconst reason: unknown = signal.reason;\n\treturn reason instanceof Error ? reason : new Error('MCP Portal core stream aborted.');\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n\tif (signal?.aborted) {\n\t\tthrow errorFromAbortSignal(signal);\n\t}\n}\n\nfunction assertPortalCoreEventSize(event: PortalCoreEvent): void {\n\tconst serialized = JSON.stringify(event);\n\tif (serialized === undefined) {\n\t\treturn;\n\t}\n\tconst byteLength = Buffer.byteLength(serialized, 'utf8');\n\tif (byteLength > maxPortalCoreEventBytes) {\n\t\tthrow new Error(\n\t\t\t`MCP Portal core event exceeded ${String(maxPortalCoreEventBytes)} bytes (${String(byteLength)} bytes).`,\n\t\t);\n\t}\n}\n\nfunction waitForQueuedCoreEvent(props: {\n\treadonly setNotifyQueuedEvent: (notify: (() => void) | undefined) => void;\n\treadonly signal?: AbortSignal;\n}): Promise<void> {\n\tif (props.signal === undefined) {\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tprops.setNotifyQueuedEvent(resolve);\n\t\t});\n\t}\n\tconst signal = props.signal;\n\treturn new Promise<void>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst settle = (complete: () => void): void => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tsignal.removeEventListener('abort', onAbort);\n\t\t\tprops.setNotifyQueuedEvent(undefined);\n\t\t\tcomplete();\n\t\t};\n\t\tconst onNotify = (): void => {\n\t\t\tsettle(resolve);\n\t\t};\n\t\tconst onAbort = (): void => {\n\t\t\tsettle(() => reject(errorFromAbortSignal(signal)));\n\t\t};\n\t\tprops.setNotifyQueuedEvent(onNotify);\n\t\tsignal.addEventListener('abort', onAbort, { once: true });\n\t\tif (signal.aborted) {\n\t\t\tonAbort();\n\t\t}\n\t});\n}\n\nfunction itemErrorFromPortalResult(result: PortalToolResult): PortalCoreItemError {\n\tif (result.ok) {\n\t\tthrow new Error('Cannot convert successful portal result into an item error.');\n\t}\n\tconst errorRecord = errorRecordFromUnknown(result.error);\n\tconst kind = errorRecord.kind;\n\tconst namespace = errorRecord.namespace;\n\tconst toolName = errorRecord.toolName;\n\tconst upstream = errorRecord.upstream;\n\n\treturn {\n\t\tcode: typeof kind === 'string' ? kind : 'portal_item_failed',\n\t\tmessage: messageFromUnknown(result.error),\n\t\t...(typeof namespace === 'string' ? { namespace } : {}),\n\t\t...(typeof toolName === 'string' ? { toolName } : {}),\n\t\t...(upstream === undefined ? {} : { upstream }),\n\t};\n}\n\nfunction itemResultFromPortalToolResult(\n\trequestId: string,\n\tresult: PortalToolResult,\n): PortalCoreItemResult {\n\tif (!result.ok) {\n\t\treturn {\n\t\t\terror: itemErrorFromPortalResult(result),\n\t\t\trequestId,\n\t\t\tstatus: 'failed',\n\t\t};\n\t}\n\n\treturn {\n\t\tcontent: [{ type: 'json', value: result.output }],\n\t\trequestId,\n\t\tstatus: 'success',\n\t\tstructuredContent: result.output,\n\t};\n}\n\nfunction scalarBatchResultToCoreResult(batchResult: PortalBatchResult): PortalCoreResult {\n\treturn {\n\t\tauditEvents: diagnosticsToAuditEvents(batchResult.diagnostics),\n\t\tcontent: [{ type: 'json', value: batchResult }],\n\t\titems: [],\n\t\tstructuredContent: batchResult,\n\t};\n}\n\nfunction batchItemsToCoreResult(props: {\n\treadonly diagnostics: readonly PortalBatchDiagnostic[];\n\treadonly items: readonly PortalCoreItemResult[];\n}): PortalCoreResult {\n\treturn {\n\t\tauditEvents: diagnosticsToAuditEvents(props.diagnostics),\n\t\tcontent: [],\n\t\titems: props.items,\n\t};\n}\n\nfunction namespaceDescription(namespaces: readonly string[]): string {\n\treturn namespaces.length === 0\n\t\t? 'No upstream MCP namespaces are authorized for this agent scope.'\n\t\t: `Allowed namespaces for this agent: ${namespaces.join(', ')}.`;\n}\n\nfunction cloneJsonObject<TValue>(value: TValue): TValue {\n\treturn structuredClone(value);\n}\n\nfunction withListNamespaceSchemaDescription(\n\tinputSchema: Tool['inputSchema'],\n\tnamespaces: readonly string[],\n): Tool['inputSchema'] {\n\tconst clonedSchema = cloneJsonObject(inputSchema);\n\tconst requests = isUnknownRecord(clonedSchema.properties)\n\t\t? clonedSchema.properties.requests\n\t\t: undefined;\n\tconst requestItems = isUnknownRecord(requests) ? requests.items : undefined;\n\tconst requestProperties = isUnknownRecord(requestItems) ? requestItems.properties : undefined;\n\tconst namespaceProperty = isUnknownRecord(requestProperties)\n\t\t? requestProperties.namespaces\n\t\t: undefined;\n\tif (isUnknownRecord(namespaceProperty)) {\n\t\tnamespaceProperty.description =\n\t\t\tnamespaces.length === 0\n\t\t\t\t? 'Optional namespace filter. No upstream MCP namespaces are authorized for this agent. Omit to list all currently discovered authorized namespaces.'\n\t\t\t\t: `Optional namespace filter. Allowed namespaces for this agent: ${namespaces.join(', ')}. Omit to list all currently discovered authorized namespaces.`;\n\t}\n\treturn clonedSchema;\n}\n\nexport function listPortalCoreToolDescriptors(\n\tnamespaces: readonly string[] = [],\n): readonly PortalCoreToolDescriptor[] {\n\tconst scopeDescription = namespaceDescription(namespaces);\n\treturn [\n\t\t{\n\t\t\tdescription: `List authorized MCP namespaces and compact tool summaries. ${scopeDescription}`,\n\t\t\tinputSchema: withListNamespaceSchemaDescription(\n\t\t\t\tportalToolInputSchemas.mcp_portal_list,\n\t\t\t\tnamespaces,\n\t\t\t),\n\t\t\tname: 'mcp_portal_list',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\tname: 'mcp_portal_search',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\tname: 'mcp_portal_describe',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\tname: 'mcp_portal_call',\n\t\t},\n\t];\n}\n\nexport async function collectPortalCoreResult(\n\tevents: AsyncIterable<PortalCoreEvent>,\n\toptions: PortalCoreCollectOptions = {},\n): Promise<PortalCoreResult> {\n\tlet result: PortalCoreResult | undefined;\n\tfor await (const event of events) {\n\t\tawait options.onEvent?.(event);\n\t\tif (event.kind === 'completed') {\n\t\t\tresult = event.result;\n\t\t}\n\t\tif (event.kind === 'failed') {\n\t\t\tthrow event.error;\n\t\t}\n\t}\n\tif (result === undefined) {\n\t\tthrow new Error('MCP Portal core stream ended without a completed event.');\n\t}\n\treturn result;\n}\n\nasync function* scalarToolStream(props: {\n\treadonly input: unknown;\n\treadonly scope: PortalAgentScope;\n\treadonly signal?: AbortSignal;\n\treadonly sessionManager: PortalSessionManager;\n\treadonly toolName: Exclude<PortalCoreToolName, 'mcp_portal_call'>;\n\treadonly toolRuntime: PortalToolRuntime;\n}): AsyncIterable<PortalCoreEvent> {\n\tconst handlers = createPortalToolHandlers(props.toolRuntime);\n\tconst handler =\n\t\tprops.toolName === 'mcp_portal_list'\n\t\t\t? handlers.list\n\t\t\t: props.toolName === 'mcp_portal_search'\n\t\t\t\t? handlers.search\n\t\t\t\t: handlers.describe;\n\tthrowIfAborted(props.signal);\n\tconst batchResult = await handler({ identity: props.scope, input: props.input });\n\tthrowIfAborted(props.signal);\n\tyield { kind: 'completed', result: scalarBatchResultToCoreResult(batchResult) };\n}\n\nasync function* callToolStream(props: {\n\treadonly input: unknown;\n\treadonly scope: PortalAgentScope;\n\treadonly signal?: AbortSignal;\n\treadonly toolRuntime: PortalToolRuntime;\n}): AsyncIterable<PortalCoreEvent> {\n\tconst parsedInput = portalCallInputSchema.safeParse(props.input);\n\tconst queuedEvents: PortalCoreEvent[] = [];\n\tlet notifyQueuedEvent: (() => void) | undefined;\n\tlet executionDone = false;\n\tconst pushEvent = (event: PortalCoreEvent): void => {\n\t\tassertPortalCoreEventSize(event);\n\t\tif (queuedEvents.length >= maxQueuedPortalCoreEvents) {\n\t\t\tthrow new Error(`MCP Portal core event queue exceeded ${maxQueuedPortalCoreEvents} events.`);\n\t\t}\n\t\tqueuedEvents.push(event);\n\t\tnotifyQueuedEvent?.();\n\t\tnotifyQueuedEvent = undefined;\n\t};\n\tconst streamingToolRuntime: PortalToolRuntime = {\n\t\t...props.toolRuntime,\n\t\tcallUpstreamTool: async (call) => {\n\t\t\tthrowIfAborted(props.signal);\n\t\t\tpushEvent({\n\t\t\t\tkind: 'item_started',\n\t\t\t\tnamespace: call.namespace,\n\t\t\t\trequestId: call.requestId,\n\t\t\t\ttoolName: call.toolName,\n\t\t\t});\n\t\t\tpushEvent({\n\t\t\t\tkind: 'progress',\n\t\t\t\tmessage: `Calling upstream MCP tool ${call.namespace}.${call.toolName}.`,\n\t\t\t\trequestId: call.requestId,\n\t\t\t});\n\t\t\treturn await props.toolRuntime.callUpstreamTool({\n\t\t\t\t...call,\n\t\t\t\t...(props.signal !== undefined ? { signal: props.signal } : {}),\n\t\t\t\tonEvent: (event) => {\n\t\t\t\t\tif (event.kind === 'progress') {\n\t\t\t\t\t\tpushEvent({\n\t\t\t\t\t\t\tkind: 'progress',\n\t\t\t\t\t\t\t...(event.message !== undefined ? { message: event.message } : {}),\n\t\t\t\t\t\t\t...(event.progress !== undefined ? { progress: event.progress } : {}),\n\t\t\t\t\t\t\trequestId: call.requestId,\n\t\t\t\t\t\t\t...(event.total !== undefined ? { total: event.total } : {}),\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (event.kind === 'partial_content') {\n\t\t\t\t\t\tpushEvent({\n\t\t\t\t\t\t\tcontent: event.content,\n\t\t\t\t\t\t\tkind: 'partial_content',\n\t\t\t\t\t\t\trequestId: call.requestId,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tpushEvent({\n\t\t\t\t\t\tkind: 'upstream_notification',\n\t\t\t\t\t\tmethod: event.method,\n\t\t\t\t\t\tparams: event.params,\n\t\t\t\t\t\trequestId: call.requestId,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n\tconst handlers = createPortalToolHandlers(streamingToolRuntime);\n\tif (!parsedInput.success) {\n\t\tconst batchResult = await handlers.call({ identity: props.scope, input: props.input });\n\t\tyield { kind: 'completed', result: scalarBatchResultToCoreResult(batchResult) };\n\t\treturn;\n\t}\n\n\tconst itemResults: PortalCoreItemResult[] = [];\n\tconst batchResultPromise = handlers\n\t\t.call({\n\t\t\tidentity: props.scope,\n\t\t\tinput: props.input,\n\t\t})\n\t\t.finally(() => {\n\t\t\texecutionDone = true;\n\t\t\tnotifyQueuedEvent?.();\n\t\t\tnotifyQueuedEvent = undefined;\n\t\t});\n\tconst hasPendingExecutionEvents = (): boolean => !executionDone || queuedEvents.length > 0;\n\twhile (hasPendingExecutionEvents()) {\n\t\tconst event = queuedEvents.shift();\n\t\tif (event !== undefined) {\n\t\t\tyield event;\n\t\t\tcontinue;\n\t\t}\n\t\tthrowIfAborted(props.signal);\n\t\t// Streaming consumes events as they arrive; there is no parallel work to collect here.\n\t\t// eslint-disable-next-line no-await-in-loop\n\t\tawait waitForQueuedCoreEvent({\n\t\t\tsetNotifyQueuedEvent: (notify) => {\n\t\t\t\tnotifyQueuedEvent = notify;\n\t\t\t},\n\t\t\t...(props.signal !== undefined ? { signal: props.signal } : {}),\n\t\t});\n\t}\n\tconst batchResult = await batchResultPromise;\n\tthrowIfAborted(props.signal);\n\tif (batchResult.errors.length > 0) {\n\t\tyield { kind: 'completed', result: scalarBatchResultToCoreResult(batchResult) };\n\t\treturn;\n\t}\n\tfor (const request of parsedInput.data.calls) {\n\t\tconst portalResult = batchResult.results[request.id];\n\t\tconst itemResult =\n\t\t\tportalResult === undefined\n\t\t\t\t? ({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tcode: 'portal_item_missing',\n\t\t\t\t\t\t\tmessage: `MCP Portal did not return a result for request \"${request.id}\".`,\n\t\t\t\t\t\t\tnamespace: request.namespace,\n\t\t\t\t\t\t\ttoolName: request.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequestId: request.id,\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t} satisfies PortalCoreItemResult)\n\t\t\t\t: itemResultFromPortalToolResult(request.id, portalResult);\n\t\titemResults.push(itemResult);\n\t\tif (itemResult.status === 'success') {\n\t\t\tyield { kind: 'item_completed', requestId: request.id, result: itemResult };\n\t\t} else {\n\t\t\tyield { error: itemResult.error, kind: 'item_failed', requestId: request.id };\n\t\t}\n\t}\n\n\tyield {\n\t\tkind: 'completed',\n\t\tresult: batchItemsToCoreResult({ diagnostics: batchResult.diagnostics, items: itemResults }),\n\t};\n}\n\nexport function createPortalCore(props: CreatePortalCoreProps): PortalCore {\n\tconst sessionManager = createPortalSessionManager({\n\t\taccessPolicy: props.accessPolicy,\n\t\tcatalogTtlMs: props.catalogTtlMs,\n\t\truntime: props.runtime,\n\t\t...(props.skills !== undefined ? { skills: props.skills } : {}),\n\t\tupstreamNamespaces: props.upstreamNamespaces,\n\t});\n\tconst createdAgentScopeIds = new Set<string>();\n\tconst approval: PortalApprovalEvaluator =\n\t\tprops.approval ??\n\t\t(() => {\n\t\t\tif (props.approvalTrustBoundary === 'openclaw-before-tool-call-hook') {\n\t\t\t\treturn { kind: 'allow' };\n\t\t\t}\n\t\t\tthrow new Error('MCP Portal approval evaluation is not configured.');\n\t\t});\n\tconst toolRuntime: PortalToolRuntime = {\n\t\tapproval,\n\t\tcallUpstreamTool: props.runtime.callUpstreamTool,\n\t\tgetSession: sessionManager.getSession,\n\t};\n\n\tasync function* callStream(call: PortalCoreStreamCall): AsyncIterable<PortalCoreEvent> {\n\t\ttry {\n\t\t\tthrowIfAborted(call.signal);\n\t\t\tyield { kind: 'started', toolName: call.toolName };\n\t\t\tthrowIfAborted(call.signal);\n\t\t\tif (call.toolName === 'mcp_portal_call') {\n\t\t\t\tyield* callToolStream({\n\t\t\t\t\tinput: call.input,\n\t\t\t\t\tscope: call.scope,\n\t\t\t\t\t...(call.signal !== undefined ? { signal: call.signal } : {}),\n\t\t\t\t\ttoolRuntime,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tyield* scalarToolStream({\n\t\t\t\tinput: call.input,\n\t\t\t\tscope: call.scope,\n\t\t\t\t...(call.signal !== undefined ? { signal: call.signal } : {}),\n\t\t\t\tsessionManager,\n\t\t\t\ttoolName: call.toolName,\n\t\t\t\ttoolRuntime,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tyield { error, kind: 'failed' };\n\t\t}\n\t}\n\n\treturn {\n\t\tapproval: {\n\t\t\tevaluateCalls: (calls, scope, approvalToken) => approval(calls, scope, approvalToken),\n\t\t},\n\t\tcallStream,\n\t\tclose: async () => {\n\t\t\tawait Promise.all(\n\t\t\t\t[...createdAgentScopeIds].map((agentScopeId) =>\n\t\t\t\t\tsessionManager.invalidateAgentScope(agentScopeId),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\tcollectPortalCoreResult,\n\t\tcreateAgentScope: (input) => {\n\t\t\tconst scope = createPortalAgentIdentity(input);\n\t\t\tcreatedAgentScopeIds.add(scope.agentScopeId);\n\t\t\treturn scope;\n\t\t},\n\t\tdescribeTools: (scope) => {\n\t\t\tconst policy = resolvePortalAccessPolicy({\n\t\t\t\tconfig: props.accessPolicy,\n\t\t\t\tidentity: scope,\n\t\t\t\tupstreamNamespaces: props.upstreamNamespaces,\n\t\t\t});\n\t\t\treturn listPortalCoreToolDescriptors(policy.allowedNamespaces);\n\t\t},\n\t\tinvalidateAgentScope: async (agentScopeId) => {\n\t\t\tcreatedAgentScopeIds.delete(agentScopeId);\n\t\t\tawait sessionManager.invalidateAgentScope(agentScopeId);\n\t\t},\n\t\tinvalidateSession: async (scope) => {\n\t\t\tawait sessionManager.invalidateSession(scope);\n\t\t},\n\t\tupstreamNamespaces: props.upstreamNamespaces,\n\t};\n}\n"],"mappings":";;;;;;;AAcA,eAAe,4BACd,SACA,eAC4C;CAC5C,MAAM,kBAAkB,MAAM,QAAQ,IACrC,OAAO,QAAQ,QAAQ,CAAC,IACvB,OAAO,CAAC,MAAM,YAAY,CAAC,MAAM,MAAM,cAAc,OAAO,CAAC,CAC7D,CACD;CACD,OAAO,OAAO,YAAY,gBAAgB;;AAG3C,eAAe,sBACd,UACA,eACuC;CACvC,IAAI,SAAS,cAAc,SAC1B,OAAO;EACN,MAAM,SAAS;EACf,SAAS,SAAS;EAClB,GAAI,SAAS,QAAQ,KAAA,IAAY,EAAE,GAAG,EAAE,KAAK,SAAS,KAAK;EAC3D,KAAK,MAAM,4BAA4B,SAAS,KAAK,cAAc;EACnE,WAAW,SAAS;EACpB,WAAW;EACX;CAGF,OAAO;EACN,SAAS,MAAM,4BAA4B,SAAS,SAAS,cAAc;EAC3E,WAAW,SAAS;EACpB,WAAW,SAAS;EACpB,KAAK,SAAS;EACd;;AAGF,eAAsB,uBACrB,OACkD;CAClD,OAAO,MAAM,QAAQ,IACpB,6BAA6B,MAAM,OAAO,CAAC,IAAI,OAAO,aACrD,sBAAsB,UAAU,MAAM,cAAc,CACpD,CACD;;;;ACgFF,MAAM,4BAA4B;AAClC,MAAM,0BAA0B,MAAM;AA6DtC,MAAM,0BAA0B,EAC9B,OAAO;CACP,WAAW;CACX,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;CACrB,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE;CAC5B,UAAU,EAAE,QAAQ,CAAC,IAAI,EAAE;CAC3B,CAAC,CACD,QAAQ;AACV,MAAM,wBAAwB,EAC5B,OAAO;CACP,OAAO,EAAE,MAAM,wBAAwB,CAAC,IAAI,EAAE;CAC9C,qBAAqB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;CACjD,CAAC,CACD,QAAQ;AAEV,SAAS,yBACR,aAC8B;CAC9B,OAAO,YAAY,KAAK,gBAAgB,EAAE,GAAG,YAAY,EAAE;;AAG5D,SAAS,gBAAgB,OAAkD;CAC1E,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,uBAAuB,OAAyC;CACxE,OAAO,gBAAgB,MAAM,GAAG,QAAQ,EAAE;;AAG3C,SAAS,mBAAmB,OAAwB;CACnD,IAAI,iBAAiB,OACpB,OAAO,MAAM;CAGd,MAAM,UADS,uBAAuB,MAChB,CAAC;CACvB,OAAO,OAAO,YAAY,WAAW,UAAU,OAAO,MAAM;;AAG7D,SAAS,qBAAqB,QAA4B;CACzD,MAAM,SAAkB,OAAO;CAC/B,OAAO,kBAAkB,QAAQ,yBAAS,IAAI,MAAM,kCAAkC;;AAGvF,SAAS,eAAe,QAAuC;CAC9D,IAAI,QAAQ,SACX,MAAM,qBAAqB,OAAO;;AAIpC,SAAS,0BAA0B,OAA8B;CAChE,MAAM,aAAa,KAAK,UAAU,MAAM;CACxC,IAAI,eAAe,KAAA,GAClB;CAED,MAAM,aAAa,OAAO,WAAW,YAAY,OAAO;CACxD,IAAI,aAAa,yBAChB,MAAM,IAAI,MACT,kCAAkC,OAAO,wBAAwB,CAAC,UAAU,OAAO,WAAW,CAAC,UAC/F;;AAIH,SAAS,uBAAuB,OAGd;CACjB,IAAI,MAAM,WAAW,KAAA,GACpB,OAAO,IAAI,SAAe,YAAY;EACrC,MAAM,qBAAqB,QAAQ;GAClC;CAEH,MAAM,SAAS,MAAM;CACrB,OAAO,IAAI,SAAe,SAAS,WAAW;EAC7C,IAAI,UAAU;EACd,MAAM,UAAU,aAA+B;GAC9C,IAAI,SACH;GAED,UAAU;GACV,OAAO,oBAAoB,SAAS,QAAQ;GAC5C,MAAM,qBAAqB,KAAA,EAAU;GACrC,UAAU;;EAEX,MAAM,iBAAuB;GAC5B,OAAO,QAAQ;;EAEhB,MAAM,gBAAsB;GAC3B,aAAa,OAAO,qBAAqB,OAAO,CAAC,CAAC;;EAEnD,MAAM,qBAAqB,SAAS;EACpC,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;EACzD,IAAI,OAAO,SACV,SAAS;GAET;;AAGH,SAAS,0BAA0B,QAA+C;CACjF,IAAI,OAAO,IACV,MAAM,IAAI,MAAM,8DAA8D;CAE/E,MAAM,cAAc,uBAAuB,OAAO,MAAM;CACxD,MAAM,OAAO,YAAY;CACzB,MAAM,YAAY,YAAY;CAC9B,MAAM,WAAW,YAAY;CAC7B,MAAM,WAAW,YAAY;CAE7B,OAAO;EACN,MAAM,OAAO,SAAS,WAAW,OAAO;EACxC,SAAS,mBAAmB,OAAO,MAAM;EACzC,GAAI,OAAO,cAAc,WAAW,EAAE,WAAW,GAAG,EAAE;EACtD,GAAI,OAAO,aAAa,WAAW,EAAE,UAAU,GAAG,EAAE;EACpD,GAAI,aAAa,KAAA,IAAY,EAAE,GAAG,EAAE,UAAU;EAC9C;;AAGF,SAAS,+BACR,WACA,QACuB;CACvB,IAAI,CAAC,OAAO,IACX,OAAO;EACN,OAAO,0BAA0B,OAAO;EACxC;EACA,QAAQ;EACR;CAGF,OAAO;EACN,SAAS,CAAC;GAAE,MAAM;GAAQ,OAAO,OAAO;GAAQ,CAAC;EACjD;EACA,QAAQ;EACR,mBAAmB,OAAO;EAC1B;;AAGF,SAAS,8BAA8B,aAAkD;CACxF,OAAO;EACN,aAAa,yBAAyB,YAAY,YAAY;EAC9D,SAAS,CAAC;GAAE,MAAM;GAAQ,OAAO;GAAa,CAAC;EAC/C,OAAO,EAAE;EACT,mBAAmB;EACnB;;AAGF,SAAS,uBAAuB,OAGX;CACpB,OAAO;EACN,aAAa,yBAAyB,MAAM,YAAY;EACxD,SAAS,EAAE;EACX,OAAO,MAAM;EACb;;AAGF,SAAS,qBAAqB,YAAuC;CACpE,OAAO,WAAW,WAAW,IAC1B,oEACA,sCAAsC,WAAW,KAAK,KAAK,CAAC;;AAGhE,SAAS,gBAAwB,OAAuB;CACvD,OAAO,gBAAgB,MAAM;;AAG9B,SAAS,mCACR,aACA,YACsB;CACtB,MAAM,eAAe,gBAAgB,YAAY;CACjD,MAAM,WAAW,gBAAgB,aAAa,WAAW,GACtD,aAAa,WAAW,WACxB,KAAA;CACH,MAAM,eAAe,gBAAgB,SAAS,GAAG,SAAS,QAAQ,KAAA;CAClE,MAAM,oBAAoB,gBAAgB,aAAa,GAAG,aAAa,aAAa,KAAA;CACpF,MAAM,oBAAoB,gBAAgB,kBAAkB,GACzD,kBAAkB,aAClB,KAAA;CACH,IAAI,gBAAgB,kBAAkB,EACrC,kBAAkB,cACjB,WAAW,WAAW,IACnB,sJACA,iEAAiE,WAAW,KAAK,KAAK,CAAC;CAE5F,OAAO;;AAGR,SAAgB,8BACf,aAAgC,EAAE,EACI;CAEtC,OAAO;EACN;GACC,aAAa,8DAHU,qBAAqB,WAG+C;GAC3F,aAAa,mCACZ,uBAAuB,iBACvB,WACA;GACD,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;;AAGF,eAAsB,wBACrB,QACA,UAAoC,EAAE,EACV;CAC5B,IAAI;CACJ,WAAW,MAAM,SAAS,QAAQ;EACjC,MAAM,QAAQ,UAAU,MAAM;EAC9B,IAAI,MAAM,SAAS,aAClB,SAAS,MAAM;EAEhB,IAAI,MAAM,SAAS,UAClB,MAAM,MAAM;;CAGd,IAAI,WAAW,KAAA,GACd,MAAM,IAAI,MAAM,0DAA0D;CAE3E,OAAO;;AAGR,gBAAgB,iBAAiB,OAOE;CAClC,MAAM,WAAW,yBAAyB,MAAM,YAAY;CAC5D,MAAM,UACL,MAAM,aAAa,oBAChB,SAAS,OACT,MAAM,aAAa,sBAClB,SAAS,SACT,SAAS;CACd,eAAe,MAAM,OAAO;CAC5B,MAAM,cAAc,MAAM,QAAQ;EAAE,UAAU,MAAM;EAAO,OAAO,MAAM;EAAO,CAAC;CAChF,eAAe,MAAM,OAAO;CAC5B,MAAM;EAAE,MAAM;EAAa,QAAQ,8BAA8B,YAAY;EAAE;;AAGhF,gBAAgB,eAAe,OAKI;CAClC,MAAM,cAAc,sBAAsB,UAAU,MAAM,MAAM;CAChE,MAAM,eAAkC,EAAE;CAC1C,IAAI;CACJ,IAAI,gBAAgB;CACpB,MAAM,aAAa,UAAiC;EACnD,0BAA0B,MAAM;EAChC,IAAI,aAAa,UAAU,2BAC1B,MAAM,IAAI,MAAM,wCAAwC,0BAA0B,UAAU;EAE7F,aAAa,KAAK,MAAM;EACxB,qBAAqB;EACrB,oBAAoB,KAAA;;CAiDrB,MAAM,WAAW,yBAAyB;EA9CzC,GAAG,MAAM;EACT,kBAAkB,OAAO,SAAS;GACjC,eAAe,MAAM,OAAO;GAC5B,UAAU;IACT,MAAM;IACN,WAAW,KAAK;IAChB,WAAW,KAAK;IAChB,UAAU,KAAK;IACf,CAAC;GACF,UAAU;IACT,MAAM;IACN,SAAS,6BAA6B,KAAK,UAAU,GAAG,KAAK,SAAS;IACtE,WAAW,KAAK;IAChB,CAAC;GACF,OAAO,MAAM,MAAM,YAAY,iBAAiB;IAC/C,GAAG;IACH,GAAI,MAAM,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,QAAQ,GAAG,EAAE;IAC9D,UAAU,UAAU;KACnB,IAAI,MAAM,SAAS,YAAY;MAC9B,UAAU;OACT,MAAM;OACN,GAAI,MAAM,YAAY,KAAA,IAAY,EAAE,SAAS,MAAM,SAAS,GAAG,EAAE;OACjE,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,UAAU,GAAG,EAAE;OACpE,WAAW,KAAK;OAChB,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,OAAO,GAAG,EAAE;OAC3D,CAAC;MACF;;KAED,IAAI,MAAM,SAAS,mBAAmB;MACrC,UAAU;OACT,SAAS,MAAM;OACf,MAAM;OACN,WAAW,KAAK;OAChB,CAAC;MACF;;KAED,UAAU;MACT,MAAM;MACN,QAAQ,MAAM;MACd,QAAQ,MAAM;MACd,WAAW,KAAK;MAChB,CAAC;;IAEH,CAAC;;EAG0D,CAAC;CAC/D,IAAI,CAAC,YAAY,SAAS;EAEzB,MAAM;GAAE,MAAM;GAAa,QAAQ,8BAA8B,MADvC,SAAS,KAAK;IAAE,UAAU,MAAM;IAAO,OAAO,MAAM;IAAO,CAAC,CACT;GAAE;EAC/E;;CAGD,MAAM,cAAsC,EAAE;CAC9C,MAAM,qBAAqB,SACzB,KAAK;EACL,UAAU,MAAM;EAChB,OAAO,MAAM;EACb,CAAC,CACD,cAAc;EACd,gBAAgB;EAChB,qBAAqB;EACrB,oBAAoB,KAAA;GACnB;CACH,MAAM,kCAA2C,CAAC,iBAAiB,aAAa,SAAS;CACzF,OAAO,2BAA2B,EAAE;EACnC,MAAM,QAAQ,aAAa,OAAO;EAClC,IAAI,UAAU,KAAA,GAAW;GACxB,MAAM;GACN;;EAED,eAAe,MAAM,OAAO;EAG5B,MAAM,uBAAuB;GAC5B,uBAAuB,WAAW;IACjC,oBAAoB;;GAErB,GAAI,MAAM,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,QAAQ,GAAG,EAAE;GAC9D,CAAC;;CAEH,MAAM,cAAc,MAAM;CAC1B,eAAe,MAAM,OAAO;CAC5B,IAAI,YAAY,OAAO,SAAS,GAAG;EAClC,MAAM;GAAE,MAAM;GAAa,QAAQ,8BAA8B,YAAY;GAAE;EAC/E;;CAED,KAAK,MAAM,WAAW,YAAY,KAAK,OAAO;EAC7C,MAAM,eAAe,YAAY,QAAQ,QAAQ;EACjD,MAAM,aACL,iBAAiB,KAAA,IACb;GACD,OAAO;IACN,MAAM;IACN,SAAS,mDAAmD,QAAQ,GAAG;IACvE,WAAW,QAAQ;IACnB,UAAU,QAAQ;IAClB;GACD,WAAW,QAAQ;GACnB,QAAQ;GACR,GACA,+BAA+B,QAAQ,IAAI,aAAa;EAC5D,YAAY,KAAK,WAAW;EAC5B,IAAI,WAAW,WAAW,WACzB,MAAM;GAAE,MAAM;GAAkB,WAAW,QAAQ;GAAI,QAAQ;GAAY;OAE3E,MAAM;GAAE,OAAO,WAAW;GAAO,MAAM;GAAe,WAAW,QAAQ;GAAI;;CAI/E,MAAM;EACL,MAAM;EACN,QAAQ,uBAAuB;GAAE,aAAa,YAAY;GAAa,OAAO;GAAa,CAAC;EAC5F;;AAGF,SAAgB,iBAAiB,OAA0C;CAC1E,MAAM,iBAAiB,2BAA2B;EACjD,cAAc,MAAM;EACpB,cAAc,MAAM;EACpB,SAAS,MAAM;EACf,GAAI,MAAM,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,QAAQ,GAAG,EAAE;EAC9D,oBAAoB,MAAM;EAC1B,CAAC;CACF,MAAM,uCAAuB,IAAI,KAAa;CAC9C,MAAM,WACL,MAAM,mBACC;EACN,IAAI,MAAM,0BAA0B,kCACnC,OAAO,EAAE,MAAM,SAAS;EAEzB,MAAM,IAAI,MAAM,oDAAoD;;CAEtE,MAAM,cAAiC;EACtC;EACA,kBAAkB,MAAM,QAAQ;EAChC,YAAY,eAAe;EAC3B;CAED,gBAAgB,WAAW,MAA4D;EACtF,IAAI;GACH,eAAe,KAAK,OAAO;GAC3B,MAAM;IAAE,MAAM;IAAW,UAAU,KAAK;IAAU;GAClD,eAAe,KAAK,OAAO;GAC3B,IAAI,KAAK,aAAa,mBAAmB;IACxC,OAAO,eAAe;KACrB,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,QAAQ,KAAK,QAAQ,GAAG,EAAE;KAC5D;KACA,CAAC;IACF;;GAED,OAAO,iBAAiB;IACvB,OAAO,KAAK;IACZ,OAAO,KAAK;IACZ,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,QAAQ,KAAK,QAAQ,GAAG,EAAE;IAC5D;IACA,UAAU,KAAK;IACf;IACA,CAAC;WACM,OAAO;GACf,MAAM;IAAE;IAAO,MAAM;IAAU;;;CAIjC,OAAO;EACN,UAAU,EACT,gBAAgB,OAAO,OAAO,kBAAkB,SAAS,OAAO,OAAO,cAAc,EACrF;EACD;EACA,OAAO,YAAY;GAClB,MAAM,QAAQ,IACb,CAAC,GAAG,qBAAqB,CAAC,KAAK,iBAC9B,eAAe,qBAAqB,aAAa,CACjD,CACD;;EAEF;EACA,mBAAmB,UAAU;GAC5B,MAAM,QAAQ,0BAA0B,MAAM;GAC9C,qBAAqB,IAAI,MAAM,aAAa;GAC5C,OAAO;;EAER,gBAAgB,UAAU;GAMzB,OAAO,8BALQ,0BAA0B;IACxC,QAAQ,MAAM;IACd,UAAU;IACV,oBAAoB,MAAM;IAC1B,CAC0C,CAAC,kBAAkB;;EAE/D,sBAAsB,OAAO,iBAAiB;GAC7C,qBAAqB,OAAO,aAAa;GACzC,MAAM,eAAe,qBAAqB,aAAa;;EAExD,mBAAmB,OAAO,UAAU;GACnC,MAAM,eAAe,kBAAkB,MAAM;;EAE9C,oBAAoB,MAAM;EAC1B"}
1
+ {"version":3,"file":"portal-core-e-qajblz.js","names":[],"sources":["../src/core/provider-runtime.ts","../src/core/portal-core.ts"],"sourcesContent":["import {\n\tmcpConfigToResolvedProviders,\n\ttype McpConfig,\n\ttype ResolvedMcpProvider,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport type { NormalizedUpstreamMcpServer } from '../upstream-mcp-client-runtime.js';\n\nexport interface ResolveUpstreamServersProps {\n\treadonly config: McpConfig;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nasync function resolveProviderSecretRecord(\n\tsecrets: Readonly<Record<string, SecretValue>>,\n\tresolveSecret: (secret: SecretValue) => Promise<string>,\n): Promise<Readonly<Record<string, string>>> {\n\tconst resolvedEntries = await Promise.all(\n\t\tObject.entries(secrets).map(\n\t\t\tasync ([name, secret]) => [name, await resolveSecret(secret)] as const,\n\t\t),\n\t);\n\treturn Object.fromEntries(resolvedEntries);\n}\n\nasync function resolveUpstreamServer(\n\tprovider: ResolvedMcpProvider,\n\tresolveSecret: (secret: SecretValue) => Promise<string>,\n): Promise<NormalizedUpstreamMcpServer> {\n\tif (provider.transport === 'stdio') {\n\t\treturn {\n\t\t\targs: provider.args,\n\t\t\tcommand: provider.command,\n\t\t\t...(provider.cwd === undefined ? {} : { cwd: provider.cwd }),\n\t\t\tenv: await resolveProviderSecretRecord(provider.env, resolveSecret),\n\t\t\tnamespace: provider.namespace,\n\t\t\ttransport: 'stdio',\n\t\t};\n\t}\n\n\treturn {\n\t\theaders: await resolveProviderSecretRecord(provider.headers, resolveSecret),\n\t\tnamespace: provider.namespace,\n\t\ttransport: provider.transport,\n\t\turl: provider.url,\n\t};\n}\n\nexport async function resolveUpstreamServers(\n\tprops: ResolveUpstreamServersProps,\n): Promise<readonly NormalizedUpstreamMcpServer[]> {\n\treturn await Promise.all(\n\t\tmcpConfigToResolvedProviders(props.config).map(async (provider) =>\n\t\t\tresolveUpstreamServer(provider, props.resolveSecret),\n\t\t),\n\t);\n}\n","import type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\n\nimport { jsonObjectSchema } from '../json-schema.js';\nimport {\n\tcreatePortalAgentIdentity,\n\tresolvePortalAccessPolicy,\n\ttype PortalAccessPolicyConfig,\n\ttype PortalAgentIdentity,\n\ttype PortalAgentScopeSource,\n} from '../portal-access-policy.js';\nimport {\n\tcreatePortalSessionManager,\n\ttype PortalSessionManager,\n\ttype PortalSessionRuntime,\n} from '../portal-session.js';\nimport type { SkillGraphInput } from '../tool-graph.js';\nimport {\n\tcreatePortalToolHandlers,\n\tportalToolInputSchemas,\n\ttype PortalApprovalCall,\n\ttype PortalBatchDiagnostic,\n\ttype PortalBatchResult,\n\ttype PortalToolResult,\n\ttype PortalToolRuntime,\n} from './portal-tools.js';\n\nexport type PortalAgentScope = PortalAgentIdentity;\n\nexport type PortalCoreToolName =\n\t| 'mcp_portal_list'\n\t| 'mcp_portal_search'\n\t| 'mcp_portal_describe'\n\t| 'mcp_portal_call';\n\nexport interface PortalAuditEvent {\n\treadonly causeMessage?: string;\n\treadonly elapsedMs?: number;\n\treadonly hint?: string;\n\treadonly kind: string;\n\treadonly message: string;\n\treadonly namespace?: string;\n\treadonly operation?: string;\n\treadonly phase?: string;\n\treadonly timeoutMs?: number;\n\treadonly toolName?: string;\n\treadonly transport?: unknown;\n}\n\nexport interface PortalCoreResult {\n\treadonly auditEvents?: readonly PortalAuditEvent[];\n\treadonly content: readonly PortalCoreContentBlock[];\n\treadonly items: readonly PortalCoreItemResult[];\n\treadonly structuredContent?: unknown;\n}\n\nexport type PortalCoreItemResult =\n\t| {\n\t\t\treadonly content: readonly PortalCoreContentBlock[];\n\t\t\treadonly requestId: string;\n\t\t\treadonly status: 'success';\n\t\t\treadonly structuredContent?: unknown;\n\t }\n\t| {\n\t\t\treadonly error: PortalCoreItemError;\n\t\t\treadonly requestId: string;\n\t\t\treadonly status: 'failed';\n\t };\n\nexport interface PortalCoreItemError {\n\treadonly code: string;\n\treadonly message: string;\n\treadonly namespace?: string;\n\treadonly toolName?: string;\n\treadonly upstream?: unknown;\n}\n\nexport type PortalCoreContentBlock =\n\t| { readonly text: string; readonly type: 'text' }\n\t| { readonly type: 'json'; readonly value: unknown };\n\nexport type PortalCoreEvent =\n\t| {\n\t\t\treadonly kind: 'started';\n\t\t\treadonly toolName: PortalCoreToolName;\n\t }\n\t| {\n\t\t\treadonly kind: 'item_started';\n\t\t\treadonly namespace?: string;\n\t\t\treadonly requestId: string;\n\t\t\treadonly toolName?: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'progress';\n\t\t\treadonly message?: string;\n\t\t\treadonly progress?: number;\n\t\t\treadonly requestId?: string;\n\t\t\treadonly total?: number;\n\t }\n\t| {\n\t\t\treadonly kind: 'upstream_notification';\n\t\t\treadonly method: string;\n\t\t\treadonly params: unknown;\n\t\t\treadonly requestId?: string;\n\t }\n\t| {\n\t\t\treadonly content: PortalCoreContentBlock;\n\t\t\treadonly kind: 'partial_content';\n\t\t\treadonly requestId?: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'item_completed';\n\t\t\treadonly requestId: string;\n\t\t\treadonly result: Extract<PortalCoreItemResult, { readonly status: 'success' }>;\n\t }\n\t| {\n\t\t\treadonly error: PortalCoreItemError;\n\t\t\treadonly kind: 'item_failed';\n\t\t\treadonly requestId: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'completed';\n\t\t\treadonly result: PortalCoreResult;\n\t }\n\t| {\n\t\t\treadonly error: unknown;\n\t\t\treadonly kind: 'failed';\n\t };\n\nexport interface PortalCoreStreamCall {\n\treadonly input: unknown;\n\treadonly scope: PortalAgentScope;\n\treadonly signal?: AbortSignal;\n\treadonly toolName: PortalCoreToolName;\n}\n\nconst maxQueuedPortalCoreEvents = 1_024;\nconst maxPortalCoreEventBytes = 256 * 1_024;\n\nexport interface PortalCoreCollectOptions {\n\treadonly onEvent?: (event: PortalCoreEvent) => Promise<void> | void;\n}\n\nexport interface PortalCoreRuntime extends PortalSessionRuntime {\n\treadonly callUpstreamTool: PortalToolRuntime['callUpstreamTool'];\n}\n\nexport type PortalApprovalEvaluator = NonNullable<PortalToolRuntime['approval']>;\n\ninterface CreatePortalCoreBaseProps {\n\treadonly accessPolicy: PortalAccessPolicyConfig;\n\treadonly catalogTtlMs: number;\n\treadonly runtime: PortalCoreRuntime;\n\treadonly skills?: readonly SkillGraphInput[];\n\treadonly upstreamNamespaces: readonly string[];\n}\n\nexport type CreatePortalCoreProps =\n\t| (CreatePortalCoreBaseProps & {\n\t\t\treadonly approval: PortalApprovalEvaluator;\n\t\t\treadonly approvalTrustBoundary?: never;\n\t })\n\t| (CreatePortalCoreBaseProps & {\n\t\t\treadonly approval?: never;\n\t\t\treadonly approvalTrustBoundary: 'openclaw-before-tool-call-hook';\n\t });\n\nexport interface PortalCore {\n\treadonly approval: {\n\t\treadonly evaluateCalls: (\n\t\t\tcalls: readonly PortalApprovalCall[],\n\t\t\tscope: PortalAgentScope,\n\t\t\tapprovalToken: string | undefined,\n\t\t) => ReturnType<PortalApprovalEvaluator>;\n\t};\n\treadonly callStream: (call: PortalCoreStreamCall) => AsyncIterable<PortalCoreEvent>;\n\treadonly close: () => Promise<void>;\n\treadonly collectPortalCoreResult: typeof collectPortalCoreResult;\n\treadonly createAgentScope: (input: {\n\t\treadonly agentId: string;\n\t\treadonly agentScopeId: string;\n\t\treadonly authSubject?: string;\n\t\treadonly sessionId?: string;\n\t\treadonly sessionKey?: string;\n\t\treadonly source: PortalAgentScopeSource;\n\t}) => PortalAgentScope;\n\treadonly describeTools: (scope: PortalAgentScope) => readonly PortalCoreToolDescriptor[];\n\treadonly invalidateAgentScope: (agentScopeId: string) => Promise<void>;\n\treadonly invalidateSession: (scope: PortalAgentScope) => Promise<void>;\n\treadonly upstreamNamespaces: readonly string[];\n}\n\nexport interface PortalCoreToolDescriptor {\n\treadonly description: string;\n\treadonly inputSchema: Tool['inputSchema'];\n\treadonly name: PortalCoreToolName;\n}\n\nconst portalCallRequestSchema = z\n\t.object({\n\t\targuments: jsonObjectSchema,\n\t\tid: z.string().min(1),\n\t\tnamespace: z.string().min(1),\n\t\ttoolName: z.string().min(1),\n\t})\n\t.strict();\nconst portalCallInputSchema = z\n\t.object({\n\t\tcalls: z.array(portalCallRequestSchema).min(1),\n\t\tportalApprovalToken: z.string().min(1).optional(),\n\t})\n\t.strict();\n\nfunction diagnosticsToAuditEvents(\n\tdiagnostics: readonly PortalBatchDiagnostic[],\n): readonly PortalAuditEvent[] {\n\treturn diagnostics.map((diagnostic) => ({ ...diagnostic }));\n}\n\nfunction isUnknownRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction errorRecordFromUnknown(error: unknown): Record<string, unknown> {\n\treturn isUnknownRecord(error) ? error : {};\n}\n\nfunction messageFromUnknown(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\tconst record = errorRecordFromUnknown(error);\n\tconst message = record.message;\n\treturn typeof message === 'string' ? message : String(error);\n}\n\nfunction errorFromAbortSignal(signal: AbortSignal): Error {\n\tconst reason: unknown = signal.reason;\n\treturn reason instanceof Error ? reason : new Error('MCP Portal core stream aborted.');\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n\tif (signal?.aborted) {\n\t\tthrow errorFromAbortSignal(signal);\n\t}\n}\n\nfunction assertPortalCoreEventSize(event: PortalCoreEvent): void {\n\tconst serialized = JSON.stringify(event);\n\tif (serialized === undefined) {\n\t\treturn;\n\t}\n\tconst byteLength = Buffer.byteLength(serialized, 'utf8');\n\tif (byteLength > maxPortalCoreEventBytes) {\n\t\tthrow new Error(\n\t\t\t`MCP Portal core event exceeded ${String(maxPortalCoreEventBytes)} bytes (${String(byteLength)} bytes).`,\n\t\t);\n\t}\n}\n\nfunction waitForQueuedCoreEvent(props: {\n\treadonly setNotifyQueuedEvent: (notify: (() => void) | undefined) => void;\n\treadonly signal?: AbortSignal;\n}): Promise<void> {\n\tif (props.signal === undefined) {\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tprops.setNotifyQueuedEvent(resolve);\n\t\t});\n\t}\n\tconst signal = props.signal;\n\treturn new Promise<void>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst settle = (complete: () => void): void => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tsignal.removeEventListener('abort', onAbort);\n\t\t\tprops.setNotifyQueuedEvent(undefined);\n\t\t\tcomplete();\n\t\t};\n\t\tconst onNotify = (): void => {\n\t\t\tsettle(resolve);\n\t\t};\n\t\tconst onAbort = (): void => {\n\t\t\tsettle(() => reject(errorFromAbortSignal(signal)));\n\t\t};\n\t\tprops.setNotifyQueuedEvent(onNotify);\n\t\tsignal.addEventListener('abort', onAbort, { once: true });\n\t\tif (signal.aborted) {\n\t\t\tonAbort();\n\t\t}\n\t});\n}\n\nfunction itemErrorFromPortalResult(result: PortalToolResult): PortalCoreItemError {\n\tif (result.ok) {\n\t\tthrow new Error('Cannot convert successful portal result into an item error.');\n\t}\n\tconst errorRecord = errorRecordFromUnknown(result.error);\n\tconst kind = errorRecord.kind;\n\tconst namespace = errorRecord.namespace;\n\tconst toolName = errorRecord.toolName;\n\tconst upstream = errorRecord.upstream;\n\n\treturn {\n\t\tcode: typeof kind === 'string' ? kind : 'portal_item_failed',\n\t\tmessage: messageFromUnknown(result.error),\n\t\t...(typeof namespace === 'string' ? { namespace } : {}),\n\t\t...(typeof toolName === 'string' ? { toolName } : {}),\n\t\t...(upstream === undefined ? {} : { upstream }),\n\t};\n}\n\nfunction itemResultFromPortalToolResult(\n\trequestId: string,\n\tresult: PortalToolResult,\n): PortalCoreItemResult {\n\tif (!result.ok) {\n\t\treturn {\n\t\t\terror: itemErrorFromPortalResult(result),\n\t\t\trequestId,\n\t\t\tstatus: 'failed',\n\t\t};\n\t}\n\n\treturn {\n\t\tcontent: [{ type: 'json', value: result.output }],\n\t\trequestId,\n\t\tstatus: 'success',\n\t\tstructuredContent: result.output,\n\t};\n}\n\nfunction scalarBatchResultToCoreResult(batchResult: PortalBatchResult): PortalCoreResult {\n\treturn {\n\t\tauditEvents: diagnosticsToAuditEvents(batchResult.diagnostics),\n\t\tcontent: [{ type: 'json', value: batchResult }],\n\t\titems: [],\n\t\tstructuredContent: batchResult,\n\t};\n}\n\nfunction batchItemsToCoreResult(props: {\n\treadonly diagnostics: readonly PortalBatchDiagnostic[];\n\treadonly items: readonly PortalCoreItemResult[];\n}): PortalCoreResult {\n\treturn {\n\t\tauditEvents: diagnosticsToAuditEvents(props.diagnostics),\n\t\tcontent: [],\n\t\titems: props.items,\n\t};\n}\n\nfunction namespaceDescription(namespaces: readonly string[]): string {\n\treturn namespaces.length === 0\n\t\t? 'No upstream MCP namespaces are authorized for this agent scope.'\n\t\t: `Allowed namespaces for this agent: ${namespaces.join(', ')}.`;\n}\n\nfunction cloneJsonObject<TValue>(value: TValue): TValue {\n\treturn structuredClone(value);\n}\n\nfunction withListNamespaceSchemaDescription(\n\tinputSchema: Tool['inputSchema'],\n\tnamespaces: readonly string[],\n): Tool['inputSchema'] {\n\tconst clonedSchema = cloneJsonObject(inputSchema);\n\tconst requests = isUnknownRecord(clonedSchema.properties)\n\t\t? clonedSchema.properties.requests\n\t\t: undefined;\n\tconst requestItems = isUnknownRecord(requests) ? requests.items : undefined;\n\tconst requestProperties = isUnknownRecord(requestItems) ? requestItems.properties : undefined;\n\tconst namespaceProperty = isUnknownRecord(requestProperties)\n\t\t? requestProperties.namespaces\n\t\t: undefined;\n\tif (isUnknownRecord(namespaceProperty)) {\n\t\tnamespaceProperty.description =\n\t\t\tnamespaces.length === 0\n\t\t\t\t? 'Optional namespace filter. No upstream MCP namespaces are authorized for this agent. Omit to list all currently discovered authorized namespaces.'\n\t\t\t\t: `Optional namespace filter. Allowed namespaces for this agent: ${namespaces.join(', ')}. Omit to list all currently discovered authorized namespaces.`;\n\t}\n\treturn clonedSchema;\n}\n\nexport function listPortalCoreToolDescriptors(\n\tnamespaces: readonly string[] = [],\n): readonly PortalCoreToolDescriptor[] {\n\tconst scopeDescription = namespaceDescription(namespaces);\n\treturn [\n\t\t{\n\t\t\tdescription: `List authorized MCP namespaces and compact tool summaries. ${scopeDescription}`,\n\t\t\tinputSchema: withListNamespaceSchemaDescription(\n\t\t\t\tportalToolInputSchemas.mcp_portal_list,\n\t\t\t\tnamespaces,\n\t\t\t),\n\t\t\tname: 'mcp_portal_list',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\tname: 'mcp_portal_search',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\tname: 'mcp_portal_describe',\n\t\t},\n\t\t{\n\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\tname: 'mcp_portal_call',\n\t\t},\n\t];\n}\n\nexport async function collectPortalCoreResult(\n\tevents: AsyncIterable<PortalCoreEvent>,\n\toptions: PortalCoreCollectOptions = {},\n): Promise<PortalCoreResult> {\n\tlet result: PortalCoreResult | undefined;\n\tfor await (const event of events) {\n\t\tawait options.onEvent?.(event);\n\t\tif (event.kind === 'completed') {\n\t\t\tresult = event.result;\n\t\t}\n\t\tif (event.kind === 'failed') {\n\t\t\tthrow event.error;\n\t\t}\n\t}\n\tif (result === undefined) {\n\t\tthrow new Error('MCP Portal core stream ended without a completed event.');\n\t}\n\treturn result;\n}\n\nasync function* scalarToolStream(props: {\n\treadonly input: unknown;\n\treadonly scope: PortalAgentScope;\n\treadonly signal?: AbortSignal;\n\treadonly sessionManager: PortalSessionManager;\n\treadonly toolName: Exclude<PortalCoreToolName, 'mcp_portal_call'>;\n\treadonly toolRuntime: PortalToolRuntime;\n}): AsyncIterable<PortalCoreEvent> {\n\tconst handlers = createPortalToolHandlers(props.toolRuntime);\n\tconst handler =\n\t\tprops.toolName === 'mcp_portal_list'\n\t\t\t? handlers.list\n\t\t\t: props.toolName === 'mcp_portal_search'\n\t\t\t\t? handlers.search\n\t\t\t\t: handlers.describe;\n\tthrowIfAborted(props.signal);\n\tconst batchResult = await handler({ identity: props.scope, input: props.input });\n\tthrowIfAborted(props.signal);\n\tyield { kind: 'completed', result: scalarBatchResultToCoreResult(batchResult) };\n}\n\nasync function* callToolStream(props: {\n\treadonly input: unknown;\n\treadonly scope: PortalAgentScope;\n\treadonly signal?: AbortSignal;\n\treadonly toolRuntime: PortalToolRuntime;\n}): AsyncIterable<PortalCoreEvent> {\n\tconst parsedInput = portalCallInputSchema.safeParse(props.input);\n\tconst queuedEvents: PortalCoreEvent[] = [];\n\tlet notifyQueuedEvent: (() => void) | undefined;\n\tlet executionDone = false;\n\tconst pushEvent = (event: PortalCoreEvent): void => {\n\t\tassertPortalCoreEventSize(event);\n\t\tif (queuedEvents.length >= maxQueuedPortalCoreEvents) {\n\t\t\tthrow new Error(`MCP Portal core event queue exceeded ${maxQueuedPortalCoreEvents} events.`);\n\t\t}\n\t\tqueuedEvents.push(event);\n\t\tnotifyQueuedEvent?.();\n\t\tnotifyQueuedEvent = undefined;\n\t};\n\tconst streamingToolRuntime: PortalToolRuntime = {\n\t\t...props.toolRuntime,\n\t\tcallUpstreamTool: async (call) => {\n\t\t\tthrowIfAborted(props.signal);\n\t\t\tpushEvent({\n\t\t\t\tkind: 'item_started',\n\t\t\t\tnamespace: call.namespace,\n\t\t\t\trequestId: call.requestId,\n\t\t\t\ttoolName: call.toolName,\n\t\t\t});\n\t\t\tpushEvent({\n\t\t\t\tkind: 'progress',\n\t\t\t\tmessage: `Calling upstream MCP tool ${call.namespace}.${call.toolName}.`,\n\t\t\t\trequestId: call.requestId,\n\t\t\t});\n\t\t\treturn await props.toolRuntime.callUpstreamTool({\n\t\t\t\t...call,\n\t\t\t\t...(props.signal !== undefined ? { signal: props.signal } : {}),\n\t\t\t\tonEvent: (event) => {\n\t\t\t\t\tif (event.kind === 'progress') {\n\t\t\t\t\t\tpushEvent({\n\t\t\t\t\t\t\tkind: 'progress',\n\t\t\t\t\t\t\t...(event.message !== undefined ? { message: event.message } : {}),\n\t\t\t\t\t\t\t...(event.progress !== undefined ? { progress: event.progress } : {}),\n\t\t\t\t\t\t\trequestId: call.requestId,\n\t\t\t\t\t\t\t...(event.total !== undefined ? { total: event.total } : {}),\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (event.kind === 'partial_content') {\n\t\t\t\t\t\tpushEvent({\n\t\t\t\t\t\t\tcontent: event.content,\n\t\t\t\t\t\t\tkind: 'partial_content',\n\t\t\t\t\t\t\trequestId: call.requestId,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tpushEvent({\n\t\t\t\t\t\tkind: 'upstream_notification',\n\t\t\t\t\t\tmethod: event.method,\n\t\t\t\t\t\tparams: event.params,\n\t\t\t\t\t\trequestId: call.requestId,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n\tconst handlers = createPortalToolHandlers(streamingToolRuntime);\n\tif (!parsedInput.success) {\n\t\tconst batchResult = await handlers.call({ identity: props.scope, input: props.input });\n\t\tyield { kind: 'completed', result: scalarBatchResultToCoreResult(batchResult) };\n\t\treturn;\n\t}\n\n\tconst itemResults: PortalCoreItemResult[] = [];\n\tconst batchResultPromise = handlers\n\t\t.call({\n\t\t\tidentity: props.scope,\n\t\t\tinput: props.input,\n\t\t})\n\t\t.finally(() => {\n\t\t\texecutionDone = true;\n\t\t\tnotifyQueuedEvent?.();\n\t\t\tnotifyQueuedEvent = undefined;\n\t\t});\n\tconst hasPendingExecutionEvents = (): boolean => !executionDone || queuedEvents.length > 0;\n\twhile (hasPendingExecutionEvents()) {\n\t\tconst event = queuedEvents.shift();\n\t\tif (event !== undefined) {\n\t\t\tyield event;\n\t\t\tcontinue;\n\t\t}\n\t\tthrowIfAborted(props.signal);\n\t\t// Streaming consumes events as they arrive; there is no parallel work to collect here.\n\t\t// eslint-disable-next-line no-await-in-loop\n\t\tawait waitForQueuedCoreEvent({\n\t\t\tsetNotifyQueuedEvent: (notify) => {\n\t\t\t\tnotifyQueuedEvent = notify;\n\t\t\t},\n\t\t\t...(props.signal !== undefined ? { signal: props.signal } : {}),\n\t\t});\n\t}\n\tconst batchResult = await batchResultPromise;\n\tthrowIfAborted(props.signal);\n\tif (batchResult.errors.length > 0) {\n\t\tyield { kind: 'completed', result: scalarBatchResultToCoreResult(batchResult) };\n\t\treturn;\n\t}\n\tfor (const request of parsedInput.data.calls) {\n\t\tconst portalResult = batchResult.results[request.id];\n\t\tconst itemResult =\n\t\t\tportalResult === undefined\n\t\t\t\t? ({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tcode: 'portal_item_missing',\n\t\t\t\t\t\t\tmessage: `MCP Portal did not return a result for request \"${request.id}\".`,\n\t\t\t\t\t\t\tnamespace: request.namespace,\n\t\t\t\t\t\t\ttoolName: request.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequestId: request.id,\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t} satisfies PortalCoreItemResult)\n\t\t\t\t: itemResultFromPortalToolResult(request.id, portalResult);\n\t\titemResults.push(itemResult);\n\t\tif (itemResult.status === 'success') {\n\t\t\tyield { kind: 'item_completed', requestId: request.id, result: itemResult };\n\t\t} else {\n\t\t\tyield { error: itemResult.error, kind: 'item_failed', requestId: request.id };\n\t\t}\n\t}\n\n\tyield {\n\t\tkind: 'completed',\n\t\tresult: batchItemsToCoreResult({ diagnostics: batchResult.diagnostics, items: itemResults }),\n\t};\n}\n\nexport function createPortalCore(props: CreatePortalCoreProps): PortalCore {\n\tconst sessionManager = createPortalSessionManager({\n\t\taccessPolicy: props.accessPolicy,\n\t\tcatalogTtlMs: props.catalogTtlMs,\n\t\truntime: props.runtime,\n\t\t...(props.skills !== undefined ? { skills: props.skills } : {}),\n\t\tupstreamNamespaces: props.upstreamNamespaces,\n\t});\n\tconst createdAgentScopeIds = new Set<string>();\n\tconst approval: PortalApprovalEvaluator =\n\t\tprops.approval ??\n\t\t(() => {\n\t\t\tif (props.approvalTrustBoundary === 'openclaw-before-tool-call-hook') {\n\t\t\t\treturn { kind: 'allow' };\n\t\t\t}\n\t\t\tthrow new Error('MCP Portal approval evaluation is not configured.');\n\t\t});\n\tconst toolRuntime: PortalToolRuntime = {\n\t\tapproval,\n\t\tcallUpstreamTool: props.runtime.callUpstreamTool,\n\t\tgetSession: sessionManager.getSession,\n\t};\n\n\tasync function* callStream(call: PortalCoreStreamCall): AsyncIterable<PortalCoreEvent> {\n\t\ttry {\n\t\t\tthrowIfAborted(call.signal);\n\t\t\tyield { kind: 'started', toolName: call.toolName };\n\t\t\tthrowIfAborted(call.signal);\n\t\t\tif (call.toolName === 'mcp_portal_call') {\n\t\t\t\tyield* callToolStream({\n\t\t\t\t\tinput: call.input,\n\t\t\t\t\tscope: call.scope,\n\t\t\t\t\t...(call.signal !== undefined ? { signal: call.signal } : {}),\n\t\t\t\t\ttoolRuntime,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tyield* scalarToolStream({\n\t\t\t\tinput: call.input,\n\t\t\t\tscope: call.scope,\n\t\t\t\t...(call.signal !== undefined ? { signal: call.signal } : {}),\n\t\t\t\tsessionManager,\n\t\t\t\ttoolName: call.toolName,\n\t\t\t\ttoolRuntime,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tyield { error, kind: 'failed' };\n\t\t}\n\t}\n\n\treturn {\n\t\tapproval: {\n\t\t\tevaluateCalls: (calls, scope, approvalToken) => approval(calls, scope, approvalToken),\n\t\t},\n\t\tcallStream,\n\t\tclose: async () => {\n\t\t\tawait Promise.all(\n\t\t\t\t[...createdAgentScopeIds].map((agentScopeId) =>\n\t\t\t\t\tsessionManager.invalidateAgentScope(agentScopeId),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\tcollectPortalCoreResult,\n\t\tcreateAgentScope: (input) => {\n\t\t\tconst scope = createPortalAgentIdentity(input);\n\t\t\tcreatedAgentScopeIds.add(scope.agentScopeId);\n\t\t\treturn scope;\n\t\t},\n\t\tdescribeTools: (scope) => {\n\t\t\tconst policy = resolvePortalAccessPolicy({\n\t\t\t\tconfig: props.accessPolicy,\n\t\t\t\tidentity: scope,\n\t\t\t\tupstreamNamespaces: props.upstreamNamespaces,\n\t\t\t});\n\t\t\treturn listPortalCoreToolDescriptors(policy.allowedNamespaces);\n\t\t},\n\t\tinvalidateAgentScope: async (agentScopeId) => {\n\t\t\tcreatedAgentScopeIds.delete(agentScopeId);\n\t\t\tawait sessionManager.invalidateAgentScope(agentScopeId);\n\t\t},\n\t\tinvalidateSession: async (scope) => {\n\t\t\tawait sessionManager.invalidateSession(scope);\n\t\t},\n\t\tupstreamNamespaces: props.upstreamNamespaces,\n\t};\n}\n"],"mappings":"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"}
@@ -488,6 +488,21 @@ function createPortalToolHandlers(runtime) {
488
488
  });
489
489
  continue;
490
490
  }
491
+ if (approval.kind === "call_blocked") {
492
+ results[preparedResult.input.id] = itemError({
493
+ error: {
494
+ kind: "call_blocked",
495
+ message: "MCP Portal policy does not allow this tool call.",
496
+ namespace: preparedResult.tool.namespace,
497
+ toolName: preparedResult.tool.toolName
498
+ },
499
+ input: {
500
+ ...preparedResult.input,
501
+ arguments: preparedResult.validatedArguments
502
+ }
503
+ });
504
+ continue;
505
+ }
491
506
  if (approval.kind === "approval_configuration_missing") {
492
507
  results[preparedResult.input.id] = itemError({
493
508
  error: {
@@ -542,4 +557,4 @@ function createPortalToolHandlers(runtime) {
542
557
  //#endregion
543
558
  export { portalToolInputSchemas as n, validatePortalToolArguments as r, createPortalToolHandlers as t };
544
559
 
545
- //# sourceMappingURL=portal-tools-DA7j2pyv.js.map
560
+ //# sourceMappingURL=portal-tools-Ct2GuFSc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-tools-Ct2GuFSc.js","names":[],"sources":["../src/core/portal-call-validation.ts","../src/core/portal-tools.ts"],"sourcesContent":["import type { PortalToolRecord } from '../catalog-types.js';\nimport type { JsonObject } from '../json-schema.js';\nimport { buildZodValidatorFromJsonSchema } from '../zod-schema-loader.js';\n\nexport function validatePortalToolArguments(\n\ttool: PortalToolRecord,\n\targumentsValue: JsonObject,\n):\n\t| { readonly ok: true; readonly value: unknown }\n\t| {\n\t\t\treadonly error:\n\t\t\t\t| {\n\t\t\t\t\t\treadonly issues: readonly {\n\t\t\t\t\t\t\treadonly code: string;\n\t\t\t\t\t\t\treadonly message: string;\n\t\t\t\t\t\t\treadonly path: readonly (number | string)[];\n\t\t\t\t\t\t}[];\n\t\t\t\t\t\treadonly kind: 'input_validation';\n\t\t\t\t\t\treadonly namespace: string;\n\t\t\t\t\t\treadonly toolName: string;\n\t\t\t\t }\n\t\t\t\t| {\n\t\t\t\t\t\treadonly feature: string;\n\t\t\t\t\t\treadonly kind: 'schema_validation_unavailable';\n\t\t\t\t\t\treadonly message: string;\n\t\t\t\t\t\treadonly namespace: string;\n\t\t\t\t\t\treadonly path: readonly (number | string)[];\n\t\t\t\t\t\treadonly toolName: string;\n\t\t\t\t };\n\t\t\treadonly ok: false;\n\t } {\n\tconst validator = buildZodValidatorFromJsonSchema(tool.inputSchema);\n\tif (!validator.ok) {\n\t\treturn {\n\t\t\terror: { ...validator.error, namespace: tool.namespace, toolName: tool.toolName },\n\t\t\tok: false,\n\t\t};\n\t}\n\n\tconst result = validator.validate(argumentsValue);\n\tif (!result.ok) {\n\t\treturn {\n\t\t\terror: { ...result.error, namespace: tool.namespace, toolName: tool.toolName },\n\t\t\tok: false,\n\t\t};\n\t}\n\n\treturn result;\n}\n","import type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\n\nimport type { PortalToolRecord } from '../catalog-types.js';\nimport { jsonObjectSchema, type JsonObject } from '../json-schema.js';\nimport {\n\tportalAgentScopeKey,\n\ttype PortalAgentIdentity,\n\ttype PortalToolSelector,\n} from '../portal-access-policy.js';\nimport { generateTypescriptCatalogArtifact } from '../portal-config/typescript-artifact.js';\nimport type { PortalSession } from '../portal-session.js';\nimport type { ToolSearchResult } from '../search-index.js';\nimport { decodeToolRef } from '../tool-ref.js';\nimport { createToolSummary, type ToolSchemaHint, type ToolSummary } from '../tool-summary.js';\nimport { upstreamMcpFailureDetailsFromUnknown } from '../upstream-mcp-errors.js';\nimport { validatePortalToolArguments } from './portal-call-validation.js';\n\nexport interface PortalToolSuccess {\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly ok: true;\n\treadonly output: Readonly<Record<string, unknown>>;\n}\n\nexport interface PortalToolFailure {\n\treadonly error: unknown;\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly ok: false;\n}\n\nexport type PortalToolResult = PortalToolFailure | PortalToolSuccess;\nexport type PortalToolResultMap = Readonly<Record<string, PortalToolResult>>;\n\nexport interface PortalBatchError {\n\treadonly id?: string;\n\treadonly kind: string;\n\treadonly message: string;\n}\n\nexport interface PortalBatchDiagnostic {\n\treadonly causeMessage?: string;\n\treadonly elapsedMs?: number;\n\treadonly hint?: string;\n\treadonly kind: string;\n\treadonly message: string;\n\treadonly namespace?: string;\n\treadonly operation?: string;\n\treadonly phase?: string;\n\treadonly timeoutMs?: number;\n\treadonly toolName?: string;\n\treadonly transport?: unknown;\n}\n\nexport interface PortalBatchResult {\n\treadonly diagnostics: readonly PortalBatchDiagnostic[];\n\treadonly errors: readonly PortalBatchError[];\n\treadonly ok: boolean;\n\treadonly results: PortalToolResultMap;\n}\n\nexport interface PortalApprovalCall {\n\treadonly arguments: JsonObject;\n\treadonly id: string;\n\treadonly namespace: string;\n\treadonly tool: PortalToolRecord;\n\treadonly toolName: string;\n}\n\ntype SelectorInputResult =\n\t| { readonly error: PortalBatchError; readonly ok: false }\n\t| { readonly ok: true; readonly selectors: readonly PortalToolSelector[] };\ntype ExactFilterResult =\n\t| { readonly error: PortalBatchError; readonly ok: false }\n\t| { readonly ok: true; readonly tools: readonly PortalToolRecord[] };\n\nconst requestIdSchema = z.string().min(1);\nconst reservedRequestIds = new Set(['__proto__', 'constructor', 'prototype']);\nconst safeRequestIdSchema = requestIdSchema.refine((id) => !reservedRequestIds.has(id), {\n\tmessage: 'Portal request id uses a reserved object property name.',\n});\nconst namespaceToolSelectorSchema = z\n\t.object({ namespace: z.string().min(1), toolName: z.string().min(1) })\n\t.strict();\nconst listRequestSchema = z\n\t.object({\n\t\tcursor: z.string().regex(/^\\d+$/u).optional(),\n\t\tid: safeRequestIdSchema,\n\t\tlimit: z.number().int().positive().max(100).default(20),\n\t\tnamespaces: z.array(z.string()).optional(),\n\t\trefs: z.array(z.string()).optional(),\n\t\ttools: z.array(namespaceToolSelectorSchema).optional(),\n\t})\n\t.strict();\nconst searchRequestSchema = z\n\t.object({\n\t\tid: safeRequestIdSchema,\n\t\tlimit: z.number().int().positive().max(50).default(10),\n\t\tnamespaces: z.array(z.string()).optional(),\n\t\tquery: z.string().optional(),\n\t\tschemaDetail: z.enum(['none', 'summary', 'full']).default('summary'),\n\t})\n\t.strict();\nconst describeRequestSchema = z\n\t.object({\n\t\tid: safeRequestIdSchema,\n\t\tincludeJsonSchema: z.boolean().default(true),\n\t\tincludeRelated: z.boolean().default(true),\n\t\tincludeTypescriptHelper: z.boolean().default(false),\n\t\tincludeZod: z.boolean().default(false),\n\t\trefs: z.array(z.string()).optional(),\n\t\ttools: z.array(namespaceToolSelectorSchema).optional(),\n\t})\n\t.strict();\nconst callRequestSchema = z\n\t.object({\n\t\targuments: jsonObjectSchema,\n\t\tid: safeRequestIdSchema,\n\t\tnamespace: z.string().min(1),\n\t\ttoolName: z.string().min(1),\n\t})\n\t.strict();\nconst listInputSchema = z.object({ requests: z.array(listRequestSchema).min(1) }).strict();\nconst searchInputSchema = z.object({ requests: z.array(searchRequestSchema).min(1) }).strict();\nconst describeInputSchema = z.object({ requests: z.array(describeRequestSchema).min(1) }).strict();\nconst callInputSchema = z.object({ calls: z.array(callRequestSchema).min(1) }).strict();\nconst callExecutionInputSchema = z\n\t.object({\n\t\tcalls: z.array(callRequestSchema).min(1),\n\t\tportalApprovalToken: z.string().min(1).optional(),\n\t})\n\t.strict();\n\ntype ListRequest = z.infer<typeof listRequestSchema>;\ntype SearchRequest = z.infer<typeof searchRequestSchema>;\ntype DescribeRequest = z.infer<typeof describeRequestSchema>;\ntype CallRequest = z.infer<typeof callRequestSchema>;\n\ninterface PreparedPortalCall {\n\treadonly input: CallRequest;\n\treadonly validatedArguments: JsonObject;\n\treadonly tool: PortalToolRecord;\n}\n\nconst describeBeforeCallSchemaHint = {\n\tmessage: 'Use mcp_portal_describe for exact input schema before calling.',\n\tnext: 'describe_before_call',\n} as const satisfies ToolSchemaHint;\n\nconst callReadySchemaHint = {\n\tmessage: 'Full input schema included.',\n\tnext: 'call_ready',\n} as const satisfies ToolSchemaHint;\n\nfunction isToolSchemaProperties(value: unknown): value is Record<string, object> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t!Array.isArray(value) &&\n\t\tObject.values(value).every(\n\t\t\t(entry) => typeof entry === 'object' && entry !== null && !Array.isArray(entry),\n\t\t)\n\t);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\nfunction toPortalInputJsonSchema(schema: z.ZodType): Tool['inputSchema'] {\n\tconst jsonSchema = jsonObjectSchema.parse(z.toJSONSchema(schema, { io: 'input' }));\n\tif (jsonSchema.type !== 'object') {\n\t\tthrow new Error('MCP Portal tool input schemas must be JSON Schema objects.');\n\t}\n\tconst properties = isToolSchemaProperties(jsonSchema.properties)\n\t\t? jsonSchema.properties\n\t\t: undefined;\n\tconst required = isStringArray(jsonSchema.required) ? jsonSchema.required : undefined;\n\n\treturn {\n\t\t...jsonSchema,\n\t\t...(properties !== undefined ? { properties } : {}),\n\t\t...(required !== undefined ? { required } : {}),\n\t\ttype: 'object',\n\t};\n}\n\nexport const portalToolInputSchemas = {\n\tmcp_portal_call: toPortalInputJsonSchema(callInputSchema),\n\tmcp_portal_describe: toPortalInputJsonSchema(describeInputSchema),\n\tmcp_portal_list: toPortalInputJsonSchema(listInputSchema),\n\tmcp_portal_search: toPortalInputJsonSchema(searchInputSchema),\n} as const;\n\nexport interface PortalToolHandlerCall {\n\treadonly identity: PortalAgentIdentity;\n\treadonly input: unknown;\n}\n\nexport interface PortalCallUpstreamTool {\n\treadonly arguments: JsonObject;\n\treadonly agentScopeId: string;\n\treadonly namespace: string;\n\treadonly onEvent?: (event: PortalUpstreamEvent) => Promise<void> | void;\n\treadonly requestId: string;\n\treadonly signal?: AbortSignal;\n\treadonly toolName: string;\n}\n\nexport type PortalUpstreamEvent =\n\t| {\n\t\t\treadonly kind: 'progress';\n\t\t\treadonly message?: string;\n\t\t\treadonly progress?: number;\n\t\t\treadonly total?: number;\n\t }\n\t| {\n\t\t\treadonly kind: 'upstream_notification';\n\t\t\treadonly method: string;\n\t\t\treadonly params: unknown;\n\t }\n\t| {\n\t\t\treadonly content:\n\t\t\t\t| { readonly text: string; readonly type: 'text' }\n\t\t\t\t| { readonly type: 'json'; readonly value: unknown };\n\t\t\treadonly kind: 'partial_content';\n\t };\n\nexport interface PortalToolRuntime {\n\treadonly approval?: (\n\t\tcalls: readonly PortalApprovalCall[],\n\t\tidentity: PortalAgentIdentity,\n\t\tapprovalToken: string | undefined,\n\t) =>\n\t\t| { readonly kind: 'allow' }\n\t\t| { readonly kind: 'call_blocked' }\n\t\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t\t| { readonly kind: 'approval_token_missing' }\n\t\t| { readonly kind: 'approval_required'; readonly level: 'critical' | 'standard' };\n\treadonly callUpstreamTool: (call: PortalCallUpstreamTool) => Promise<unknown>;\n\treadonly getSession: (identity: PortalAgentIdentity) => Promise<PortalSession>;\n}\n\ntype PortalApprovalDecision =\n\t| { readonly kind: 'allow' }\n\t| { readonly kind: 'approval_configuration_missing' }\n\t| { readonly kind: 'approval_required'; readonly level: 'critical' | 'standard' }\n\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t| { readonly kind: 'approval_token_missing' }\n\t| { readonly kind: 'call_blocked' };\n\nexport interface PortalToolHandlers {\n\treadonly call: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly describe: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly list: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly search: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n}\n\nfunction messageFromError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction invalidPortalInput(error: unknown): PortalBatchResult {\n\treturn {\n\t\tdiagnostics: [],\n\t\terrors: [{ kind: 'invalid_portal_input', message: messageFromError(error) }],\n\t\tok: false,\n\t\tresults: {},\n\t};\n}\n\nfunction itemError(props: {\n\treadonly error: unknown;\n\treadonly input: Readonly<Record<string, unknown>>;\n}): PortalToolResult {\n\treturn {\n\t\terror: props.error,\n\t\tinput: props.input,\n\t\tok: false,\n\t};\n}\n\nfunction itemOutput(props: {\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly output: Readonly<Record<string, unknown>>;\n}): PortalToolResult {\n\treturn {\n\t\tinput: props.input,\n\t\tok: true,\n\t\toutput: props.output,\n\t};\n}\n\nfunction discoveryDiagnostics(session: PortalSession): readonly PortalBatchDiagnostic[] {\n\treturn session.catalog.discoveryFailures.map((failure) => ({\n\t\t...failure,\n\t\tkind:\n\t\t\tfailure.kind === 'upstream_mcp_failed' ? 'upstream_mcp_failed' : 'upstream_discovery_failed',\n\t}));\n}\n\nfunction portalBatchResult(\n\tresults: PortalToolResultMap,\n\tdiagnostics: readonly PortalBatchDiagnostic[] = [],\n): PortalBatchResult {\n\tconst allItemsOk = Object.values(results).every((result) => result.ok);\n\treturn { diagnostics, errors: [], ok: allItemsOk, results };\n}\n\nfunction duplicateIdErrors(items: readonly { readonly id: string }[]): readonly PortalBatchError[] {\n\tconst seenIds = new Set<string>();\n\tconst duplicateIds = new Set<string>();\n\tfor (const item of items) {\n\t\tif (seenIds.has(item.id)) {\n\t\t\tduplicateIds.add(item.id);\n\t\t}\n\t\tseenIds.add(item.id);\n\t}\n\n\treturn [...duplicateIds].toSorted().map((id) => ({\n\t\tid,\n\t\tkind: 'duplicate_id',\n\t\tmessage: `Duplicate portal request id \"${id}\". Each request id must be unique.`,\n\t}));\n}\n\nfunction duplicateIdResult(items: readonly { readonly id: string }[]): PortalBatchResult | null {\n\tconst errors = duplicateIdErrors(items);\n\treturn errors.length > 0 ? { diagnostics: [], errors, ok: false, results: {} } : null;\n}\n\nfunction findTool(session: PortalSession, selector: PortalToolSelector): PortalToolRecord | null {\n\treturn (\n\t\tsession.catalog.tools.find(\n\t\t\t(tool) => tool.namespace === selector.namespace && tool.toolName === selector.toolName,\n\t\t) ?? null\n\t);\n}\n\nfunction selectorsFromInput(\n\ttools?: readonly PortalToolSelector[],\n\trefs?: readonly string[],\n): SelectorInputResult {\n\tconst selectors: PortalToolSelector[] = [...(tools ?? [])];\n\tfor (const toolRef of refs ?? []) {\n\t\ttry {\n\t\t\tselectors.push(decodeToolRef(toolRef));\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\terror: { kind: 'invalid_portal_input', message: messageFromError(error) },\n\t\t\t\tok: false,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { ok: true, selectors };\n}\n\nfunction applyExactFilters(\n\ttools: readonly PortalToolRecord[],\n\tfilters: {\n\t\treadonly namespaces?: readonly string[];\n\t\treadonly refs?: readonly string[];\n\t\treadonly tools?: readonly PortalToolSelector[];\n\t},\n): ExactFilterResult {\n\tconst namespaceFilter = new Set(filters.namespaces ?? []);\n\tconst selectorResult = selectorsFromInput(filters.tools, filters.refs);\n\tif (!selectorResult.ok) {\n\t\treturn selectorResult;\n\t}\n\tconst exactSelectors = selectorResult.selectors;\n\tif (exactSelectors.length === 0) {\n\t\treturn {\n\t\t\tok: true,\n\t\t\ttools: tools.filter(\n\t\t\t\t(tool) => namespaceFilter.size === 0 || namespaceFilter.has(tool.namespace),\n\t\t\t),\n\t\t};\n\t}\n\n\treturn {\n\t\tok: true,\n\t\ttools: tools.filter(\n\t\t\t(tool) =>\n\t\t\t\t(namespaceFilter.size === 0 || namespaceFilter.has(tool.namespace)) &&\n\t\t\t\texactSelectors.some(\n\t\t\t\t\t(selector) =>\n\t\t\t\t\t\tselector.namespace === tool.namespace && selector.toolName === tool.toolName,\n\t\t\t\t),\n\t\t),\n\t};\n}\n\nfunction selectorKey(selector: PortalToolSelector): string {\n\treturn `${selector.namespace}\\n${selector.toolName}`;\n}\n\nfunction missingSelectorError(\n\trequestedSelectors: readonly PortalToolSelector[],\n\tselectedTools: readonly PortalToolRecord[],\n): PortalBatchError | null {\n\tconst foundKeys = new Set(\n\t\tselectedTools.map((tool) =>\n\t\t\tselectorKey({ namespace: tool.namespace, toolName: tool.toolName }),\n\t\t),\n\t);\n\tconst missingSelectors = requestedSelectors.filter(\n\t\t(selector) => !foundKeys.has(selectorKey(selector)),\n\t);\n\tif (missingSelectors.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: 'unknown_or_denied_tool',\n\t\tmessage: 'One or more requested tools are unknown or denied for this portal agent scope.',\n\t};\n}\n\nfunction paginate<TItem>(\n\titems: readonly TItem[],\n\tlimit: number,\n\tcursor?: string,\n): { readonly items: readonly TItem[]; readonly nextCursor?: string } {\n\tconst offset = cursor ? Number.parseInt(cursor, 10) : 0;\n\tconst safeOffset = Number.isFinite(offset) && offset > 0 ? offset : 0;\n\tconst page = items.slice(safeOffset, safeOffset + limit);\n\tconst nextOffset = safeOffset + page.length;\n\n\treturn {\n\t\titems: page,\n\t\t...(nextOffset < items.length ? { nextCursor: String(nextOffset) } : {}),\n\t};\n}\n\nfunction describeToolOutput(props: {\n\treadonly includeJsonSchema: boolean;\n\treadonly includeRelated: boolean;\n\treadonly includeTypescriptHelper: boolean;\n\treadonly includeZod: boolean;\n\treadonly session: PortalSession;\n\treadonly tool: PortalToolRecord;\n}): Readonly<Record<string, unknown>> {\n\tconst toolSummary = createToolSummary(props.tool);\n\tconst result: Record<string, unknown> = {\n\t\tannotations: props.tool.annotations ?? {},\n\t\tnamespace: props.tool.namespace,\n\t\trelated: props.includeRelated\n\t\t\t? props.session.graph.relationships.filter(\n\t\t\t\t\t(relationship) =>\n\t\t\t\t\t\trelationship.from.toolRef === toolSummary.toolRef ||\n\t\t\t\t\t\trelationship.to.toolRef === toolSummary.toolRef,\n\t\t\t\t)\n\t\t\t: [],\n\t\tschemaHint: callReadySchemaHint,\n\t\ttoolName: props.tool.toolName,\n\t\ttoolRef: toolSummary.toolRef,\n\t};\n\n\tif (props.includeJsonSchema) {\n\t\tresult.inputSchema = props.tool.inputSchema;\n\t\tresult.outputSchema = props.tool.outputSchema;\n\t}\n\tif (props.includeZod) {\n\t\tresult.zod = { experimental: true, source: 'z.fromJSONSchema(inputSchema)' };\n\t}\n\tif (props.includeTypescriptHelper) {\n\t\tresult.typescriptHelper = generateTypescriptCatalogArtifact({ tools: [props.tool] });\n\t}\n\n\treturn result;\n}\n\nfunction searchOutputWithFullSchema(\n\tsession: PortalSession,\n\tsummary: ToolSearchResult,\n): Readonly<Record<string, unknown>> {\n\tconst tool = findTool(session, summary);\n\tconst result: Record<string, unknown> = {\n\t\tinput: summary.input,\n\t\tnamespace: summary.namespace,\n\t\tsafety: summary.safety,\n\t\tschemaHint: callReadySchemaHint,\n\t\ttoolName: summary.toolName,\n\t\ttoolRef: summary.toolRef,\n\t};\n\n\tif (summary.description !== undefined) {\n\t\tresult.description = summary.description;\n\t}\n\tif (summary.output !== undefined) {\n\t\tresult.output = summary.output;\n\t}\n\tif (summary.relationshipHints !== undefined) {\n\t\tresult.relationshipHints = summary.relationshipHints;\n\t}\n\tif (summary.schemaFieldMatches !== undefined) {\n\t\tresult.schemaFieldMatches = summary.schemaFieldMatches;\n\t}\n\tif (summary.title !== undefined) {\n\t\tresult.title = summary.title;\n\t}\n\n\tif (tool) {\n\t\tresult.inputSchema = tool.inputSchema;\n\t\tresult.outputSchema = tool.outputSchema;\n\t}\n\n\treturn result;\n}\n\nfunction toolSummaryWithSchemaHint(summary: ToolSummary): ToolSummary {\n\treturn Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });\n}\n\nfunction toolSearchResultWithSchemaHint(\n\tsummary: ToolSearchResult,\n): ToolSearchResult & { readonly schemaHint: ToolSchemaHint } {\n\treturn Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });\n}\n\nfunction listRequestResult(session: PortalSession, request: ListRequest): PortalToolResult {\n\tconst filteredTools = applyExactFilters(session.catalog.tools, {\n\t\t...(request.namespaces !== undefined ? { namespaces: request.namespaces } : {}),\n\t\t...(request.refs !== undefined ? { refs: request.refs } : {}),\n\t\t...(request.tools !== undefined ? { tools: request.tools } : {}),\n\t});\n\tif (!filteredTools.ok) {\n\t\treturn itemError({ error: filteredTools.error, input: request });\n\t}\n\tconst page = paginate(\n\t\tfilteredTools.tools.map((tool) => toolSummaryWithSchemaHint(createToolSummary(tool))),\n\t\trequest.limit,\n\t\trequest.cursor,\n\t);\n\tconst output = {\n\t\tnamespaces: [...new Set(filteredTools.tools.map((tool) => tool.namespace))].toSorted(),\n\t\t...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}),\n\t\ttools: page.items,\n\t} satisfies {\n\t\treadonly namespaces: readonly string[];\n\t\treadonly nextCursor?: string;\n\t\treadonly tools: readonly ToolSummary[];\n\t};\n\n\treturn itemOutput({ input: request, output });\n}\n\nfunction searchRequestResult(session: PortalSession, request: SearchRequest): PortalToolResult {\n\tconst result = session.searchIndex.search({\n\t\tlimit: request.limit,\n\t\t...(request.namespaces ? { namespaces: request.namespaces } : {}),\n\t\t...(request.query !== undefined ? { query: request.query } : {}),\n\t});\n\tconst tools =\n\t\trequest.schemaDetail === 'full'\n\t\t\t? result.results.map((summary) => searchOutputWithFullSchema(session, summary))\n\t\t\t: result.results.map((summary) => toolSearchResultWithSchemaHint(summary));\n\n\treturn itemOutput({ input: request, output: { tools } });\n}\n\nfunction describeRequestResult(session: PortalSession, request: DescribeRequest): PortalToolResult {\n\tconst selectorResult = selectorsFromInput(request.tools, request.refs);\n\tif (!selectorResult.ok) {\n\t\treturn itemError({ error: selectorResult.error, input: request });\n\t}\n\tconst selectors = selectorResult.selectors;\n\tconst selectedTools = selectors\n\t\t.map((selector) => findTool(session, selector))\n\t\t.filter((tool): tool is PortalToolRecord => tool !== null);\n\tconst missingError = missingSelectorError(selectors, selectedTools);\n\tif (missingError) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\t...missingError,\n\t\t\t\ttools: selectors.filter((selector) => findTool(session, selector) === null),\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\tconst tools = selectedTools.map((tool) =>\n\t\tdescribeToolOutput({\n\t\t\tincludeJsonSchema: request.includeJsonSchema,\n\t\t\tincludeRelated: request.includeRelated,\n\t\t\tincludeTypescriptHelper: request.includeTypescriptHelper,\n\t\t\tincludeZod: request.includeZod,\n\t\t\tsession,\n\t\t\ttool,\n\t\t}),\n\t);\n\treturn itemOutput({ input: request, output: { tools } });\n}\n\nfunction preparePortalCall(\n\tsession: PortalSession,\n\trequest: CallRequest,\n): PreparedPortalCall | PortalToolResult {\n\tconst tool = findTool(session, request);\n\tif (!tool) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'unknown_or_denied_tool',\n\t\t\t\tmessage: 'The requested tool is unknown or denied for this portal agent scope.',\n\t\t\t\tnamespace: request.namespace,\n\t\t\t\ttoolName: request.toolName,\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\tconst validation = validatePortalToolArguments(tool, request.arguments);\n\tif (!validation.ok) {\n\t\treturn itemError({ error: validation.error, input: request });\n\t}\n\tconst validatedArgumentsResult = jsonObjectSchema.safeParse(validation.value);\n\tif (!validatedArgumentsResult.success) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'invalid_portal_input',\n\t\t\t\tmessage: validatedArgumentsResult.error.message,\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\treturn { input: request, tool, validatedArguments: validatedArgumentsResult.data };\n}\n\nasync function executePreparedPortalCall(\n\tcall: PreparedPortalCall,\n\tidentity: PortalAgentIdentity,\n\truntime: PortalToolRuntime,\n): Promise<PortalToolResult> {\n\tconst input = { ...call.input, arguments: call.validatedArguments };\n\ttry {\n\t\treturn itemOutput({\n\t\t\tinput,\n\t\t\toutput: {\n\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\tresult: await runtime.callUpstreamTool({\n\t\t\t\t\targuments: call.validatedArguments,\n\t\t\t\t\tagentScopeId: portalAgentScopeKey(identity),\n\t\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\t\trequestId: call.input.id,\n\t\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t\t}),\n\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tconst upstream = upstreamMcpFailureDetailsFromUnknown(error);\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'upstream_call_failed',\n\t\t\t\tmessage: messageFromError(error),\n\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t\t...(upstream === null ? {} : { upstream }),\n\t\t\t},\n\t\t\tinput,\n\t\t});\n\t}\n}\n\nfunction isPreparedPortalCall(\n\tvalue: PreparedPortalCall | PortalToolResult,\n): value is PreparedPortalCall {\n\treturn 'validatedArguments' in value;\n}\n\nasync function addExecutableCallResults(props: {\n\treadonly identity: PortalAgentIdentity;\n\treadonly preparedCalls: readonly PreparedPortalCall[];\n\treadonly results: Record<string, PortalToolResult>;\n\treadonly runtime: PortalToolRuntime;\n}): Promise<void> {\n\tawait Promise.all(\n\t\tprops.preparedCalls.map(async (preparedCall): Promise<void> => {\n\t\t\tprops.results[preparedCall.input.id] = await executePreparedPortalCall(\n\t\t\t\tpreparedCall,\n\t\t\t\tprops.identity,\n\t\t\t\tprops.runtime,\n\t\t\t);\n\t\t}),\n\t);\n}\n\nexport function createPortalToolHandlers(runtime: PortalToolRuntime): PortalToolHandlers {\n\treturn {\n\t\tasync call(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = callExecutionInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.calls);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\tconst preparedResults = parsedInput.data.calls.map((request) =>\n\t\t\t\tpreparePortalCall(session, request),\n\t\t\t);\n\t\t\tconst executableCalls = preparedResults.filter(isPreparedPortalCall);\n\t\t\tconst approvalCalls = executableCalls.map(\n\t\t\t\t(executableCall) =>\n\t\t\t\t\t({\n\t\t\t\t\t\targuments: executableCall.validatedArguments,\n\t\t\t\t\t\tid: executableCall.input.id,\n\t\t\t\t\t\tnamespace: executableCall.tool.namespace,\n\t\t\t\t\t\ttool: executableCall.tool,\n\t\t\t\t\t\ttoolName: executableCall.tool.toolName,\n\t\t\t\t\t}) satisfies PortalApprovalCall,\n\t\t\t);\n\t\t\tconst allowDecision = { kind: 'allow' } satisfies PortalApprovalDecision;\n\t\t\tconst approval: PortalApprovalDecision =\n\t\t\t\tapprovalCalls.length === 0\n\t\t\t\t\t? allowDecision\n\t\t\t\t\t: (runtime.approval?.(\n\t\t\t\t\t\t\tapprovalCalls,\n\t\t\t\t\t\t\tcall.identity,\n\t\t\t\t\t\t\tparsedInput.data.portalApprovalToken,\n\t\t\t\t\t\t) ?? { kind: 'approval_configuration_missing' });\n\n\t\t\tconst results: Record<string, PortalToolResult> = {};\n\t\t\tconst callsToExecute: PreparedPortalCall[] = [];\n\t\t\tfor (const preparedResult of preparedResults) {\n\t\t\t\tif (!isPreparedPortalCall(preparedResult)) {\n\t\t\t\t\tconst input = preparedResult.input;\n\t\t\t\t\tif (typeof input === 'object' && input !== null && 'id' in input) {\n\t\t\t\t\t\tconst id = input.id;\n\t\t\t\t\t\tif (typeof id === 'string') {\n\t\t\t\t\t\t\tresults[id] = preparedResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (approval.kind === 'approval_required') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_required',\n\t\t\t\t\t\t\tlevel: approval.level,\n\t\t\t\t\t\t\tmessage: 'Operator approval is required before this batch can run.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_token_missing') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_token_missing',\n\t\t\t\t\t\t\tmessage: 'An MCP Portal approval token is required before this batch can run.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_token_invalid') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_token_invalid',\n\t\t\t\t\t\t\tmessage: `MCP Portal approval token is invalid: ${approval.reason}.`,\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\treason: approval.reason,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'call_blocked') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'call_blocked',\n\t\t\t\t\t\t\tmessage: 'MCP Portal policy does not allow this tool call.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_configuration_missing') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_configuration_missing',\n\t\t\t\t\t\t\tmessage: 'MCP Portal approval evaluation is not configured.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcallsToExecute.push(preparedResult);\n\t\t\t}\n\t\t\tawait addExecutableCallResults({\n\t\t\t\tidentity: call.identity,\n\t\t\t\tpreparedCalls: callsToExecute,\n\t\t\t\tresults,\n\t\t\t\truntime,\n\t\t\t});\n\n\t\t\treturn portalBatchResult(results, discoveryDiagnostics(session));\n\t\t},\n\t\tasync describe(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = describeInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tdescribeRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t\tasync list(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = listInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tlistRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t\tasync search(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = searchInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tsearchRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { P as PortalAgentIdentity, z as createPortalAgentIdentity } from "./portal-session-5ksK1G9Z.js";
2
- import { a as PortalCore, y as PortalApprovalCall } from "./portal-core-Ckq-Mrzb.js";
2
+ import { a as PortalCore, y as PortalApprovalCall } from "./portal-core-CatZlNq_.js";
3
3
  import { McpPortalAgentConfig, McpPortalConfig, ResolvedMcpPortalProfile, SecretValue } from "@agent-vm/config-contracts";
4
4
  import { Hono } from "hono";
5
5
 
@@ -53,7 +53,7 @@ interface PortalApprovalAuditEvent {
53
53
  readonly agentId: string;
54
54
  readonly decision: 'allow' | 'deny';
55
55
  readonly kind: 'mcp_portal_approval';
56
- readonly reason?: 'approval_token_invalid' | 'approval_token_missing' | 'no_approval_required';
56
+ readonly reason?: 'approval_token_invalid' | 'approval_token_missing' | 'call_blocked' | 'no_approval_required';
57
57
  readonly timeMs: number;
58
58
  readonly verifierReason?: string;
59
59
  }
@@ -70,6 +70,8 @@ declare function createPortalApprovalVerifier(props: {
70
70
  readonly records: ReadonlyMap<string, PortalAgentRuntimeRecord>;
71
71
  }): (calls: readonly PortalApprovalCall[], agentId: string, token: string | undefined) => {
72
72
  readonly kind: 'allow';
73
+ } | {
74
+ readonly kind: 'call_blocked';
73
75
  } | {
74
76
  readonly kind: 'approval_token_invalid';
75
77
  readonly reason: string;
@@ -78,4 +80,4 @@ declare function createPortalApprovalVerifier(props: {
78
80
  };
79
81
  //#endregion
80
82
  export { createPortalApprovalVerifier as a, PortalAgentBearerAuth as c, PortalHttpAppOptions as d, PortalHttpAuditEvent as f, createPortalAgentRuntimeRecords as i, PortalHttpAgentIdentity as l, PortalApprovalAuditEvent as n, createPortalHttpAgentResolver as o, createPortalHttpApp as p, ResolveAgentHmacKeysProps as r, resolveAgentHmacKeys as s, PortalAgentRuntimeRecord as t, PortalHttpApp as u };
81
- //# sourceMappingURL=resolve-agent-identity-C9Jc2NhJ.d.ts.map
83
+ //# sourceMappingURL=resolve-agent-identity-C1xp9_2R.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-agent-identity-C9Jc2NhJ.d.ts","names":[],"sources":["../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"mappings":";;;;;;UAWiB,uBAAA,SAAgC,mBAAA;AAAA,UAEhC,qBAAA;EAAA,SACP,uBAAA;EAAA,SACA,yBAAA,GAA4B,QAAA,CAAS,MAAA;EAAA,SACrC,SAAA,EAAW,MAAA;AAAA;AAAA,KAGT,oBAAA;EAAA,SACF,OAAA;EAAA,SACA,aAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SAMA,MAAA;AAAA;AAAA,UAGO,oBAAA;EAAA,SACP,eAAA,EAAiB,qBAAA;EAAA,SACjB,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAChE,SAAA,IAAa,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAC7C,gBAAA;IAAA,SACC,WAAA;IAAA,SACA,QAAA;EAAA;EAAA,SAED,IAAA,EAAM,UAAA;EAAA,SACN,eAAA,IAAmB,QAAA,EAAU,mBAAA,KAAwB,OAAA;EAAA,SACrD,mBAAA,IACR,KAAA,EAAO,KAAA,EACP,QAAA,EAAU,mBAAA,KACN,OAAA;EAAA,SACI,kBAAA;EAAA,SACA,oBAAA,IAAwB,OAAA,aAAoB,uBAAA;AAAA;AAAA,KAG1C,aAAA,GAAgB,IAAA;EAAA,SAClB,mBAAA,QAA2B,OAAA;AAAA;AAAA,iBAiDrB,mBAAA,CAAoB,OAAA,EAAS,oBAAA,GAAuB,aAAA;;;UCrFnD,yBAAA;EAAA,SACP,MAAA,EAAQ,QAAA,CAAS,MAAA,SAAe,oBAAA;EAAA,SAChC,OAAA,EAAS,WAAA,SAAoB,MAAA;EAAA,SAC7B,aAAA,GAAgB,MAAA,EAAQ,WAAA,KAAgB,OAAA;AAAA;AAAA,UAGjC,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,OAAA,EAAS,MAAA;EAAA,SACT,OAAA,EAAS,wBAAA;EAAA,SACT,WAAA;AAAA;AAAA,UAGO,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;EAAA,SACA,cAAA;AAAA;AAAA,iBAuBY,oBAAA,CACrB,KAAA,EAAO,yBAAA,GACL,OAAA,CAAQ,WAAA,SAAoB,MAAA;AAAA,iBAef,+BAAA,CAAgC,KAAA;EAAA,SACtC,QAAA,EAAU,WAAA,SAAoB,MAAA;EAAA,SAC9B,YAAA,EAAc,eAAA;AAAA,IACpB,WAAA,SAAoB,wBAAA;AAAA,iBAiBR,6BAAA,CACf,OAAA,EAAS,WAAA,SAAoB,wBAAA,KAC1B,OAAA,aAAoB,UAAA,QAAkB,yBAAA;AAAA,iBAsC1B,4BAAA,CAA6B,KAAA;EAAA,SACnC,6BAAA;EAAA,SACA,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,wBAAA;EAAA,SACvC,SAAA,IAAa,KAAA,EAAO,wBAAA;EAAA,SACpB,OAAA,EAAS,WAAA,SAAoB,wBAAA;AAAA,KAEtC,KAAA,WAAgB,kBAAA,IAChB,OAAA,UACA,KAAA;EAAA,SAEa,IAAA;AAAA;EAAA,SACA,IAAA;EAAA,SAAyC,MAAA;AAAA;EAAA,SACzC,IAAA;AAAA"}
1
+ {"version":3,"file":"resolve-agent-identity-C1xp9_2R.d.ts","names":[],"sources":["../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"mappings":";;;;;;UAWiB,uBAAA,SAAgC,mBAAA;AAAA,UAEhC,qBAAA;EAAA,SACP,uBAAA;EAAA,SACA,yBAAA,GAA4B,QAAA,CAAS,MAAA;EAAA,SACrC,SAAA,EAAW,MAAA;AAAA;AAAA,KAGT,oBAAA;EAAA,SACF,OAAA;EAAA,SACA,aAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SAMA,MAAA;AAAA;AAAA,UAGO,oBAAA;EAAA,SACP,eAAA,EAAiB,qBAAA;EAAA,SACjB,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAChE,SAAA,IAAa,KAAA,EAAO,oBAAA,KAAyB,OAAA;EAAA,SAC7C,gBAAA;IAAA,SACC,WAAA;IAAA,SACA,QAAA;EAAA;EAAA,SAED,IAAA,EAAM,UAAA;EAAA,SACN,eAAA,IAAmB,QAAA,EAAU,mBAAA,KAAwB,OAAA;EAAA,SACrD,mBAAA,IACR,KAAA,EAAO,KAAA,EACP,QAAA,EAAU,mBAAA,KACN,OAAA;EAAA,SACI,kBAAA;EAAA,SACA,oBAAA,IAAwB,OAAA,aAAoB,uBAAA;AAAA;AAAA,KAG1C,aAAA,GAAgB,IAAA;EAAA,SAClB,mBAAA,QAA2B,OAAA;AAAA;AAAA,iBAiDrB,mBAAA,CAAoB,OAAA,EAAS,oBAAA,GAAuB,aAAA;;;UCrFnD,yBAAA;EAAA,SACP,MAAA,EAAQ,QAAA,CAAS,MAAA,SAAe,oBAAA;EAAA,SAChC,OAAA,EAAS,WAAA,SAAoB,MAAA;EAAA,SAC7B,aAAA,GAAgB,MAAA,EAAQ,WAAA,KAAgB,OAAA;AAAA;AAAA,UAGjC,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,OAAA,EAAS,MAAA;EAAA,SACT,OAAA,EAAS,wBAAA;EAAA,SACT,WAAA;AAAA;AAAA,UAGO,wBAAA;EAAA,SACP,OAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;EAAA,SAKA,MAAA;EAAA,SACA,cAAA;AAAA;AAAA,iBAuBY,oBAAA,CACrB,KAAA,EAAO,yBAAA,GACL,OAAA,CAAQ,WAAA,SAAoB,MAAA;AAAA,iBAef,+BAAA,CAAgC,KAAA;EAAA,SACtC,QAAA,EAAU,WAAA,SAAoB,MAAA;EAAA,SAC9B,YAAA,EAAc,eAAA;AAAA,IACpB,WAAA,SAAoB,wBAAA;AAAA,iBAiBR,6BAAA,CACf,OAAA,EAAS,WAAA,SAAoB,wBAAA,KAC1B,OAAA,aAAoB,UAAA,QAAkB,yBAAA;AAAA,iBAsC1B,4BAAA,CAA6B,KAAA;EAAA,SACnC,6BAAA;EAAA,SACA,cAAA,IAAkB,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,wBAAA;EAAA,SACvC,SAAA,IAAa,KAAA,EAAO,wBAAA;EAAA,SACpB,OAAA,EAAS,WAAA,SAAoB,wBAAA;AAAA,KAEtC,KAAA,WAAgB,kBAAA,IAChB,OAAA,UACA,KAAA;EAAA,SAEa,IAAA;AAAA;EAAA,SACA,IAAA;AAAA;EAAA,SACA,IAAA;EAAA,SAAyC,MAAA;AAAA;EAAA,SACzC,IAAA;AAAA"}
@@ -1,10 +1,10 @@
1
1
  import { _ as createPortalAgentIdentity, i as redactThrownError } from "./upstream-response-middleware-Cd1MxA6A.js";
2
- import { n as portalToolInputSchemas } from "./portal-tools-DA7j2pyv.js";
2
+ import { n as portalToolInputSchemas } from "./portal-tools-Ct2GuFSc.js";
3
3
  import { i as verifyAgentBearerAuthorization } from "./agent-bearer-token-DCtpDPCZ.js";
4
4
  import { r as verifyApprovalToken, t as hashCallArguments } from "./hmac-token-DBqWY3-w.js";
5
5
  import { randomUUID } from "node:crypto";
6
6
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
7
- import { mcpPortalCallRequiresApproval, resolveMcpPortalProfile } from "@agent-vm/config-contracts";
7
+ import { mcpPortalCallPolicyDecision, resolveMcpPortalProfile } from "@agent-vm/config-contracts";
8
8
  import { StreamableHTTPTransport } from "@hono/mcp";
9
9
  import { getConnInfo } from "@hono/node-server/conninfo";
10
10
  import { Hono } from "hono";
@@ -440,9 +440,9 @@ function createPortalHttpAgentResolver(records) {
440
440
  });
441
441
  };
442
442
  }
443
- function approvalRequiredByProfile(profile, call) {
443
+ function callDecisionByProfile(profile, call) {
444
444
  const annotations = call.tool.annotations;
445
- return mcpPortalCallRequiresApproval(profile, {
445
+ return mcpPortalCallPolicyDecision(profile, {
446
446
  ...annotations === void 0 ? {} : { annotations },
447
447
  namespace: call.namespace,
448
448
  toolName: call.toolName
@@ -499,7 +499,16 @@ function createPortalApprovalVerifier(props) {
499
499
  reason: "unknown-agent"
500
500
  };
501
501
  }
502
- const callsRequiringApproval = calls.filter((call) => approvalRequiredByProfile(record.profile, call));
502
+ const callDecisions = calls.map((call) => callDecisionByProfile(record.profile, call));
503
+ if (callDecisions.some((decision) => decision.kind === "blocked")) {
504
+ auditApproval({
505
+ agentId,
506
+ decision: "deny",
507
+ reason: "call_blocked"
508
+ });
509
+ return { kind: "call_blocked" };
510
+ }
511
+ const callsRequiringApproval = calls.filter((_call, index) => callDecisions[index]?.kind === "requires_approval");
503
512
  if (callsRequiringApproval.length === 0) {
504
513
  auditApproval({
505
514
  agentId,
@@ -547,4 +556,4 @@ function createPortalApprovalVerifier(props) {
547
556
  //#endregion
548
557
  export { createPortalHttpApp as a, listPortalMcpTools as c, resolveAgentHmacKeys as i, portalMcpToolNames as l, createPortalApprovalVerifier as n, createPortalMcpServer as o, createPortalHttpAgentResolver as r, emitMcpProgress as s, createPortalAgentRuntimeRecords as t };
549
558
 
550
- //# sourceMappingURL=resolve-agent-identity-ZMMY2Wqm.js.map
559
+ //# sourceMappingURL=resolve-agent-identity-Dnqv2hAW.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-agent-identity-ZMMY2Wqm.js","names":[],"sources":["../src/mcp-proxy/portal-mcp-server.ts","../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n\tCallToolRequestSchema,\n\tListToolsRequestSchema,\n\ttype CallToolResult,\n\ttype Tool,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport type {\n\tPortalAgentScope,\n\tPortalCore,\n\tPortalCoreEvent,\n\tPortalCoreToolDescriptor,\n\tPortalCoreResult,\n\tPortalCoreToolName,\n} from '../core/portal-core.js';\nimport { portalToolInputSchemas } from '../core/portal-tools.js';\nimport { redactThrownError } from '../upstream-response-middleware.js';\n\nexport const portalMcpToolNames = [\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n] as const;\n\nexport type PortalMcpToolName = (typeof portalMcpToolNames)[number];\n\nconst portalMcpToolNameSet = new Set<string>(portalMcpToolNames);\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalMcpToolNameSet.has(value);\n}\n\nexport function listPortalMcpTools(\n\tdescriptors?: readonly PortalCoreToolDescriptor[],\n): readonly Tool[] {\n\treturn (\n\t\tdescriptors ?? [\n\t\t\t{\n\t\t\t\tdescription: 'List authorized MCP namespaces and compact tool summaries.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_list,\n\t\t\t\tname: 'mcp_portal_list',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\t\tname: 'mcp_portal_search',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\t\tname: 'mcp_portal_describe',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\t\tname: 'mcp_portal_call',\n\t\t\t},\n\t\t]\n\t);\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction coreResultIsError(value: PortalCoreResult): boolean {\n\tif (value.items.some((item) => item.status === 'failed')) {\n\t\treturn true;\n\t}\n\tif (!isObjectRecord(value.structuredContent)) {\n\t\treturn false;\n\t}\n\treturn value.structuredContent.ok === false;\n}\n\nfunction jsonToolResult(value: PortalCoreResult): CallToolResult {\n\treturn {\n\t\tcontent: [{ text: JSON.stringify(value), type: 'text' }],\n\t\t...(coreResultIsError(value) ? { isError: true } : {}),\n\t};\n}\n\nfunction errorToolResult(error: unknown): CallToolResult {\n\tconst redactedError = redactThrownError(error);\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttext: redactedError.message,\n\t\t\t\ttype: 'text',\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\nasync function sendBestEffortNotification(\n\tnotification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t},\n\tsendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tawait sendNotification(notification);\n\t} catch {\n\t\t// Progress is advisory; unsupported client notification channels must not fail the tool call.\n\t}\n}\n\nexport async function emitMcpProgress(props: {\n\treadonly event: PortalCoreEvent;\n\treadonly sendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>;\n\treadonly progressToken: number | string | undefined;\n}): Promise<void> {\n\tif (props.event.kind === 'upstream_notification') {\n\t\tif (!isObjectRecord(props.event.params)) {\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method === 'notifications/progress') {\n\t\t\tif (props.progressToken === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait sendBestEffortNotification(\n\t\t\t\t{\n\t\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\t\tparams: { ...props.event.params, progressToken: props.progressToken },\n\t\t\t\t},\n\t\t\t\tprops.sendNotification,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method !== 'notifications/message') {\n\t\t\treturn;\n\t\t}\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/message',\n\t\t\t\tparams: props.event.params,\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tif (props.event.kind !== 'progress' && props.event.kind !== 'partial_content') {\n\t\treturn;\n\t}\n\tconst message =\n\t\tprops.event.kind === 'progress'\n\t\t\t? props.event.message\n\t\t\t: props.event.content.type === 'text'\n\t\t\t\t? props.event.content.text\n\t\t\t\t: JSON.stringify(props.event.content.value);\n\tif (message === undefined || message.length === 0) {\n\t\treturn;\n\t}\n\tif (props.progressToken !== undefined) {\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\tparams: {\n\t\t\t\t\tmessage,\n\t\t\t\t\tprogress: props.event.kind === 'progress' ? (props.event.progress ?? 0) : 0,\n\t\t\t\t\tprogressToken: props.progressToken,\n\t\t\t\t\t...(props.event.kind === 'progress' && props.event.total !== undefined\n\t\t\t\t\t\t? { total: props.event.total }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tawait sendBestEffortNotification(\n\t\t{\n\t\t\tmethod: 'notifications/message',\n\t\t\tparams: {\n\t\t\t\tdata: message,\n\t\t\t\tlevel: 'info',\n\t\t\t},\n\t\t},\n\t\tprops.sendNotification,\n\t);\n}\n\nexport function createPortalMcpServer(props: {\n\treadonly core: PortalCore;\n\treadonly scope: PortalAgentScope;\n}): Server {\n\tconst server = new Server(\n\t\t{ name: 'mcp-portal', version: '1.0.0' },\n\t\t{ capabilities: { tools: { listChanged: false } } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: listPortalMcpTools(props.core.describeTools(props.scope)),\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n\t\tif (!isPortalCoreToolName(request.params.name)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ text: `Unknown MCP Portal tool: ${request.params.name}`, type: 'text' }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst result = await props.core.collectPortalCoreResult(\n\t\t\t\tprops.core.callStream({\n\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\tscope: props.scope,\n\t\t\t\t\tsignal: extra.signal,\n\t\t\t\t\ttoolName: request.params.name,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tonEvent: async (event) => {\n\t\t\t\t\t\tawait emitMcpProgress({\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\tprogressToken: extra['_meta']?.progressToken,\n\t\t\t\t\t\t\tsendNotification: extra.sendNotification,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn jsonToolResult(result);\n\t\t} catch (error) {\n\t\t\treturn errorToolResult(error);\n\t\t}\n\t});\n\n\treturn server;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport { StreamableHTTPTransport } from '@hono/mcp';\nimport { getConnInfo } from '@hono/node-server/conninfo';\nimport { Hono, type Context } from 'hono';\n\nimport type { PortalCore } from '../core/portal-core.js';\nimport { createPortalAgentIdentity, type PortalAgentIdentity } from '../portal-access-policy.js';\nimport { verifyAgentBearerAuthorization } from '../portal-auth/agent-bearer-token.js';\nimport { createPortalMcpServer } from './portal-mcp-server.js';\n\nexport interface PortalHttpAgentIdentity extends PortalAgentIdentity {}\n\nexport interface PortalAgentBearerAuth {\n\treadonly authorizationHeaderName: string;\n\treadonly credentialVersionsByAgent?: Readonly<Record<string, number>>;\n\treadonly masterKey: Buffer;\n}\n\nexport type PortalHttpAuditEvent = {\n\treadonly agentId: string;\n\treadonly clientAddress: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_proxy_auth';\n\treadonly reason?:\n\t\t| 'malformed'\n\t\t| 'missing'\n\t\t| 'rate_limited'\n\t\t| 'signature-mismatch'\n\t\t| 'unknown_agent';\n\treadonly timeMs: number;\n};\n\nexport interface PortalHttpAppOptions {\n\treadonly agentBearerAuth: PortalAgentBearerAuth;\n\treadonly auditErrorSink?: (error: Error, event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly auditSink?: (event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly authFailureLimit?: {\n\t\treadonly maxFailures: number;\n\t\treadonly windowMs: number;\n\t};\n\treadonly core: PortalCore;\n\treadonly onSessionClosed?: (identity: PortalAgentIdentity) => Promise<void> | void;\n\treadonly onSessionCloseError?: (\n\t\terror: Error,\n\t\tidentity: PortalAgentIdentity,\n\t) => Promise<void> | void;\n\treadonly registeredAgentIds?: readonly string[];\n\treadonly resolveAgentIdentity?: (agentId: string) => PortalHttpAgentIdentity | null;\n}\n\nexport type PortalHttpApp = Hono & {\n\treadonly closePortalSessions: () => Promise<void>;\n};\n\nconst mcpSessionIdHeader = 'mcp-session-id';\nconst defaultAuthFailureLimit = { maxFailures: 60, windowMs: 60_000 } as const;\nconst authFailureBucketLimit = 1_024;\nconst directClientAddress = 'direct-client';\nconst unknownAgentCredentialVersionForOpaqueAuthTiming = 1;\n\ninterface ActivePortalMcpSession {\n\treadonly identity: PortalAgentIdentity;\n\treadonly server: ReturnType<typeof createPortalMcpServer>;\n\treadonly transport: StreamableHTTPTransport;\n}\n\ninterface AuthFailureBucket {\n\treadonly resetAtMs: number;\n\tfailures: number;\n}\n\nfunction activeSessionKey(scopeId: string, sessionId: string): string {\n\treturn `${scopeId}\\n${sessionId}`;\n}\n\nfunction unauthorizedResponse(): Response {\n\treturn Response.json({ error: { kind: 'unauthorized' }, ok: false }, { status: 401 });\n}\n\nfunction rateLimitedResponse(): Response {\n\treturn Response.json({ error: { kind: 'rate_limited' }, ok: false }, { status: 429 });\n}\n\nfunction unavailableResponse(): Response {\n\treturn Response.json({ error: { kind: 'shutting_down' }, ok: false }, { status: 503 });\n}\n\nfunction errorFromUnknown(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction clientAddressFromContext(context: Context): string {\n\ttry {\n\t\tconst address = getConnInfo(context).remote.address;\n\t\treturn address && address.length > 0 ? address : directClientAddress;\n\t} catch {\n\t\treturn directClientAddress;\n\t}\n}\n\nexport function createPortalHttpApp(options: PortalHttpAppOptions): PortalHttpApp {\n\tif (options.agentBearerAuth === undefined) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth.');\n\t}\n\tif (options.agentBearerAuth.authorizationHeaderName.length === 0) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth header name.');\n\t}\n\tconst app = new Hono();\n\tconst activeSessions = new Map<string, ActivePortalMcpSession>();\n\tconst authFailureBuckets = new Map<string, AuthFailureBucket>();\n\tconst pendingNewSessionRequests = new Set<Promise<void>>();\n\tconst authFailureLimit = options.authFailureLimit ?? defaultAuthFailureLimit;\n\tlet closing = false;\n\n\tasync function auditAuth(event: Omit<PortalHttpAuditEvent, 'kind' | 'timeMs'>): Promise<void> {\n\t\tconst auditEvent = { ...event, kind: 'mcp_proxy_auth', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tawait options.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tawait options.auditErrorSink?.(errorFromUnknown(error), auditEvent);\n\t\t}\n\t}\n\n\tasync function reportSessionCloseError(\n\t\terror: unknown,\n\t\tidentity: PortalAgentIdentity,\n\t): Promise<void> {\n\t\tawait options.onSessionCloseError?.(errorFromUnknown(error), identity);\n\t}\n\n\tfunction pruneAuthFailureBuckets(nowMs: number): void {\n\t\tfor (const [key, bucket] of authFailureBuckets) {\n\t\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\t\tauthFailureBuckets.delete(key);\n\t\t\t}\n\t\t}\n\t\twhile (authFailureBuckets.size > authFailureBucketLimit) {\n\t\t\tconst firstKey = authFailureBuckets.keys().next().value;\n\t\t\tif (typeof firstKey !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthFailureBuckets.delete(firstKey);\n\t\t}\n\t}\n\n\tfunction isAuthFailureRateLimited(clientAddress: string): boolean {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket === undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\tauthFailureBuckets.delete(clientAddress);\n\t\t\treturn false;\n\t\t}\n\t\treturn bucket.failures >= authFailureLimit.maxFailures;\n\t}\n\n\tfunction recordAuthFailure(clientAddress: string): void {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket !== undefined && bucket.resetAtMs > nowMs) {\n\t\t\tbucket.failures += 1;\n\t\t\treturn;\n\t\t}\n\t\tauthFailureBuckets.set(clientAddress, {\n\t\t\tfailures: 1,\n\t\t\tresetAtMs: nowMs + authFailureLimit.windowMs,\n\t\t});\n\t\tpruneAuthFailureBuckets(nowMs);\n\t}\n\n\tfunction clearAuthFailures(clientAddress: string): void {\n\t\tauthFailureBuckets.delete(clientAddress);\n\t}\n\n\tasync function closeActiveSession(\n\t\tsessionKey: string,\n\t\tcloseOptions: { readonly closeTransport: boolean },\n\t): Promise<void> {\n\t\tconst activeSession = activeSessions.get(sessionKey);\n\t\tif (!activeSession) {\n\t\t\treturn;\n\t\t}\n\t\tactiveSessions.delete(sessionKey);\n\t\ttry {\n\t\t\tif (closeOptions.closeTransport) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t}\n\t\t} finally {\n\t\t\tawait options.onSessionClosed?.(activeSession.identity);\n\t\t}\n\t}\n\n\tfunction trackPendingNewSessionRequest(): () => void {\n\t\tlet resolvePending: (() => void) | undefined;\n\t\tconst pendingRequest = new Promise<void>((resolve) => {\n\t\t\tresolvePending = resolve;\n\t\t});\n\t\tpendingNewSessionRequests.add(pendingRequest);\n\t\treturn () => {\n\t\t\tpendingNewSessionRequests.delete(pendingRequest);\n\t\t\tresolvePending?.();\n\t\t};\n\t}\n\n\tasync function createActiveSession(\n\t\tidentityBase: PortalAgentIdentity,\n\t): Promise<ActivePortalMcpSession> {\n\t\tconst sessionId = randomUUID();\n\t\tconst sessionKey = activeSessionKey(identityBase.agentScopeId, sessionId);\n\t\tlet server: ReturnType<typeof createPortalMcpServer> | null = null;\n\t\tconst identity = createPortalAgentIdentity({\n\t\t\tagentId: identityBase.agentId,\n\t\t\tagentScopeId: identityBase.agentScopeId,\n\t\t\tsessionId,\n\t\t\tsource: identityBase.source,\n\t\t});\n\t\tconst transport = new StreamableHTTPTransport({\n\t\t\tonsessionclosed: () => {\n\t\t\t\tvoid closeActiveSession(sessionKey, { closeTransport: false }).catch((error: unknown) =>\n\t\t\t\t\treportSessionCloseError(error, identity),\n\t\t\t\t);\n\t\t\t},\n\t\t\tonsessioninitialized: (initializedSessionId) => {\n\t\t\t\tif (!server) {\n\t\t\t\t\tthrow new Error('MCP Portal session initialized before server connection.');\n\t\t\t\t}\n\t\t\t\tactiveSessions.set(activeSessionKey(identityBase.agentScopeId, initializedSessionId), {\n\t\t\t\t\tidentity,\n\t\t\t\t\tserver,\n\t\t\t\t\ttransport,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsessionIdGenerator: () => sessionId,\n\t\t});\n\t\tserver = createPortalMcpServer({\n\t\t\tcore: options.core,\n\t\t\tscope: identity,\n\t\t});\n\t\tawait server.connect(transport);\n\t\treturn { identity, server, transport };\n\t}\n\n\tasync function closePortalSessions(): Promise<void> {\n\t\tclosing = true;\n\t\tconst closeErrors: Error[] = [];\n\t\twhile (activeSessions.size > 0 || pendingNewSessionRequests.size > 0) {\n\t\t\tif (pendingNewSessionRequests.size > 0) {\n\t\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\t\tawait Promise.allSettled(pendingNewSessionRequests);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Closing may trigger callbacks that mutate activeSessions, so drain snapshots until empty.\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst closeResults = await Promise.allSettled(\n\t\t\t\t[...activeSessions.keys()].map((sessionKey) =>\n\t\t\t\t\tcloseActiveSession(sessionKey, { closeTransport: true }),\n\t\t\t\t),\n\t\t\t);\n\t\t\tcloseErrors.push(\n\t\t\t\t...closeResults\n\t\t\t\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t\t\t\t.map((result): Error => errorFromUnknown(result.reason)),\n\t\t\t);\n\t\t}\n\t\tif (closeErrors.length > 0) {\n\t\t\tthrow new AggregateError(closeErrors, 'Failed to close one or more MCP Portal sessions.');\n\t\t}\n\t}\n\n\tapp.get('/health', (context) =>\n\t\tcontext.json({ agents: [...(options.registeredAgentIds ?? [])].toSorted(), ok: true }),\n\t);\n\n\tapp.all('/agents/:agentId/mcp', async (context) => {\n\t\tconst agentId = context.req.param('agentId');\n\t\tconst clientAddress = clientAddressFromContext(context);\n\t\tif (closing) {\n\t\t\treturn unavailableResponse();\n\t\t}\n\t\tif (isAuthFailureRateLimited(clientAddress)) {\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'rate_limited',\n\t\t\t});\n\t\t\treturn rateLimitedResponse();\n\t\t}\n\t\tconst agentBearerAuth = options.agentBearerAuth;\n\t\tconst credentialVersion = agentBearerAuth.credentialVersionsByAgent?.[agentId];\n\t\tconst verification = verifyAgentBearerAuthorization({\n\t\t\tagentId,\n\t\t\tauthorizationHeader: context.req.header(agentBearerAuth.authorizationHeaderName),\n\t\t\tcredentialVersion: credentialVersion ?? unknownAgentCredentialVersionForOpaqueAuthTiming,\n\t\t\tmasterKey: agentBearerAuth.masterKey,\n\t\t});\n\t\tconst agentIdentity = options.resolveAgentIdentity?.(agentId) ?? null;\n\t\tif (agentIdentity === null) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'unknown_agent',\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tif (!verification.ok) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: verification.reason,\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tclearAuthFailures(clientAddress);\n\t\tawait auditAuth({ agentId, clientAddress, decision: 'allow' });\n\n\t\tconst mcpSessionId = context.req.header(mcpSessionIdHeader);\n\t\tif (mcpSessionId) {\n\t\t\tconst activeSession = activeSessions.get(\n\t\t\t\tactiveSessionKey(agentIdentity.agentScopeId, mcpSessionId),\n\t\t\t);\n\t\t\tif (!activeSession) {\n\t\t\t\treturn new Response('Unknown MCP portal session', { status: 404 });\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t}\n\n\t\tconst finishPendingRequest = trackPendingNewSessionRequest();\n\t\ttry {\n\t\t\tif (closing) {\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\tconst activeSession = await createActiveSession(agentIdentity);\n\t\t\tif (closing) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t} finally {\n\t\t\tfinishPendingRequest();\n\t\t}\n\t});\n\n\treturn Object.assign(app, { closePortalSessions });\n}\n","import {\n\tresolveMcpPortalProfile,\n\tmcpPortalCallRequiresApproval,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport type { PortalApprovalCall } from '../core/portal-tools.js';\nimport { createPortalAgentIdentity } from '../portal-access-policy.js';\nimport { hashCallArguments, verifyApprovalToken } from '../portal-auth/hmac-token.js';\n\nconst approvalTokenMaxLifetimeMs = 5 * 60_000;\nconst approvalTokenReplayCacheLimit = 4_096;\n\nexport interface ResolveAgentHmacKeysProps {\n\treadonly agents: Readonly<Record<string, McpPortalAgentConfig>>;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nexport interface PortalAgentRuntimeRecord {\n\treadonly agentId: string;\n\treadonly hmacKey: Buffer;\n\treadonly profile: ResolvedMcpPortalProfile;\n\treadonly profileName: string;\n}\n\nexport interface PortalApprovalAuditEvent {\n\treadonly agentId: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_portal_approval';\n\treadonly reason?: 'approval_token_invalid' | 'approval_token_missing' | 'no_approval_required';\n\treadonly timeMs: number;\n\treadonly verifierReason?: string;\n}\n\nasync function resolveAgentHmacKeyEntry(props: {\n\treadonly agent: McpPortalAgentConfig;\n\treadonly agentId: string;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<readonly [string, Buffer]> {\n\tconst envKey = props.envKeys.get(props.agentId);\n\tif (envKey !== undefined) {\n\t\treturn [props.agentId, envKey];\n\t}\n\tif (props.agent.hmacKey === undefined) {\n\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${props.agentId}\".`);\n\t}\n\tconst secretValue = await props.resolveSecret(props.agent.hmacKey);\n\tif (!/^[0-9a-f]+$/u.test(secretValue) || secretValue.length !== 64) {\n\t\tthrow new Error(`MCP Portal agent \"${props.agentId}\" HMAC key must be 64 hex characters.`);\n\t}\n\treturn [props.agentId, Buffer.from(secretValue, 'hex')];\n}\n\nexport async function resolveAgentHmacKeys(\n\tprops: ResolveAgentHmacKeysProps,\n): Promise<ReadonlyMap<string, Buffer>> {\n\treturn new Map(\n\t\tawait Promise.all(\n\t\t\tObject.entries(props.agents).map(([agentId, agent]) =>\n\t\t\t\tresolveAgentHmacKeyEntry({\n\t\t\t\t\tagent,\n\t\t\t\t\tagentId,\n\t\t\t\t\tenvKeys: props.envKeys,\n\t\t\t\t\tresolveSecret: props.resolveSecret,\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t);\n}\n\nexport function createPortalAgentRuntimeRecords(props: {\n\treadonly hmacKeys: ReadonlyMap<string, Buffer>;\n\treadonly portalConfig: McpPortalConfig;\n}): ReadonlyMap<string, PortalAgentRuntimeRecord> {\n\tconst records = new Map<string, PortalAgentRuntimeRecord>();\n\tfor (const [agentId, agent] of Object.entries(props.portalConfig.agents)) {\n\t\tconst hmacKey = props.hmacKeys.get(agentId);\n\t\tif (hmacKey === undefined) {\n\t\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\trecords.set(agentId, {\n\t\t\tagentId,\n\t\t\thmacKey,\n\t\t\tprofile: resolveMcpPortalProfile(props.portalConfig, agent.profile),\n\t\t\tprofileName: agent.profile,\n\t\t});\n\t}\n\treturn records;\n}\n\nexport function createPortalHttpAgentResolver(\n\trecords: ReadonlyMap<string, PortalAgentRuntimeRecord>,\n): (agentId: string) => ReturnType<typeof createPortalAgentIdentity> | null {\n\treturn (agentId) => {\n\t\tconst record = records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn createPortalAgentIdentity({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'mcp-proxy-bearer',\n\t\t});\n\t};\n}\n\nfunction approvalRequiredByProfile(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: PortalApprovalCall,\n): boolean {\n\tconst annotations = call.tool.annotations;\n\treturn mcpPortalCallRequiresApproval(profile, {\n\t\t...(annotations === undefined ? {} : { annotations }),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t});\n}\n\nfunction approvalTokenCallDigests(calls: readonly PortalApprovalCall[]): readonly {\n\treadonly argumentsHash: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}[] {\n\treturn calls.map((call) => ({\n\t\targumentsHash: hashCallArguments(call.arguments),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t}));\n}\n\nexport function createPortalApprovalVerifier(props: {\n\treadonly approvalTokenReplayCacheLimit?: number;\n\treadonly auditErrorSink?: (error: Error, event: PortalApprovalAuditEvent) => void;\n\treadonly auditSink?: (event: PortalApprovalAuditEvent) => void;\n\treadonly records: ReadonlyMap<string, PortalAgentRuntimeRecord>;\n}): (\n\tcalls: readonly PortalApprovalCall[],\n\tagentId: string,\n\ttoken: string | undefined,\n) =>\n\t| { readonly kind: 'allow' }\n\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t| { readonly kind: 'approval_token_missing' } {\n\tfunction auditApproval(event: Omit<PortalApprovalAuditEvent, 'kind' | 'timeMs'>): void {\n\t\tconst auditEvent = { ...event, kind: 'mcp_portal_approval', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tprops.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tprops.auditErrorSink?.(error instanceof Error ? error : new Error(String(error)), auditEvent);\n\t\t}\n\t}\n\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = props.approvalTokenReplayCacheLimit ?? approvalTokenReplayCacheLimit;\n\tconst consumeTokenId = (\n\t\tagentId: string,\n\t\tjti: string,\n\t\texpiresAtMs: number,\n\t):\n\t\t| { readonly ok: true }\n\t\t| { readonly ok: false; readonly reason: 'replay-cache-full' | 'replayed' } => {\n\t\tconst nowMs = Date.now();\n\t\tfor (const [tokenKey, tokenExpiresAtMs] of consumedApprovalTokenIds) {\n\t\t\tif (tokenExpiresAtMs <= nowMs) {\n\t\t\t\tconsumedApprovalTokenIds.delete(tokenKey);\n\t\t\t}\n\t\t}\n\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t}\n\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t}\n\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\treturn { ok: true };\n\t};\n\treturn (calls, agentId, token) => {\n\t\tconst record = props.records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\tauditApproval({\n\t\t\t\tagentId,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'approval_token_invalid',\n\t\t\t\tverifierReason: 'unknown-agent',\n\t\t\t});\n\t\t\treturn { kind: 'approval_token_invalid', reason: 'unknown-agent' };\n\t\t}\n\t\tconst callsRequiringApproval = calls.filter((call) =>\n\t\t\tapprovalRequiredByProfile(record.profile, call),\n\t\t);\n\t\tif (callsRequiringApproval.length === 0) {\n\t\t\tauditApproval({ agentId, decision: 'allow', reason: 'no_approval_required' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tif (token === undefined) {\n\t\t\tauditApproval({ agentId, decision: 'deny', reason: 'approval_token_missing' });\n\t\t\treturn { kind: 'approval_token_missing' };\n\t\t}\n\t\tconst verificationProps = {\n\t\t\tagentId,\n\t\t\tcalls: approvalTokenCallDigests(callsRequiringApproval),\n\t\t\tconsumeTokenId: (jti: string, expiresAtMs: number) =>\n\t\t\t\tconsumeTokenId(agentId, jti, expiresAtMs),\n\t\t\tkey: record.hmacKey,\n\t\t\tmaxLifetimeMs: approvalTokenMaxLifetimeMs,\n\t\t\tnowMs: Date.now(),\n\t\t\ttoken,\n\t\t};\n\t\tconst verification = verifyApprovalToken(verificationProps);\n\t\tif (verification.ok) {\n\t\t\tauditApproval({ agentId, decision: 'allow' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tauditApproval({\n\t\t\tagentId,\n\t\t\tdecision: 'deny',\n\t\t\treason: 'approval_token_invalid',\n\t\t\tverifierReason: verification.reason,\n\t\t});\n\t\treturn { kind: 'approval_token_invalid', reason: verification.reason };\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resolve-agent-identity-Dnqv2hAW.js","names":[],"sources":["../src/mcp-proxy/portal-mcp-server.ts","../src/mcp-proxy/portal-http-server.ts","../src/mcp-proxy/resolve-agent-identity.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n\tCallToolRequestSchema,\n\tListToolsRequestSchema,\n\ttype CallToolResult,\n\ttype Tool,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport type {\n\tPortalAgentScope,\n\tPortalCore,\n\tPortalCoreEvent,\n\tPortalCoreToolDescriptor,\n\tPortalCoreResult,\n\tPortalCoreToolName,\n} from '../core/portal-core.js';\nimport { portalToolInputSchemas } from '../core/portal-tools.js';\nimport { redactThrownError } from '../upstream-response-middleware.js';\n\nexport const portalMcpToolNames = [\n\t'mcp_portal_list',\n\t'mcp_portal_search',\n\t'mcp_portal_describe',\n\t'mcp_portal_call',\n] as const;\n\nexport type PortalMcpToolName = (typeof portalMcpToolNames)[number];\n\nconst portalMcpToolNameSet = new Set<string>(portalMcpToolNames);\n\nfunction isPortalCoreToolName(value: string): value is PortalCoreToolName {\n\treturn portalMcpToolNameSet.has(value);\n}\n\nexport function listPortalMcpTools(\n\tdescriptors?: readonly PortalCoreToolDescriptor[],\n): readonly Tool[] {\n\treturn (\n\t\tdescriptors ?? [\n\t\t\t{\n\t\t\t\tdescription: 'List authorized MCP namespaces and compact tool summaries.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_list,\n\t\t\t\tname: 'mcp_portal_list',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Search the caller scoped MCP Portal index.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_search,\n\t\t\t\tname: 'mcp_portal_search',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Describe exact MCP tool schemas and optional TypeScript/Zod helpers.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_describe,\n\t\t\t\tname: 'mcp_portal_describe',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription: 'Validate and call an authorized upstream MCP tool by namespace and toolName.',\n\t\t\t\tinputSchema: portalToolInputSchemas.mcp_portal_call,\n\t\t\t\tname: 'mcp_portal_call',\n\t\t\t},\n\t\t]\n\t);\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction coreResultIsError(value: PortalCoreResult): boolean {\n\tif (value.items.some((item) => item.status === 'failed')) {\n\t\treturn true;\n\t}\n\tif (!isObjectRecord(value.structuredContent)) {\n\t\treturn false;\n\t}\n\treturn value.structuredContent.ok === false;\n}\n\nfunction jsonToolResult(value: PortalCoreResult): CallToolResult {\n\treturn {\n\t\tcontent: [{ text: JSON.stringify(value), type: 'text' }],\n\t\t...(coreResultIsError(value) ? { isError: true } : {}),\n\t};\n}\n\nfunction errorToolResult(error: unknown): CallToolResult {\n\tconst redactedError = redactThrownError(error);\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttext: redactedError.message,\n\t\t\t\ttype: 'text',\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\nasync function sendBestEffortNotification(\n\tnotification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t},\n\tsendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tawait sendNotification(notification);\n\t} catch {\n\t\t// Progress is advisory; unsupported client notification channels must not fail the tool call.\n\t}\n}\n\nexport async function emitMcpProgress(props: {\n\treadonly event: PortalCoreEvent;\n\treadonly sendNotification: (notification: {\n\t\treadonly method: 'notifications/message' | 'notifications/progress';\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<void>;\n\treadonly progressToken: number | string | undefined;\n}): Promise<void> {\n\tif (props.event.kind === 'upstream_notification') {\n\t\tif (!isObjectRecord(props.event.params)) {\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method === 'notifications/progress') {\n\t\t\tif (props.progressToken === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait sendBestEffortNotification(\n\t\t\t\t{\n\t\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\t\tparams: { ...props.event.params, progressToken: props.progressToken },\n\t\t\t\t},\n\t\t\t\tprops.sendNotification,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (props.event.method !== 'notifications/message') {\n\t\t\treturn;\n\t\t}\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/message',\n\t\t\t\tparams: props.event.params,\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tif (props.event.kind !== 'progress' && props.event.kind !== 'partial_content') {\n\t\treturn;\n\t}\n\tconst message =\n\t\tprops.event.kind === 'progress'\n\t\t\t? props.event.message\n\t\t\t: props.event.content.type === 'text'\n\t\t\t\t? props.event.content.text\n\t\t\t\t: JSON.stringify(props.event.content.value);\n\tif (message === undefined || message.length === 0) {\n\t\treturn;\n\t}\n\tif (props.progressToken !== undefined) {\n\t\tawait sendBestEffortNotification(\n\t\t\t{\n\t\t\t\tmethod: 'notifications/progress',\n\t\t\t\tparams: {\n\t\t\t\t\tmessage,\n\t\t\t\t\tprogress: props.event.kind === 'progress' ? (props.event.progress ?? 0) : 0,\n\t\t\t\t\tprogressToken: props.progressToken,\n\t\t\t\t\t...(props.event.kind === 'progress' && props.event.total !== undefined\n\t\t\t\t\t\t? { total: props.event.total }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.sendNotification,\n\t\t);\n\t\treturn;\n\t}\n\tawait sendBestEffortNotification(\n\t\t{\n\t\t\tmethod: 'notifications/message',\n\t\t\tparams: {\n\t\t\t\tdata: message,\n\t\t\t\tlevel: 'info',\n\t\t\t},\n\t\t},\n\t\tprops.sendNotification,\n\t);\n}\n\nexport function createPortalMcpServer(props: {\n\treadonly core: PortalCore;\n\treadonly scope: PortalAgentScope;\n}): Server {\n\tconst server = new Server(\n\t\t{ name: 'mcp-portal', version: '1.0.0' },\n\t\t{ capabilities: { tools: { listChanged: false } } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: listPortalMcpTools(props.core.describeTools(props.scope)),\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n\t\tif (!isPortalCoreToolName(request.params.name)) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ text: `Unknown MCP Portal tool: ${request.params.name}`, type: 'text' }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst result = await props.core.collectPortalCoreResult(\n\t\t\t\tprops.core.callStream({\n\t\t\t\t\tinput: request.params.arguments ?? {},\n\t\t\t\t\tscope: props.scope,\n\t\t\t\t\tsignal: extra.signal,\n\t\t\t\t\ttoolName: request.params.name,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tonEvent: async (event) => {\n\t\t\t\t\t\tawait emitMcpProgress({\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\tprogressToken: extra['_meta']?.progressToken,\n\t\t\t\t\t\t\tsendNotification: extra.sendNotification,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn jsonToolResult(result);\n\t\t} catch (error) {\n\t\t\treturn errorToolResult(error);\n\t\t}\n\t});\n\n\treturn server;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport { StreamableHTTPTransport } from '@hono/mcp';\nimport { getConnInfo } from '@hono/node-server/conninfo';\nimport { Hono, type Context } from 'hono';\n\nimport type { PortalCore } from '../core/portal-core.js';\nimport { createPortalAgentIdentity, type PortalAgentIdentity } from '../portal-access-policy.js';\nimport { verifyAgentBearerAuthorization } from '../portal-auth/agent-bearer-token.js';\nimport { createPortalMcpServer } from './portal-mcp-server.js';\n\nexport interface PortalHttpAgentIdentity extends PortalAgentIdentity {}\n\nexport interface PortalAgentBearerAuth {\n\treadonly authorizationHeaderName: string;\n\treadonly credentialVersionsByAgent?: Readonly<Record<string, number>>;\n\treadonly masterKey: Buffer;\n}\n\nexport type PortalHttpAuditEvent = {\n\treadonly agentId: string;\n\treadonly clientAddress: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_proxy_auth';\n\treadonly reason?:\n\t\t| 'malformed'\n\t\t| 'missing'\n\t\t| 'rate_limited'\n\t\t| 'signature-mismatch'\n\t\t| 'unknown_agent';\n\treadonly timeMs: number;\n};\n\nexport interface PortalHttpAppOptions {\n\treadonly agentBearerAuth: PortalAgentBearerAuth;\n\treadonly auditErrorSink?: (error: Error, event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly auditSink?: (event: PortalHttpAuditEvent) => Promise<void> | void;\n\treadonly authFailureLimit?: {\n\t\treadonly maxFailures: number;\n\t\treadonly windowMs: number;\n\t};\n\treadonly core: PortalCore;\n\treadonly onSessionClosed?: (identity: PortalAgentIdentity) => Promise<void> | void;\n\treadonly onSessionCloseError?: (\n\t\terror: Error,\n\t\tidentity: PortalAgentIdentity,\n\t) => Promise<void> | void;\n\treadonly registeredAgentIds?: readonly string[];\n\treadonly resolveAgentIdentity?: (agentId: string) => PortalHttpAgentIdentity | null;\n}\n\nexport type PortalHttpApp = Hono & {\n\treadonly closePortalSessions: () => Promise<void>;\n};\n\nconst mcpSessionIdHeader = 'mcp-session-id';\nconst defaultAuthFailureLimit = { maxFailures: 60, windowMs: 60_000 } as const;\nconst authFailureBucketLimit = 1_024;\nconst directClientAddress = 'direct-client';\nconst unknownAgentCredentialVersionForOpaqueAuthTiming = 1;\n\ninterface ActivePortalMcpSession {\n\treadonly identity: PortalAgentIdentity;\n\treadonly server: ReturnType<typeof createPortalMcpServer>;\n\treadonly transport: StreamableHTTPTransport;\n}\n\ninterface AuthFailureBucket {\n\treadonly resetAtMs: number;\n\tfailures: number;\n}\n\nfunction activeSessionKey(scopeId: string, sessionId: string): string {\n\treturn `${scopeId}\\n${sessionId}`;\n}\n\nfunction unauthorizedResponse(): Response {\n\treturn Response.json({ error: { kind: 'unauthorized' }, ok: false }, { status: 401 });\n}\n\nfunction rateLimitedResponse(): Response {\n\treturn Response.json({ error: { kind: 'rate_limited' }, ok: false }, { status: 429 });\n}\n\nfunction unavailableResponse(): Response {\n\treturn Response.json({ error: { kind: 'shutting_down' }, ok: false }, { status: 503 });\n}\n\nfunction errorFromUnknown(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction clientAddressFromContext(context: Context): string {\n\ttry {\n\t\tconst address = getConnInfo(context).remote.address;\n\t\treturn address && address.length > 0 ? address : directClientAddress;\n\t} catch {\n\t\treturn directClientAddress;\n\t}\n}\n\nexport function createPortalHttpApp(options: PortalHttpAppOptions): PortalHttpApp {\n\tif (options.agentBearerAuth === undefined) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth.');\n\t}\n\tif (options.agentBearerAuth.authorizationHeaderName.length === 0) {\n\t\tthrow new Error('MCP Portal HTTP app requires agent bearer auth header name.');\n\t}\n\tconst app = new Hono();\n\tconst activeSessions = new Map<string, ActivePortalMcpSession>();\n\tconst authFailureBuckets = new Map<string, AuthFailureBucket>();\n\tconst pendingNewSessionRequests = new Set<Promise<void>>();\n\tconst authFailureLimit = options.authFailureLimit ?? defaultAuthFailureLimit;\n\tlet closing = false;\n\n\tasync function auditAuth(event: Omit<PortalHttpAuditEvent, 'kind' | 'timeMs'>): Promise<void> {\n\t\tconst auditEvent = { ...event, kind: 'mcp_proxy_auth', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tawait options.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tawait options.auditErrorSink?.(errorFromUnknown(error), auditEvent);\n\t\t}\n\t}\n\n\tasync function reportSessionCloseError(\n\t\terror: unknown,\n\t\tidentity: PortalAgentIdentity,\n\t): Promise<void> {\n\t\tawait options.onSessionCloseError?.(errorFromUnknown(error), identity);\n\t}\n\n\tfunction pruneAuthFailureBuckets(nowMs: number): void {\n\t\tfor (const [key, bucket] of authFailureBuckets) {\n\t\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\t\tauthFailureBuckets.delete(key);\n\t\t\t}\n\t\t}\n\t\twhile (authFailureBuckets.size > authFailureBucketLimit) {\n\t\t\tconst firstKey = authFailureBuckets.keys().next().value;\n\t\t\tif (typeof firstKey !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthFailureBuckets.delete(firstKey);\n\t\t}\n\t}\n\n\tfunction isAuthFailureRateLimited(clientAddress: string): boolean {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket === undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (bucket.resetAtMs <= nowMs) {\n\t\t\tauthFailureBuckets.delete(clientAddress);\n\t\t\treturn false;\n\t\t}\n\t\treturn bucket.failures >= authFailureLimit.maxFailures;\n\t}\n\n\tfunction recordAuthFailure(clientAddress: string): void {\n\t\tconst nowMs = Date.now();\n\t\tpruneAuthFailureBuckets(nowMs);\n\t\tconst bucket = authFailureBuckets.get(clientAddress);\n\t\tif (bucket !== undefined && bucket.resetAtMs > nowMs) {\n\t\t\tbucket.failures += 1;\n\t\t\treturn;\n\t\t}\n\t\tauthFailureBuckets.set(clientAddress, {\n\t\t\tfailures: 1,\n\t\t\tresetAtMs: nowMs + authFailureLimit.windowMs,\n\t\t});\n\t\tpruneAuthFailureBuckets(nowMs);\n\t}\n\n\tfunction clearAuthFailures(clientAddress: string): void {\n\t\tauthFailureBuckets.delete(clientAddress);\n\t}\n\n\tasync function closeActiveSession(\n\t\tsessionKey: string,\n\t\tcloseOptions: { readonly closeTransport: boolean },\n\t): Promise<void> {\n\t\tconst activeSession = activeSessions.get(sessionKey);\n\t\tif (!activeSession) {\n\t\t\treturn;\n\t\t}\n\t\tactiveSessions.delete(sessionKey);\n\t\ttry {\n\t\t\tif (closeOptions.closeTransport) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t}\n\t\t} finally {\n\t\t\tawait options.onSessionClosed?.(activeSession.identity);\n\t\t}\n\t}\n\n\tfunction trackPendingNewSessionRequest(): () => void {\n\t\tlet resolvePending: (() => void) | undefined;\n\t\tconst pendingRequest = new Promise<void>((resolve) => {\n\t\t\tresolvePending = resolve;\n\t\t});\n\t\tpendingNewSessionRequests.add(pendingRequest);\n\t\treturn () => {\n\t\t\tpendingNewSessionRequests.delete(pendingRequest);\n\t\t\tresolvePending?.();\n\t\t};\n\t}\n\n\tasync function createActiveSession(\n\t\tidentityBase: PortalAgentIdentity,\n\t): Promise<ActivePortalMcpSession> {\n\t\tconst sessionId = randomUUID();\n\t\tconst sessionKey = activeSessionKey(identityBase.agentScopeId, sessionId);\n\t\tlet server: ReturnType<typeof createPortalMcpServer> | null = null;\n\t\tconst identity = createPortalAgentIdentity({\n\t\t\tagentId: identityBase.agentId,\n\t\t\tagentScopeId: identityBase.agentScopeId,\n\t\t\tsessionId,\n\t\t\tsource: identityBase.source,\n\t\t});\n\t\tconst transport = new StreamableHTTPTransport({\n\t\t\tonsessionclosed: () => {\n\t\t\t\tvoid closeActiveSession(sessionKey, { closeTransport: false }).catch((error: unknown) =>\n\t\t\t\t\treportSessionCloseError(error, identity),\n\t\t\t\t);\n\t\t\t},\n\t\t\tonsessioninitialized: (initializedSessionId) => {\n\t\t\t\tif (!server) {\n\t\t\t\t\tthrow new Error('MCP Portal session initialized before server connection.');\n\t\t\t\t}\n\t\t\t\tactiveSessions.set(activeSessionKey(identityBase.agentScopeId, initializedSessionId), {\n\t\t\t\t\tidentity,\n\t\t\t\t\tserver,\n\t\t\t\t\ttransport,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsessionIdGenerator: () => sessionId,\n\t\t});\n\t\tserver = createPortalMcpServer({\n\t\t\tcore: options.core,\n\t\t\tscope: identity,\n\t\t});\n\t\tawait server.connect(transport);\n\t\treturn { identity, server, transport };\n\t}\n\n\tasync function closePortalSessions(): Promise<void> {\n\t\tclosing = true;\n\t\tconst closeErrors: Error[] = [];\n\t\twhile (activeSessions.size > 0 || pendingNewSessionRequests.size > 0) {\n\t\t\tif (pendingNewSessionRequests.size > 0) {\n\t\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\t\tawait Promise.allSettled(pendingNewSessionRequests);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Closing may trigger callbacks that mutate activeSessions, so drain snapshots until empty.\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst closeResults = await Promise.allSettled(\n\t\t\t\t[...activeSessions.keys()].map((sessionKey) =>\n\t\t\t\t\tcloseActiveSession(sessionKey, { closeTransport: true }),\n\t\t\t\t),\n\t\t\t);\n\t\t\tcloseErrors.push(\n\t\t\t\t...closeResults\n\t\t\t\t\t.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n\t\t\t\t\t.map((result): Error => errorFromUnknown(result.reason)),\n\t\t\t);\n\t\t}\n\t\tif (closeErrors.length > 0) {\n\t\t\tthrow new AggregateError(closeErrors, 'Failed to close one or more MCP Portal sessions.');\n\t\t}\n\t}\n\n\tapp.get('/health', (context) =>\n\t\tcontext.json({ agents: [...(options.registeredAgentIds ?? [])].toSorted(), ok: true }),\n\t);\n\n\tapp.all('/agents/:agentId/mcp', async (context) => {\n\t\tconst agentId = context.req.param('agentId');\n\t\tconst clientAddress = clientAddressFromContext(context);\n\t\tif (closing) {\n\t\t\treturn unavailableResponse();\n\t\t}\n\t\tif (isAuthFailureRateLimited(clientAddress)) {\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'rate_limited',\n\t\t\t});\n\t\t\treturn rateLimitedResponse();\n\t\t}\n\t\tconst agentBearerAuth = options.agentBearerAuth;\n\t\tconst credentialVersion = agentBearerAuth.credentialVersionsByAgent?.[agentId];\n\t\tconst verification = verifyAgentBearerAuthorization({\n\t\t\tagentId,\n\t\t\tauthorizationHeader: context.req.header(agentBearerAuth.authorizationHeaderName),\n\t\t\tcredentialVersion: credentialVersion ?? unknownAgentCredentialVersionForOpaqueAuthTiming,\n\t\t\tmasterKey: agentBearerAuth.masterKey,\n\t\t});\n\t\tconst agentIdentity = options.resolveAgentIdentity?.(agentId) ?? null;\n\t\tif (agentIdentity === null) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'unknown_agent',\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tif (!verification.ok) {\n\t\t\trecordAuthFailure(clientAddress);\n\t\t\tawait auditAuth({\n\t\t\t\tagentId,\n\t\t\t\tclientAddress,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: verification.reason,\n\t\t\t});\n\t\t\treturn unauthorizedResponse();\n\t\t}\n\t\tclearAuthFailures(clientAddress);\n\t\tawait auditAuth({ agentId, clientAddress, decision: 'allow' });\n\n\t\tconst mcpSessionId = context.req.header(mcpSessionIdHeader);\n\t\tif (mcpSessionId) {\n\t\t\tconst activeSession = activeSessions.get(\n\t\t\t\tactiveSessionKey(agentIdentity.agentScopeId, mcpSessionId),\n\t\t\t);\n\t\t\tif (!activeSession) {\n\t\t\t\treturn new Response('Unknown MCP portal session', { status: 404 });\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t}\n\n\t\tconst finishPendingRequest = trackPendingNewSessionRequest();\n\t\ttry {\n\t\t\tif (closing) {\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\tconst activeSession = await createActiveSession(agentIdentity);\n\t\t\tif (closing) {\n\t\t\t\tawait activeSession.transport.close();\n\t\t\t\treturn unavailableResponse();\n\t\t\t}\n\t\t\treturn await activeSession.transport.handleRequest(context);\n\t\t} finally {\n\t\t\tfinishPendingRequest();\n\t\t}\n\t});\n\n\treturn Object.assign(app, { closePortalSessions });\n}\n","import {\n\tresolveMcpPortalProfile,\n\tmcpPortalCallPolicyDecision,\n\ttype McpPortalAgentConfig,\n\ttype McpPortalConfig,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\n\nimport type { PortalApprovalCall } from '../core/portal-tools.js';\nimport { createPortalAgentIdentity } from '../portal-access-policy.js';\nimport { hashCallArguments, verifyApprovalToken } from '../portal-auth/hmac-token.js';\n\nconst approvalTokenMaxLifetimeMs = 5 * 60_000;\nconst approvalTokenReplayCacheLimit = 4_096;\n\nexport interface ResolveAgentHmacKeysProps {\n\treadonly agents: Readonly<Record<string, McpPortalAgentConfig>>;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}\n\nexport interface PortalAgentRuntimeRecord {\n\treadonly agentId: string;\n\treadonly hmacKey: Buffer;\n\treadonly profile: ResolvedMcpPortalProfile;\n\treadonly profileName: string;\n}\n\nexport interface PortalApprovalAuditEvent {\n\treadonly agentId: string;\n\treadonly decision: 'allow' | 'deny';\n\treadonly kind: 'mcp_portal_approval';\n\treadonly reason?:\n\t\t| 'approval_token_invalid'\n\t\t| 'approval_token_missing'\n\t\t| 'call_blocked'\n\t\t| 'no_approval_required';\n\treadonly timeMs: number;\n\treadonly verifierReason?: string;\n}\n\nasync function resolveAgentHmacKeyEntry(props: {\n\treadonly agent: McpPortalAgentConfig;\n\treadonly agentId: string;\n\treadonly envKeys: ReadonlyMap<string, Buffer>;\n\treadonly resolveSecret: (secret: SecretValue) => Promise<string>;\n}): Promise<readonly [string, Buffer]> {\n\tconst envKey = props.envKeys.get(props.agentId);\n\tif (envKey !== undefined) {\n\t\treturn [props.agentId, envKey];\n\t}\n\tif (props.agent.hmacKey === undefined) {\n\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${props.agentId}\".`);\n\t}\n\tconst secretValue = await props.resolveSecret(props.agent.hmacKey);\n\tif (!/^[0-9a-f]+$/u.test(secretValue) || secretValue.length !== 64) {\n\t\tthrow new Error(`MCP Portal agent \"${props.agentId}\" HMAC key must be 64 hex characters.`);\n\t}\n\treturn [props.agentId, Buffer.from(secretValue, 'hex')];\n}\n\nexport async function resolveAgentHmacKeys(\n\tprops: ResolveAgentHmacKeysProps,\n): Promise<ReadonlyMap<string, Buffer>> {\n\treturn new Map(\n\t\tawait Promise.all(\n\t\t\tObject.entries(props.agents).map(([agentId, agent]) =>\n\t\t\t\tresolveAgentHmacKeyEntry({\n\t\t\t\t\tagent,\n\t\t\t\t\tagentId,\n\t\t\t\t\tenvKeys: props.envKeys,\n\t\t\t\t\tresolveSecret: props.resolveSecret,\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t);\n}\n\nexport function createPortalAgentRuntimeRecords(props: {\n\treadonly hmacKeys: ReadonlyMap<string, Buffer>;\n\treadonly portalConfig: McpPortalConfig;\n}): ReadonlyMap<string, PortalAgentRuntimeRecord> {\n\tconst records = new Map<string, PortalAgentRuntimeRecord>();\n\tfor (const [agentId, agent] of Object.entries(props.portalConfig.agents)) {\n\t\tconst hmacKey = props.hmacKeys.get(agentId);\n\t\tif (hmacKey === undefined) {\n\t\t\tthrow new Error(`Missing HMAC key for MCP Portal agent \"${agentId}\".`);\n\t\t}\n\t\trecords.set(agentId, {\n\t\t\tagentId,\n\t\t\thmacKey,\n\t\t\tprofile: resolveMcpPortalProfile(props.portalConfig, agent.profile),\n\t\t\tprofileName: agent.profile,\n\t\t});\n\t}\n\treturn records;\n}\n\nexport function createPortalHttpAgentResolver(\n\trecords: ReadonlyMap<string, PortalAgentRuntimeRecord>,\n): (agentId: string) => ReturnType<typeof createPortalAgentIdentity> | null {\n\treturn (agentId) => {\n\t\tconst record = records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn createPortalAgentIdentity({\n\t\t\tagentId,\n\t\t\tagentScopeId: agentId,\n\t\t\tsource: 'mcp-proxy-bearer',\n\t\t});\n\t};\n}\n\nfunction callDecisionByProfile(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: PortalApprovalCall,\n): ReturnType<typeof mcpPortalCallPolicyDecision> {\n\tconst annotations = call.tool.annotations;\n\treturn mcpPortalCallPolicyDecision(profile, {\n\t\t...(annotations === undefined ? {} : { annotations }),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t});\n}\n\nfunction approvalTokenCallDigests(calls: readonly PortalApprovalCall[]): readonly {\n\treadonly argumentsHash: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}[] {\n\treturn calls.map((call) => ({\n\t\targumentsHash: hashCallArguments(call.arguments),\n\t\tnamespace: call.namespace,\n\t\ttoolName: call.toolName,\n\t}));\n}\n\nexport function createPortalApprovalVerifier(props: {\n\treadonly approvalTokenReplayCacheLimit?: number;\n\treadonly auditErrorSink?: (error: Error, event: PortalApprovalAuditEvent) => void;\n\treadonly auditSink?: (event: PortalApprovalAuditEvent) => void;\n\treadonly records: ReadonlyMap<string, PortalAgentRuntimeRecord>;\n}): (\n\tcalls: readonly PortalApprovalCall[],\n\tagentId: string,\n\ttoken: string | undefined,\n) =>\n\t| { readonly kind: 'allow' }\n\t| { readonly kind: 'call_blocked' }\n\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t| { readonly kind: 'approval_token_missing' } {\n\tfunction auditApproval(event: Omit<PortalApprovalAuditEvent, 'kind' | 'timeMs'>): void {\n\t\tconst auditEvent = { ...event, kind: 'mcp_portal_approval', timeMs: Date.now() } as const;\n\t\ttry {\n\t\t\tprops.auditSink?.(auditEvent);\n\t\t} catch (error) {\n\t\t\tprops.auditErrorSink?.(error instanceof Error ? error : new Error(String(error)), auditEvent);\n\t\t}\n\t}\n\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = props.approvalTokenReplayCacheLimit ?? approvalTokenReplayCacheLimit;\n\tconst consumeTokenId = (\n\t\tagentId: string,\n\t\tjti: string,\n\t\texpiresAtMs: number,\n\t):\n\t\t| { readonly ok: true }\n\t\t| { readonly ok: false; readonly reason: 'replay-cache-full' | 'replayed' } => {\n\t\tconst nowMs = Date.now();\n\t\tfor (const [tokenKey, tokenExpiresAtMs] of consumedApprovalTokenIds) {\n\t\t\tif (tokenExpiresAtMs <= nowMs) {\n\t\t\t\tconsumedApprovalTokenIds.delete(tokenKey);\n\t\t\t}\n\t\t}\n\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t}\n\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t}\n\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\treturn { ok: true };\n\t};\n\treturn (calls, agentId, token) => {\n\t\tconst record = props.records.get(agentId);\n\t\tif (record === undefined) {\n\t\t\tauditApproval({\n\t\t\t\tagentId,\n\t\t\t\tdecision: 'deny',\n\t\t\t\treason: 'approval_token_invalid',\n\t\t\t\tverifierReason: 'unknown-agent',\n\t\t\t});\n\t\t\treturn { kind: 'approval_token_invalid', reason: 'unknown-agent' };\n\t\t}\n\t\tconst callDecisions = calls.map((call) => callDecisionByProfile(record.profile, call));\n\t\tif (callDecisions.some((decision) => decision.kind === 'blocked')) {\n\t\t\tauditApproval({ agentId, decision: 'deny', reason: 'call_blocked' });\n\t\t\treturn { kind: 'call_blocked' };\n\t\t}\n\t\tconst callsRequiringApproval = calls.filter(\n\t\t\t(_call, index) => callDecisions[index]?.kind === 'requires_approval',\n\t\t);\n\t\tif (callsRequiringApproval.length === 0) {\n\t\t\tauditApproval({ agentId, decision: 'allow', reason: 'no_approval_required' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tif (token === undefined) {\n\t\t\tauditApproval({ agentId, decision: 'deny', reason: 'approval_token_missing' });\n\t\t\treturn { kind: 'approval_token_missing' };\n\t\t}\n\t\tconst verificationProps = {\n\t\t\tagentId,\n\t\t\tcalls: approvalTokenCallDigests(callsRequiringApproval),\n\t\t\tconsumeTokenId: (jti: string, expiresAtMs: number) =>\n\t\t\t\tconsumeTokenId(agentId, jti, expiresAtMs),\n\t\t\tkey: record.hmacKey,\n\t\t\tmaxLifetimeMs: approvalTokenMaxLifetimeMs,\n\t\t\tnowMs: Date.now(),\n\t\t\ttoken,\n\t\t};\n\t\tconst verification = verifyApprovalToken(verificationProps);\n\t\tif (verification.ok) {\n\t\t\tauditApproval({ agentId, decision: 'allow' });\n\t\t\treturn { kind: 'allow' };\n\t\t}\n\t\tauditApproval({\n\t\t\tagentId,\n\t\t\tdecision: 'deny',\n\t\t\treason: 'approval_token_invalid',\n\t\t\tverifierReason: verification.reason,\n\t\t});\n\t\treturn { kind: 'approval_token_invalid', reason: verification.reason };\n\t};\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { t as createUpstreamMcpClientRuntime } from "./upstream-mcp-client-runtime-Be_cw6pV.js";
2
- import { i as resolveUpstreamServers, n as createPortalCore } from "./portal-core-B5cRpZMG.js";
2
+ import { i as resolveUpstreamServers, n as createPortalCore } from "./portal-core-e-qajblz.js";
3
3
  import { t as decodePortalMasterKey } from "./agent-bearer-token-DCtpDPCZ.js";
4
- import { a as createPortalHttpApp, n as createPortalApprovalVerifier, r as createPortalHttpAgentResolver, t as createPortalAgentRuntimeRecords } from "./resolve-agent-identity-ZMMY2Wqm.js";
4
+ import { a as createPortalHttpApp, n as createPortalApprovalVerifier, r as createPortalHttpAgentResolver, t as createPortalAgentRuntimeRecords } from "./resolve-agent-identity-Dnqv2hAW.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-Dz6nvnzQ.js.map
358
+ //# sourceMappingURL=serve-command-DHkYmO6n.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"serve-command-Dz6nvnzQ.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-DHkYmO6n.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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-vm/mcp-portal",
3
- "version": "0.0.79",
3
+ "version": "0.0.80",
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/config-contracts": "0.0.79",
73
- "@agent-vm/secret-management": "0.0.79"
72
+ "@agent-vm/config-contracts": "0.0.80",
73
+ "@agent-vm/secret-management": "0.0.80"
74
74
  },
75
75
  "devDependencies": {
76
76
  "vitest": "^4.1.5"
@@ -1 +0,0 @@
1
- {"version":3,"file":"portal-core-Ckq-Mrzb.d.ts","names":[],"sources":["../src/core/portal-tools.ts","../src/core/portal-core.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"portal-tools-DA7j2pyv.js","names":[],"sources":["../src/core/portal-call-validation.ts","../src/core/portal-tools.ts"],"sourcesContent":["import type { PortalToolRecord } from '../catalog-types.js';\nimport type { JsonObject } from '../json-schema.js';\nimport { buildZodValidatorFromJsonSchema } from '../zod-schema-loader.js';\n\nexport function validatePortalToolArguments(\n\ttool: PortalToolRecord,\n\targumentsValue: JsonObject,\n):\n\t| { readonly ok: true; readonly value: unknown }\n\t| {\n\t\t\treadonly error:\n\t\t\t\t| {\n\t\t\t\t\t\treadonly issues: readonly {\n\t\t\t\t\t\t\treadonly code: string;\n\t\t\t\t\t\t\treadonly message: string;\n\t\t\t\t\t\t\treadonly path: readonly (number | string)[];\n\t\t\t\t\t\t}[];\n\t\t\t\t\t\treadonly kind: 'input_validation';\n\t\t\t\t\t\treadonly namespace: string;\n\t\t\t\t\t\treadonly toolName: string;\n\t\t\t\t }\n\t\t\t\t| {\n\t\t\t\t\t\treadonly feature: string;\n\t\t\t\t\t\treadonly kind: 'schema_validation_unavailable';\n\t\t\t\t\t\treadonly message: string;\n\t\t\t\t\t\treadonly namespace: string;\n\t\t\t\t\t\treadonly path: readonly (number | string)[];\n\t\t\t\t\t\treadonly toolName: string;\n\t\t\t\t };\n\t\t\treadonly ok: false;\n\t } {\n\tconst validator = buildZodValidatorFromJsonSchema(tool.inputSchema);\n\tif (!validator.ok) {\n\t\treturn {\n\t\t\terror: { ...validator.error, namespace: tool.namespace, toolName: tool.toolName },\n\t\t\tok: false,\n\t\t};\n\t}\n\n\tconst result = validator.validate(argumentsValue);\n\tif (!result.ok) {\n\t\treturn {\n\t\t\terror: { ...result.error, namespace: tool.namespace, toolName: tool.toolName },\n\t\t\tok: false,\n\t\t};\n\t}\n\n\treturn result;\n}\n","import type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\n\nimport type { PortalToolRecord } from '../catalog-types.js';\nimport { jsonObjectSchema, type JsonObject } from '../json-schema.js';\nimport {\n\tportalAgentScopeKey,\n\ttype PortalAgentIdentity,\n\ttype PortalToolSelector,\n} from '../portal-access-policy.js';\nimport { generateTypescriptCatalogArtifact } from '../portal-config/typescript-artifact.js';\nimport type { PortalSession } from '../portal-session.js';\nimport type { ToolSearchResult } from '../search-index.js';\nimport { decodeToolRef } from '../tool-ref.js';\nimport { createToolSummary, type ToolSchemaHint, type ToolSummary } from '../tool-summary.js';\nimport { upstreamMcpFailureDetailsFromUnknown } from '../upstream-mcp-errors.js';\nimport { validatePortalToolArguments } from './portal-call-validation.js';\n\nexport interface PortalToolSuccess {\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly ok: true;\n\treadonly output: Readonly<Record<string, unknown>>;\n}\n\nexport interface PortalToolFailure {\n\treadonly error: unknown;\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly ok: false;\n}\n\nexport type PortalToolResult = PortalToolFailure | PortalToolSuccess;\nexport type PortalToolResultMap = Readonly<Record<string, PortalToolResult>>;\n\nexport interface PortalBatchError {\n\treadonly id?: string;\n\treadonly kind: string;\n\treadonly message: string;\n}\n\nexport interface PortalBatchDiagnostic {\n\treadonly causeMessage?: string;\n\treadonly elapsedMs?: number;\n\treadonly hint?: string;\n\treadonly kind: string;\n\treadonly message: string;\n\treadonly namespace?: string;\n\treadonly operation?: string;\n\treadonly phase?: string;\n\treadonly timeoutMs?: number;\n\treadonly toolName?: string;\n\treadonly transport?: unknown;\n}\n\nexport interface PortalBatchResult {\n\treadonly diagnostics: readonly PortalBatchDiagnostic[];\n\treadonly errors: readonly PortalBatchError[];\n\treadonly ok: boolean;\n\treadonly results: PortalToolResultMap;\n}\n\nexport interface PortalApprovalCall {\n\treadonly arguments: JsonObject;\n\treadonly id: string;\n\treadonly namespace: string;\n\treadonly tool: PortalToolRecord;\n\treadonly toolName: string;\n}\n\ntype SelectorInputResult =\n\t| { readonly error: PortalBatchError; readonly ok: false }\n\t| { readonly ok: true; readonly selectors: readonly PortalToolSelector[] };\ntype ExactFilterResult =\n\t| { readonly error: PortalBatchError; readonly ok: false }\n\t| { readonly ok: true; readonly tools: readonly PortalToolRecord[] };\n\nconst requestIdSchema = z.string().min(1);\nconst reservedRequestIds = new Set(['__proto__', 'constructor', 'prototype']);\nconst safeRequestIdSchema = requestIdSchema.refine((id) => !reservedRequestIds.has(id), {\n\tmessage: 'Portal request id uses a reserved object property name.',\n});\nconst namespaceToolSelectorSchema = z\n\t.object({ namespace: z.string().min(1), toolName: z.string().min(1) })\n\t.strict();\nconst listRequestSchema = z\n\t.object({\n\t\tcursor: z.string().regex(/^\\d+$/u).optional(),\n\t\tid: safeRequestIdSchema,\n\t\tlimit: z.number().int().positive().max(100).default(20),\n\t\tnamespaces: z.array(z.string()).optional(),\n\t\trefs: z.array(z.string()).optional(),\n\t\ttools: z.array(namespaceToolSelectorSchema).optional(),\n\t})\n\t.strict();\nconst searchRequestSchema = z\n\t.object({\n\t\tid: safeRequestIdSchema,\n\t\tlimit: z.number().int().positive().max(50).default(10),\n\t\tnamespaces: z.array(z.string()).optional(),\n\t\tquery: z.string().optional(),\n\t\tschemaDetail: z.enum(['none', 'summary', 'full']).default('summary'),\n\t})\n\t.strict();\nconst describeRequestSchema = z\n\t.object({\n\t\tid: safeRequestIdSchema,\n\t\tincludeJsonSchema: z.boolean().default(true),\n\t\tincludeRelated: z.boolean().default(true),\n\t\tincludeTypescriptHelper: z.boolean().default(false),\n\t\tincludeZod: z.boolean().default(false),\n\t\trefs: z.array(z.string()).optional(),\n\t\ttools: z.array(namespaceToolSelectorSchema).optional(),\n\t})\n\t.strict();\nconst callRequestSchema = z\n\t.object({\n\t\targuments: jsonObjectSchema,\n\t\tid: safeRequestIdSchema,\n\t\tnamespace: z.string().min(1),\n\t\ttoolName: z.string().min(1),\n\t})\n\t.strict();\nconst listInputSchema = z.object({ requests: z.array(listRequestSchema).min(1) }).strict();\nconst searchInputSchema = z.object({ requests: z.array(searchRequestSchema).min(1) }).strict();\nconst describeInputSchema = z.object({ requests: z.array(describeRequestSchema).min(1) }).strict();\nconst callInputSchema = z.object({ calls: z.array(callRequestSchema).min(1) }).strict();\nconst callExecutionInputSchema = z\n\t.object({\n\t\tcalls: z.array(callRequestSchema).min(1),\n\t\tportalApprovalToken: z.string().min(1).optional(),\n\t})\n\t.strict();\n\ntype ListRequest = z.infer<typeof listRequestSchema>;\ntype SearchRequest = z.infer<typeof searchRequestSchema>;\ntype DescribeRequest = z.infer<typeof describeRequestSchema>;\ntype CallRequest = z.infer<typeof callRequestSchema>;\n\ninterface PreparedPortalCall {\n\treadonly input: CallRequest;\n\treadonly validatedArguments: JsonObject;\n\treadonly tool: PortalToolRecord;\n}\n\nconst describeBeforeCallSchemaHint = {\n\tmessage: 'Use mcp_portal_describe for exact input schema before calling.',\n\tnext: 'describe_before_call',\n} as const satisfies ToolSchemaHint;\n\nconst callReadySchemaHint = {\n\tmessage: 'Full input schema included.',\n\tnext: 'call_ready',\n} as const satisfies ToolSchemaHint;\n\nfunction isToolSchemaProperties(value: unknown): value is Record<string, object> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t!Array.isArray(value) &&\n\t\tObject.values(value).every(\n\t\t\t(entry) => typeof entry === 'object' && entry !== null && !Array.isArray(entry),\n\t\t)\n\t);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\nfunction toPortalInputJsonSchema(schema: z.ZodType): Tool['inputSchema'] {\n\tconst jsonSchema = jsonObjectSchema.parse(z.toJSONSchema(schema, { io: 'input' }));\n\tif (jsonSchema.type !== 'object') {\n\t\tthrow new Error('MCP Portal tool input schemas must be JSON Schema objects.');\n\t}\n\tconst properties = isToolSchemaProperties(jsonSchema.properties)\n\t\t? jsonSchema.properties\n\t\t: undefined;\n\tconst required = isStringArray(jsonSchema.required) ? jsonSchema.required : undefined;\n\n\treturn {\n\t\t...jsonSchema,\n\t\t...(properties !== undefined ? { properties } : {}),\n\t\t...(required !== undefined ? { required } : {}),\n\t\ttype: 'object',\n\t};\n}\n\nexport const portalToolInputSchemas = {\n\tmcp_portal_call: toPortalInputJsonSchema(callInputSchema),\n\tmcp_portal_describe: toPortalInputJsonSchema(describeInputSchema),\n\tmcp_portal_list: toPortalInputJsonSchema(listInputSchema),\n\tmcp_portal_search: toPortalInputJsonSchema(searchInputSchema),\n} as const;\n\nexport interface PortalToolHandlerCall {\n\treadonly identity: PortalAgentIdentity;\n\treadonly input: unknown;\n}\n\nexport interface PortalCallUpstreamTool {\n\treadonly arguments: JsonObject;\n\treadonly agentScopeId: string;\n\treadonly namespace: string;\n\treadonly onEvent?: (event: PortalUpstreamEvent) => Promise<void> | void;\n\treadonly requestId: string;\n\treadonly signal?: AbortSignal;\n\treadonly toolName: string;\n}\n\nexport type PortalUpstreamEvent =\n\t| {\n\t\t\treadonly kind: 'progress';\n\t\t\treadonly message?: string;\n\t\t\treadonly progress?: number;\n\t\t\treadonly total?: number;\n\t }\n\t| {\n\t\t\treadonly kind: 'upstream_notification';\n\t\t\treadonly method: string;\n\t\t\treadonly params: unknown;\n\t }\n\t| {\n\t\t\treadonly content:\n\t\t\t\t| { readonly text: string; readonly type: 'text' }\n\t\t\t\t| { readonly type: 'json'; readonly value: unknown };\n\t\t\treadonly kind: 'partial_content';\n\t };\n\nexport interface PortalToolRuntime {\n\treadonly approval?: (\n\t\tcalls: readonly PortalApprovalCall[],\n\t\tidentity: PortalAgentIdentity,\n\t\tapprovalToken: string | undefined,\n\t) =>\n\t\t| { readonly kind: 'allow' }\n\t\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t\t| { readonly kind: 'approval_token_missing' }\n\t\t| { readonly kind: 'approval_required'; readonly level: 'critical' | 'standard' };\n\treadonly callUpstreamTool: (call: PortalCallUpstreamTool) => Promise<unknown>;\n\treadonly getSession: (identity: PortalAgentIdentity) => Promise<PortalSession>;\n}\n\ntype PortalApprovalDecision =\n\t| { readonly kind: 'allow' }\n\t| { readonly kind: 'approval_configuration_missing' }\n\t| { readonly kind: 'approval_required'; readonly level: 'critical' | 'standard' }\n\t| { readonly kind: 'approval_token_invalid'; readonly reason: string }\n\t| { readonly kind: 'approval_token_missing' };\n\nexport interface PortalToolHandlers {\n\treadonly call: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly describe: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly list: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n\treadonly search: (call: PortalToolHandlerCall) => Promise<PortalBatchResult>;\n}\n\nfunction messageFromError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction invalidPortalInput(error: unknown): PortalBatchResult {\n\treturn {\n\t\tdiagnostics: [],\n\t\terrors: [{ kind: 'invalid_portal_input', message: messageFromError(error) }],\n\t\tok: false,\n\t\tresults: {},\n\t};\n}\n\nfunction itemError(props: {\n\treadonly error: unknown;\n\treadonly input: Readonly<Record<string, unknown>>;\n}): PortalToolResult {\n\treturn {\n\t\terror: props.error,\n\t\tinput: props.input,\n\t\tok: false,\n\t};\n}\n\nfunction itemOutput(props: {\n\treadonly input: Readonly<Record<string, unknown>>;\n\treadonly output: Readonly<Record<string, unknown>>;\n}): PortalToolResult {\n\treturn {\n\t\tinput: props.input,\n\t\tok: true,\n\t\toutput: props.output,\n\t};\n}\n\nfunction discoveryDiagnostics(session: PortalSession): readonly PortalBatchDiagnostic[] {\n\treturn session.catalog.discoveryFailures.map((failure) => ({\n\t\t...failure,\n\t\tkind:\n\t\t\tfailure.kind === 'upstream_mcp_failed' ? 'upstream_mcp_failed' : 'upstream_discovery_failed',\n\t}));\n}\n\nfunction portalBatchResult(\n\tresults: PortalToolResultMap,\n\tdiagnostics: readonly PortalBatchDiagnostic[] = [],\n): PortalBatchResult {\n\tconst allItemsOk = Object.values(results).every((result) => result.ok);\n\treturn { diagnostics, errors: [], ok: allItemsOk, results };\n}\n\nfunction duplicateIdErrors(items: readonly { readonly id: string }[]): readonly PortalBatchError[] {\n\tconst seenIds = new Set<string>();\n\tconst duplicateIds = new Set<string>();\n\tfor (const item of items) {\n\t\tif (seenIds.has(item.id)) {\n\t\t\tduplicateIds.add(item.id);\n\t\t}\n\t\tseenIds.add(item.id);\n\t}\n\n\treturn [...duplicateIds].toSorted().map((id) => ({\n\t\tid,\n\t\tkind: 'duplicate_id',\n\t\tmessage: `Duplicate portal request id \"${id}\". Each request id must be unique.`,\n\t}));\n}\n\nfunction duplicateIdResult(items: readonly { readonly id: string }[]): PortalBatchResult | null {\n\tconst errors = duplicateIdErrors(items);\n\treturn errors.length > 0 ? { diagnostics: [], errors, ok: false, results: {} } : null;\n}\n\nfunction findTool(session: PortalSession, selector: PortalToolSelector): PortalToolRecord | null {\n\treturn (\n\t\tsession.catalog.tools.find(\n\t\t\t(tool) => tool.namespace === selector.namespace && tool.toolName === selector.toolName,\n\t\t) ?? null\n\t);\n}\n\nfunction selectorsFromInput(\n\ttools?: readonly PortalToolSelector[],\n\trefs?: readonly string[],\n): SelectorInputResult {\n\tconst selectors: PortalToolSelector[] = [...(tools ?? [])];\n\tfor (const toolRef of refs ?? []) {\n\t\ttry {\n\t\t\tselectors.push(decodeToolRef(toolRef));\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\terror: { kind: 'invalid_portal_input', message: messageFromError(error) },\n\t\t\t\tok: false,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { ok: true, selectors };\n}\n\nfunction applyExactFilters(\n\ttools: readonly PortalToolRecord[],\n\tfilters: {\n\t\treadonly namespaces?: readonly string[];\n\t\treadonly refs?: readonly string[];\n\t\treadonly tools?: readonly PortalToolSelector[];\n\t},\n): ExactFilterResult {\n\tconst namespaceFilter = new Set(filters.namespaces ?? []);\n\tconst selectorResult = selectorsFromInput(filters.tools, filters.refs);\n\tif (!selectorResult.ok) {\n\t\treturn selectorResult;\n\t}\n\tconst exactSelectors = selectorResult.selectors;\n\tif (exactSelectors.length === 0) {\n\t\treturn {\n\t\t\tok: true,\n\t\t\ttools: tools.filter(\n\t\t\t\t(tool) => namespaceFilter.size === 0 || namespaceFilter.has(tool.namespace),\n\t\t\t),\n\t\t};\n\t}\n\n\treturn {\n\t\tok: true,\n\t\ttools: tools.filter(\n\t\t\t(tool) =>\n\t\t\t\t(namespaceFilter.size === 0 || namespaceFilter.has(tool.namespace)) &&\n\t\t\t\texactSelectors.some(\n\t\t\t\t\t(selector) =>\n\t\t\t\t\t\tselector.namespace === tool.namespace && selector.toolName === tool.toolName,\n\t\t\t\t),\n\t\t),\n\t};\n}\n\nfunction selectorKey(selector: PortalToolSelector): string {\n\treturn `${selector.namespace}\\n${selector.toolName}`;\n}\n\nfunction missingSelectorError(\n\trequestedSelectors: readonly PortalToolSelector[],\n\tselectedTools: readonly PortalToolRecord[],\n): PortalBatchError | null {\n\tconst foundKeys = new Set(\n\t\tselectedTools.map((tool) =>\n\t\t\tselectorKey({ namespace: tool.namespace, toolName: tool.toolName }),\n\t\t),\n\t);\n\tconst missingSelectors = requestedSelectors.filter(\n\t\t(selector) => !foundKeys.has(selectorKey(selector)),\n\t);\n\tif (missingSelectors.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: 'unknown_or_denied_tool',\n\t\tmessage: 'One or more requested tools are unknown or denied for this portal agent scope.',\n\t};\n}\n\nfunction paginate<TItem>(\n\titems: readonly TItem[],\n\tlimit: number,\n\tcursor?: string,\n): { readonly items: readonly TItem[]; readonly nextCursor?: string } {\n\tconst offset = cursor ? Number.parseInt(cursor, 10) : 0;\n\tconst safeOffset = Number.isFinite(offset) && offset > 0 ? offset : 0;\n\tconst page = items.slice(safeOffset, safeOffset + limit);\n\tconst nextOffset = safeOffset + page.length;\n\n\treturn {\n\t\titems: page,\n\t\t...(nextOffset < items.length ? { nextCursor: String(nextOffset) } : {}),\n\t};\n}\n\nfunction describeToolOutput(props: {\n\treadonly includeJsonSchema: boolean;\n\treadonly includeRelated: boolean;\n\treadonly includeTypescriptHelper: boolean;\n\treadonly includeZod: boolean;\n\treadonly session: PortalSession;\n\treadonly tool: PortalToolRecord;\n}): Readonly<Record<string, unknown>> {\n\tconst toolSummary = createToolSummary(props.tool);\n\tconst result: Record<string, unknown> = {\n\t\tannotations: props.tool.annotations ?? {},\n\t\tnamespace: props.tool.namespace,\n\t\trelated: props.includeRelated\n\t\t\t? props.session.graph.relationships.filter(\n\t\t\t\t\t(relationship) =>\n\t\t\t\t\t\trelationship.from.toolRef === toolSummary.toolRef ||\n\t\t\t\t\t\trelationship.to.toolRef === toolSummary.toolRef,\n\t\t\t\t)\n\t\t\t: [],\n\t\tschemaHint: callReadySchemaHint,\n\t\ttoolName: props.tool.toolName,\n\t\ttoolRef: toolSummary.toolRef,\n\t};\n\n\tif (props.includeJsonSchema) {\n\t\tresult.inputSchema = props.tool.inputSchema;\n\t\tresult.outputSchema = props.tool.outputSchema;\n\t}\n\tif (props.includeZod) {\n\t\tresult.zod = { experimental: true, source: 'z.fromJSONSchema(inputSchema)' };\n\t}\n\tif (props.includeTypescriptHelper) {\n\t\tresult.typescriptHelper = generateTypescriptCatalogArtifact({ tools: [props.tool] });\n\t}\n\n\treturn result;\n}\n\nfunction searchOutputWithFullSchema(\n\tsession: PortalSession,\n\tsummary: ToolSearchResult,\n): Readonly<Record<string, unknown>> {\n\tconst tool = findTool(session, summary);\n\tconst result: Record<string, unknown> = {\n\t\tinput: summary.input,\n\t\tnamespace: summary.namespace,\n\t\tsafety: summary.safety,\n\t\tschemaHint: callReadySchemaHint,\n\t\ttoolName: summary.toolName,\n\t\ttoolRef: summary.toolRef,\n\t};\n\n\tif (summary.description !== undefined) {\n\t\tresult.description = summary.description;\n\t}\n\tif (summary.output !== undefined) {\n\t\tresult.output = summary.output;\n\t}\n\tif (summary.relationshipHints !== undefined) {\n\t\tresult.relationshipHints = summary.relationshipHints;\n\t}\n\tif (summary.schemaFieldMatches !== undefined) {\n\t\tresult.schemaFieldMatches = summary.schemaFieldMatches;\n\t}\n\tif (summary.title !== undefined) {\n\t\tresult.title = summary.title;\n\t}\n\n\tif (tool) {\n\t\tresult.inputSchema = tool.inputSchema;\n\t\tresult.outputSchema = tool.outputSchema;\n\t}\n\n\treturn result;\n}\n\nfunction toolSummaryWithSchemaHint(summary: ToolSummary): ToolSummary {\n\treturn Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });\n}\n\nfunction toolSearchResultWithSchemaHint(\n\tsummary: ToolSearchResult,\n): ToolSearchResult & { readonly schemaHint: ToolSchemaHint } {\n\treturn Object.assign({}, summary, { schemaHint: describeBeforeCallSchemaHint });\n}\n\nfunction listRequestResult(session: PortalSession, request: ListRequest): PortalToolResult {\n\tconst filteredTools = applyExactFilters(session.catalog.tools, {\n\t\t...(request.namespaces !== undefined ? { namespaces: request.namespaces } : {}),\n\t\t...(request.refs !== undefined ? { refs: request.refs } : {}),\n\t\t...(request.tools !== undefined ? { tools: request.tools } : {}),\n\t});\n\tif (!filteredTools.ok) {\n\t\treturn itemError({ error: filteredTools.error, input: request });\n\t}\n\tconst page = paginate(\n\t\tfilteredTools.tools.map((tool) => toolSummaryWithSchemaHint(createToolSummary(tool))),\n\t\trequest.limit,\n\t\trequest.cursor,\n\t);\n\tconst output = {\n\t\tnamespaces: [...new Set(filteredTools.tools.map((tool) => tool.namespace))].toSorted(),\n\t\t...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}),\n\t\ttools: page.items,\n\t} satisfies {\n\t\treadonly namespaces: readonly string[];\n\t\treadonly nextCursor?: string;\n\t\treadonly tools: readonly ToolSummary[];\n\t};\n\n\treturn itemOutput({ input: request, output });\n}\n\nfunction searchRequestResult(session: PortalSession, request: SearchRequest): PortalToolResult {\n\tconst result = session.searchIndex.search({\n\t\tlimit: request.limit,\n\t\t...(request.namespaces ? { namespaces: request.namespaces } : {}),\n\t\t...(request.query !== undefined ? { query: request.query } : {}),\n\t});\n\tconst tools =\n\t\trequest.schemaDetail === 'full'\n\t\t\t? result.results.map((summary) => searchOutputWithFullSchema(session, summary))\n\t\t\t: result.results.map((summary) => toolSearchResultWithSchemaHint(summary));\n\n\treturn itemOutput({ input: request, output: { tools } });\n}\n\nfunction describeRequestResult(session: PortalSession, request: DescribeRequest): PortalToolResult {\n\tconst selectorResult = selectorsFromInput(request.tools, request.refs);\n\tif (!selectorResult.ok) {\n\t\treturn itemError({ error: selectorResult.error, input: request });\n\t}\n\tconst selectors = selectorResult.selectors;\n\tconst selectedTools = selectors\n\t\t.map((selector) => findTool(session, selector))\n\t\t.filter((tool): tool is PortalToolRecord => tool !== null);\n\tconst missingError = missingSelectorError(selectors, selectedTools);\n\tif (missingError) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\t...missingError,\n\t\t\t\ttools: selectors.filter((selector) => findTool(session, selector) === null),\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\tconst tools = selectedTools.map((tool) =>\n\t\tdescribeToolOutput({\n\t\t\tincludeJsonSchema: request.includeJsonSchema,\n\t\t\tincludeRelated: request.includeRelated,\n\t\t\tincludeTypescriptHelper: request.includeTypescriptHelper,\n\t\t\tincludeZod: request.includeZod,\n\t\t\tsession,\n\t\t\ttool,\n\t\t}),\n\t);\n\treturn itemOutput({ input: request, output: { tools } });\n}\n\nfunction preparePortalCall(\n\tsession: PortalSession,\n\trequest: CallRequest,\n): PreparedPortalCall | PortalToolResult {\n\tconst tool = findTool(session, request);\n\tif (!tool) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'unknown_or_denied_tool',\n\t\t\t\tmessage: 'The requested tool is unknown or denied for this portal agent scope.',\n\t\t\t\tnamespace: request.namespace,\n\t\t\t\ttoolName: request.toolName,\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\tconst validation = validatePortalToolArguments(tool, request.arguments);\n\tif (!validation.ok) {\n\t\treturn itemError({ error: validation.error, input: request });\n\t}\n\tconst validatedArgumentsResult = jsonObjectSchema.safeParse(validation.value);\n\tif (!validatedArgumentsResult.success) {\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'invalid_portal_input',\n\t\t\t\tmessage: validatedArgumentsResult.error.message,\n\t\t\t},\n\t\t\tinput: request,\n\t\t});\n\t}\n\n\treturn { input: request, tool, validatedArguments: validatedArgumentsResult.data };\n}\n\nasync function executePreparedPortalCall(\n\tcall: PreparedPortalCall,\n\tidentity: PortalAgentIdentity,\n\truntime: PortalToolRuntime,\n): Promise<PortalToolResult> {\n\tconst input = { ...call.input, arguments: call.validatedArguments };\n\ttry {\n\t\treturn itemOutput({\n\t\t\tinput,\n\t\t\toutput: {\n\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\tresult: await runtime.callUpstreamTool({\n\t\t\t\t\targuments: call.validatedArguments,\n\t\t\t\t\tagentScopeId: portalAgentScopeKey(identity),\n\t\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\t\trequestId: call.input.id,\n\t\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t\t}),\n\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tconst upstream = upstreamMcpFailureDetailsFromUnknown(error);\n\t\treturn itemError({\n\t\t\terror: {\n\t\t\t\tkind: 'upstream_call_failed',\n\t\t\t\tmessage: messageFromError(error),\n\t\t\t\tnamespace: call.tool.namespace,\n\t\t\t\ttoolName: call.tool.toolName,\n\t\t\t\t...(upstream === null ? {} : { upstream }),\n\t\t\t},\n\t\t\tinput,\n\t\t});\n\t}\n}\n\nfunction isPreparedPortalCall(\n\tvalue: PreparedPortalCall | PortalToolResult,\n): value is PreparedPortalCall {\n\treturn 'validatedArguments' in value;\n}\n\nasync function addExecutableCallResults(props: {\n\treadonly identity: PortalAgentIdentity;\n\treadonly preparedCalls: readonly PreparedPortalCall[];\n\treadonly results: Record<string, PortalToolResult>;\n\treadonly runtime: PortalToolRuntime;\n}): Promise<void> {\n\tawait Promise.all(\n\t\tprops.preparedCalls.map(async (preparedCall): Promise<void> => {\n\t\t\tprops.results[preparedCall.input.id] = await executePreparedPortalCall(\n\t\t\t\tpreparedCall,\n\t\t\t\tprops.identity,\n\t\t\t\tprops.runtime,\n\t\t\t);\n\t\t}),\n\t);\n}\n\nexport function createPortalToolHandlers(runtime: PortalToolRuntime): PortalToolHandlers {\n\treturn {\n\t\tasync call(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = callExecutionInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.calls);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\tconst preparedResults = parsedInput.data.calls.map((request) =>\n\t\t\t\tpreparePortalCall(session, request),\n\t\t\t);\n\t\t\tconst executableCalls = preparedResults.filter(isPreparedPortalCall);\n\t\t\tconst approvalCalls = executableCalls.map(\n\t\t\t\t(executableCall) =>\n\t\t\t\t\t({\n\t\t\t\t\t\targuments: executableCall.validatedArguments,\n\t\t\t\t\t\tid: executableCall.input.id,\n\t\t\t\t\t\tnamespace: executableCall.tool.namespace,\n\t\t\t\t\t\ttool: executableCall.tool,\n\t\t\t\t\t\ttoolName: executableCall.tool.toolName,\n\t\t\t\t\t}) satisfies PortalApprovalCall,\n\t\t\t);\n\t\t\tconst allowDecision = { kind: 'allow' } satisfies PortalApprovalDecision;\n\t\t\tconst approval: PortalApprovalDecision =\n\t\t\t\tapprovalCalls.length === 0\n\t\t\t\t\t? allowDecision\n\t\t\t\t\t: (runtime.approval?.(\n\t\t\t\t\t\t\tapprovalCalls,\n\t\t\t\t\t\t\tcall.identity,\n\t\t\t\t\t\t\tparsedInput.data.portalApprovalToken,\n\t\t\t\t\t\t) ?? { kind: 'approval_configuration_missing' });\n\n\t\t\tconst results: Record<string, PortalToolResult> = {};\n\t\t\tconst callsToExecute: PreparedPortalCall[] = [];\n\t\t\tfor (const preparedResult of preparedResults) {\n\t\t\t\tif (!isPreparedPortalCall(preparedResult)) {\n\t\t\t\t\tconst input = preparedResult.input;\n\t\t\t\t\tif (typeof input === 'object' && input !== null && 'id' in input) {\n\t\t\t\t\t\tconst id = input.id;\n\t\t\t\t\t\tif (typeof id === 'string') {\n\t\t\t\t\t\t\tresults[id] = preparedResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (approval.kind === 'approval_required') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_required',\n\t\t\t\t\t\t\tlevel: approval.level,\n\t\t\t\t\t\t\tmessage: 'Operator approval is required before this batch can run.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_token_missing') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_token_missing',\n\t\t\t\t\t\t\tmessage: 'An MCP Portal approval token is required before this batch can run.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_token_invalid') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_token_invalid',\n\t\t\t\t\t\t\tmessage: `MCP Portal approval token is invalid: ${approval.reason}.`,\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\treason: approval.reason,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (approval.kind === 'approval_configuration_missing') {\n\t\t\t\t\tresults[preparedResult.input.id] = itemError({\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'approval_configuration_missing',\n\t\t\t\t\t\t\tmessage: 'MCP Portal approval evaluation is not configured.',\n\t\t\t\t\t\t\tnamespace: preparedResult.tool.namespace,\n\t\t\t\t\t\t\ttoolName: preparedResult.tool.toolName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinput: { ...preparedResult.input, arguments: preparedResult.validatedArguments },\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcallsToExecute.push(preparedResult);\n\t\t\t}\n\t\t\tawait addExecutableCallResults({\n\t\t\t\tidentity: call.identity,\n\t\t\t\tpreparedCalls: callsToExecute,\n\t\t\t\tresults,\n\t\t\t\truntime,\n\t\t\t});\n\n\t\t\treturn portalBatchResult(results, discoveryDiagnostics(session));\n\t\t},\n\t\tasync describe(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = describeInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tdescribeRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t\tasync list(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = listInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tlistRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t\tasync search(call: PortalToolHandlerCall): Promise<PortalBatchResult> {\n\t\t\tconst parsedInput = searchInputSchema.safeParse(call.input);\n\t\t\tif (!parsedInput.success) {\n\t\t\t\treturn invalidPortalInput(parsedInput.error);\n\t\t\t}\n\t\t\tconst duplicateResult = duplicateIdResult(parsedInput.data.requests);\n\t\t\tif (duplicateResult) {\n\t\t\t\treturn duplicateResult;\n\t\t\t}\n\n\t\t\tconst session = await runtime.getSession(call.identity);\n\t\t\treturn portalBatchResult(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tparsedInput.data.requests.map((request) => [\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\tsearchRequestResult(session, request),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t\tdiscoveryDiagnostics(session),\n\t\t\t);\n\t\t},\n\t};\n}\n"],"mappings":"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"}