@agent-vm/openclaw-mcp-portal-plugin 0.0.92 → 0.0.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/openclaw-plugin-api.ts","../src/plugin-registration.ts","../src/portal-plugin-runtime-state.ts","../src/before-prompt-build-handler.ts","../src/portal-tool-policy.ts","../src/before-tool-call-handler.ts","../src/portal-config.ts","../src/portal-prompt-context.ts","../src/redaction.ts","../src/index.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/openclaw-plugin-api.ts","../src/plugin-registration.ts","../src/portal-plugin-runtime-state.ts","../src/before-prompt-build-handler.ts","../src/portal-tool-policy.ts","../src/before-tool-call-handler.ts","../src/portal-config.ts","../src/portal-prompt-context.ts","../src/redaction.ts","../src/index.ts"],"mappings":";;;;;;UAEiB,yBAAA;EAAA,SACP,OAAA;EAAA,SACA,YAAA,IAAgB,OAAA;AAAA;AAAA,UAGT,yBAAA;EAAA,SACP,OAAA;EAAA,SACA,SAAA;EAAA,SACA,UAAA;AAAA;AAAA,KAGE,0BAAA,IAA8B,MAAA,cAAoB,OAAA;AAAA,UAE7C,8BAAA;EAAA,SACP,OAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGO,wBAAA;EAAA,SACP,WAAA;EAAA,SACA,OAAA,GACR,UAAA,UACA,MAAA,WACA,MAAA,GAAS,WAAA,EACT,QAAA,GAAW,0BAAA,KACP,OAAA,CAAQ,8BAAA;EAAA,SACJ,KAAA;EAAA,SACA,IAAA;EAAA,SACA,UAAA;AAAA;AAAA,KAGE,mBAAA,IACX,OAAA,EAAS,yBAAA,KACL,wBAAA,YAAoC,wBAAA;AAAA,UAExB,yBAAA;EAAA,SACP,OAAA;EAAA,SACA,SAAA;EAAA,SACA,UAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;AAAA;AAAA,UAGO,6BAAA;EAAA,SACP,QAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAGO,8BAAA;EAAA,SACP,QAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAGO,2BAAA;EAAA,SACP,MAAA,EAAQ,MAAA;EAAA,SACR,UAAA;EAAA,SACA,QAAA;AAAA;AAAA,KAGE,0BAAA;AAAA,UAOK,4BAAA;EAAA,SACP,KAAA;EAAA,SACA,WAAA;EAAA,SACA,MAAA,GAAS,MAAA;EAAA,SACT,eAAA;IAAA,SACC,WAAA;IAAA,SACA,YAAA,IAAgB,QAAA,EAAU,0BAAA,KAA+B,OAAA;IAAA,SACzD,QAAA;IAAA,SACA,QAAA;IAAA,SACA,eAAA;IAAA,SACA,SAAA;IAAA,SACA,KAAA;EAAA;AAAA;AAAA,UAIM,wBAAA;EAAA,SACP,aAAA;EAAA,SACA,mBAAA;EAAA,SACA,cAAA;EAAA,SACA,oBAAA;AAAA;AAAA,KAGE,0BAAA;EAAA,SACF,kBAAA,EAAoB,6BAAA;EAAA,SACpB,mBAAA,EAAqB,8BAAA;EAAA,SACrB,gBAAA,EAAkB,2BAAA;AAAA;AAAA,KAGhB,2BAAA;EAAA,SACF,kBAAA,EAAoB,wBAAA;EAAA,SACpB,mBAAA,EAAqB,wBAAA;EAAA,SACrB,gBAAA,EAAkB,4BAAA;AAAA;AAAA,UAGX,yBAAA;EAAA,SACP,QAAA;EAAA,SACA,SAAA;AAAA;AAAA,UAGO,6BAAA;EAAA,SACP,IAAA;EAAA,SACA,OAAA,GACR,OAAA,EAAS,eAAA,EACT,QAAA,EAAU,cAAA,KACN,OAAA;EAAA,SACI,KAAA;EAAA,SACA,IAAA;EAAA,SACA,eAAA;AAAA;AAAA,UAGO,qBAAA;EAAA,SACP,EAAA;EAAA,SACA,KAAA,QAAa,OAAA;EAAA,SACb,IAAA,SAAa,OAAA;AAAA;AAAA,KAGX,+BAAA;AAAA,UAEK,oCAAA;EAAA,SACP,EAAA;EAAA,SACA,WAAA;EAAA,SACA,OAAA,IAAW,OAAA;IAAA,SACV,MAAA,EAAQ,+BAAA;IAAA,SACR,UAAA;IAAA,SACA,KAAA;EAAA,MACJ,OAAA;AAAA;AAAA,KAGK,iCAAA,IACX,SAAA,EAAW,oCAAA;AAAA,UAGK,uBAAA;EAAA,SACP,MAAA;EAAA,SACA,SAAA;IAAA,SACC,wBAAA,EAA0B,iCAAA;EAAA;EAAA,SAE3B,MAAA;IAAA,SACC,KAAA,IAAS,OAAA;IAAA,SACT,KAAA,IAAS,OAAA;IAAA,SACT,IAAA,IAAQ,OAAA;IAAA,SACR,IAAA,IAAQ,OAAA;EAAA;EAAA,SAET,YAAA;EAAA,SACA,gBAAA;EAAA,SACA,YAAA,IACR,IAAA,EAAM,wBAAA,GAA2B,mBAAA,EACjC,OAAA;IAAA,SACU,IAAA;IAAA,SACA,KAAA;IAAA,SACA,QAAA;EAAA;EAAA,SAGF,wBAAA,GAA2B,iCAAA;EAAA,SAC3B,eAAA,IAAmB,OAAA,EAAS,qBAAA;EAAA,SAC5B,EAAA,4BAA8B,0BAAA,EACtC,QAAA,EAAU,SAAA,EACV,OAAA,GACC,KAAA,EAAO,0BAAA,CAA2B,SAAA,GAClC,OAAA,EAAS,yBAAA,KAEP,2BAAA,CAA4B,SAAA,IAC5B,OAAA,CAAQ,2BAAA,CAA4B,SAAA,kBAEvC,OAAA,GAAU,yBAAA;EAAA,SAEF,kBAAA,IACR,QAAA,gDACA,OAAA,GAAU,OAAA,EAAS,yBAAA,KAA8B,OAAA;EAAA,SAEzC,iBAAA,IAAqB,YAAA,EAAc,6BAAA;AAAA;;;UC1InC,aAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;AAAA;AAAA,iBA2DM,gCAAA,CAAiC,KAAA;EAAA,SACvC,IAAA;EAAA,SACA,OAAA,EAAS,aAAA;AAAA;AAAA,iBA2BH,uBAAA,CAAwB,GAAA,EAAK,uBAAA;AAAA,iBAuQ7B,uBAAA,CAAwB,GAAA,EAAK,uBAAA;AAAA,cAqFvC,WAAA;;;;mBAKuB,uBAAA;AAAA;;;UC7dZ,wBAAA;EAAA,SACP,sBAAA,GACR,OAAA,UACA,GAAA,UACA,WAAA;IAAA,SAEa,EAAA;EAAA;IAAA,SACA,EAAA;IAAA,SAAoB,MAAA;EAAA;EAAA,SACzB,SAAA;EAAA,SACA,kBAAA,QAA0B,MAAA;EAAA,SAC1B,qBAAA,QAA6B,eAAA;EAAA,SAC7B,0BAAA;EAAA,SACA,gBAAA,QAAwB,OAAA,CAAQ,eAAA;EAAA,SAChC,mBAAA;EAAA,SACA,qBAAA,GAAwB,MAAA;AAAA;AAAA,iBAGlB,8BAAA,CAA+B,KAAA;EAAA,SACrC,SAAA;EAAA,SACA,gBAAA,IAAoB,IAAA,aAAiB,OAAA,CAAQ,eAAA;AAAA,IACnD,wBAAA;;;UCjBa,mCAAA;EAAA,SACP,YAAA,EAAc,wBAAA;AAAA;AAAA,iBAGR,8BAAA,CACf,KAAA,EAAO,mCAAA,IAEP,KAAA,EAAO,8BAAA,EACP,OAAA,EAAS,yBAAA,KACL,OAAA,CAAQ,wBAAA;;;UCZI,iBAAA;EAAA,SACP,SAAA,EAAW,MAAA;EAAA,SACX,EAAA;EAAA,SACA,SAAA;EAAA,SACA,QAAA;AAAA;AAAA,iBAGM,uBAAA,CACf,OAAA,EAAS,wBAAA,EACT,IAAA;EAAA,SAAiB,SAAA;EAAA,SAA4B,QAAA;AAAA;AAAA,iBAa9B,yBAAA,CACf,OAAA,EAAS,wBAAA,EACT,IAAA;EAAA,SAAiB,SAAA;EAAA,SAA4B,QAAA;AAAA,IAC3C,2BAAA;;;UCRc,gCAAA;EAAA,SACP,MAAA;IAAA,SACC,KAAA,IAAS,OAAA;IAAA,SACT,IAAA,IAAQ,OAAA;EAAA;EAAA,SAET,+BAAA,IAAmC,KAAA;IAAA,SAClC,OAAA;IAAA,SACA,aAAA,WAAwB,iBAAA;IAAA,SACxB,OAAA,EAAS,yBAAA;IAAA,SACT,MAAA,EAAQ,MAAA;EAAA,MACZ,OAAA,UAAiB,uBAAA;EAAA,SACd,YAAA,EAAc,wBAAA;AAAA;AAAA,iBAgGR,2BAAA,CACf,KAAA,EAAO,gCAAA,IAEP,KAAA,EAAO,2BAAA,EACP,OAAA,EAAS,yBAAA,KACL,OAAA,CAAQ,4BAAA;;;cCrIA,wBAAA,EAAwB,CAAA,CAAA,SAAA;;;KAMzB,kBAAA,GAAqB,CAAA,CAAE,KAAA,QAAa,wBAAA;AAAA,iBAEhC,iBAAA,CAAkB,KAAA,YAAiB,kBAAA;;;UCVlC,4BAAA;EAAA,SACP,SAAA;EAAA,SACA,SAAA;AAAA;AAAA,UAGO,sBAAA;EAAA,SACP,IAAA;EAAA,SACA,OAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA;AAAA;AAAA,iBASM,yBAAA,CAA0B,KAAA;EAAA,SAChC,WAAA,YAAuB,sBAAA;EAAA,SACvB,UAAA,WAAqB,4BAAA;AAAA;;;iBClBf,mBAAA,CAAoB,IAAA,UAAc,YAAA;;;cCSrC,uCAAA"}
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,27 @@ function createBeforePromptBuildHandler(props) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
//#endregion
|
|
27
|
+
//#region src/openclaw-tool-params.ts
|
|
28
|
+
function isObjectRecord$3(value) {
|
|
29
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30
|
+
}
|
|
31
|
+
function parseJsonObjectString(value) {
|
|
32
|
+
try {
|
|
33
|
+
const parsedValue = JSON.parse(value);
|
|
34
|
+
return isObjectRecord$3(parsedValue) ? parsedValue : null;
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function normalizeOpenClawToolParams(params) {
|
|
40
|
+
if (typeof params !== "string") return params;
|
|
41
|
+
return parseJsonObjectString(params) ?? params;
|
|
42
|
+
}
|
|
43
|
+
function normalizeOpenClawToolParamsRecord(params) {
|
|
44
|
+
const normalizedParams = normalizeOpenClawToolParams(params);
|
|
45
|
+
return isObjectRecord$3(normalizedParams) ? normalizedParams : null;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
27
48
|
//#region src/portal-tool-policy.ts
|
|
28
49
|
function profileAllowsPortalCall(profile, call) {
|
|
29
50
|
if (!profile.enabledNamespaces.includes(call.namespace)) return false;
|
|
@@ -110,7 +131,12 @@ function createBeforeToolCallHandler(props) {
|
|
|
110
131
|
blockReason: `mcp-portal: agent "${agentId}" is not configured.`
|
|
111
132
|
};
|
|
112
133
|
const profile = resolveMcpPortalProfile(portalConfig, agent.profile);
|
|
113
|
-
const
|
|
134
|
+
const params = normalizeOpenClawToolParamsRecord(event.params);
|
|
135
|
+
if (params === null) return {
|
|
136
|
+
block: true,
|
|
137
|
+
blockReason: "mcp-portal: malformed portal call batch."
|
|
138
|
+
};
|
|
139
|
+
const calls = parseCallRequests(params);
|
|
114
140
|
if (calls === null || calls.length === 0) return {
|
|
115
141
|
block: true,
|
|
116
142
|
blockReason: "mcp-portal: malformed portal call batch."
|
|
@@ -137,7 +163,7 @@ function createBeforeToolCallHandler(props) {
|
|
|
137
163
|
agentId,
|
|
138
164
|
approvalCalls,
|
|
139
165
|
context,
|
|
140
|
-
params
|
|
166
|
+
params
|
|
141
167
|
}) ?? fallbackApprovalTokenCallDigests(approvalCalls);
|
|
142
168
|
if (callDigests.length !== approvalCalls.length) throw new Error(`prepared ${callDigests.length} approval token digests for ${approvalCalls.length} approval call(s)`);
|
|
143
169
|
portalApprovalToken = approvalTokenForCallDigests({
|
|
@@ -156,7 +182,7 @@ function createBeforeToolCallHandler(props) {
|
|
|
156
182
|
const approvalPreview = approvalCalls.map(approvalCallPreview).join("\n");
|
|
157
183
|
return {
|
|
158
184
|
params: {
|
|
159
|
-
...
|
|
185
|
+
...params,
|
|
160
186
|
portalApprovalToken
|
|
161
187
|
},
|
|
162
188
|
requireApproval: {
|
|
@@ -442,6 +468,7 @@ function createNativeTool(props) {
|
|
|
442
468
|
description: props.descriptor.description,
|
|
443
469
|
execute: async (_toolCallId, params, signal, onUpdate) => {
|
|
444
470
|
if (props.context.agentId === void 0 || props.context.agentId.length === 0) throw new Error("mcp-portal: OpenClaw did not provide a trusted agentId.");
|
|
471
|
+
const normalizedParams = normalizeOpenClawToolParams(params);
|
|
445
472
|
const core = await props.getCore();
|
|
446
473
|
const scope = core.createAgentScope({
|
|
447
474
|
agentId: props.context.agentId,
|
|
@@ -451,7 +478,7 @@ function createNativeTool(props) {
|
|
|
451
478
|
source: "openclaw-trusted"
|
|
452
479
|
});
|
|
453
480
|
const result = await core.collectPortalCoreResult(core.callStream({
|
|
454
|
-
input:
|
|
481
|
+
input: normalizedParams,
|
|
455
482
|
scope,
|
|
456
483
|
...signal !== void 0 ? { signal } : {},
|
|
457
484
|
toolName: props.descriptor.name
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isObjectRecord","isObjectRecord"],"sources":["../src/before-prompt-build-handler.ts","../src/portal-tool-policy.ts","../src/before-tool-call-handler.ts","../src/effective-config-manifest.ts","../src/portal-config.ts","../src/portal-plugin-runtime-state.ts","../src/plugin-registration.ts","../src/portal-prompt-context.ts","../src/redaction.ts","../src/index.ts"],"sourcesContent":["import { resolveMcpPortalProfile } from '@agent-vm/config-contracts';\n\nimport type {\n\tOpenClawBeforePromptBuildEvent,\n\tOpenClawPluginHookContext,\n\tOpenClawPromptHookResult,\n} from './openclaw-plugin-api.js';\nimport type { PortalPluginRuntimeState } from './portal-plugin-runtime-state.js';\n\nexport interface CreateBeforePromptBuildHandlerProps {\n\treadonly runtimeState: PortalPluginRuntimeState;\n}\n\nexport function createBeforePromptBuildHandler(\n\tprops: CreateBeforePromptBuildHandlerProps,\n): (\n\tevent: OpenClawBeforePromptBuildEvent,\n\tcontext: OpenClawPluginHookContext,\n) => Promise<OpenClawPromptHookResult | undefined> {\n\treturn async (_event, context) => {\n\t\tconst agentId = context.agentId;\n\t\tif (agentId === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst portalConfig = await props.runtimeState.loadPortalConfig();\n\t\tconst agent = portalConfig.agents[agentId];\n\t\tif (agent === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst profile = resolveMcpPortalProfile(portalConfig, agent.profile);\n\t\tif (!profile.promptContext.enabled) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst namespaces = profile.enabledNamespaces\n\t\t\t.toSorted()\n\t\t\t.slice(0, profile.promptContext.maxNamespaces);\n\t\tconst namespaceText =\n\t\t\tnamespaces.length === 0\n\t\t\t\t? ' (none in your profile)'\n\t\t\t\t: namespaces.map((name) => ` ${name}`).join('\\n');\n\t\treturn {\n\t\t\tappendSystemContext: [\n\t\t\t\t'MCP Portal namespaces available to this agent:',\n\t\t\t\tnamespaceText,\n\t\t\t\t'Use mcp_portal_search to find tools by intent, then mcp_portal_describe before mcp_portal_call.',\n\t\t\t].join('\\n'),\n\t\t};\n\t};\n}\n","import {\n\tmcpPortalCallPolicyDecision,\n\ttype McpPortalCallPolicyDecision,\n\ttype ResolvedMcpPortalProfile,\n} from '@agent-vm/config-contracts';\n\nexport interface PortalCallRequest {\n\treadonly arguments: Record<string, unknown>;\n\treadonly id: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}\n\nexport function profileAllowsPortalCall(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: { readonly namespace: string; readonly toolName: string },\n): boolean {\n\tif (!profile.enabledNamespaces.includes(call.namespace)) {\n\t\treturn false;\n\t}\n\tconst enabledTools = profile.enabledToolsByNamespace[call.namespace];\n\tif (enabledTools !== undefined && !enabledTools.includes(call.toolName)) {\n\t\treturn false;\n\t}\n\tconst hiddenTools = profile.hiddenToolsByNamespace[call.namespace] ?? [];\n\treturn !hiddenTools.includes(call.toolName);\n}\n\nexport function profilePortalCallDecision(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: { readonly namespace: string; readonly toolName: string },\n): McpPortalCallPolicyDecision {\n\treturn mcpPortalCallPolicyDecision(profile, call);\n}\n","import { resolveMcpPortalProfile } from '@agent-vm/config-contracts';\nimport {\n\thashCallArguments,\n\tsignApprovalToken,\n\ttype ApprovalTokenCallDigest,\n} from '@agent-vm/mcp-portal/portal-auth/hmac-token';\n\nimport type {\n\tOpenClawBeforeToolCallEvent,\n\tOpenClawBeforeToolCallResult,\n\tOpenClawPluginHookContext,\n} from './openclaw-plugin-api.js';\nimport type { PortalPluginRuntimeState } from './portal-plugin-runtime-state.js';\nimport {\n\tprofileAllowsPortalCall,\n\tprofilePortalCallDecision,\n\ttype PortalCallRequest,\n} from './portal-tool-policy.js';\n\nconst approvalPromptTimeoutMs = 60_000;\nconst approvalTokenLifetimeMs = 5 * 60_000;\n\nexport interface CreateBeforeToolCallHandlerProps {\n\treadonly logger?: {\n\t\treadonly error?: (message: string) => void;\n\t\treadonly warn?: (message: string) => void;\n\t};\n\treadonly resolveApprovalTokenCallDigests?: (props: {\n\t\treadonly agentId: string;\n\t\treadonly approvalCalls: readonly PortalCallRequest[];\n\t\treadonly context: OpenClawPluginHookContext;\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<readonly ApprovalTokenCallDigest[]>;\n\treadonly runtimeState: PortalPluginRuntimeState;\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseCallRequest(value: unknown): PortalCallRequest | null {\n\tif (!isObjectRecord(value)) {\n\t\treturn null;\n\t}\n\tconst id = value.id;\n\tconst namespace = value.namespace;\n\tconst toolName = value.toolName;\n\tconst argumentsValue = value.arguments;\n\tif (\n\t\ttypeof id !== 'string' ||\n\t\ttypeof namespace !== 'string' ||\n\t\ttypeof toolName !== 'string' ||\n\t\t!isObjectRecord(argumentsValue)\n\t) {\n\t\treturn null;\n\t}\n\treturn { arguments: argumentsValue, id, namespace, toolName };\n}\n\nfunction parseCallRequests(params: Record<string, unknown>): readonly PortalCallRequest[] | null {\n\tconst calls = params.calls;\n\tif (!Array.isArray(calls)) {\n\t\treturn null;\n\t}\n\tconst parsedCalls: PortalCallRequest[] = [];\n\tfor (const call of calls) {\n\t\tconst parsedCall = parseCallRequest(call);\n\t\tif (parsedCall === null) {\n\t\t\treturn null;\n\t\t}\n\t\tparsedCalls.push(parsedCall);\n\t}\n\treturn parsedCalls;\n}\n\nfunction fallbackApprovalTokenCallDigests(\n\tcalls: readonly PortalCallRequest[],\n): readonly ApprovalTokenCallDigest[] {\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\nfunction approvalTokenForCallDigests(props: {\n\treadonly agentId: string;\n\treadonly callDigests: readonly ApprovalTokenCallDigest[];\n\treadonly key: Buffer;\n\treadonly nowMs?: number;\n}): string {\n\tconst nowMs = props.nowMs ?? Date.now();\n\treturn signApprovalToken({\n\t\tagentId: props.agentId,\n\t\tcalls: props.callDigests,\n\t\texpiresAtMs: nowMs + approvalTokenLifetimeMs,\n\t\tissuedAtMs: nowMs,\n\t\tkey: props.key,\n\t});\n}\n\nfunction redactApprovalPreviewValue(key: string, value: unknown): unknown {\n\tif (/token|secret|password|credential|api[-_]?key/iu.test(key)) {\n\t\treturn '[redacted]';\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => redactApprovalPreviewValue(key, entry));\n\t}\n\tif (typeof value === 'object' && value !== null) {\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(value).map(([entryKey, entryValue]) => [\n\t\t\t\tentryKey,\n\t\t\t\tredactApprovalPreviewValue(entryKey, entryValue),\n\t\t\t]),\n\t\t);\n\t}\n\treturn value;\n}\n\nfunction approvalCallPreview(call: PortalCallRequest): string {\n\tconst redactedArguments = redactApprovalPreviewValue('arguments', call.arguments);\n\tconst serializedArguments = JSON.stringify(redactedArguments);\n\tconst preview =\n\t\tserializedArguments.length > 500\n\t\t\t? `${serializedArguments.slice(0, 497)}...`\n\t\t\t: serializedArguments;\n\treturn `${call.id}: ${call.namespace}.${call.toolName} args=${preview}`;\n}\n\nexport function createBeforeToolCallHandler(\n\tprops: CreateBeforeToolCallHandlerProps,\n): (\n\tevent: OpenClawBeforeToolCallEvent,\n\tcontext: OpenClawPluginHookContext,\n) => Promise<OpenClawBeforeToolCallResult | undefined> {\n\treturn async (event, context) => {\n\t\tif (event.toolName !== 'mcp_portal_call') {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (context.agentId === undefined) {\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\tblockReason: `mcp-portal: missing OpenClaw agent context for ${event.toolName}.`,\n\t\t\t};\n\t\t}\n\t\tconst portalConfig = await props.runtimeState.loadPortalConfig();\n\t\tconst agentId = context.agentId;\n\t\tconst agent = portalConfig.agents[agentId];\n\t\tif (agent === undefined) {\n\t\t\treturn { block: true, blockReason: `mcp-portal: agent \"${agentId}\" is not configured.` };\n\t\t}\n\t\tconst profile = resolveMcpPortalProfile(portalConfig, agent.profile);\n\t\tconst calls = parseCallRequests(event.params);\n\t\tif (calls === null || calls.length === 0) {\n\t\t\treturn { block: true, blockReason: 'mcp-portal: malformed portal call batch.' };\n\t\t}\n\n\t\tconst disabledCalls = calls.filter((call) => !profileAllowsPortalCall(profile, call));\n\t\tif (disabledCalls.length > 0) {\n\t\t\tif (disabledCalls.length === calls.length) {\n\t\t\t\tconst call = disabledCalls[0];\n\t\t\t\treturn {\n\t\t\t\t\tblock: true,\n\t\t\t\t\tblockReason:\n\t\t\t\t\t\tcall === undefined\n\t\t\t\t\t\t\t? `policy: ${agentId} has no enabled MCP Portal calls in this batch`\n\t\t\t\t\t\t\t: `policy: ${agentId}/${call.namespace}/${call.toolName} not enabled`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst approvalCalls: PortalCallRequest[] = [];\n\t\tfor (const call of calls) {\n\t\t\tconst decision = profilePortalCallDecision(profile, call);\n\t\t\tif (decision.kind === 'requires_approval') {\n\t\t\t\tapprovalCalls.push(call);\n\t\t\t}\n\t\t}\n\t\tif (approvalCalls.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (approvalCalls.length !== calls.length) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst toolNames = approvalCalls\n\t\t\t.map((call) => `${call.namespace}.${call.toolName}`)\n\t\t\t.toSorted()\n\t\t\t.join(', ');\n\t\tlet portalApprovalToken: string;\n\t\ttry {\n\t\t\tconst callDigests =\n\t\t\t\t(await props.resolveApprovalTokenCallDigests?.({\n\t\t\t\t\tagentId,\n\t\t\t\t\tapprovalCalls,\n\t\t\t\t\tcontext,\n\t\t\t\t\tparams: event.params,\n\t\t\t\t})) ?? fallbackApprovalTokenCallDigests(approvalCalls);\n\t\t\tif (callDigests.length !== approvalCalls.length) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`prepared ${callDigests.length} approval token digests for ${approvalCalls.length} approval call(s)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tportalApprovalToken = approvalTokenForCallDigests({\n\t\t\t\tagentId,\n\t\t\t\tcallDigests,\n\t\t\t\tkey: props.runtimeState.getApprovalHmacKey(),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = `mcp-portal: failed to prepare approval token: ${\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t}`;\n\t\t\tprops.logger?.error?.(message);\n\t\t\treturn { block: true, blockReason: message };\n\t\t}\n\t\tconst approvalPreview = approvalCalls.map(approvalCallPreview).join('\\n');\n\t\treturn {\n\t\t\tparams: { ...event.params, portalApprovalToken },\n\t\t\trequireApproval: {\n\t\t\t\tdescription: `Allow MCP Portal batch for agent ${agentId}:\\n${approvalPreview}`,\n\t\t\t\tpluginId: 'mcp-portal',\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttimeoutBehavior: 'deny',\n\t\t\t\ttimeoutMs: approvalPromptTimeoutMs,\n\t\t\t\ttitle: `MCP Portal batch: ${toolNames}`,\n\t\t\t},\n\t\t};\n\t};\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nconst effectiveConfigManifestFileName = 'mcp-portal-effective-manifest.json';\n\nexport interface EffectiveConfigPaths {\n\treadonly mcpConfigPath: string;\n\treadonly portalConfigPath: string;\n}\n\nfunction isObjectRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isSafeManifestFileName(value: string): boolean {\n\treturn value.length > 0 && !value.includes('/') && !value.includes('\\\\');\n}\n\nfunction parseEffectiveConfigManifest(value: unknown): {\n\treadonly mcpConfigFile: string;\n\treadonly portalConfigFile: string;\n} {\n\tif (!isObjectRecord(value)) {\n\t\tthrow new Error('MCP Portal effective config manifest must be an object.');\n\t}\n\tif (value.schemaVersion !== 1) {\n\t\tthrow new Error('MCP Portal effective config manifest must use schemaVersion 1.');\n\t}\n\tif (typeof value.mcpConfigFile !== 'string' || !isSafeManifestFileName(value.mcpConfigFile)) {\n\t\tthrow new Error('MCP Portal effective config manifest must contain a safe mcpConfigFile.');\n\t}\n\tif (\n\t\ttypeof value.portalConfigFile !== 'string' ||\n\t\t!isSafeManifestFileName(value.portalConfigFile)\n\t) {\n\t\tthrow new Error('MCP Portal effective config manifest must contain a safe portalConfigFile.');\n\t}\n\treturn {\n\t\tmcpConfigFile: value.mcpConfigFile,\n\t\tportalConfigFile: value.portalConfigFile,\n\t};\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n\treturn (\n\t\tisObjectRecord(error) &&\n\t\ttypeof error.code === 'string' &&\n\t\t(error.code === 'ENOENT' || error.code === 'ENOTDIR')\n\t);\n}\n\nexport async function resolveEffectiveConfigPaths(\n\tconfigDir: string,\n): Promise<EffectiveConfigPaths> {\n\tconst manifestPath = join(configDir, effectiveConfigManifestFileName);\n\tlet manifestText: string;\n\ttry {\n\t\tmanifestText = await readFile(manifestPath, 'utf8');\n\t} catch (error) {\n\t\tif (isMissingFileError(error)) {\n\t\t\treturn {\n\t\t\t\tmcpConfigPath: join(configDir, 'mcp.config.jsonc'),\n\t\t\t\tportalConfigPath: join(configDir, 'mcp-portal.config.jsonc'),\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n\tconst manifest = parseEffectiveConfigManifest(JSON.parse(manifestText));\n\treturn {\n\t\tmcpConfigPath: join(configDir, manifest.mcpConfigFile),\n\t\tportalConfigPath: join(configDir, manifest.portalConfigFile),\n\t};\n}\n","import { z } from 'zod';\n\nexport const portalPluginConfigSchema = z\n\t.object({\n\t\tconfigDir: z.string().min(1),\n\t})\n\t.strict();\n\nexport type PortalPluginConfig = z.infer<typeof portalPluginConfigSchema>;\n\nexport function parsePortalConfig(value: unknown): PortalPluginConfig {\n\treturn portalPluginConfigSchema.parse(value ?? {});\n}\n","import { randomBytes } from 'node:crypto';\n\nimport { loadMcpPortalConfig, type McpPortalConfig } from '@agent-vm/config-contracts';\n\nimport { resolveEffectiveConfigPaths } from './effective-config-manifest.js';\n\nexport interface PortalPluginRuntimeState {\n\treadonly consumeApprovalTokenId: (\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\treadonly configDir: string;\n\treadonly getApprovalHmacKey: () => Buffer;\n\treadonly getLoadedPortalConfig: () => McpPortalConfig | null;\n\treadonly getPortalUnavailableReason: () => string | null;\n\treadonly loadPortalConfig: () => Promise<McpPortalConfig>;\n\treadonly markPortalAvailable: () => void;\n\treadonly markPortalUnavailable: (reason: string) => void;\n}\n\nexport function createPortalPluginRuntimeState(props: {\n\treadonly configDir: string;\n\treadonly loadPortalConfig?: (path: string) => Promise<McpPortalConfig>;\n}): PortalPluginRuntimeState {\n\tlet loadedPortalConfig: McpPortalConfig | null = null;\n\tlet portalConfigPromise: Promise<McpPortalConfig> | null = null;\n\tlet portalUnavailableReason: string | null = null;\n\tconst approvalHmacKey = randomBytes(32);\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = 4096;\n\tconst replayCacheCleanupThreshold = replayCacheLimit / 2;\n\tconst loadPortalConfigFile = props.loadPortalConfig ?? loadMcpPortalConfig;\n\n\tfunction loadPortalConfig(): Promise<McpPortalConfig> {\n\t\tif (portalConfigPromise !== null) {\n\t\t\treturn portalConfigPromise;\n\t\t}\n\t\tconst nextPromise = resolveEffectiveConfigPaths(props.configDir)\n\t\t\t.then((effectiveConfigPaths) => loadPortalConfigFile(effectiveConfigPaths.portalConfigPath))\n\t\t\t.then((portalConfig) => {\n\t\t\t\tloadedPortalConfig = portalConfig;\n\t\t\t\treturn portalConfig;\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (portalConfigPromise === nextPromise) {\n\t\t\t\t\tportalConfigPromise = null;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tportalConfigPromise = nextPromise;\n\t\treturn portalConfigPromise;\n\t}\n\n\tfunction sweepExpiredApprovalTokenIds(nowMs: number): void {\n\t\tif (consumedApprovalTokenIds.size < replayCacheCleanupThreshold) {\n\t\t\treturn;\n\t\t}\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}\n\n\treturn {\n\t\tconsumeApprovalTokenId: (agentId, jti, expiresAtMs) => {\n\t\t\tconst nowMs = Date.now();\n\t\t\tsweepExpiredApprovalTokenIds(nowMs);\n\t\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t\t}\n\t\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t\t}\n\t\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\t\treturn { ok: true };\n\t\t},\n\t\tconfigDir: props.configDir,\n\t\tgetApprovalHmacKey: () => approvalHmacKey,\n\t\tgetLoadedPortalConfig: () => loadedPortalConfig,\n\t\tgetPortalUnavailableReason: () => portalUnavailableReason,\n\t\tloadPortalConfig,\n\t\tmarkPortalAvailable: () => {\n\t\t\tportalUnavailableReason = null;\n\t\t},\n\t\tmarkPortalUnavailable: (reason) => {\n\t\t\tportalUnavailableReason = reason;\n\t\t},\n\t};\n}\n","import {\n\tloadMcpConfig,\n\tloadMcpPortalConfig,\n\ttype McpPortalConfig,\n\tresolveMcpPortalProfile,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\nimport {\n\tcreatePortalCore,\n\tcreatePortalPolicyApprovalEvaluator,\n\tcreateUpstreamMcpClientRuntime,\n\tlistPortalCoreToolDescriptors,\n\tresolveUpstreamServers,\n\ttype PortalCore,\n\ttype PortalCoreEvent,\n\ttype PortalCoreToolDescriptor,\n\ttype PortalToolSelector,\n} from '@agent-vm/mcp-portal/core';\n\nimport { createBeforePromptBuildHandler } from './before-prompt-build-handler.js';\nimport { createBeforeToolCallHandler } from './before-tool-call-handler.js';\nimport { resolveEffectiveConfigPaths } from './effective-config-manifest.js';\nimport type {\n\tOpenClawPortalPluginApi,\n\tOpenClawPluginToolContext,\n\tOpenClawToolRegistration,\n\tOpenClawToolUpdateCallback,\n} from './openclaw-plugin-api.js';\nimport { parsePortalConfig } from './portal-config.js';\nimport { createPortalPluginRuntimeState } from './portal-plugin-runtime-state.js';\n\ninterface PortalPluginEntry {\n\treadonly description: string;\n\treadonly id: string;\n\treadonly name: string;\n\treadonly register: (api: OpenClawPortalPluginApi) => void;\n}\n\ninterface TcpPoolConfig {\n\treadonly basePort: number;\n\treadonly size: number;\n}\n\ninterface ProfilePolicyMaps {\n\treadonly cacheTtlMs: number;\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\nconst pluginId = 'mcp-portal';\n\nfunction hasFunction(value: unknown): value is (...args: readonly unknown[]) => unknown {\n\treturn typeof value === 'function';\n}\n\nfunction isObjectRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isUnknownArray(value: unknown): value is readonly unknown[] {\n\treturn Array.isArray(value);\n}\n\nfunction getObjectProperty(value: unknown, property: string): unknown {\n\treturn isObjectRecord(value) ? value[property] : undefined;\n}\n\nfunction resolveConfigDir(api: OpenClawPortalPluginApi): string {\n\tif (api.pluginConfig !== undefined) {\n\t\treturn parsePortalConfig(api.pluginConfig).configDir;\n\t}\n\t// Managed agent-vm passes pluginConfig. The config fallbacks keep the plugin usable\n\t// in direct OpenClaw test harnesses that load plugin config through the root config.\n\tconst topLevelMcpConfigDir = getObjectProperty(\n\t\tgetObjectProperty(api.config, 'mcpPortal'),\n\t\t'configDir',\n\t);\n\tif (typeof topLevelMcpConfigDir === 'string' && topLevelMcpConfigDir.length > 0) {\n\t\treturn topLevelMcpConfigDir;\n\t}\n\tconst zones = getObjectProperty(api.config, 'zones');\n\tif (isUnknownArray(zones)) {\n\t\tconst firstZone = zones.at(0);\n\t\tconst zoneMcpConfigDir = getObjectProperty(\n\t\t\tgetObjectProperty(firstZone, 'mcpPortal'),\n\t\t\t'configDir',\n\t\t);\n\t\tif (typeof zoneMcpConfigDir === 'string' && zoneMcpConfigDir.length > 0) {\n\t\t\treturn zoneMcpConfigDir;\n\t\t}\n\t}\n\tthrow new Error(\n\t\t'MCP Portal plugin requires configDir in plugin config or zone mcpPortal config.',\n\t);\n}\n\nexport function validatePortalPortAgainstTcpPool(props: {\n\treadonly port: number;\n\treadonly tcpPool: TcpPoolConfig | null;\n}): void {\n\tif (props.tcpPool === null) {\n\t\treturn;\n\t}\n\tconst firstTcpPoolPort = props.tcpPool.basePort;\n\tconst lastTcpPoolPortExclusive = props.tcpPool.basePort + props.tcpPool.size;\n\tif (props.port >= firstTcpPoolPort && props.port < lastTcpPoolPortExclusive) {\n\t\tthrow new Error(\n\t\t\t`MCP Portal port ${String(props.port)} overlaps the Tool VM TCP pool ` +\n\t\t\t\t`[${String(firstTcpPoolPort)}, ${String(lastTcpPoolPortExclusive)}).`,\n\t\t);\n\t}\n}\n\nfunction createLoggerAdapter(api: OpenClawPortalPluginApi): {\n\treadonly error: (message: string) => void;\n\treadonly info: (message: string) => void;\n\treadonly warn: (message: string) => void;\n} {\n\treturn {\n\t\terror: (message) => api.logger?.error?.(message),\n\t\tinfo: (message) => api.logger?.info?.(message),\n\t\twarn: (message) => api.logger?.warn?.(message),\n\t};\n}\n\nexport function validatePortalPluginApi(api: OpenClawPortalPluginApi): void {\n\tif (!hasFunction(api.registerTool)) {\n\t\tthrow new Error('MCP Portal plugin requires OpenClaw registerTool API.');\n\t}\n\tif (!hasFunction(api.on)) {\n\t\tthrow new Error('MCP Portal plugin requires OpenClaw before_tool_call hook API.');\n\t}\n\tconst hasLifecycleCleanupApi =\n\t\thasFunction(api.lifecycle?.registerRuntimeLifecycle) ||\n\t\thasFunction(api.registerRuntimeLifecycle);\n\tif (hasLifecycleCleanupApi) {\n\t\treturn;\n\t}\n\tthrow new Error('MCP Portal plugin requires an OpenClaw lifecycle cleanup API.');\n}\n\nfunction registerPortalRuntimeCleanup(\n\tapi: OpenClawPortalPluginApi,\n\tcleanup: () => Promise<void> | void,\n): void {\n\tconst runtimeLifecycle = {\n\t\tcleanup: async () => {\n\t\t\tawait cleanup();\n\t\t},\n\t\tdescription: 'Closes MCP Portal upstream clients owned by the agent-vm plugin.',\n\t\tid: 'mcp-portal-core',\n\t} satisfies Parameters<NonNullable<OpenClawPortalPluginApi['registerRuntimeLifecycle']>>[0];\n\tif (hasFunction(api.lifecycle?.registerRuntimeLifecycle)) {\n\t\tapi.lifecycle.registerRuntimeLifecycle(runtimeLifecycle);\n\t\treturn;\n\t}\n\tif (hasFunction(api.registerRuntimeLifecycle)) {\n\t\tapi.registerRuntimeLifecycle(runtimeLifecycle);\n\t\treturn;\n\t}\n\tthrow new Error('MCP Portal plugin requires an OpenClaw lifecycle cleanup API.');\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\nfunction buildProfilePolicyMaps(portalConfig: McpPortalConfig): ProfilePolicyMaps {\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\nasync function resolveManagedPortalSecret(secret: SecretValue): Promise<string> {\n\tif (secret.source !== 'environment') {\n\t\tthrow new Error(\n\t\t\t'MCP Portal managed OpenClaw effective config must use environment secret refs.',\n\t\t);\n\t}\n\tconst value = process.env[secret.name];\n\tif (value === undefined || value.length === 0) {\n\t\tthrow new Error(`Missing environment secret ${secret.name} for MCP Portal native plugin.`);\n\t}\n\treturn value;\n}\n\nasync function createManagedPortalCore(\n\tconfigDir: string,\n\truntimeState: ReturnType<typeof createPortalPluginRuntimeState>,\n): Promise<PortalCore> {\n\tconst effectiveConfigPaths = await resolveEffectiveConfigPaths(configDir);\n\tconst [mcpConfig, portalConfig] = await Promise.all([\n\t\tloadMcpConfig(effectiveConfigPaths.mcpConfigPath),\n\t\tloadMcpPortalConfig(effectiveConfigPaths.portalConfigPath),\n\t]);\n\tconst upstreamServers = await resolveUpstreamServers({\n\t\tconfig: mcpConfig,\n\t\tresolveSecret: resolveManagedPortalSecret,\n\t});\n\tconst upstreamRuntime = createUpstreamMcpClientRuntime({ servers: upstreamServers });\n\tconst profilePolicyMaps = buildProfilePolicyMaps(portalConfig);\n\tconst approval = createPortalPolicyApprovalEvaluator({\n\t\tconsumeTokenId: (agentId, jti, expiresAtMs) =>\n\t\t\truntimeState.consumeApprovalTokenId(agentId, jti, expiresAtMs),\n\t\tmissingApprovalTokenDecision: { kind: 'approval_required', level: 'standard' },\n\t\tresolveRecord: (agentId) => {\n\t\t\tconst agent = portalConfig.agents[agentId];\n\t\t\tif (agent === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\thmacKey: runtimeState.getApprovalHmacKey(),\n\t\t\t\tprofile: resolveMcpPortalProfile(portalConfig, agent.profile),\n\t\t\t};\n\t\t},\n\t});\n\n\treturn 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,\n\t\tcatalogTtlMs: profilePolicyMaps.cacheTtlMs,\n\t\truntime: {\n\t\t\tcallUpstreamTool: upstreamRuntime.callTool,\n\t\t\tcloseAgentScope: upstreamRuntime.closeAgentScope,\n\t\t\tcloseSession: upstreamRuntime.closeSession,\n\t\t\tlistTools: upstreamRuntime.listTools,\n\t\t},\n\t\tupstreamNamespaces: upstreamServers.map((server) => server.namespace),\n\t});\n}\n\nfunction portalUpdateFromCoreEvent(event: PortalCoreEvent): Record<string, unknown> | null {\n\tif (event.kind === 'progress') {\n\t\treturn {\n\t\t\tmessage: event.message ?? 'MCP Portal progress',\n\t\t\t...(event.progress !== undefined ? { progress: event.progress } : {}),\n\t\t\trequestId: event.requestId,\n\t\t\t...(event.total !== undefined ? { total: event.total } : {}),\n\t\t\ttype: 'mcp_portal_progress',\n\t\t};\n\t}\n\tif (event.kind === 'partial_content') {\n\t\treturn {\n\t\t\tcontent: event.content,\n\t\t\trequestId: event.requestId,\n\t\t\ttype: 'mcp_portal_partial_content',\n\t\t};\n\t}\n\tif (event.kind === 'upstream_notification') {\n\t\treturn {\n\t\t\tmethod: event.method,\n\t\t\tparams: event.params,\n\t\t\trequestId: event.requestId,\n\t\t\ttype: 'mcp_portal_upstream_notification',\n\t\t};\n\t}\n\treturn null;\n}\n\nasync function forwardCoreEvent(\n\tevent: PortalCoreEvent,\n\tlogger: ReturnType<typeof createLoggerAdapter>,\n\tonUpdate: OpenClawToolUpdateCallback | undefined,\n): Promise<void> {\n\tconst update = portalUpdateFromCoreEvent(event);\n\tif (update !== null) {\n\t\ttry {\n\t\t\tawait onUpdate?.(update);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.warn(`[mcp-portal] OpenClaw onUpdate delivery failed: ${message}`);\n\t\t}\n\t}\n}\n\nfunction createNativeTool(props: {\n\treadonly context: OpenClawPluginToolContext;\n\treadonly descriptor: PortalCoreToolDescriptor;\n\treadonly getCore: () => Promise<PortalCore>;\n\treadonly logger: ReturnType<typeof createLoggerAdapter>;\n}): OpenClawToolRegistration {\n\treturn {\n\t\tdescription: props.descriptor.description,\n\t\texecute: async (_toolCallId, params, signal, onUpdate) => {\n\t\t\tif (props.context.agentId === undefined || props.context.agentId.length === 0) {\n\t\t\t\tthrow new Error('mcp-portal: OpenClaw did not provide a trusted agentId.');\n\t\t\t}\n\t\t\tconst core = await props.getCore();\n\t\t\tconst scope = core.createAgentScope({\n\t\t\t\tagentId: props.context.agentId,\n\t\t\t\tagentScopeId: props.context.agentId,\n\t\t\t\t...(props.context.sessionId ? { sessionId: props.context.sessionId } : {}),\n\t\t\t\t...(props.context.sessionKey ? { sessionKey: props.context.sessionKey } : {}),\n\t\t\t\tsource: 'openclaw-trusted',\n\t\t\t});\n\t\t\tconst result = await core.collectPortalCoreResult(\n\t\t\t\tcore.callStream({\n\t\t\t\t\tinput: params,\n\t\t\t\t\tscope,\n\t\t\t\t\t...(signal !== undefined ? { signal } : {}),\n\t\t\t\t\ttoolName: props.descriptor.name,\n\t\t\t\t}),\n\t\t\t\t{ onEvent: (event) => forwardCoreEvent(event, props.logger, onUpdate) },\n\t\t\t);\n\t\t\treturn { content: JSON.stringify(result), details: result };\n\t\t},\n\t\tlabel: props.descriptor.name,\n\t\tname: props.descriptor.name,\n\t\tparameters: props.descriptor.inputSchema,\n\t};\n}\n\nfunction descriptorsForOpenClawContext(props: {\n\treadonly context: OpenClawPluginToolContext;\n\treadonly portalConfig: McpPortalConfig | null;\n}): readonly PortalCoreToolDescriptor[] {\n\tif (props.portalConfig === null || props.context.agentId === undefined) {\n\t\treturn listPortalCoreToolDescriptors();\n\t}\n\tconst agent = props.portalConfig.agents[props.context.agentId];\n\tif (agent === undefined) {\n\t\treturn listPortalCoreToolDescriptors();\n\t}\n\tconst profile = resolveMcpPortalProfile(props.portalConfig, agent.profile);\n\treturn listPortalCoreToolDescriptors(profile.enabledNamespaces);\n}\n\nfunction registerNativePortalTools(props: {\n\treadonly api: OpenClawPortalPluginApi;\n\treadonly getCore: () => Promise<PortalCore>;\n\treadonly runtimeState: ReturnType<typeof createPortalPluginRuntimeState>;\n}): void {\n\tconst descriptorNames = listPortalCoreToolDescriptors().map((descriptor) => descriptor.name);\n\tconst logger = createLoggerAdapter(props.api);\n\tprops.api.registerTool?.(\n\t\t(context) => {\n\t\t\tconst descriptors = descriptorsForOpenClawContext({\n\t\t\t\tcontext,\n\t\t\t\tportalConfig: props.runtimeState.getLoadedPortalConfig(),\n\t\t\t});\n\t\t\treturn descriptors.map((descriptor) =>\n\t\t\t\tcreateNativeTool({ context, descriptor, getCore: props.getCore, logger }),\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tnames: descriptorNames,\n\t\t\toptional: true,\n\t\t},\n\t);\n}\n\nfunction shouldRegisterPortalRuntimeHooks(api: OpenClawPortalPluginApi): boolean {\n\treturn api.registrationMode === undefined || api.registrationMode === 'full';\n}\n\nfunction formatRegistrationMode(api: OpenClawPortalPluginApi): string {\n\treturn api.registrationMode ?? 'full';\n}\n\nexport function registerMcpPortalPlugin(api: OpenClawPortalPluginApi): void {\n\tconst logger = createLoggerAdapter(api);\n\tconst registerRuntimeHooks = shouldRegisterPortalRuntimeHooks(api);\n\tif (registerRuntimeHooks) {\n\t\tvalidatePortalPluginApi(api);\n\t} else if (!hasFunction(api.registerTool)) {\n\t\tlogger.warn(\n\t\t\t`[mcp-portal] skipped native portal tool registration for registrationMode='${formatRegistrationMode(api)}' because OpenClaw did not expose registerTool.`,\n\t\t);\n\t\treturn;\n\t}\n\tconst configDir = resolveConfigDir(api);\n\tconst runtimeState = createPortalPluginRuntimeState({ configDir });\n\tlet corePromise: Promise<PortalCore> | undefined;\n\tconst getCore = (): Promise<PortalCore> => {\n\t\tcorePromise ??= createManagedPortalCore(configDir, runtimeState).catch((error: unknown) => {\n\t\t\tcorePromise = undefined;\n\t\t\tthrow error;\n\t\t});\n\t\treturn corePromise;\n\t};\n\tregisterNativePortalTools({ api, getCore, runtimeState });\n\n\tif (!registerRuntimeHooks) {\n\t\tlogger.info(\n\t\t\t`[mcp-portal] registered native portal tools for registrationMode='${formatRegistrationMode(api)}'.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tapi.on?.(\n\t\t'before_tool_call',\n\t\tcreateBeforeToolCallHandler({\n\t\t\tlogger,\n\t\t\tresolveApprovalTokenCallDigests: async ({ agentId, approvalCalls, context, params }) => {\n\t\t\t\tconst core = await getCore();\n\t\t\t\tconst scope = core.createAgentScope({\n\t\t\t\t\tagentId,\n\t\t\t\t\tagentScopeId: agentId,\n\t\t\t\t\t...(context.sessionId ? { sessionId: context.sessionId } : {}),\n\t\t\t\t\t...(context.sessionKey ? { sessionKey: context.sessionKey } : {}),\n\t\t\t\t\tsource: 'openclaw-trusted',\n\t\t\t\t});\n\t\t\t\tconst digestsByCallId = await core.approval.prepareCallDigests({ input: params, scope });\n\t\t\t\tif (digestsByCallId === null) {\n\t\t\t\t\tthrow new Error('MCP Portal core could not prepare approval token digests.');\n\t\t\t\t}\n\t\t\t\treturn approvalCalls.map((call) => {\n\t\t\t\t\tconst digest = digestsByCallId[call.id];\n\t\t\t\t\tif (digest === undefined) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`MCP Portal core did not prepare an approval token digest for call '${call.id}'.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn digest;\n\t\t\t\t});\n\t\t\t},\n\t\t\truntimeState,\n\t\t}),\n\t\t{\n\t\t\tpriority: 80,\n\t\t},\n\t);\n\n\tapi.on?.('before_prompt_build', createBeforePromptBuildHandler({ runtimeState }), {\n\t\tpriority: 80,\n\t});\n\n\tif (!api.on && api.registerPromptHook) {\n\t\tapi.registerPromptHook('before_prompt_build', async (context) => {\n\t\t\tconst handler = createBeforePromptBuildHandler({ runtimeState });\n\t\t\tconst result = await handler({}, context);\n\t\t\tif (result?.appendSystemContext !== undefined) {\n\t\t\t\tcontext.appendPrompt?.(result.appendSystemContext);\n\t\t\t}\n\t\t});\n\t}\n\n\tregisterPortalRuntimeCleanup(api, async () => {\n\t\tconst core = await corePromise?.catch(() => undefined);\n\t\tawait core?.close();\n\t});\n\tlogger.info('[mcp-portal] registered native portal tools and runtime hooks.');\n}\n\nconst pluginEntry = {\n\tdescription: 'Registers native OpenClaw MCP Portal tools and wires per-agent approval hooks.',\n\tid: pluginId,\n\tname: 'MCP Portal',\n\tregister: registerMcpPortalPlugin,\n} satisfies PortalPluginEntry;\n\nexport default pluginEntry;\n","export interface PortalPromptNamespaceSummary {\n\treadonly namespace: string;\n\treadonly toolCount: number;\n}\n\nexport interface PortalPromptDiagnostic {\n\treadonly hint?: string;\n\treadonly message: string;\n\treadonly namespace: string;\n\treadonly phase?: string;\n}\n\nfunction formatDiagnostic(entry: PortalPromptDiagnostic): string {\n\tconst phase = entry.phase === undefined ? '' : ` ${entry.phase}`;\n\tconst hint = entry.hint === undefined ? '' : ` Hint: ${entry.hint}`;\n\treturn `${entry.namespace}${phase}: ${entry.message}.${hint}`;\n}\n\nexport function createPortalPromptContext(props: {\n\treadonly diagnostics?: readonly PortalPromptDiagnostic[];\n\treadonly namespaces: readonly PortalPromptNamespaceSummary[];\n}): string {\n\tconst namespaceList =\n\t\tprops.namespaces.length > 0\n\t\t\t? props.namespaces.map((entry) => `${entry.namespace}(${entry.toolCount} tools)`).join(', ')\n\t\t\t: 'none configured';\n\tconst diagnostics =\n\t\tprops.diagnostics !== undefined && props.diagnostics.length > 0\n\t\t\t? [`Discovery diagnostics: ${props.diagnostics.map(formatDiagnostic).join('; ')}`]\n\t\t\t: [];\n\n\treturn [\n\t\t'MCP Portal is available as native OpenClaw tools.',\n\t\t'Use mcp_portal_list with requests[], mcp_portal_search with requests[],',\n\t\t'mcp_portal_describe with requests[], and mcp_portal_call with calls[].',\n\t\t'Responses are { ok, results, errors, diagnostics }; results is keyed by each request/call id and each value is discriminated by ok: true or ok: false.',\n\t\t'Call upstream tools by namespace + toolName inside calls[].',\n\t\t'Call mcp_portal_describe before mcp_portal_call unless you already saw the full schema for that tool in this portal session.',\n\t\t'Gateway owns MCP auth.',\n\t\t`Namespaces: ${namespaceList}`,\n\t\t...diagnostics,\n\t].join('\\n');\n}\n","import { redactCredentialText } from '@agent-vm/mcp-portal/core';\n\nexport function redactPortalSecrets(text: string, secretValues: readonly string[] = []): string {\n\treturn secretValues\n\t\t.filter((secretValue) => secretValue.length > 0)\n\t\t.reduce(\n\t\t\t(current, secretValue) => current.split(secretValue).join('[REDACTED]'),\n\t\t\tredactCredentialText(text),\n\t\t);\n}\n","export * from './openclaw-plugin-api.js';\nexport * from './plugin-registration.js';\nexport * from './before-prompt-build-handler.js';\nexport * from './before-tool-call-handler.js';\nexport * from './portal-config.js';\nexport * from './portal-plugin-runtime-state.js';\nexport * from './portal-tool-policy.js';\nexport * from './portal-prompt-context.js';\nexport * from './redaction.js';\nexport { default } from './plugin-registration.js';\n\nexport const OPENCLAW_MCP_PORTAL_PLUGIN_PACKAGE_NAME = '@agent-vm/openclaw-mcp-portal-plugin';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["isObjectRecord","isObjectRecord","isObjectRecord"],"sources":["../src/before-prompt-build-handler.ts","../src/openclaw-tool-params.ts","../src/portal-tool-policy.ts","../src/before-tool-call-handler.ts","../src/effective-config-manifest.ts","../src/portal-config.ts","../src/portal-plugin-runtime-state.ts","../src/plugin-registration.ts","../src/portal-prompt-context.ts","../src/redaction.ts","../src/index.ts"],"sourcesContent":["import { resolveMcpPortalProfile } from '@agent-vm/config-contracts';\n\nimport type {\n\tOpenClawBeforePromptBuildEvent,\n\tOpenClawPluginHookContext,\n\tOpenClawPromptHookResult,\n} from './openclaw-plugin-api.js';\nimport type { PortalPluginRuntimeState } from './portal-plugin-runtime-state.js';\n\nexport interface CreateBeforePromptBuildHandlerProps {\n\treadonly runtimeState: PortalPluginRuntimeState;\n}\n\nexport function createBeforePromptBuildHandler(\n\tprops: CreateBeforePromptBuildHandlerProps,\n): (\n\tevent: OpenClawBeforePromptBuildEvent,\n\tcontext: OpenClawPluginHookContext,\n) => Promise<OpenClawPromptHookResult | undefined> {\n\treturn async (_event, context) => {\n\t\tconst agentId = context.agentId;\n\t\tif (agentId === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst portalConfig = await props.runtimeState.loadPortalConfig();\n\t\tconst agent = portalConfig.agents[agentId];\n\t\tif (agent === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst profile = resolveMcpPortalProfile(portalConfig, agent.profile);\n\t\tif (!profile.promptContext.enabled) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst namespaces = profile.enabledNamespaces\n\t\t\t.toSorted()\n\t\t\t.slice(0, profile.promptContext.maxNamespaces);\n\t\tconst namespaceText =\n\t\t\tnamespaces.length === 0\n\t\t\t\t? ' (none in your profile)'\n\t\t\t\t: namespaces.map((name) => ` ${name}`).join('\\n');\n\t\treturn {\n\t\t\tappendSystemContext: [\n\t\t\t\t'MCP Portal namespaces available to this agent:',\n\t\t\t\tnamespaceText,\n\t\t\t\t'Use mcp_portal_search to find tools by intent, then mcp_portal_describe before mcp_portal_call.',\n\t\t\t].join('\\n'),\n\t\t};\n\t};\n}\n","function isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseJsonObjectString(value: string): Record<string, unknown> | null {\n\ttry {\n\t\tconst parsedValue: unknown = JSON.parse(value);\n\t\treturn isObjectRecord(parsedValue) ? parsedValue : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function normalizeOpenClawToolParams(params: unknown): unknown {\n\tif (typeof params !== 'string') {\n\t\treturn params;\n\t}\n\treturn parseJsonObjectString(params) ?? params;\n}\n\nexport function normalizeOpenClawToolParamsRecord(params: unknown): Record<string, unknown> | null {\n\tconst normalizedParams = normalizeOpenClawToolParams(params);\n\treturn isObjectRecord(normalizedParams) ? normalizedParams : null;\n}\n","import {\n\tmcpPortalCallPolicyDecision,\n\ttype McpPortalCallPolicyDecision,\n\ttype ResolvedMcpPortalProfile,\n} from '@agent-vm/config-contracts';\n\nexport interface PortalCallRequest {\n\treadonly arguments: Record<string, unknown>;\n\treadonly id: string;\n\treadonly namespace: string;\n\treadonly toolName: string;\n}\n\nexport function profileAllowsPortalCall(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: { readonly namespace: string; readonly toolName: string },\n): boolean {\n\tif (!profile.enabledNamespaces.includes(call.namespace)) {\n\t\treturn false;\n\t}\n\tconst enabledTools = profile.enabledToolsByNamespace[call.namespace];\n\tif (enabledTools !== undefined && !enabledTools.includes(call.toolName)) {\n\t\treturn false;\n\t}\n\tconst hiddenTools = profile.hiddenToolsByNamespace[call.namespace] ?? [];\n\treturn !hiddenTools.includes(call.toolName);\n}\n\nexport function profilePortalCallDecision(\n\tprofile: ResolvedMcpPortalProfile,\n\tcall: { readonly namespace: string; readonly toolName: string },\n): McpPortalCallPolicyDecision {\n\treturn mcpPortalCallPolicyDecision(profile, call);\n}\n","import { resolveMcpPortalProfile } from '@agent-vm/config-contracts';\nimport {\n\thashCallArguments,\n\tsignApprovalToken,\n\ttype ApprovalTokenCallDigest,\n} from '@agent-vm/mcp-portal/portal-auth/hmac-token';\n\nimport type {\n\tOpenClawBeforeToolCallEvent,\n\tOpenClawBeforeToolCallResult,\n\tOpenClawPluginHookContext,\n} from './openclaw-plugin-api.js';\nimport { normalizeOpenClawToolParamsRecord } from './openclaw-tool-params.js';\nimport type { PortalPluginRuntimeState } from './portal-plugin-runtime-state.js';\nimport {\n\tprofileAllowsPortalCall,\n\tprofilePortalCallDecision,\n\ttype PortalCallRequest,\n} from './portal-tool-policy.js';\n\nconst approvalPromptTimeoutMs = 60_000;\nconst approvalTokenLifetimeMs = 5 * 60_000;\n\nexport interface CreateBeforeToolCallHandlerProps {\n\treadonly logger?: {\n\t\treadonly error?: (message: string) => void;\n\t\treadonly warn?: (message: string) => void;\n\t};\n\treadonly resolveApprovalTokenCallDigests?: (props: {\n\t\treadonly agentId: string;\n\t\treadonly approvalCalls: readonly PortalCallRequest[];\n\t\treadonly context: OpenClawPluginHookContext;\n\t\treadonly params: Record<string, unknown>;\n\t}) => Promise<readonly ApprovalTokenCallDigest[]>;\n\treadonly runtimeState: PortalPluginRuntimeState;\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseCallRequest(value: unknown): PortalCallRequest | null {\n\tif (!isObjectRecord(value)) {\n\t\treturn null;\n\t}\n\tconst id = value.id;\n\tconst namespace = value.namespace;\n\tconst toolName = value.toolName;\n\tconst argumentsValue = value.arguments;\n\tif (\n\t\ttypeof id !== 'string' ||\n\t\ttypeof namespace !== 'string' ||\n\t\ttypeof toolName !== 'string' ||\n\t\t!isObjectRecord(argumentsValue)\n\t) {\n\t\treturn null;\n\t}\n\treturn { arguments: argumentsValue, id, namespace, toolName };\n}\n\nfunction parseCallRequests(params: Record<string, unknown>): readonly PortalCallRequest[] | null {\n\tconst calls = params.calls;\n\tif (!Array.isArray(calls)) {\n\t\treturn null;\n\t}\n\tconst parsedCalls: PortalCallRequest[] = [];\n\tfor (const call of calls) {\n\t\tconst parsedCall = parseCallRequest(call);\n\t\tif (parsedCall === null) {\n\t\t\treturn null;\n\t\t}\n\t\tparsedCalls.push(parsedCall);\n\t}\n\treturn parsedCalls;\n}\n\nfunction fallbackApprovalTokenCallDigests(\n\tcalls: readonly PortalCallRequest[],\n): readonly ApprovalTokenCallDigest[] {\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\nfunction approvalTokenForCallDigests(props: {\n\treadonly agentId: string;\n\treadonly callDigests: readonly ApprovalTokenCallDigest[];\n\treadonly key: Buffer;\n\treadonly nowMs?: number;\n}): string {\n\tconst nowMs = props.nowMs ?? Date.now();\n\treturn signApprovalToken({\n\t\tagentId: props.agentId,\n\t\tcalls: props.callDigests,\n\t\texpiresAtMs: nowMs + approvalTokenLifetimeMs,\n\t\tissuedAtMs: nowMs,\n\t\tkey: props.key,\n\t});\n}\n\nfunction redactApprovalPreviewValue(key: string, value: unknown): unknown {\n\tif (/token|secret|password|credential|api[-_]?key/iu.test(key)) {\n\t\treturn '[redacted]';\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => redactApprovalPreviewValue(key, entry));\n\t}\n\tif (typeof value === 'object' && value !== null) {\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(value).map(([entryKey, entryValue]) => [\n\t\t\t\tentryKey,\n\t\t\t\tredactApprovalPreviewValue(entryKey, entryValue),\n\t\t\t]),\n\t\t);\n\t}\n\treturn value;\n}\n\nfunction approvalCallPreview(call: PortalCallRequest): string {\n\tconst redactedArguments = redactApprovalPreviewValue('arguments', call.arguments);\n\tconst serializedArguments = JSON.stringify(redactedArguments);\n\tconst preview =\n\t\tserializedArguments.length > 500\n\t\t\t? `${serializedArguments.slice(0, 497)}...`\n\t\t\t: serializedArguments;\n\treturn `${call.id}: ${call.namespace}.${call.toolName} args=${preview}`;\n}\n\nexport function createBeforeToolCallHandler(\n\tprops: CreateBeforeToolCallHandlerProps,\n): (\n\tevent: OpenClawBeforeToolCallEvent,\n\tcontext: OpenClawPluginHookContext,\n) => Promise<OpenClawBeforeToolCallResult | undefined> {\n\treturn async (event, context) => {\n\t\tif (event.toolName !== 'mcp_portal_call') {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (context.agentId === undefined) {\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\tblockReason: `mcp-portal: missing OpenClaw agent context for ${event.toolName}.`,\n\t\t\t};\n\t\t}\n\t\tconst portalConfig = await props.runtimeState.loadPortalConfig();\n\t\tconst agentId = context.agentId;\n\t\tconst agent = portalConfig.agents[agentId];\n\t\tif (agent === undefined) {\n\t\t\treturn { block: true, blockReason: `mcp-portal: agent \"${agentId}\" is not configured.` };\n\t\t}\n\t\tconst profile = resolveMcpPortalProfile(portalConfig, agent.profile);\n\t\tconst params = normalizeOpenClawToolParamsRecord(event.params);\n\t\tif (params === null) {\n\t\t\treturn { block: true, blockReason: 'mcp-portal: malformed portal call batch.' };\n\t\t}\n\t\tconst calls = parseCallRequests(params);\n\t\tif (calls === null || calls.length === 0) {\n\t\t\treturn { block: true, blockReason: 'mcp-portal: malformed portal call batch.' };\n\t\t}\n\n\t\tconst disabledCalls = calls.filter((call) => !profileAllowsPortalCall(profile, call));\n\t\tif (disabledCalls.length > 0) {\n\t\t\tif (disabledCalls.length === calls.length) {\n\t\t\t\tconst call = disabledCalls[0];\n\t\t\t\treturn {\n\t\t\t\t\tblock: true,\n\t\t\t\t\tblockReason:\n\t\t\t\t\t\tcall === undefined\n\t\t\t\t\t\t\t? `policy: ${agentId} has no enabled MCP Portal calls in this batch`\n\t\t\t\t\t\t\t: `policy: ${agentId}/${call.namespace}/${call.toolName} not enabled`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst approvalCalls: PortalCallRequest[] = [];\n\t\tfor (const call of calls) {\n\t\t\tconst decision = profilePortalCallDecision(profile, call);\n\t\t\tif (decision.kind === 'requires_approval') {\n\t\t\t\tapprovalCalls.push(call);\n\t\t\t}\n\t\t}\n\t\tif (approvalCalls.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (approvalCalls.length !== calls.length) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst toolNames = approvalCalls\n\t\t\t.map((call) => `${call.namespace}.${call.toolName}`)\n\t\t\t.toSorted()\n\t\t\t.join(', ');\n\t\tlet portalApprovalToken: string;\n\t\ttry {\n\t\t\tconst callDigests =\n\t\t\t\t(await props.resolveApprovalTokenCallDigests?.({\n\t\t\t\t\tagentId,\n\t\t\t\t\tapprovalCalls,\n\t\t\t\t\tcontext,\n\t\t\t\t\tparams,\n\t\t\t\t})) ?? fallbackApprovalTokenCallDigests(approvalCalls);\n\t\t\tif (callDigests.length !== approvalCalls.length) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`prepared ${callDigests.length} approval token digests for ${approvalCalls.length} approval call(s)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tportalApprovalToken = approvalTokenForCallDigests({\n\t\t\t\tagentId,\n\t\t\t\tcallDigests,\n\t\t\t\tkey: props.runtimeState.getApprovalHmacKey(),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = `mcp-portal: failed to prepare approval token: ${\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t}`;\n\t\t\tprops.logger?.error?.(message);\n\t\t\treturn { block: true, blockReason: message };\n\t\t}\n\t\tconst approvalPreview = approvalCalls.map(approvalCallPreview).join('\\n');\n\t\treturn {\n\t\t\tparams: { ...params, portalApprovalToken },\n\t\t\trequireApproval: {\n\t\t\t\tdescription: `Allow MCP Portal batch for agent ${agentId}:\\n${approvalPreview}`,\n\t\t\t\tpluginId: 'mcp-portal',\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttimeoutBehavior: 'deny',\n\t\t\t\ttimeoutMs: approvalPromptTimeoutMs,\n\t\t\t\ttitle: `MCP Portal batch: ${toolNames}`,\n\t\t\t},\n\t\t};\n\t};\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nconst effectiveConfigManifestFileName = 'mcp-portal-effective-manifest.json';\n\nexport interface EffectiveConfigPaths {\n\treadonly mcpConfigPath: string;\n\treadonly portalConfigPath: string;\n}\n\nfunction isObjectRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isSafeManifestFileName(value: string): boolean {\n\treturn value.length > 0 && !value.includes('/') && !value.includes('\\\\');\n}\n\nfunction parseEffectiveConfigManifest(value: unknown): {\n\treadonly mcpConfigFile: string;\n\treadonly portalConfigFile: string;\n} {\n\tif (!isObjectRecord(value)) {\n\t\tthrow new Error('MCP Portal effective config manifest must be an object.');\n\t}\n\tif (value.schemaVersion !== 1) {\n\t\tthrow new Error('MCP Portal effective config manifest must use schemaVersion 1.');\n\t}\n\tif (typeof value.mcpConfigFile !== 'string' || !isSafeManifestFileName(value.mcpConfigFile)) {\n\t\tthrow new Error('MCP Portal effective config manifest must contain a safe mcpConfigFile.');\n\t}\n\tif (\n\t\ttypeof value.portalConfigFile !== 'string' ||\n\t\t!isSafeManifestFileName(value.portalConfigFile)\n\t) {\n\t\tthrow new Error('MCP Portal effective config manifest must contain a safe portalConfigFile.');\n\t}\n\treturn {\n\t\tmcpConfigFile: value.mcpConfigFile,\n\t\tportalConfigFile: value.portalConfigFile,\n\t};\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n\treturn (\n\t\tisObjectRecord(error) &&\n\t\ttypeof error.code === 'string' &&\n\t\t(error.code === 'ENOENT' || error.code === 'ENOTDIR')\n\t);\n}\n\nexport async function resolveEffectiveConfigPaths(\n\tconfigDir: string,\n): Promise<EffectiveConfigPaths> {\n\tconst manifestPath = join(configDir, effectiveConfigManifestFileName);\n\tlet manifestText: string;\n\ttry {\n\t\tmanifestText = await readFile(manifestPath, 'utf8');\n\t} catch (error) {\n\t\tif (isMissingFileError(error)) {\n\t\t\treturn {\n\t\t\t\tmcpConfigPath: join(configDir, 'mcp.config.jsonc'),\n\t\t\t\tportalConfigPath: join(configDir, 'mcp-portal.config.jsonc'),\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n\tconst manifest = parseEffectiveConfigManifest(JSON.parse(manifestText));\n\treturn {\n\t\tmcpConfigPath: join(configDir, manifest.mcpConfigFile),\n\t\tportalConfigPath: join(configDir, manifest.portalConfigFile),\n\t};\n}\n","import { z } from 'zod';\n\nexport const portalPluginConfigSchema = z\n\t.object({\n\t\tconfigDir: z.string().min(1),\n\t})\n\t.strict();\n\nexport type PortalPluginConfig = z.infer<typeof portalPluginConfigSchema>;\n\nexport function parsePortalConfig(value: unknown): PortalPluginConfig {\n\treturn portalPluginConfigSchema.parse(value ?? {});\n}\n","import { randomBytes } from 'node:crypto';\n\nimport { loadMcpPortalConfig, type McpPortalConfig } from '@agent-vm/config-contracts';\n\nimport { resolveEffectiveConfigPaths } from './effective-config-manifest.js';\n\nexport interface PortalPluginRuntimeState {\n\treadonly consumeApprovalTokenId: (\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\treadonly configDir: string;\n\treadonly getApprovalHmacKey: () => Buffer;\n\treadonly getLoadedPortalConfig: () => McpPortalConfig | null;\n\treadonly getPortalUnavailableReason: () => string | null;\n\treadonly loadPortalConfig: () => Promise<McpPortalConfig>;\n\treadonly markPortalAvailable: () => void;\n\treadonly markPortalUnavailable: (reason: string) => void;\n}\n\nexport function createPortalPluginRuntimeState(props: {\n\treadonly configDir: string;\n\treadonly loadPortalConfig?: (path: string) => Promise<McpPortalConfig>;\n}): PortalPluginRuntimeState {\n\tlet loadedPortalConfig: McpPortalConfig | null = null;\n\tlet portalConfigPromise: Promise<McpPortalConfig> | null = null;\n\tlet portalUnavailableReason: string | null = null;\n\tconst approvalHmacKey = randomBytes(32);\n\tconst consumedApprovalTokenIds = new Map<string, number>();\n\tconst replayCacheLimit = 4096;\n\tconst replayCacheCleanupThreshold = replayCacheLimit / 2;\n\tconst loadPortalConfigFile = props.loadPortalConfig ?? loadMcpPortalConfig;\n\n\tfunction loadPortalConfig(): Promise<McpPortalConfig> {\n\t\tif (portalConfigPromise !== null) {\n\t\t\treturn portalConfigPromise;\n\t\t}\n\t\tconst nextPromise = resolveEffectiveConfigPaths(props.configDir)\n\t\t\t.then((effectiveConfigPaths) => loadPortalConfigFile(effectiveConfigPaths.portalConfigPath))\n\t\t\t.then((portalConfig) => {\n\t\t\t\tloadedPortalConfig = portalConfig;\n\t\t\t\treturn portalConfig;\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (portalConfigPromise === nextPromise) {\n\t\t\t\t\tportalConfigPromise = null;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tportalConfigPromise = nextPromise;\n\t\treturn portalConfigPromise;\n\t}\n\n\tfunction sweepExpiredApprovalTokenIds(nowMs: number): void {\n\t\tif (consumedApprovalTokenIds.size < replayCacheCleanupThreshold) {\n\t\t\treturn;\n\t\t}\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}\n\n\treturn {\n\t\tconsumeApprovalTokenId: (agentId, jti, expiresAtMs) => {\n\t\t\tconst nowMs = Date.now();\n\t\t\tsweepExpiredApprovalTokenIds(nowMs);\n\t\t\tconst tokenKey = `${agentId}\\n${jti}`;\n\t\t\tif (consumedApprovalTokenIds.has(tokenKey)) {\n\t\t\t\treturn { ok: false, reason: 'replayed' };\n\t\t\t}\n\t\t\tif (consumedApprovalTokenIds.size >= replayCacheLimit) {\n\t\t\t\treturn { ok: false, reason: 'replay-cache-full' };\n\t\t\t}\n\t\t\tconsumedApprovalTokenIds.set(tokenKey, expiresAtMs);\n\t\t\treturn { ok: true };\n\t\t},\n\t\tconfigDir: props.configDir,\n\t\tgetApprovalHmacKey: () => approvalHmacKey,\n\t\tgetLoadedPortalConfig: () => loadedPortalConfig,\n\t\tgetPortalUnavailableReason: () => portalUnavailableReason,\n\t\tloadPortalConfig,\n\t\tmarkPortalAvailable: () => {\n\t\t\tportalUnavailableReason = null;\n\t\t},\n\t\tmarkPortalUnavailable: (reason) => {\n\t\t\tportalUnavailableReason = reason;\n\t\t},\n\t};\n}\n","import {\n\tloadMcpConfig,\n\tloadMcpPortalConfig,\n\ttype McpPortalConfig,\n\tresolveMcpPortalProfile,\n\ttype ResolvedMcpPortalProfile,\n\ttype SecretValue,\n} from '@agent-vm/config-contracts';\nimport {\n\tcreatePortalCore,\n\tcreatePortalPolicyApprovalEvaluator,\n\tcreateUpstreamMcpClientRuntime,\n\tlistPortalCoreToolDescriptors,\n\tresolveUpstreamServers,\n\ttype PortalCore,\n\ttype PortalCoreEvent,\n\ttype PortalCoreToolDescriptor,\n\ttype PortalToolSelector,\n} from '@agent-vm/mcp-portal/core';\n\nimport { createBeforePromptBuildHandler } from './before-prompt-build-handler.js';\nimport { createBeforeToolCallHandler } from './before-tool-call-handler.js';\nimport { resolveEffectiveConfigPaths } from './effective-config-manifest.js';\nimport type {\n\tOpenClawPortalPluginApi,\n\tOpenClawPluginToolContext,\n\tOpenClawToolRegistration,\n\tOpenClawToolUpdateCallback,\n} from './openclaw-plugin-api.js';\nimport { normalizeOpenClawToolParams } from './openclaw-tool-params.js';\nimport { parsePortalConfig } from './portal-config.js';\nimport { createPortalPluginRuntimeState } from './portal-plugin-runtime-state.js';\n\ninterface PortalPluginEntry {\n\treadonly description: string;\n\treadonly id: string;\n\treadonly name: string;\n\treadonly register: (api: OpenClawPortalPluginApi) => void;\n}\n\ninterface TcpPoolConfig {\n\treadonly basePort: number;\n\treadonly size: number;\n}\n\ninterface ProfilePolicyMaps {\n\treadonly cacheTtlMs: number;\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\nconst pluginId = 'mcp-portal';\n\nfunction hasFunction(value: unknown): value is (...args: readonly unknown[]) => unknown {\n\treturn typeof value === 'function';\n}\n\nfunction isObjectRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isUnknownArray(value: unknown): value is readonly unknown[] {\n\treturn Array.isArray(value);\n}\n\nfunction getObjectProperty(value: unknown, property: string): unknown {\n\treturn isObjectRecord(value) ? value[property] : undefined;\n}\n\nfunction resolveConfigDir(api: OpenClawPortalPluginApi): string {\n\tif (api.pluginConfig !== undefined) {\n\t\treturn parsePortalConfig(api.pluginConfig).configDir;\n\t}\n\t// Managed agent-vm passes pluginConfig. The config fallbacks keep the plugin usable\n\t// in direct OpenClaw test harnesses that load plugin config through the root config.\n\tconst topLevelMcpConfigDir = getObjectProperty(\n\t\tgetObjectProperty(api.config, 'mcpPortal'),\n\t\t'configDir',\n\t);\n\tif (typeof topLevelMcpConfigDir === 'string' && topLevelMcpConfigDir.length > 0) {\n\t\treturn topLevelMcpConfigDir;\n\t}\n\tconst zones = getObjectProperty(api.config, 'zones');\n\tif (isUnknownArray(zones)) {\n\t\tconst firstZone = zones.at(0);\n\t\tconst zoneMcpConfigDir = getObjectProperty(\n\t\t\tgetObjectProperty(firstZone, 'mcpPortal'),\n\t\t\t'configDir',\n\t\t);\n\t\tif (typeof zoneMcpConfigDir === 'string' && zoneMcpConfigDir.length > 0) {\n\t\t\treturn zoneMcpConfigDir;\n\t\t}\n\t}\n\tthrow new Error(\n\t\t'MCP Portal plugin requires configDir in plugin config or zone mcpPortal config.',\n\t);\n}\n\nexport function validatePortalPortAgainstTcpPool(props: {\n\treadonly port: number;\n\treadonly tcpPool: TcpPoolConfig | null;\n}): void {\n\tif (props.tcpPool === null) {\n\t\treturn;\n\t}\n\tconst firstTcpPoolPort = props.tcpPool.basePort;\n\tconst lastTcpPoolPortExclusive = props.tcpPool.basePort + props.tcpPool.size;\n\tif (props.port >= firstTcpPoolPort && props.port < lastTcpPoolPortExclusive) {\n\t\tthrow new Error(\n\t\t\t`MCP Portal port ${String(props.port)} overlaps the Tool VM TCP pool ` +\n\t\t\t\t`[${String(firstTcpPoolPort)}, ${String(lastTcpPoolPortExclusive)}).`,\n\t\t);\n\t}\n}\n\nfunction createLoggerAdapter(api: OpenClawPortalPluginApi): {\n\treadonly error: (message: string) => void;\n\treadonly info: (message: string) => void;\n\treadonly warn: (message: string) => void;\n} {\n\treturn {\n\t\terror: (message) => api.logger?.error?.(message),\n\t\tinfo: (message) => api.logger?.info?.(message),\n\t\twarn: (message) => api.logger?.warn?.(message),\n\t};\n}\n\nexport function validatePortalPluginApi(api: OpenClawPortalPluginApi): void {\n\tif (!hasFunction(api.registerTool)) {\n\t\tthrow new Error('MCP Portal plugin requires OpenClaw registerTool API.');\n\t}\n\tif (!hasFunction(api.on)) {\n\t\tthrow new Error('MCP Portal plugin requires OpenClaw before_tool_call hook API.');\n\t}\n\tconst hasLifecycleCleanupApi =\n\t\thasFunction(api.lifecycle?.registerRuntimeLifecycle) ||\n\t\thasFunction(api.registerRuntimeLifecycle);\n\tif (hasLifecycleCleanupApi) {\n\t\treturn;\n\t}\n\tthrow new Error('MCP Portal plugin requires an OpenClaw lifecycle cleanup API.');\n}\n\nfunction registerPortalRuntimeCleanup(\n\tapi: OpenClawPortalPluginApi,\n\tcleanup: () => Promise<void> | void,\n): void {\n\tconst runtimeLifecycle = {\n\t\tcleanup: async () => {\n\t\t\tawait cleanup();\n\t\t},\n\t\tdescription: 'Closes MCP Portal upstream clients owned by the agent-vm plugin.',\n\t\tid: 'mcp-portal-core',\n\t} satisfies Parameters<NonNullable<OpenClawPortalPluginApi['registerRuntimeLifecycle']>>[0];\n\tif (hasFunction(api.lifecycle?.registerRuntimeLifecycle)) {\n\t\tapi.lifecycle.registerRuntimeLifecycle(runtimeLifecycle);\n\t\treturn;\n\t}\n\tif (hasFunction(api.registerRuntimeLifecycle)) {\n\t\tapi.registerRuntimeLifecycle(runtimeLifecycle);\n\t\treturn;\n\t}\n\tthrow new Error('MCP Portal plugin requires an OpenClaw lifecycle cleanup API.');\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\nfunction buildProfilePolicyMaps(portalConfig: McpPortalConfig): ProfilePolicyMaps {\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\nasync function resolveManagedPortalSecret(secret: SecretValue): Promise<string> {\n\tif (secret.source !== 'environment') {\n\t\tthrow new Error(\n\t\t\t'MCP Portal managed OpenClaw effective config must use environment secret refs.',\n\t\t);\n\t}\n\tconst value = process.env[secret.name];\n\tif (value === undefined || value.length === 0) {\n\t\tthrow new Error(`Missing environment secret ${secret.name} for MCP Portal native plugin.`);\n\t}\n\treturn value;\n}\n\nasync function createManagedPortalCore(\n\tconfigDir: string,\n\truntimeState: ReturnType<typeof createPortalPluginRuntimeState>,\n): Promise<PortalCore> {\n\tconst effectiveConfigPaths = await resolveEffectiveConfigPaths(configDir);\n\tconst [mcpConfig, portalConfig] = await Promise.all([\n\t\tloadMcpConfig(effectiveConfigPaths.mcpConfigPath),\n\t\tloadMcpPortalConfig(effectiveConfigPaths.portalConfigPath),\n\t]);\n\tconst upstreamServers = await resolveUpstreamServers({\n\t\tconfig: mcpConfig,\n\t\tresolveSecret: resolveManagedPortalSecret,\n\t});\n\tconst upstreamRuntime = createUpstreamMcpClientRuntime({ servers: upstreamServers });\n\tconst profilePolicyMaps = buildProfilePolicyMaps(portalConfig);\n\tconst approval = createPortalPolicyApprovalEvaluator({\n\t\tconsumeTokenId: (agentId, jti, expiresAtMs) =>\n\t\t\truntimeState.consumeApprovalTokenId(agentId, jti, expiresAtMs),\n\t\tmissingApprovalTokenDecision: { kind: 'approval_required', level: 'standard' },\n\t\tresolveRecord: (agentId) => {\n\t\t\tconst agent = portalConfig.agents[agentId];\n\t\t\tif (agent === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\thmacKey: runtimeState.getApprovalHmacKey(),\n\t\t\t\tprofile: resolveMcpPortalProfile(portalConfig, agent.profile),\n\t\t\t};\n\t\t},\n\t});\n\n\treturn 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,\n\t\tcatalogTtlMs: profilePolicyMaps.cacheTtlMs,\n\t\truntime: {\n\t\t\tcallUpstreamTool: upstreamRuntime.callTool,\n\t\t\tcloseAgentScope: upstreamRuntime.closeAgentScope,\n\t\t\tcloseSession: upstreamRuntime.closeSession,\n\t\t\tlistTools: upstreamRuntime.listTools,\n\t\t},\n\t\tupstreamNamespaces: upstreamServers.map((server) => server.namespace),\n\t});\n}\n\nfunction portalUpdateFromCoreEvent(event: PortalCoreEvent): Record<string, unknown> | null {\n\tif (event.kind === 'progress') {\n\t\treturn {\n\t\t\tmessage: event.message ?? 'MCP Portal progress',\n\t\t\t...(event.progress !== undefined ? { progress: event.progress } : {}),\n\t\t\trequestId: event.requestId,\n\t\t\t...(event.total !== undefined ? { total: event.total } : {}),\n\t\t\ttype: 'mcp_portal_progress',\n\t\t};\n\t}\n\tif (event.kind === 'partial_content') {\n\t\treturn {\n\t\t\tcontent: event.content,\n\t\t\trequestId: event.requestId,\n\t\t\ttype: 'mcp_portal_partial_content',\n\t\t};\n\t}\n\tif (event.kind === 'upstream_notification') {\n\t\treturn {\n\t\t\tmethod: event.method,\n\t\t\tparams: event.params,\n\t\t\trequestId: event.requestId,\n\t\t\ttype: 'mcp_portal_upstream_notification',\n\t\t};\n\t}\n\treturn null;\n}\n\nasync function forwardCoreEvent(\n\tevent: PortalCoreEvent,\n\tlogger: ReturnType<typeof createLoggerAdapter>,\n\tonUpdate: OpenClawToolUpdateCallback | undefined,\n): Promise<void> {\n\tconst update = portalUpdateFromCoreEvent(event);\n\tif (update !== null) {\n\t\ttry {\n\t\t\tawait onUpdate?.(update);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tlogger.warn(`[mcp-portal] OpenClaw onUpdate delivery failed: ${message}`);\n\t\t}\n\t}\n}\n\nfunction createNativeTool(props: {\n\treadonly context: OpenClawPluginToolContext;\n\treadonly descriptor: PortalCoreToolDescriptor;\n\treadonly getCore: () => Promise<PortalCore>;\n\treadonly logger: ReturnType<typeof createLoggerAdapter>;\n}): OpenClawToolRegistration {\n\treturn {\n\t\tdescription: props.descriptor.description,\n\t\texecute: async (_toolCallId, params, signal, onUpdate) => {\n\t\t\tif (props.context.agentId === undefined || props.context.agentId.length === 0) {\n\t\t\t\tthrow new Error('mcp-portal: OpenClaw did not provide a trusted agentId.');\n\t\t\t}\n\t\t\tconst normalizedParams = normalizeOpenClawToolParams(params);\n\t\t\tconst core = await props.getCore();\n\t\t\tconst scope = core.createAgentScope({\n\t\t\t\tagentId: props.context.agentId,\n\t\t\t\tagentScopeId: props.context.agentId,\n\t\t\t\t...(props.context.sessionId ? { sessionId: props.context.sessionId } : {}),\n\t\t\t\t...(props.context.sessionKey ? { sessionKey: props.context.sessionKey } : {}),\n\t\t\t\tsource: 'openclaw-trusted',\n\t\t\t});\n\t\t\tconst result = await core.collectPortalCoreResult(\n\t\t\t\tcore.callStream({\n\t\t\t\t\tinput: normalizedParams,\n\t\t\t\t\tscope,\n\t\t\t\t\t...(signal !== undefined ? { signal } : {}),\n\t\t\t\t\ttoolName: props.descriptor.name,\n\t\t\t\t}),\n\t\t\t\t{ onEvent: (event) => forwardCoreEvent(event, props.logger, onUpdate) },\n\t\t\t);\n\t\t\treturn { content: JSON.stringify(result), details: result };\n\t\t},\n\t\tlabel: props.descriptor.name,\n\t\tname: props.descriptor.name,\n\t\tparameters: props.descriptor.inputSchema,\n\t};\n}\n\nfunction descriptorsForOpenClawContext(props: {\n\treadonly context: OpenClawPluginToolContext;\n\treadonly portalConfig: McpPortalConfig | null;\n}): readonly PortalCoreToolDescriptor[] {\n\tif (props.portalConfig === null || props.context.agentId === undefined) {\n\t\treturn listPortalCoreToolDescriptors();\n\t}\n\tconst agent = props.portalConfig.agents[props.context.agentId];\n\tif (agent === undefined) {\n\t\treturn listPortalCoreToolDescriptors();\n\t}\n\tconst profile = resolveMcpPortalProfile(props.portalConfig, agent.profile);\n\treturn listPortalCoreToolDescriptors(profile.enabledNamespaces);\n}\n\nfunction registerNativePortalTools(props: {\n\treadonly api: OpenClawPortalPluginApi;\n\treadonly getCore: () => Promise<PortalCore>;\n\treadonly runtimeState: ReturnType<typeof createPortalPluginRuntimeState>;\n}): void {\n\tconst descriptorNames = listPortalCoreToolDescriptors().map((descriptor) => descriptor.name);\n\tconst logger = createLoggerAdapter(props.api);\n\tprops.api.registerTool?.(\n\t\t(context) => {\n\t\t\tconst descriptors = descriptorsForOpenClawContext({\n\t\t\t\tcontext,\n\t\t\t\tportalConfig: props.runtimeState.getLoadedPortalConfig(),\n\t\t\t});\n\t\t\treturn descriptors.map((descriptor) =>\n\t\t\t\tcreateNativeTool({ context, descriptor, getCore: props.getCore, logger }),\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tnames: descriptorNames,\n\t\t\toptional: true,\n\t\t},\n\t);\n}\n\nfunction shouldRegisterPortalRuntimeHooks(api: OpenClawPortalPluginApi): boolean {\n\treturn api.registrationMode === undefined || api.registrationMode === 'full';\n}\n\nfunction formatRegistrationMode(api: OpenClawPortalPluginApi): string {\n\treturn api.registrationMode ?? 'full';\n}\n\nexport function registerMcpPortalPlugin(api: OpenClawPortalPluginApi): void {\n\tconst logger = createLoggerAdapter(api);\n\tconst registerRuntimeHooks = shouldRegisterPortalRuntimeHooks(api);\n\tif (registerRuntimeHooks) {\n\t\tvalidatePortalPluginApi(api);\n\t} else if (!hasFunction(api.registerTool)) {\n\t\tlogger.warn(\n\t\t\t`[mcp-portal] skipped native portal tool registration for registrationMode='${formatRegistrationMode(api)}' because OpenClaw did not expose registerTool.`,\n\t\t);\n\t\treturn;\n\t}\n\tconst configDir = resolveConfigDir(api);\n\tconst runtimeState = createPortalPluginRuntimeState({ configDir });\n\tlet corePromise: Promise<PortalCore> | undefined;\n\tconst getCore = (): Promise<PortalCore> => {\n\t\tcorePromise ??= createManagedPortalCore(configDir, runtimeState).catch((error: unknown) => {\n\t\t\tcorePromise = undefined;\n\t\t\tthrow error;\n\t\t});\n\t\treturn corePromise;\n\t};\n\tregisterNativePortalTools({ api, getCore, runtimeState });\n\n\tif (!registerRuntimeHooks) {\n\t\tlogger.info(\n\t\t\t`[mcp-portal] registered native portal tools for registrationMode='${formatRegistrationMode(api)}'.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tapi.on?.(\n\t\t'before_tool_call',\n\t\tcreateBeforeToolCallHandler({\n\t\t\tlogger,\n\t\t\tresolveApprovalTokenCallDigests: async ({ agentId, approvalCalls, context, params }) => {\n\t\t\t\tconst core = await getCore();\n\t\t\t\tconst scope = core.createAgentScope({\n\t\t\t\t\tagentId,\n\t\t\t\t\tagentScopeId: agentId,\n\t\t\t\t\t...(context.sessionId ? { sessionId: context.sessionId } : {}),\n\t\t\t\t\t...(context.sessionKey ? { sessionKey: context.sessionKey } : {}),\n\t\t\t\t\tsource: 'openclaw-trusted',\n\t\t\t\t});\n\t\t\t\tconst digestsByCallId = await core.approval.prepareCallDigests({ input: params, scope });\n\t\t\t\tif (digestsByCallId === null) {\n\t\t\t\t\tthrow new Error('MCP Portal core could not prepare approval token digests.');\n\t\t\t\t}\n\t\t\t\treturn approvalCalls.map((call) => {\n\t\t\t\t\tconst digest = digestsByCallId[call.id];\n\t\t\t\t\tif (digest === undefined) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`MCP Portal core did not prepare an approval token digest for call '${call.id}'.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn digest;\n\t\t\t\t});\n\t\t\t},\n\t\t\truntimeState,\n\t\t}),\n\t\t{\n\t\t\tpriority: 80,\n\t\t},\n\t);\n\n\tapi.on?.('before_prompt_build', createBeforePromptBuildHandler({ runtimeState }), {\n\t\tpriority: 80,\n\t});\n\n\tif (!api.on && api.registerPromptHook) {\n\t\tapi.registerPromptHook('before_prompt_build', async (context) => {\n\t\t\tconst handler = createBeforePromptBuildHandler({ runtimeState });\n\t\t\tconst result = await handler({}, context);\n\t\t\tif (result?.appendSystemContext !== undefined) {\n\t\t\t\tcontext.appendPrompt?.(result.appendSystemContext);\n\t\t\t}\n\t\t});\n\t}\n\n\tregisterPortalRuntimeCleanup(api, async () => {\n\t\tconst core = await corePromise?.catch(() => undefined);\n\t\tawait core?.close();\n\t});\n\tlogger.info('[mcp-portal] registered native portal tools and runtime hooks.');\n}\n\nconst pluginEntry = {\n\tdescription: 'Registers native OpenClaw MCP Portal tools and wires per-agent approval hooks.',\n\tid: pluginId,\n\tname: 'MCP Portal',\n\tregister: registerMcpPortalPlugin,\n} satisfies PortalPluginEntry;\n\nexport default pluginEntry;\n","export interface PortalPromptNamespaceSummary {\n\treadonly namespace: string;\n\treadonly toolCount: number;\n}\n\nexport interface PortalPromptDiagnostic {\n\treadonly hint?: string;\n\treadonly message: string;\n\treadonly namespace: string;\n\treadonly phase?: string;\n}\n\nfunction formatDiagnostic(entry: PortalPromptDiagnostic): string {\n\tconst phase = entry.phase === undefined ? '' : ` ${entry.phase}`;\n\tconst hint = entry.hint === undefined ? '' : ` Hint: ${entry.hint}`;\n\treturn `${entry.namespace}${phase}: ${entry.message}.${hint}`;\n}\n\nexport function createPortalPromptContext(props: {\n\treadonly diagnostics?: readonly PortalPromptDiagnostic[];\n\treadonly namespaces: readonly PortalPromptNamespaceSummary[];\n}): string {\n\tconst namespaceList =\n\t\tprops.namespaces.length > 0\n\t\t\t? props.namespaces.map((entry) => `${entry.namespace}(${entry.toolCount} tools)`).join(', ')\n\t\t\t: 'none configured';\n\tconst diagnostics =\n\t\tprops.diagnostics !== undefined && props.diagnostics.length > 0\n\t\t\t? [`Discovery diagnostics: ${props.diagnostics.map(formatDiagnostic).join('; ')}`]\n\t\t\t: [];\n\n\treturn [\n\t\t'MCP Portal is available as native OpenClaw tools.',\n\t\t'Use mcp_portal_list with requests[], mcp_portal_search with requests[],',\n\t\t'mcp_portal_describe with requests[], and mcp_portal_call with calls[].',\n\t\t'Responses are { ok, results, errors, diagnostics }; results is keyed by each request/call id and each value is discriminated by ok: true or ok: false.',\n\t\t'Call upstream tools by namespace + toolName inside calls[].',\n\t\t'Call mcp_portal_describe before mcp_portal_call unless you already saw the full schema for that tool in this portal session.',\n\t\t'Gateway owns MCP auth.',\n\t\t`Namespaces: ${namespaceList}`,\n\t\t...diagnostics,\n\t].join('\\n');\n}\n","import { redactCredentialText } from '@agent-vm/mcp-portal/core';\n\nexport function redactPortalSecrets(text: string, secretValues: readonly string[] = []): string {\n\treturn secretValues\n\t\t.filter((secretValue) => secretValue.length > 0)\n\t\t.reduce(\n\t\t\t(current, secretValue) => current.split(secretValue).join('[REDACTED]'),\n\t\t\tredactCredentialText(text),\n\t\t);\n}\n","export * from './openclaw-plugin-api.js';\nexport * from './plugin-registration.js';\nexport * from './before-prompt-build-handler.js';\nexport * from './before-tool-call-handler.js';\nexport * from './portal-config.js';\nexport * from './portal-plugin-runtime-state.js';\nexport * from './portal-tool-policy.js';\nexport * from './portal-prompt-context.js';\nexport * from './redaction.js';\nexport { default } from './plugin-registration.js';\n\nexport const OPENCLAW_MCP_PORTAL_PLUGIN_PACKAGE_NAME = '@agent-vm/openclaw-mcp-portal-plugin';\n"],"mappings":";;;;;;;;AAaA,SAAgB,+BACf,OAIkD;CAClD,OAAO,OAAO,QAAQ,YAAY;EACjC,MAAM,UAAU,QAAQ;EACxB,IAAI,YAAY,KAAA,GACf;EAED,MAAM,eAAe,MAAM,MAAM,aAAa,kBAAkB;EAChE,MAAM,QAAQ,aAAa,OAAO;EAClC,IAAI,UAAU,KAAA,GACb;EAED,MAAM,UAAU,wBAAwB,cAAc,MAAM,QAAQ;EACpE,IAAI,CAAC,QAAQ,cAAc,SAC1B;EAED,MAAM,aAAa,QAAQ,kBACzB,UAAU,CACV,MAAM,GAAG,QAAQ,cAAc,cAAc;EAK/C,OAAO,EACN,qBAAqB;GACpB;GALD,WAAW,WAAW,IACnB,6BACA,WAAW,KAAK,SAAS,KAAK,OAAO,CAAC,KAAK,KAAK;GAKlD;GACA,CAAC,KAAK,KAAK,EACZ;;;;;AC9CH,SAASA,iBAAe,OAAkD;CACzE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,sBAAsB,OAA+C;CAC7E,IAAI;EACH,MAAM,cAAuB,KAAK,MAAM,MAAM;EAC9C,OAAOA,iBAAe,YAAY,GAAG,cAAc;SAC5C;EACP,OAAO;;;AAIT,SAAgB,4BAA4B,QAA0B;CACrE,IAAI,OAAO,WAAW,UACrB,OAAO;CAER,OAAO,sBAAsB,OAAO,IAAI;;AAGzC,SAAgB,kCAAkC,QAAiD;CAClG,MAAM,mBAAmB,4BAA4B,OAAO;CAC5D,OAAOA,iBAAe,iBAAiB,GAAG,mBAAmB;;;;ACT9D,SAAgB,wBACf,SACA,MACU;CACV,IAAI,CAAC,QAAQ,kBAAkB,SAAS,KAAK,UAAU,EACtD,OAAO;CAER,MAAM,eAAe,QAAQ,wBAAwB,KAAK;CAC1D,IAAI,iBAAiB,KAAA,KAAa,CAAC,aAAa,SAAS,KAAK,SAAS,EACtE,OAAO;CAGR,OAAO,EADa,QAAQ,uBAAuB,KAAK,cAAc,EAAE,EACpD,SAAS,KAAK,SAAS;;AAG5C,SAAgB,0BACf,SACA,MAC8B;CAC9B,OAAO,4BAA4B,SAAS,KAAK;;;;ACZlD,MAAM,0BAA0B;AAChC,MAAM,0BAA0B,IAAI;AAgBpC,SAASC,iBAAe,OAAkD;CACzE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,iBAAiB,OAA0C;CACnE,IAAI,CAACA,iBAAe,MAAM,EACzB,OAAO;CAER,MAAM,KAAK,MAAM;CACjB,MAAM,YAAY,MAAM;CACxB,MAAM,WAAW,MAAM;CACvB,MAAM,iBAAiB,MAAM;CAC7B,IACC,OAAO,OAAO,YACd,OAAO,cAAc,YACrB,OAAO,aAAa,YACpB,CAACA,iBAAe,eAAe,EAE/B,OAAO;CAER,OAAO;EAAE,WAAW;EAAgB;EAAI;EAAW;EAAU;;AAG9D,SAAS,kBAAkB,QAAsE;CAChG,MAAM,QAAQ,OAAO;CACrB,IAAI,CAAC,MAAM,QAAQ,MAAM,EACxB,OAAO;CAER,MAAM,cAAmC,EAAE;CAC3C,KAAK,MAAM,QAAQ,OAAO;EACzB,MAAM,aAAa,iBAAiB,KAAK;EACzC,IAAI,eAAe,MAClB,OAAO;EAER,YAAY,KAAK,WAAW;;CAE7B,OAAO;;AAGR,SAAS,iCACR,OACqC;CACrC,OAAO,MAAM,KAAK,UAAU;EAC3B,eAAe,kBAAkB,KAAK,UAAU;EAChD,WAAW,KAAK;EAChB,UAAU,KAAK;EACf,EAAE;;AAGJ,SAAS,4BAA4B,OAK1B;CACV,MAAM,QAAQ,MAAM,SAAS,KAAK,KAAK;CACvC,OAAO,kBAAkB;EACxB,SAAS,MAAM;EACf,OAAO,MAAM;EACb,aAAa,QAAQ;EACrB,YAAY;EACZ,KAAK,MAAM;EACX,CAAC;;AAGH,SAAS,2BAA2B,KAAa,OAAyB;CACzE,IAAI,iDAAiD,KAAK,IAAI,EAC7D,OAAO;CAER,IAAI,MAAM,QAAQ,MAAM,EACvB,OAAO,MAAM,KAAK,UAAU,2BAA2B,KAAK,MAAM,CAAC;CAEpE,IAAI,OAAO,UAAU,YAAY,UAAU,MAC1C,OAAO,OAAO,YACb,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,UAAU,gBAAgB,CACrD,UACA,2BAA2B,UAAU,WAAW,CAChD,CAAC,CACF;CAEF,OAAO;;AAGR,SAAS,oBAAoB,MAAiC;CAC7D,MAAM,oBAAoB,2BAA2B,aAAa,KAAK,UAAU;CACjF,MAAM,sBAAsB,KAAK,UAAU,kBAAkB;CAC7D,MAAM,UACL,oBAAoB,SAAS,MAC1B,GAAG,oBAAoB,MAAM,GAAG,IAAI,CAAC,OACrC;CACJ,OAAO,GAAG,KAAK,GAAG,IAAI,KAAK,UAAU,GAAG,KAAK,SAAS,QAAQ;;AAG/D,SAAgB,4BACf,OAIsD;CACtD,OAAO,OAAO,OAAO,YAAY;EAChC,IAAI,MAAM,aAAa,mBACtB;EAED,IAAI,QAAQ,YAAY,KAAA,GACvB,OAAO;GACN,OAAO;GACP,aAAa,kDAAkD,MAAM,SAAS;GAC9E;EAEF,MAAM,eAAe,MAAM,MAAM,aAAa,kBAAkB;EAChE,MAAM,UAAU,QAAQ;EACxB,MAAM,QAAQ,aAAa,OAAO;EAClC,IAAI,UAAU,KAAA,GACb,OAAO;GAAE,OAAO;GAAM,aAAa,sBAAsB,QAAQ;GAAuB;EAEzF,MAAM,UAAU,wBAAwB,cAAc,MAAM,QAAQ;EACpE,MAAM,SAAS,kCAAkC,MAAM,OAAO;EAC9D,IAAI,WAAW,MACd,OAAO;GAAE,OAAO;GAAM,aAAa;GAA4C;EAEhF,MAAM,QAAQ,kBAAkB,OAAO;EACvC,IAAI,UAAU,QAAQ,MAAM,WAAW,GACtC,OAAO;GAAE,OAAO;GAAM,aAAa;GAA4C;EAGhF,MAAM,gBAAgB,MAAM,QAAQ,SAAS,CAAC,wBAAwB,SAAS,KAAK,CAAC;EACrF,IAAI,cAAc,SAAS,GAAG;GAC7B,IAAI,cAAc,WAAW,MAAM,QAAQ;IAC1C,MAAM,OAAO,cAAc;IAC3B,OAAO;KACN,OAAO;KACP,aACC,SAAS,KAAA,IACN,WAAW,QAAQ,kDACnB,WAAW,QAAQ,GAAG,KAAK,UAAU,GAAG,KAAK,SAAS;KAC1D;;GAEF;;EAGD,MAAM,gBAAqC,EAAE;EAC7C,KAAK,MAAM,QAAQ,OAElB,IADiB,0BAA0B,SAAS,KACxC,CAAC,SAAS,qBACrB,cAAc,KAAK,KAAK;EAG1B,IAAI,cAAc,WAAW,GAC5B;EAED,IAAI,cAAc,WAAW,MAAM,QAClC;EAGD,MAAM,YAAY,cAChB,KAAK,SAAS,GAAG,KAAK,UAAU,GAAG,KAAK,WAAW,CACnD,UAAU,CACV,KAAK,KAAK;EACZ,IAAI;EACJ,IAAI;GACH,MAAM,cACJ,MAAM,MAAM,kCAAkC;IAC9C;IACA;IACA;IACA;IACA,CAAC,IAAK,iCAAiC,cAAc;GACvD,IAAI,YAAY,WAAW,cAAc,QACxC,MAAM,IAAI,MACT,YAAY,YAAY,OAAO,8BAA8B,cAAc,OAAO,mBAClF;GAEF,sBAAsB,4BAA4B;IACjD;IACA;IACA,KAAK,MAAM,aAAa,oBAAoB;IAC5C,CAAC;WACM,OAAO;GACf,MAAM,UAAU,iDACf,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAEvD,MAAM,QAAQ,QAAQ,QAAQ;GAC9B,OAAO;IAAE,OAAO;IAAM,aAAa;IAAS;;EAE7C,MAAM,kBAAkB,cAAc,IAAI,oBAAoB,CAAC,KAAK,KAAK;EACzE,OAAO;GACN,QAAQ;IAAE,GAAG;IAAQ;IAAqB;GAC1C,iBAAiB;IAChB,aAAa,oCAAoC,QAAQ,KAAK;IAC9D,UAAU;IACV,UAAU;IACV,iBAAiB;IACjB,WAAW;IACX,OAAO,qBAAqB;IAC5B;GACD;;;;;ACrOH,MAAM,kCAAkC;AAOxC,SAASC,iBAAe,OAA4D;CACnF,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,uBAAuB,OAAwB;CACvD,OAAO,MAAM,SAAS,KAAK,CAAC,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,SAAS,KAAK;;AAGzE,SAAS,6BAA6B,OAGpC;CACD,IAAI,CAACA,iBAAe,MAAM,EACzB,MAAM,IAAI,MAAM,0DAA0D;CAE3E,IAAI,MAAM,kBAAkB,GAC3B,MAAM,IAAI,MAAM,iEAAiE;CAElF,IAAI,OAAO,MAAM,kBAAkB,YAAY,CAAC,uBAAuB,MAAM,cAAc,EAC1F,MAAM,IAAI,MAAM,0EAA0E;CAE3F,IACC,OAAO,MAAM,qBAAqB,YAClC,CAAC,uBAAuB,MAAM,iBAAiB,EAE/C,MAAM,IAAI,MAAM,6EAA6E;CAE9F,OAAO;EACN,eAAe,MAAM;EACrB,kBAAkB,MAAM;EACxB;;AAGF,SAAS,mBAAmB,OAAyB;CACpD,OACCA,iBAAe,MAAM,IACrB,OAAO,MAAM,SAAS,aACrB,MAAM,SAAS,YAAY,MAAM,SAAS;;AAI7C,eAAsB,4BACrB,WACgC;CAChC,MAAM,eAAe,KAAK,WAAW,gCAAgC;CACrE,IAAI;CACJ,IAAI;EACH,eAAe,MAAM,SAAS,cAAc,OAAO;UAC3C,OAAO;EACf,IAAI,mBAAmB,MAAM,EAC5B,OAAO;GACN,eAAe,KAAK,WAAW,mBAAmB;GAClD,kBAAkB,KAAK,WAAW,0BAA0B;GAC5D;EAEF,MAAM;;CAEP,MAAM,WAAW,6BAA6B,KAAK,MAAM,aAAa,CAAC;CACvE,OAAO;EACN,eAAe,KAAK,WAAW,SAAS,cAAc;EACtD,kBAAkB,KAAK,WAAW,SAAS,iBAAiB;EAC5D;;;;ACrEF,MAAa,2BAA2B,EACtC,OAAO,EACP,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,EAC5B,CAAC,CACD,QAAQ;AAIV,SAAgB,kBAAkB,OAAoC;CACrE,OAAO,yBAAyB,MAAM,SAAS,EAAE,CAAC;;;;ACYnD,SAAgB,+BAA+B,OAGlB;CAC5B,IAAI,qBAA6C;CACjD,IAAI,sBAAuD;CAC3D,IAAI,0BAAyC;CAC7C,MAAM,kBAAkB,YAAY,GAAG;CACvC,MAAM,2CAA2B,IAAI,KAAqB;CAC1D,MAAM,mBAAmB;CACzB,MAAM,8BAA8B,mBAAmB;CACvD,MAAM,uBAAuB,MAAM,oBAAoB;CAEvD,SAAS,mBAA6C;EACrD,IAAI,wBAAwB,MAC3B,OAAO;EAER,MAAM,cAAc,4BAA4B,MAAM,UAAU,CAC9D,MAAM,yBAAyB,qBAAqB,qBAAqB,iBAAiB,CAAC,CAC3F,MAAM,iBAAiB;GACvB,qBAAqB;GACrB,OAAO;IACN,CACD,OAAO,UAAmB;GAC1B,IAAI,wBAAwB,aAC3B,sBAAsB;GAEvB,MAAM;IACL;EACH,sBAAsB;EACtB,OAAO;;CAGR,SAAS,6BAA6B,OAAqB;EAC1D,IAAI,yBAAyB,OAAO,6BACnC;EAED,KAAK,MAAM,CAAC,UAAU,qBAAqB,0BAC1C,IAAI,oBAAoB,OACvB,yBAAyB,OAAO,SAAS;;CAK5C,OAAO;EACN,yBAAyB,SAAS,KAAK,gBAAgB;GAEtD,6BADc,KAAK,KACe,CAAC;GACnC,MAAM,WAAW,GAAG,QAAQ,IAAI;GAChC,IAAI,yBAAyB,IAAI,SAAS,EACzC,OAAO;IAAE,IAAI;IAAO,QAAQ;IAAY;GAEzC,IAAI,yBAAyB,QAAQ,kBACpC,OAAO;IAAE,IAAI;IAAO,QAAQ;IAAqB;GAElD,yBAAyB,IAAI,UAAU,YAAY;GACnD,OAAO,EAAE,IAAI,MAAM;;EAEpB,WAAW,MAAM;EACjB,0BAA0B;EAC1B,6BAA6B;EAC7B,kCAAkC;EAClC;EACA,2BAA2B;GAC1B,0BAA0B;;EAE3B,wBAAwB,WAAW;GAClC,0BAA0B;;EAE3B;;;;ACtCF,MAAM,WAAW;AAEjB,SAAS,YAAY,OAAmE;CACvF,OAAO,OAAO,UAAU;;AAGzB,SAAS,eAAe,OAA4D;CACnF,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,eAAe,OAA6C;CACpE,OAAO,MAAM,QAAQ,MAAM;;AAG5B,SAAS,kBAAkB,OAAgB,UAA2B;CACrE,OAAO,eAAe,MAAM,GAAG,MAAM,YAAY,KAAA;;AAGlD,SAAS,iBAAiB,KAAsC;CAC/D,IAAI,IAAI,iBAAiB,KAAA,GACxB,OAAO,kBAAkB,IAAI,aAAa,CAAC;CAI5C,MAAM,uBAAuB,kBAC5B,kBAAkB,IAAI,QAAQ,YAAY,EAC1C,YACA;CACD,IAAI,OAAO,yBAAyB,YAAY,qBAAqB,SAAS,GAC7E,OAAO;CAER,MAAM,QAAQ,kBAAkB,IAAI,QAAQ,QAAQ;CACpD,IAAI,eAAe,MAAM,EAAE;EAE1B,MAAM,mBAAmB,kBACxB,kBAFiB,MAAM,GAAG,EAEC,EAAE,YAAY,EACzC,YACA;EACD,IAAI,OAAO,qBAAqB,YAAY,iBAAiB,SAAS,GACrE,OAAO;;CAGT,MAAM,IAAI,MACT,kFACA;;AAGF,SAAgB,iCAAiC,OAGxC;CACR,IAAI,MAAM,YAAY,MACrB;CAED,MAAM,mBAAmB,MAAM,QAAQ;CACvC,MAAM,2BAA2B,MAAM,QAAQ,WAAW,MAAM,QAAQ;CACxE,IAAI,MAAM,QAAQ,oBAAoB,MAAM,OAAO,0BAClD,MAAM,IAAI,MACT,mBAAmB,OAAO,MAAM,KAAK,CAAC,kCACjC,OAAO,iBAAiB,CAAC,IAAI,OAAO,yBAAyB,CAAC,IACnE;;AAIH,SAAS,oBAAoB,KAI3B;CACD,OAAO;EACN,QAAQ,YAAY,IAAI,QAAQ,QAAQ,QAAQ;EAChD,OAAO,YAAY,IAAI,QAAQ,OAAO,QAAQ;EAC9C,OAAO,YAAY,IAAI,QAAQ,OAAO,QAAQ;EAC9C;;AAGF,SAAgB,wBAAwB,KAAoC;CAC3E,IAAI,CAAC,YAAY,IAAI,aAAa,EACjC,MAAM,IAAI,MAAM,wDAAwD;CAEzE,IAAI,CAAC,YAAY,IAAI,GAAG,EACvB,MAAM,IAAI,MAAM,iEAAiE;CAKlF,IAFC,YAAY,IAAI,WAAW,yBAAyB,IACpD,YAAY,IAAI,yBAAyB,EAEzC;CAED,MAAM,IAAI,MAAM,gEAAgE;;AAGjF,SAAS,6BACR,KACA,SACO;CACP,MAAM,mBAAmB;EACxB,SAAS,YAAY;GACpB,MAAM,SAAS;;EAEhB,aAAa;EACb,IAAI;EACJ;CACD,IAAI,YAAY,IAAI,WAAW,yBAAyB,EAAE;EACzD,IAAI,UAAU,yBAAyB,iBAAiB;EACxD;;CAED,IAAI,YAAY,IAAI,yBAAyB,EAAE;EAC9C,IAAI,yBAAyB,iBAAiB;EAC9C;;CAED,MAAM,IAAI,MAAM,gEAAgE;;AAGjF,SAAS,4BACR,gBACgC;CAChC,OAAO,OAAO,QAAQ,eAAe,CAAC,SAAS,CAAC,WAAW,eAC1D,UAAU,KAAK,cAAc;EAAE;EAAW;EAAU,EAAE,CACtD;;AAGF,SAAS,uBAAuB,cAAkD;CACjF,MAAM,2BAA8D,EAAE;CACtE,MAAM,iCAGF,EAAE;CACN,MAAM,qBAAoE,EAAE;CAC5E,MAAM,cAAwB,EAAE;CAEhC,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,aAAa,OAAO,EAAE;EACnE,MAAM,UAAoC,wBAAwB,cAAc,MAAM,QAAQ;EAC9F,yBAAyB,WAAW,QAAQ;EAC5C,+BAA+B,WAAW,QAAQ;EAClD,mBAAmB,WAAW,4BAA4B,QAAQ,uBAAuB;EACzF,YAAY,KAAK,QAAQ,MAAM,aAAa;;CAG7C,OAAO;EACN,YAAY,YAAY,WAAW,IAAI,MAAS,KAAK,IAAI,GAAG,YAAY;EACxE;EACA;EACA;EACA;;AAGF,eAAe,2BAA2B,QAAsC;CAC/E,IAAI,OAAO,WAAW,eACrB,MAAM,IAAI,MACT,iFACA;CAEF,MAAM,QAAQ,QAAQ,IAAI,OAAO;CACjC,IAAI,UAAU,KAAA,KAAa,MAAM,WAAW,GAC3C,MAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,gCAAgC;CAE3F,OAAO;;AAGR,eAAe,wBACd,WACA,cACsB;CACtB,MAAM,uBAAuB,MAAM,4BAA4B,UAAU;CACzE,MAAM,CAAC,WAAW,gBAAgB,MAAM,QAAQ,IAAI,CACnD,cAAc,qBAAqB,cAAc,EACjD,oBAAoB,qBAAqB,iBAAiB,CAC1D,CAAC;CACF,MAAM,kBAAkB,MAAM,uBAAuB;EACpD,QAAQ;EACR,eAAe;EACf,CAAC;CACF,MAAM,kBAAkB,+BAA+B,EAAE,SAAS,iBAAiB,CAAC;CACpF,MAAM,oBAAoB,uBAAuB,aAAa;CAC9D,MAAM,WAAW,oCAAoC;EACpD,iBAAiB,SAAS,KAAK,gBAC9B,aAAa,uBAAuB,SAAS,KAAK,YAAY;EAC/D,8BAA8B;GAAE,MAAM;GAAqB,OAAO;GAAY;EAC9E,gBAAgB,YAAY;GAC3B,MAAM,QAAQ,aAAa,OAAO;GAClC,IAAI,UAAU,KAAA,GACb;GAED,OAAO;IACN,SAAS,aAAa,oBAAoB;IAC1C,SAAS,wBAAwB,cAAc,MAAM,QAAQ;IAC7D;;EAEF,CAAC;CAEF,OAAO,iBAAiB;EACvB,cAAc;GACb,eAAe;GACf,0BAA0B,kBAAkB;GAC5C,gCAAgC,kBAAkB;GAClD,oBAAoB,kBAAkB;GACtC;EACD;EACA,cAAc,kBAAkB;EAChC,SAAS;GACR,kBAAkB,gBAAgB;GAClC,iBAAiB,gBAAgB;GACjC,cAAc,gBAAgB;GAC9B,WAAW,gBAAgB;GAC3B;EACD,oBAAoB,gBAAgB,KAAK,WAAW,OAAO,UAAU;EACrE,CAAC;;AAGH,SAAS,0BAA0B,OAAwD;CAC1F,IAAI,MAAM,SAAS,YAClB,OAAO;EACN,SAAS,MAAM,WAAW;EAC1B,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,UAAU,GAAG,EAAE;EACpE,WAAW,MAAM;EACjB,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,OAAO,GAAG,EAAE;EAC3D,MAAM;EACN;CAEF,IAAI,MAAM,SAAS,mBAClB,OAAO;EACN,SAAS,MAAM;EACf,WAAW,MAAM;EACjB,MAAM;EACN;CAEF,IAAI,MAAM,SAAS,yBAClB,OAAO;EACN,QAAQ,MAAM;EACd,QAAQ,MAAM;EACd,WAAW,MAAM;EACjB,MAAM;EACN;CAEF,OAAO;;AAGR,eAAe,iBACd,OACA,QACA,UACgB;CAChB,MAAM,SAAS,0BAA0B,MAAM;CAC/C,IAAI,WAAW,MACd,IAAI;EACH,MAAM,WAAW,OAAO;UAChB,OAAO;EACf,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;EACtE,OAAO,KAAK,mDAAmD,UAAU;;;AAK5E,SAAS,iBAAiB,OAKG;CAC5B,OAAO;EACN,aAAa,MAAM,WAAW;EAC9B,SAAS,OAAO,aAAa,QAAQ,QAAQ,aAAa;GACzD,IAAI,MAAM,QAAQ,YAAY,KAAA,KAAa,MAAM,QAAQ,QAAQ,WAAW,GAC3E,MAAM,IAAI,MAAM,0DAA0D;GAE3E,MAAM,mBAAmB,4BAA4B,OAAO;GAC5D,MAAM,OAAO,MAAM,MAAM,SAAS;GAClC,MAAM,QAAQ,KAAK,iBAAiB;IACnC,SAAS,MAAM,QAAQ;IACvB,cAAc,MAAM,QAAQ;IAC5B,GAAI,MAAM,QAAQ,YAAY,EAAE,WAAW,MAAM,QAAQ,WAAW,GAAG,EAAE;IACzE,GAAI,MAAM,QAAQ,aAAa,EAAE,YAAY,MAAM,QAAQ,YAAY,GAAG,EAAE;IAC5E,QAAQ;IACR,CAAC;GACF,MAAM,SAAS,MAAM,KAAK,wBACzB,KAAK,WAAW;IACf,OAAO;IACP;IACA,GAAI,WAAW,KAAA,IAAY,EAAE,QAAQ,GAAG,EAAE;IAC1C,UAAU,MAAM,WAAW;IAC3B,CAAC,EACF,EAAE,UAAU,UAAU,iBAAiB,OAAO,MAAM,QAAQ,SAAS,EAAE,CACvE;GACD,OAAO;IAAE,SAAS,KAAK,UAAU,OAAO;IAAE,SAAS;IAAQ;;EAE5D,OAAO,MAAM,WAAW;EACxB,MAAM,MAAM,WAAW;EACvB,YAAY,MAAM,WAAW;EAC7B;;AAGF,SAAS,8BAA8B,OAGC;CACvC,IAAI,MAAM,iBAAiB,QAAQ,MAAM,QAAQ,YAAY,KAAA,GAC5D,OAAO,+BAA+B;CAEvC,MAAM,QAAQ,MAAM,aAAa,OAAO,MAAM,QAAQ;CACtD,IAAI,UAAU,KAAA,GACb,OAAO,+BAA+B;CAGvC,OAAO,8BADS,wBAAwB,MAAM,cAAc,MAAM,QACtB,CAAC,kBAAkB;;AAGhE,SAAS,0BAA0B,OAI1B;CACR,MAAM,kBAAkB,+BAA+B,CAAC,KAAK,eAAe,WAAW,KAAK;CAC5F,MAAM,SAAS,oBAAoB,MAAM,IAAI;CAC7C,MAAM,IAAI,gBACR,YAAY;EAKZ,OAJoB,8BAA8B;GACjD;GACA,cAAc,MAAM,aAAa,uBAAuB;GACxD,CACiB,CAAC,KAAK,eACvB,iBAAiB;GAAE;GAAS;GAAY,SAAS,MAAM;GAAS;GAAQ,CAAC,CACzE;IAEF;EACC,OAAO;EACP,UAAU;EACV,CACD;;AAGF,SAAS,iCAAiC,KAAuC;CAChF,OAAO,IAAI,qBAAqB,KAAA,KAAa,IAAI,qBAAqB;;AAGvE,SAAS,uBAAuB,KAAsC;CACrE,OAAO,IAAI,oBAAoB;;AAGhC,SAAgB,wBAAwB,KAAoC;CAC3E,MAAM,SAAS,oBAAoB,IAAI;CACvC,MAAM,uBAAuB,iCAAiC,IAAI;CAClE,IAAI,sBACH,wBAAwB,IAAI;MACtB,IAAI,CAAC,YAAY,IAAI,aAAa,EAAE;EAC1C,OAAO,KACN,8EAA8E,uBAAuB,IAAI,CAAC,iDAC1G;EACD;;CAED,MAAM,YAAY,iBAAiB,IAAI;CACvC,MAAM,eAAe,+BAA+B,EAAE,WAAW,CAAC;CAClE,IAAI;CACJ,MAAM,gBAAqC;EAC1C,gBAAgB,wBAAwB,WAAW,aAAa,CAAC,OAAO,UAAmB;GAC1F,cAAc,KAAA;GACd,MAAM;IACL;EACF,OAAO;;CAER,0BAA0B;EAAE;EAAK;EAAS;EAAc,CAAC;CAEzD,IAAI,CAAC,sBAAsB;EAC1B,OAAO,KACN,qEAAqE,uBAAuB,IAAI,CAAC,IACjG;EACD;;CAGD,IAAI,KACH,oBACA,4BAA4B;EAC3B;EACA,iCAAiC,OAAO,EAAE,SAAS,eAAe,SAAS,aAAa;GACvF,MAAM,OAAO,MAAM,SAAS;GAC5B,MAAM,QAAQ,KAAK,iBAAiB;IACnC;IACA,cAAc;IACd,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,WAAW,GAAG,EAAE;IAC7D,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,YAAY,GAAG,EAAE;IAChE,QAAQ;IACR,CAAC;GACF,MAAM,kBAAkB,MAAM,KAAK,SAAS,mBAAmB;IAAE,OAAO;IAAQ;IAAO,CAAC;GACxF,IAAI,oBAAoB,MACvB,MAAM,IAAI,MAAM,4DAA4D;GAE7E,OAAO,cAAc,KAAK,SAAS;IAClC,MAAM,SAAS,gBAAgB,KAAK;IACpC,IAAI,WAAW,KAAA,GACd,MAAM,IAAI,MACT,sEAAsE,KAAK,GAAG,IAC9E;IAEF,OAAO;KACN;;EAEH;EACA,CAAC,EACF,EACC,UAAU,IACV,CACD;CAED,IAAI,KAAK,uBAAuB,+BAA+B,EAAE,cAAc,CAAC,EAAE,EACjF,UAAU,IACV,CAAC;CAEF,IAAI,CAAC,IAAI,MAAM,IAAI,oBAClB,IAAI,mBAAmB,uBAAuB,OAAO,YAAY;EAEhE,MAAM,SAAS,MADC,+BAA+B,EAAE,cAAc,CACnC,CAAC,EAAE,EAAE,QAAQ;EACzC,IAAI,QAAQ,wBAAwB,KAAA,GACnC,QAAQ,eAAe,OAAO,oBAAoB;GAElD;CAGH,6BAA6B,KAAK,YAAY;EAE7C,OAAM,MADa,aAAa,YAAY,KAAA,EAAU,GAC1C,OAAO;GAClB;CACF,OAAO,KAAK,iEAAiE;;AAG9E,MAAM,cAAc;CACnB,aAAa;CACb,IAAI;CACJ,MAAM;CACN,UAAU;CACV;;;ACvdD,SAAS,iBAAiB,OAAuC;CAChE,MAAM,QAAQ,MAAM,UAAU,KAAA,IAAY,KAAK,IAAI,MAAM;CACzD,MAAM,OAAO,MAAM,SAAS,KAAA,IAAY,KAAK,UAAU,MAAM;CAC7D,OAAO,GAAG,MAAM,YAAY,MAAM,IAAI,MAAM,QAAQ,GAAG;;AAGxD,SAAgB,0BAA0B,OAG/B;CACV,MAAM,gBACL,MAAM,WAAW,SAAS,IACvB,MAAM,WAAW,KAAK,UAAU,GAAG,MAAM,UAAU,GAAG,MAAM,UAAU,SAAS,CAAC,KAAK,KAAK,GAC1F;CACJ,MAAM,cACL,MAAM,gBAAgB,KAAA,KAAa,MAAM,YAAY,SAAS,IAC3D,CAAC,0BAA0B,MAAM,YAAY,IAAI,iBAAiB,CAAC,KAAK,KAAK,GAAG,GAChF,EAAE;CAEN,OAAO;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf,GAAG;EACH,CAAC,KAAK,KAAK;;;;ACvCb,SAAgB,oBAAoB,MAAc,eAAkC,EAAE,EAAU;CAC/F,OAAO,aACL,QAAQ,gBAAgB,YAAY,SAAS,EAAE,CAC/C,QACC,SAAS,gBAAgB,QAAQ,MAAM,YAAY,CAAC,KAAK,aAAa,EACvE,qBAAqB,KAAK,CAC1B;;;;ACGH,MAAa,0CAA0C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-vm/openclaw-mcp-portal-plugin",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.94",
|
|
4
4
|
"description": "OpenClaw plugin that registers native MCP Portal tools over configured upstream MCP servers.",
|
|
5
5
|
"homepage": "https://github.com/ShravanSunder/agent-vm#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"zod": "^4.4.3",
|
|
34
|
-
"@agent-vm/
|
|
35
|
-
"@agent-vm/
|
|
34
|
+
"@agent-vm/mcp-portal": "0.0.94",
|
|
35
|
+
"@agent-vm/config-contracts": "0.0.94"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"openclaw": "^2026.5.7",
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "tsdown && cp openclaw.plugin.json dist/",
|
|
43
43
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
44
|
-
"test": "vitest run --root ../../ --config vitest.config.ts packages/openclaw-mcp-portal-plugin/src"
|
|
44
|
+
"test": "vitest run --root ../../ --config vitest.config.ts --project unit packages/openclaw-mcp-portal-plugin/src"
|
|
45
45
|
}
|
|
46
46
|
}
|