@muxoai/platform 1.4.1 → 1.4.3
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/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +2 -2
- package/README.md +1 -1
- package/dist/cli.js +94 -3
- package/dist/composio-catalog.d.ts +177 -1
- package/dist/composio-catalog.js +1427 -7
- package/dist/config.d.ts +6 -0
- package/dist/config.js +11 -1
- package/dist/durable-workflow.d.ts +71 -4
- package/dist/durable-workflow.js +199 -5
- package/dist/engine.d.ts +82 -3
- package/dist/engine.js +406 -41
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/mcp-schema.d.ts +162 -1
- package/dist/mcp-schema.js +1544 -40
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +474 -26
- package/dist/memory-graph.d.ts +26 -2
- package/dist/memory-graph.js +127 -7
- package/dist/oss-suite.d.ts +217 -0
- package/dist/oss-suite.js +836 -0
- package/dist/policy.d.ts +108 -1
- package/dist/policy.js +406 -1
- package/dist/providers/composio-instant.js +38 -3
- package/dist/providers/composio-sdk.d.ts +59 -2
- package/dist/providers/composio-sdk.js +273 -59
- package/dist/providers/stripe-projects.d.ts +4 -0
- package/dist/providers/stripe-projects.js +548 -126
- package/dist/sdk.d.ts +24 -1
- package/dist/sdk.js +53 -2
- package/dist/server.js +659 -64
- package/dist/store.js +2 -0
- package/dist/types.d.ts +34 -1
- package/dist/ui/console-html.d.ts +31 -1
- package/dist/ui/console-html.js +922 -368
- package/dist/ui/design-tokens.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
- package/plugins/muxo/.claude-plugin/plugin.json +2 -2
- package/plugins/muxo/.codex-plugin/plugin.json +15 -8
- package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
- package/plugins/muxo/hooks/session-start.sh +15 -3
- package/plugins/muxo/hooks/user-prompt-submit.sh +14 -1
- package/plugins/muxo/mcp.json +0 -10
- package/plugins/muxo/plugin.json +4 -4
- package/plugins/muxo/skills/muxo/SKILL.md +25 -16
- package/plugins/muxo/skills/muxo/references/cli.md +5 -1
- package/plugins/muxo/skills/muxo/references/mcp.md +11 -6
- package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
- package/plugins/muxo/skills/setup/SKILL.md +1 -1
- package/src/catalogues/stripe-projects-catalog.json +140 -0
package/dist/mcp.js
CHANGED
|
@@ -2,9 +2,9 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { ROOT_DIR } from "./config.js";
|
|
5
|
-
import { APPROVED_PLAN_STATUSES, DEFAULT_TOOL_SECURITY_SCHEMES, MUXO_MCP_SERVER_INSTRUCTIONS, MUXO_MCP_TOOLS, OPENAI_COMPANY_KNOWLEDGE_TOOLS, PUBLIC_MCP_TOOL_NAMES, PUBLIC_TOOL_SECURITY_SCHEMES, attachMcpHarnessGuidance, MuxoToolError, buildApprovalUrl, buildOnboardTeamGuide, clampWaitSeconds, errorPayloadFrom, findMcpSkill, securitySchemesForTool, } from "./mcp-schema.js";
|
|
5
|
+
import { APPROVED_PLAN_STATUSES, DEFAULT_LEGACY_MCP_PROTOCOL_VERSION, DEFAULT_TOOL_SECURITY_SCHEMES, LATEST_MCP_PROTOCOL_VERSION, MCP_ERR_HEADER_MISMATCH, MCP_ERR_MISSING_REQUIRED_CLIENT_CAPABILITY, MCP_ERR_UNSUPPORTED_PROTOCOL_VERSION, MUXO_MCP_RESOURCE_TEMPLATES, MUXO_MCP_SERVER_INSTRUCTIONS, MUXO_MCP_TOOLS, MUXO_UI_MCP_APP_URI, MUXO_UI_RESOURCES, MUXO_UI_WIDGET_URI, OPENAI_COMPANY_KNOWLEDGE_TOOLS, PUBLIC_MCP_TOOL_NAMES, PUBLIC_TOOL_SECURITY_SCHEMES, SUPPORTED_MCP_PROTOCOL_VERSIONS, UI_RENDERED_MCP_TOOL_NAMES, attachMcpHarnessGuidance, MuxoToolError, buildApprovalUrl, buildMcpDiscoverResult, buildMcpErrorResultMeta, buildMcpToolDescriptor, buildMcpToolResultMeta, buildOnboardTeamGuide, clampWaitSeconds, completeMcpArgument, decodeMcpHeaderValue, errorPayloadFrom, extractOpenAiClientMeta, findMcpSkill, isSupportedMcpProtocolVersion, renderMuxoUiWidgetHtml, securitySchemesForTool, validateMcpHttpHeadersAndMeta, } from "./mcp-schema.js";
|
|
6
6
|
import { MUXO_VERSION } from "./version.js";
|
|
7
|
-
export { DEFAULT_TOOL_SECURITY_SCHEMES, MUXO_MCP_SERVER_INSTRUCTIONS, MUXO_MCP_TOOLS, OPENAI_COMPANY_KNOWLEDGE_TOOLS, PUBLIC_MCP_TOOL_NAMES, PUBLIC_TOOL_SECURITY_SCHEMES, attachMcpHarnessGuidance, securitySchemesForTool, };
|
|
7
|
+
export { DEFAULT_LEGACY_MCP_PROTOCOL_VERSION, DEFAULT_TOOL_SECURITY_SCHEMES, LATEST_MCP_PROTOCOL_VERSION, MCP_ERR_HEADER_MISMATCH, MCP_ERR_MISSING_REQUIRED_CLIENT_CAPABILITY, MCP_ERR_UNSUPPORTED_PROTOCOL_VERSION, MUXO_MCP_RESOURCE_TEMPLATES, MUXO_MCP_SERVER_INSTRUCTIONS, MUXO_MCP_TOOLS, MUXO_UI_MCP_APP_URI, MUXO_UI_RESOURCES, MUXO_UI_WIDGET_URI, OPENAI_COMPANY_KNOWLEDGE_TOOLS, PUBLIC_MCP_TOOL_NAMES, PUBLIC_TOOL_SECURITY_SCHEMES, SUPPORTED_MCP_PROTOCOL_VERSIONS, UI_RENDERED_MCP_TOOL_NAMES, attachMcpHarnessGuidance, buildMcpDiscoverResult, buildMcpErrorResultMeta, buildMcpToolDescriptor, buildMcpToolResultMeta, completeMcpArgument, decodeMcpHeaderValue, extractOpenAiClientMeta, isSupportedMcpProtocolVersion, renderMuxoUiWidgetHtml, securitySchemesForTool, validateMcpHttpHeadersAndMeta, };
|
|
8
8
|
function sha256Digest(content) {
|
|
9
9
|
const hash = crypto
|
|
10
10
|
.createHash("sha256")
|
|
@@ -43,7 +43,7 @@ function readSkillFileOrDefault(relPath, fallback) {
|
|
|
43
43
|
export function getMuxoMcpSkills() {
|
|
44
44
|
const muxoSkillMd = readSkillFileOrDefault("muxo/SKILL.md", `---
|
|
45
45
|
name: muxo
|
|
46
|
-
description: Route governed Muxo work between the hosted MCP-backed app and the local Muxo CLI across Connected Apps
|
|
46
|
+
description: Route governed Muxo work between the hosted MCP-backed app and the local Muxo CLI across Muxo Connected Apps, Instant Tools, Cloud Infrastructure (Stripe Projects), Supermemory v5, and Microsoft Agent Governance.
|
|
47
47
|
---
|
|
48
48
|
|
|
49
49
|
# Muxo
|
|
@@ -168,12 +168,18 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
168
168
|
provider: args.provider ? String(args.provider) : undefined,
|
|
169
169
|
syncLive: args.sync_live !== false,
|
|
170
170
|
});
|
|
171
|
-
case "start_connection":
|
|
172
|
-
|
|
171
|
+
case "start_connection": {
|
|
172
|
+
const conn = await engine.startConnection(ctx, {
|
|
173
173
|
provider: String(args.provider || ""),
|
|
174
174
|
lane: args.lane,
|
|
175
175
|
callbackUrl: args.callback_url ? String(args.callback_url) : undefined,
|
|
176
176
|
});
|
|
177
|
+
return {
|
|
178
|
+
ok: true,
|
|
179
|
+
...conn,
|
|
180
|
+
connection: conn,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
177
183
|
case "wait_for_connection":
|
|
178
184
|
return engine.waitForConnection(ctx, {
|
|
179
185
|
provider: String(args.provider || ""),
|
|
@@ -217,8 +223,53 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
217
223
|
: Array.isArray(args.parameterRules)
|
|
218
224
|
? args.parameterRules
|
|
219
225
|
: undefined;
|
|
226
|
+
const asOf = args.as_of || args.asOf ? String(args.as_of || args.asOf) : null;
|
|
227
|
+
const focalEntity = args.focal_entity || args.focalEntity
|
|
228
|
+
? String(args.focal_entity || args.focalEntity)
|
|
229
|
+
: null;
|
|
230
|
+
const rawMaxHops = args.max_hops ?? args.maxHops;
|
|
231
|
+
const maxHops = rawMaxHops !== undefined && rawMaxHops !== null
|
|
232
|
+
? Number(rawMaxHops)
|
|
233
|
+
: undefined;
|
|
220
234
|
if (action === "memory_graph") {
|
|
221
|
-
return engine.getMemoryGraph(ctx,
|
|
235
|
+
return engine.getMemoryGraph(ctx, {
|
|
236
|
+
query,
|
|
237
|
+
asOf,
|
|
238
|
+
focalEntity,
|
|
239
|
+
maxHops,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (action === "cedar_policy" || action === "policy_as_code") {
|
|
243
|
+
if (args.tool_slug || args.slug) {
|
|
244
|
+
return engine.evaluatePolicyAsCode(ctx, {
|
|
245
|
+
toolSlug: String(args.tool_slug || args.slug),
|
|
246
|
+
input: (args.input || args.arguments) || {},
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return engine.getPolicyAsCodeBundle(ctx);
|
|
250
|
+
}
|
|
251
|
+
if (action === "otel_traces" || action === "telemetry") {
|
|
252
|
+
return engine.exportOtelTraces(ctx, Number(args.limit || 25));
|
|
253
|
+
}
|
|
254
|
+
if (action === "roi_analytics" || action === "roi") {
|
|
255
|
+
return engine.getCommercialRoiReport(ctx);
|
|
256
|
+
}
|
|
257
|
+
if (action === "playbooks") {
|
|
258
|
+
return {
|
|
259
|
+
ok: true,
|
|
260
|
+
playbooks: engine.listCommercialPlaybooks(),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
if (action === "run_playbook") {
|
|
264
|
+
const slug = String(args.slug ||
|
|
265
|
+
args.playbook ||
|
|
266
|
+
query ||
|
|
267
|
+
prompt ||
|
|
268
|
+
"fullstack-cloud-bootstrap").trim();
|
|
269
|
+
return engine.runCommercialPlaybook(ctx, {
|
|
270
|
+
slug,
|
|
271
|
+
input: (args.input || args.arguments) || {},
|
|
272
|
+
});
|
|
222
273
|
}
|
|
223
274
|
if (action === "governance_status") {
|
|
224
275
|
return engine.getGovernanceOverview(ctx);
|
|
@@ -273,6 +324,35 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
273
324
|
source: rawParamRules ? "mcp_harness" : "deterministic",
|
|
274
325
|
});
|
|
275
326
|
}
|
|
327
|
+
if (action === "reset_guardrails") {
|
|
328
|
+
return engine.resetWorkspaceGuardrails(ctx);
|
|
329
|
+
}
|
|
330
|
+
if (action === "check_policy" || action === "simulate_policy") {
|
|
331
|
+
const toolSlug = String(args.tool_slug || args.slug || args.tool_id || query || prompt || "instant.web.search").trim();
|
|
332
|
+
const input = (args.input || args.arguments) || {};
|
|
333
|
+
return engine.checkToolPolicy(ctx, { toolSlug, input });
|
|
334
|
+
}
|
|
335
|
+
if (action === "kill_switch") {
|
|
336
|
+
const enabled = typeof args.enabled === "boolean"
|
|
337
|
+
? args.enabled
|
|
338
|
+
: typeof args.active === "boolean"
|
|
339
|
+
? args.active
|
|
340
|
+
: !/\b(resume|unpause|disable|off|false)\b/i.test(prompt || query || "");
|
|
341
|
+
const reason = prompt ||
|
|
342
|
+
query ||
|
|
343
|
+
(enabled ? "Paused via MCP get_run_context" : undefined);
|
|
344
|
+
const updated = engine.setKillSwitch(ctx, enabled, reason);
|
|
345
|
+
const govOverview = engine.getGovernanceOverview(ctx);
|
|
346
|
+
return {
|
|
347
|
+
ok: true,
|
|
348
|
+
action: "kill_switch",
|
|
349
|
+
killSwitchActive: Boolean(updated.policy.killSwitchActive),
|
|
350
|
+
killSwitchReason: updated.policy.killSwitchReason || null,
|
|
351
|
+
policy: updated.policy,
|
|
352
|
+
llmPolicyBrief: govOverview.llmPolicyBrief,
|
|
353
|
+
explanation: govOverview.explanation,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
276
356
|
if (action === "scan_context") {
|
|
277
357
|
const textToScan = String(args.content || prompt || query || "");
|
|
278
358
|
return engine.scanForContextPoisoning(ctx.workspace.id, textToScan);
|
|
@@ -308,7 +388,12 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
308
388
|
}
|
|
309
389
|
const runCtx = await engine.getRunContext(ctx, query);
|
|
310
390
|
if (args.include_graph === true) {
|
|
311
|
-
const memoryGraph = await engine.getMemoryGraph(ctx,
|
|
391
|
+
const memoryGraph = await engine.getMemoryGraph(ctx, {
|
|
392
|
+
query,
|
|
393
|
+
asOf,
|
|
394
|
+
focalEntity,
|
|
395
|
+
maxHops,
|
|
396
|
+
});
|
|
312
397
|
return { ...runCtx, memoryGraph };
|
|
313
398
|
}
|
|
314
399
|
return runCtx;
|
|
@@ -390,7 +475,16 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
390
475
|
return engine.forgetWorkspaceMemoryMatching(ctx, query);
|
|
391
476
|
}
|
|
392
477
|
case "memory_graph":
|
|
393
|
-
return engine.getMemoryGraph(ctx,
|
|
478
|
+
return engine.getMemoryGraph(ctx, {
|
|
479
|
+
query: args.query ? String(args.query) : undefined,
|
|
480
|
+
asOf: args.as_of || args.asOf ? String(args.as_of || args.asOf) : null,
|
|
481
|
+
focalEntity: args.focal_entity || args.focalEntity
|
|
482
|
+
? String(args.focal_entity || args.focalEntity)
|
|
483
|
+
: null,
|
|
484
|
+
maxHops: args.max_hops !== undefined || args.maxHops !== undefined
|
|
485
|
+
? Number(args.max_hops ?? args.maxHops)
|
|
486
|
+
: undefined,
|
|
487
|
+
});
|
|
394
488
|
case "set_guardrail":
|
|
395
489
|
case "configure_guardrails": {
|
|
396
490
|
const rawParamRules = Array.isArray(args.parameter_rules)
|
|
@@ -403,6 +497,39 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
403
497
|
source: rawParamRules ? "mcp_harness" : "deterministic",
|
|
404
498
|
});
|
|
405
499
|
}
|
|
500
|
+
case "reset_guardrails":
|
|
501
|
+
return engine.resetWorkspaceGuardrails(ctx);
|
|
502
|
+
case "check_policy":
|
|
503
|
+
case "simulate_policy":
|
|
504
|
+
return engine.checkToolPolicy(ctx, {
|
|
505
|
+
toolSlug: String(args.tool_slug || args.slug || args.tool_id || args.query || "instant.web.search"),
|
|
506
|
+
input: (args.input || args.arguments) || {},
|
|
507
|
+
});
|
|
508
|
+
case "kill_switch": {
|
|
509
|
+
const enabled = typeof args.enabled === "boolean"
|
|
510
|
+
? args.enabled
|
|
511
|
+
: typeof args.active === "boolean"
|
|
512
|
+
? args.active
|
|
513
|
+
: true;
|
|
514
|
+
const reason = args.reason
|
|
515
|
+
? String(args.reason)
|
|
516
|
+
: args.prompt
|
|
517
|
+
? String(args.prompt)
|
|
518
|
+
: undefined;
|
|
519
|
+
const updated = engine.setKillSwitch(ctx, enabled, reason);
|
|
520
|
+
const govOverview = engine.getGovernanceOverview(ctx);
|
|
521
|
+
return {
|
|
522
|
+
ok: true,
|
|
523
|
+
action: "kill_switch",
|
|
524
|
+
killSwitchActive: Boolean(updated.policy.killSwitchActive),
|
|
525
|
+
killSwitchReason: updated.policy.killSwitchReason || null,
|
|
526
|
+
policy: updated.policy,
|
|
527
|
+
llmPolicyBrief: govOverview.llmPolicyBrief,
|
|
528
|
+
explanation: govOverview.explanation,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
case "scan_context":
|
|
532
|
+
return engine.scanForContextPoisoning(ctx.workspace.id, String(args.content || args.prompt || args.query || ""));
|
|
406
533
|
case "governance_status":
|
|
407
534
|
return engine.getGovernanceOverview(ctx);
|
|
408
535
|
case "verify_receipt_chain":
|
|
@@ -424,7 +551,7 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
424
551
|
const toolHits = toolsRes.tools.map((t) => ({
|
|
425
552
|
id: `tool:${t.slug}`,
|
|
426
553
|
title: `${t.name} (${t.slug})`,
|
|
427
|
-
url: t.providerUrl || `https://docs.muxo.ai/
|
|
554
|
+
url: t.providerUrl || `https://docs.muxo.ai/catalogue#${encodeURIComponent(t.providerSlug || t.slug)}`,
|
|
428
555
|
snippet: `${t.description} [lane=${t.lane}, risk=${t.riskLevel}, cost=${t.creditCost}cr]`,
|
|
429
556
|
}));
|
|
430
557
|
const memHits = (memRes.memories || []).slice(0, 5).map((m) => ({
|
|
@@ -464,7 +591,7 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
464
591
|
title: tool.name,
|
|
465
592
|
text: JSON.stringify(tool, null, 2),
|
|
466
593
|
url: tool.providerUrl ||
|
|
467
|
-
`https://docs.muxo.ai/
|
|
594
|
+
`https://docs.muxo.ai/catalogue#${encodeURIComponent(tool.providerSlug || tool.slug)}`,
|
|
468
595
|
metadata: {
|
|
469
596
|
slug: tool.slug,
|
|
470
597
|
lane: tool.lane,
|
|
@@ -485,41 +612,90 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
485
612
|
method.startsWith("notifications/")) {
|
|
486
613
|
return null;
|
|
487
614
|
}
|
|
615
|
+
const headerAndMetaCheck = validateMcpHttpHeadersAndMeta({}, rpc);
|
|
616
|
+
if (!headerAndMetaCheck.ok) {
|
|
617
|
+
return {
|
|
618
|
+
jsonrpc: "2.0",
|
|
619
|
+
id,
|
|
620
|
+
error: headerAndMetaCheck.error,
|
|
621
|
+
};
|
|
622
|
+
}
|
|
488
623
|
try {
|
|
624
|
+
if (method === "server/discover") {
|
|
625
|
+
return {
|
|
626
|
+
jsonrpc: "2.0",
|
|
627
|
+
id,
|
|
628
|
+
result: buildMcpDiscoverResult(MUXO_VERSION),
|
|
629
|
+
};
|
|
630
|
+
}
|
|
489
631
|
if (method === "initialize") {
|
|
490
|
-
const requestedProtocol =
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
: "
|
|
632
|
+
const requestedProtocol = headerAndMetaCheck.protocolVersion;
|
|
633
|
+
const serverInfo = {
|
|
634
|
+
name: "muxo-mcp-server",
|
|
635
|
+
title: "Muxo Unified Agent Runtime & Governance MCP Server",
|
|
636
|
+
version: MUXO_VERSION,
|
|
637
|
+
};
|
|
494
638
|
return {
|
|
495
639
|
jsonrpc: "2.0",
|
|
496
640
|
id,
|
|
497
641
|
result: {
|
|
642
|
+
resultType: "complete",
|
|
498
643
|
protocolVersion: requestedProtocol,
|
|
644
|
+
supportedVersions: [...SUPPORTED_MCP_PROTOCOL_VERSIONS],
|
|
499
645
|
instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
500
|
-
serverInfo
|
|
501
|
-
name: "muxo-mcp-server",
|
|
502
|
-
version: MUXO_VERSION,
|
|
503
|
-
},
|
|
646
|
+
serverInfo,
|
|
504
647
|
capabilities: {
|
|
505
648
|
tools: { listChanged: false },
|
|
506
|
-
resources: { listChanged: false },
|
|
649
|
+
resources: { listChanged: false, subscribe: false },
|
|
507
650
|
prompts: { listChanged: false },
|
|
651
|
+
completions: {},
|
|
508
652
|
extensions: {
|
|
509
653
|
"io.modelcontextprotocol/skills": {},
|
|
654
|
+
"io.modelcontextprotocol/apps": {},
|
|
510
655
|
},
|
|
511
656
|
},
|
|
657
|
+
_meta: {
|
|
658
|
+
"io.modelcontextprotocol/serverInfo": serverInfo,
|
|
659
|
+
"io.modelcontextprotocol/instructions": MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
660
|
+
},
|
|
512
661
|
},
|
|
513
662
|
};
|
|
514
663
|
}
|
|
515
664
|
if (method === "ping") {
|
|
516
|
-
return { jsonrpc: "2.0", id, result: {} };
|
|
665
|
+
return { jsonrpc: "2.0", id, result: { resultType: "complete" } };
|
|
666
|
+
}
|
|
667
|
+
if (method === "completion/complete") {
|
|
668
|
+
const catalogTools = await engine.searchTools({ lane: "all", limit: 100 });
|
|
669
|
+
const completion = completeMcpArgument(params, catalogTools.tools.map((t) => t.slug));
|
|
670
|
+
return {
|
|
671
|
+
jsonrpc: "2.0",
|
|
672
|
+
id,
|
|
673
|
+
result: {
|
|
674
|
+
resultType: "complete",
|
|
675
|
+
completion,
|
|
676
|
+
},
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
if (method === "subscriptions/listen") {
|
|
680
|
+
return {
|
|
681
|
+
jsonrpc: "2.0",
|
|
682
|
+
id,
|
|
683
|
+
result: {
|
|
684
|
+
resultType: "complete",
|
|
685
|
+
events: [],
|
|
686
|
+
ttlMs: 30_000,
|
|
687
|
+
cacheScope: "private",
|
|
688
|
+
},
|
|
689
|
+
};
|
|
517
690
|
}
|
|
518
691
|
if (method === "prompts/list") {
|
|
519
692
|
return {
|
|
520
693
|
jsonrpc: "2.0",
|
|
521
694
|
id,
|
|
522
695
|
result: {
|
|
696
|
+
resultType: "complete",
|
|
697
|
+
ttlMs: 300_000,
|
|
698
|
+
cacheScope: "public",
|
|
523
699
|
prompts: [
|
|
524
700
|
{
|
|
525
701
|
name: "context",
|
|
@@ -551,6 +727,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
551
727
|
description: "Inspect the workspace's 9-module Microsoft Agent Governance posture, Bi-Temporal Knowledge Graph, and Ed25519 AgenticReceipt hash chain.",
|
|
552
728
|
arguments: [],
|
|
553
729
|
},
|
|
730
|
+
{
|
|
731
|
+
name: "policy_guardrails",
|
|
732
|
+
title: "Workspace Policy, Parameter Guardrails & Risk Matrix",
|
|
733
|
+
description: "Load the structured LLM Policy & Governance Brief (riskLaneMatrix, conditional parameterRules with compliance guidance, budget caps, kill switch status, and control-plane commands).",
|
|
734
|
+
arguments: [],
|
|
735
|
+
},
|
|
554
736
|
],
|
|
555
737
|
},
|
|
556
738
|
};
|
|
@@ -565,6 +747,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
565
747
|
jsonrpc: "2.0",
|
|
566
748
|
id,
|
|
567
749
|
result: {
|
|
750
|
+
resultType: "complete",
|
|
568
751
|
description: "Ready-to-attach Muxo workspace memory, active defaults, and safety guardrails.",
|
|
569
752
|
messages: [
|
|
570
753
|
{
|
|
@@ -578,6 +761,36 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
578
761
|
},
|
|
579
762
|
};
|
|
580
763
|
}
|
|
764
|
+
if (promptName === "policy_guardrails") {
|
|
765
|
+
const gov = engine.getGovernanceOverview(ctx);
|
|
766
|
+
const sections = [
|
|
767
|
+
gov.llmPolicyBrief.llmSystemDirective,
|
|
768
|
+
`### Structured LLM Policy Brief (JSON)\n\`\`\`json\n${JSON.stringify(gov.llmPolicyBrief, null, 2)}\n\`\`\``,
|
|
769
|
+
];
|
|
770
|
+
if (promptArgs.tool_slug) {
|
|
771
|
+
const sim = await engine.checkToolPolicy(ctx, {
|
|
772
|
+
toolSlug: String(promptArgs.tool_slug),
|
|
773
|
+
});
|
|
774
|
+
sections.push(`### Dry-Run Policy Check for \`${sim.toolSlug}\`\n\`\`\`json\n${JSON.stringify(sim, null, 2)}\n\`\`\``);
|
|
775
|
+
}
|
|
776
|
+
return {
|
|
777
|
+
jsonrpc: "2.0",
|
|
778
|
+
id,
|
|
779
|
+
result: {
|
|
780
|
+
resultType: "complete",
|
|
781
|
+
description: "Workspace policy, conditional parameter guardrails, and risk-lane matrix for AI agents",
|
|
782
|
+
messages: [
|
|
783
|
+
{
|
|
784
|
+
role: "user",
|
|
785
|
+
content: {
|
|
786
|
+
type: "text",
|
|
787
|
+
text: sections.join("\n\n"),
|
|
788
|
+
},
|
|
789
|
+
},
|
|
790
|
+
],
|
|
791
|
+
},
|
|
792
|
+
};
|
|
793
|
+
}
|
|
581
794
|
if (promptName === "governed_execution") {
|
|
582
795
|
const task = String(promptArgs.task || "the user's requested operation");
|
|
583
796
|
const runCtx = await engine.getRunContext(ctx);
|
|
@@ -585,6 +798,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
585
798
|
jsonrpc: "2.0",
|
|
586
799
|
id,
|
|
587
800
|
result: {
|
|
801
|
+
resultType: "complete",
|
|
588
802
|
description: "Governed Muxo execution workflow prompt",
|
|
589
803
|
messages: [
|
|
590
804
|
{
|
|
@@ -608,6 +822,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
608
822
|
jsonrpc: "2.0",
|
|
609
823
|
id,
|
|
610
824
|
result: {
|
|
825
|
+
resultType: "complete",
|
|
611
826
|
description: "Workspace governance, bi-temporal graph, and receipt chain audit",
|
|
612
827
|
messages: [
|
|
613
828
|
{
|
|
@@ -640,10 +855,10 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
640
855
|
jsonrpc: "2.0",
|
|
641
856
|
id,
|
|
642
857
|
result: {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
858
|
+
resultType: "complete",
|
|
859
|
+
ttlMs: 300_000,
|
|
860
|
+
cacheScope: "public",
|
|
861
|
+
tools: MUXO_MCP_TOOLS.map((t) => buildMcpToolDescriptor(t)),
|
|
647
862
|
},
|
|
648
863
|
};
|
|
649
864
|
}
|
|
@@ -655,10 +870,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
655
870
|
const structuredContent = output && typeof output === "object" && !Array.isArray(output)
|
|
656
871
|
? output
|
|
657
872
|
: { data: output };
|
|
873
|
+
const resultMeta = buildMcpToolResultMeta(toolName, params);
|
|
658
874
|
return {
|
|
659
875
|
jsonrpc: "2.0",
|
|
660
876
|
id,
|
|
661
877
|
result: {
|
|
878
|
+
resultType: "complete",
|
|
662
879
|
structuredContent,
|
|
663
880
|
content: [
|
|
664
881
|
{
|
|
@@ -666,6 +883,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
666
883
|
text: JSON.stringify(output, null, 2),
|
|
667
884
|
},
|
|
668
885
|
],
|
|
886
|
+
...(resultMeta ? { _meta: resultMeta } : {}),
|
|
669
887
|
isError: false,
|
|
670
888
|
},
|
|
671
889
|
};
|
|
@@ -688,7 +906,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
688
906
|
return {
|
|
689
907
|
jsonrpc: "2.0",
|
|
690
908
|
id,
|
|
691
|
-
result: {
|
|
909
|
+
result: {
|
|
910
|
+
resultType: "complete",
|
|
911
|
+
ttlMs: 300_000,
|
|
912
|
+
cacheScope: "public",
|
|
913
|
+
skills,
|
|
914
|
+
},
|
|
692
915
|
};
|
|
693
916
|
}
|
|
694
917
|
if (method === "skills/get") {
|
|
@@ -711,6 +934,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
711
934
|
jsonrpc: "2.0",
|
|
712
935
|
id,
|
|
713
936
|
result: {
|
|
937
|
+
resultType: "complete",
|
|
938
|
+
ttlMs: 300_000,
|
|
939
|
+
cacheScope: "public",
|
|
714
940
|
skill: {
|
|
715
941
|
uri: skill.uri,
|
|
716
942
|
frontmatter: skill.frontmatter,
|
|
@@ -733,6 +959,18 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
733
959
|
},
|
|
734
960
|
};
|
|
735
961
|
}
|
|
962
|
+
if (method === "resources/templates/list") {
|
|
963
|
+
return {
|
|
964
|
+
jsonrpc: "2.0",
|
|
965
|
+
id,
|
|
966
|
+
result: {
|
|
967
|
+
resultType: "complete",
|
|
968
|
+
ttlMs: 300_000,
|
|
969
|
+
cacheScope: "public",
|
|
970
|
+
resourceTemplates: MUXO_MCP_RESOURCE_TEMPLATES,
|
|
971
|
+
},
|
|
972
|
+
};
|
|
973
|
+
}
|
|
736
974
|
if (method === "resources/list") {
|
|
737
975
|
const skillResources = getMuxoMcpSkills().flatMap((s) => s.files.map((f) => ({
|
|
738
976
|
uri: f.uri,
|
|
@@ -777,6 +1015,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
777
1015
|
description: "9-module Microsoft Agent Governance status, plain-English guardrails, Bayesian trust score, and OWASP ASI-06 scan status.",
|
|
778
1016
|
mimeType: "application/json",
|
|
779
1017
|
},
|
|
1018
|
+
{
|
|
1019
|
+
uri: "muxo://policy/brief",
|
|
1020
|
+
name: "LLM Policy, Risk Matrix & Parameter Guardrails Brief",
|
|
1021
|
+
description: "Structured LLM policy digest with riskLaneMatrix, conditional parameterRules compliance guidance, learned memory defaults, and control-plane commands.",
|
|
1022
|
+
mimeType: "application/json",
|
|
1023
|
+
},
|
|
780
1024
|
{
|
|
781
1025
|
uri: "muxo://receipts/chain",
|
|
782
1026
|
name: "Cryptographic AgenticReceipt Hash Chain",
|
|
@@ -787,11 +1031,36 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
787
1031
|
return {
|
|
788
1032
|
jsonrpc: "2.0",
|
|
789
1033
|
id,
|
|
790
|
-
result: {
|
|
1034
|
+
result: {
|
|
1035
|
+
resultType: "complete",
|
|
1036
|
+
ttlMs: 60_000,
|
|
1037
|
+
cacheScope: "private",
|
|
1038
|
+
resources: [...MUXO_UI_RESOURCES, ...skillResources, ...dynamicResources],
|
|
1039
|
+
},
|
|
791
1040
|
};
|
|
792
1041
|
}
|
|
793
1042
|
if (method === "resources/read") {
|
|
794
1043
|
const uri = String(params.uri || "").trim();
|
|
1044
|
+
const uiResource = MUXO_UI_RESOURCES.find((r) => r.uri === uri);
|
|
1045
|
+
if (uiResource) {
|
|
1046
|
+
return {
|
|
1047
|
+
jsonrpc: "2.0",
|
|
1048
|
+
id,
|
|
1049
|
+
result: {
|
|
1050
|
+
resultType: "complete",
|
|
1051
|
+
ttlMs: 300_000,
|
|
1052
|
+
cacheScope: "public",
|
|
1053
|
+
contents: [
|
|
1054
|
+
{
|
|
1055
|
+
uri: uiResource.uri,
|
|
1056
|
+
mimeType: uiResource.mimeType,
|
|
1057
|
+
text: renderMuxoUiWidgetHtml(),
|
|
1058
|
+
_meta: uiResource._meta,
|
|
1059
|
+
},
|
|
1060
|
+
],
|
|
1061
|
+
},
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
795
1064
|
if (uri === "muxo://profile" || uri === "supermemory://profile") {
|
|
796
1065
|
const overview = await engine.getMemoryOverview(ctx);
|
|
797
1066
|
const profile = engine.getProfile(ctx);
|
|
@@ -810,6 +1079,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
810
1079
|
jsonrpc: "2.0",
|
|
811
1080
|
id,
|
|
812
1081
|
result: {
|
|
1082
|
+
resultType: "complete",
|
|
1083
|
+
ttlMs: 60_000,
|
|
1084
|
+
cacheScope: "private",
|
|
813
1085
|
contents: [
|
|
814
1086
|
{
|
|
815
1087
|
uri,
|
|
@@ -838,6 +1110,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
838
1110
|
jsonrpc: "2.0",
|
|
839
1111
|
id,
|
|
840
1112
|
result: {
|
|
1113
|
+
resultType: "complete",
|
|
1114
|
+
ttlMs: 60_000,
|
|
1115
|
+
cacheScope: "private",
|
|
841
1116
|
contents: [
|
|
842
1117
|
{
|
|
843
1118
|
uri,
|
|
@@ -854,6 +1129,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
854
1129
|
jsonrpc: "2.0",
|
|
855
1130
|
id,
|
|
856
1131
|
result: {
|
|
1132
|
+
resultType: "complete",
|
|
1133
|
+
ttlMs: 60_000,
|
|
1134
|
+
cacheScope: "private",
|
|
857
1135
|
contents: [
|
|
858
1136
|
{
|
|
859
1137
|
uri,
|
|
@@ -870,6 +1148,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
870
1148
|
jsonrpc: "2.0",
|
|
871
1149
|
id,
|
|
872
1150
|
result: {
|
|
1151
|
+
resultType: "complete",
|
|
1152
|
+
ttlMs: 60_000,
|
|
1153
|
+
cacheScope: "private",
|
|
873
1154
|
contents: [
|
|
874
1155
|
{
|
|
875
1156
|
uri,
|
|
@@ -886,6 +1167,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
886
1167
|
jsonrpc: "2.0",
|
|
887
1168
|
id,
|
|
888
1169
|
result: {
|
|
1170
|
+
resultType: "complete",
|
|
1171
|
+
ttlMs: 60_000,
|
|
1172
|
+
cacheScope: "private",
|
|
889
1173
|
contents: [
|
|
890
1174
|
{
|
|
891
1175
|
uri,
|
|
@@ -896,12 +1180,34 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
896
1180
|
},
|
|
897
1181
|
};
|
|
898
1182
|
}
|
|
1183
|
+
if (uri === "muxo://policy/brief") {
|
|
1184
|
+
const gov = engine.getGovernanceOverview(ctx);
|
|
1185
|
+
return {
|
|
1186
|
+
jsonrpc: "2.0",
|
|
1187
|
+
id,
|
|
1188
|
+
result: {
|
|
1189
|
+
resultType: "complete",
|
|
1190
|
+
ttlMs: 60_000,
|
|
1191
|
+
cacheScope: "private",
|
|
1192
|
+
contents: [
|
|
1193
|
+
{
|
|
1194
|
+
uri,
|
|
1195
|
+
mimeType: "application/json",
|
|
1196
|
+
text: JSON.stringify(gov.llmPolicyBrief, null, 2),
|
|
1197
|
+
},
|
|
1198
|
+
],
|
|
1199
|
+
},
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
899
1202
|
if (uri === "muxo://receipts/chain") {
|
|
900
1203
|
const chain = engine.verifyReceiptChain(ctx);
|
|
901
1204
|
return {
|
|
902
1205
|
jsonrpc: "2.0",
|
|
903
1206
|
id,
|
|
904
1207
|
result: {
|
|
1208
|
+
resultType: "complete",
|
|
1209
|
+
ttlMs: 60_000,
|
|
1210
|
+
cacheScope: "private",
|
|
905
1211
|
contents: [
|
|
906
1212
|
{
|
|
907
1213
|
uri,
|
|
@@ -912,6 +1218,142 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
912
1218
|
},
|
|
913
1219
|
};
|
|
914
1220
|
}
|
|
1221
|
+
if (uri.startsWith("muxo://tools/")) {
|
|
1222
|
+
const slug = decodeURIComponent(uri.slice("muxo://tools/".length)).trim();
|
|
1223
|
+
try {
|
|
1224
|
+
const inspected = await dispatchMcpToolCall(engine, ctx, "inspect_tool", {
|
|
1225
|
+
tool_slug: slug,
|
|
1226
|
+
});
|
|
1227
|
+
return {
|
|
1228
|
+
jsonrpc: "2.0",
|
|
1229
|
+
id,
|
|
1230
|
+
result: {
|
|
1231
|
+
resultType: "complete",
|
|
1232
|
+
ttlMs: 300_000,
|
|
1233
|
+
cacheScope: "public",
|
|
1234
|
+
contents: [
|
|
1235
|
+
{
|
|
1236
|
+
uri,
|
|
1237
|
+
mimeType: "application/json",
|
|
1238
|
+
text: JSON.stringify(inspected, null, 2),
|
|
1239
|
+
},
|
|
1240
|
+
],
|
|
1241
|
+
},
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
catch {
|
|
1245
|
+
return {
|
|
1246
|
+
jsonrpc: "2.0",
|
|
1247
|
+
id,
|
|
1248
|
+
error: {
|
|
1249
|
+
code: -32602,
|
|
1250
|
+
message: `Resource not found: ${uri}`,
|
|
1251
|
+
},
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
if (uri.startsWith("muxo://plans/")) {
|
|
1256
|
+
const planId = decodeURIComponent(uri.slice("muxo://plans/".length)).trim();
|
|
1257
|
+
try {
|
|
1258
|
+
const planRecord = await dispatchMcpToolCall(engine, ctx, "get_plan", {
|
|
1259
|
+
plan_id: planId,
|
|
1260
|
+
});
|
|
1261
|
+
return {
|
|
1262
|
+
jsonrpc: "2.0",
|
|
1263
|
+
id,
|
|
1264
|
+
result: {
|
|
1265
|
+
resultType: "complete",
|
|
1266
|
+
ttlMs: 30_000,
|
|
1267
|
+
cacheScope: "private",
|
|
1268
|
+
contents: [
|
|
1269
|
+
{
|
|
1270
|
+
uri,
|
|
1271
|
+
mimeType: "application/json",
|
|
1272
|
+
text: JSON.stringify(planRecord, null, 2),
|
|
1273
|
+
},
|
|
1274
|
+
],
|
|
1275
|
+
},
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
catch {
|
|
1279
|
+
return {
|
|
1280
|
+
jsonrpc: "2.0",
|
|
1281
|
+
id,
|
|
1282
|
+
error: {
|
|
1283
|
+
code: -32602,
|
|
1284
|
+
message: `Resource not found: ${uri}`,
|
|
1285
|
+
},
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
if (uri.startsWith("muxo://runs/")) {
|
|
1290
|
+
const runId = decodeURIComponent(uri.slice("muxo://runs/".length)).trim();
|
|
1291
|
+
try {
|
|
1292
|
+
const runRecord = await dispatchMcpToolCall(engine, ctx, "get_run", {
|
|
1293
|
+
run_id: runId,
|
|
1294
|
+
});
|
|
1295
|
+
return {
|
|
1296
|
+
jsonrpc: "2.0",
|
|
1297
|
+
id,
|
|
1298
|
+
result: {
|
|
1299
|
+
resultType: "complete",
|
|
1300
|
+
ttlMs: 30_000,
|
|
1301
|
+
cacheScope: "private",
|
|
1302
|
+
contents: [
|
|
1303
|
+
{
|
|
1304
|
+
uri,
|
|
1305
|
+
mimeType: "application/json",
|
|
1306
|
+
text: JSON.stringify(runRecord, null, 2),
|
|
1307
|
+
},
|
|
1308
|
+
],
|
|
1309
|
+
},
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
catch {
|
|
1313
|
+
return {
|
|
1314
|
+
jsonrpc: "2.0",
|
|
1315
|
+
id,
|
|
1316
|
+
error: {
|
|
1317
|
+
code: -32602,
|
|
1318
|
+
message: `Resource not found: ${uri}`,
|
|
1319
|
+
},
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
if (uri.startsWith("muxo://receipts/")) {
|
|
1324
|
+
const receiptId = decodeURIComponent(uri.slice("muxo://receipts/".length)).trim();
|
|
1325
|
+
try {
|
|
1326
|
+
const receiptRecord = await dispatchMcpToolCall(engine, ctx, "get_receipt", {
|
|
1327
|
+
receipt_id: receiptId,
|
|
1328
|
+
});
|
|
1329
|
+
return {
|
|
1330
|
+
jsonrpc: "2.0",
|
|
1331
|
+
id,
|
|
1332
|
+
result: {
|
|
1333
|
+
resultType: "complete",
|
|
1334
|
+
ttlMs: 60_000,
|
|
1335
|
+
cacheScope: "private",
|
|
1336
|
+
contents: [
|
|
1337
|
+
{
|
|
1338
|
+
uri,
|
|
1339
|
+
mimeType: "application/json",
|
|
1340
|
+
text: JSON.stringify(receiptRecord, null, 2),
|
|
1341
|
+
},
|
|
1342
|
+
],
|
|
1343
|
+
},
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
catch {
|
|
1347
|
+
return {
|
|
1348
|
+
jsonrpc: "2.0",
|
|
1349
|
+
id,
|
|
1350
|
+
error: {
|
|
1351
|
+
code: -32602,
|
|
1352
|
+
message: `Resource not found: ${uri}`,
|
|
1353
|
+
},
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
915
1357
|
const allFiles = getMuxoMcpSkills().flatMap((s) => s.files);
|
|
916
1358
|
const found = allFiles.find((f) => f.uri === uri);
|
|
917
1359
|
if (!found) {
|
|
@@ -928,6 +1370,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
928
1370
|
jsonrpc: "2.0",
|
|
929
1371
|
id,
|
|
930
1372
|
result: {
|
|
1373
|
+
resultType: "complete",
|
|
1374
|
+
ttlMs: 300_000,
|
|
1375
|
+
cacheScope: "public",
|
|
931
1376
|
contents: [
|
|
932
1377
|
{
|
|
933
1378
|
uri: found.uri,
|
|
@@ -949,10 +1394,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
949
1394
|
}
|
|
950
1395
|
catch (err) {
|
|
951
1396
|
const errPayload = errorPayloadFrom(err, "MCP tool execution failed");
|
|
1397
|
+
const errMeta = buildMcpErrorResultMeta(err, engine?.config?.baseUrl || "https://api.muxo.ai");
|
|
952
1398
|
return {
|
|
953
1399
|
jsonrpc: "2.0",
|
|
954
1400
|
id,
|
|
955
1401
|
result: {
|
|
1402
|
+
resultType: "complete",
|
|
956
1403
|
structuredContent: errPayload,
|
|
957
1404
|
content: [
|
|
958
1405
|
{
|
|
@@ -960,6 +1407,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
960
1407
|
text: JSON.stringify(errPayload, null, 2),
|
|
961
1408
|
},
|
|
962
1409
|
],
|
|
1410
|
+
...(errMeta ? { _meta: errMeta } : {}),
|
|
963
1411
|
isError: true,
|
|
964
1412
|
},
|
|
965
1413
|
};
|