@muxoai/platform 1.4.1 → 1.4.2

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.
Files changed (43) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/marketplace.json +2 -2
  3. package/README.md +1 -1
  4. package/dist/cli.js +6 -3
  5. package/dist/composio-catalog.d.ts +177 -1
  6. package/dist/composio-catalog.js +1427 -7
  7. package/dist/config.d.ts +6 -0
  8. package/dist/config.js +11 -1
  9. package/dist/engine.d.ts +18 -1
  10. package/dist/engine.js +259 -35
  11. package/dist/mcp-schema.d.ts +162 -1
  12. package/dist/mcp-schema.js +1523 -40
  13. package/dist/mcp.d.ts +2 -2
  14. package/dist/mcp.js +412 -23
  15. package/dist/policy.d.ts +108 -1
  16. package/dist/policy.js +406 -1
  17. package/dist/providers/composio-instant.js +38 -3
  18. package/dist/providers/composio-sdk.d.ts +59 -2
  19. package/dist/providers/composio-sdk.js +273 -59
  20. package/dist/providers/stripe-projects.d.ts +4 -0
  21. package/dist/providers/stripe-projects.js +548 -126
  22. package/dist/server.js +531 -61
  23. package/dist/store.js +2 -0
  24. package/dist/types.d.ts +15 -0
  25. package/dist/ui/console-html.d.ts +31 -1
  26. package/dist/ui/console-html.js +922 -368
  27. package/dist/ui/design-tokens.js +1 -1
  28. package/dist/version.d.ts +1 -1
  29. package/dist/version.js +1 -1
  30. package/package.json +3 -2
  31. package/plugins/muxo/.claude-plugin/plugin.json +2 -2
  32. package/plugins/muxo/.codex-plugin/plugin.json +15 -8
  33. package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
  34. package/plugins/muxo/hooks/session-start.sh +15 -3
  35. package/plugins/muxo/hooks/user-prompt-submit.sh +14 -1
  36. package/plugins/muxo/mcp.json +0 -10
  37. package/plugins/muxo/plugin.json +4 -4
  38. package/plugins/muxo/skills/muxo/SKILL.md +25 -16
  39. package/plugins/muxo/skills/muxo/references/cli.md +5 -1
  40. package/plugins/muxo/skills/muxo/references/mcp.md +11 -6
  41. package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
  42. package/plugins/muxo/skills/setup/SKILL.md +1 -1
  43. 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 (Composio), Instant Tools, Cloud Infrastructure (Stripe Projects), Supermemory v5, and Microsoft Agent Governance.
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
- return engine.startConnection(ctx, {
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 || ""),
@@ -273,6 +279,35 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
273
279
  source: rawParamRules ? "mcp_harness" : "deterministic",
274
280
  });
275
281
  }
282
+ if (action === "reset_guardrails") {
283
+ return engine.resetWorkspaceGuardrails(ctx);
284
+ }
285
+ if (action === "check_policy" || action === "simulate_policy") {
286
+ const toolSlug = String(args.tool_slug || args.slug || args.tool_id || query || prompt || "instant.web.search").trim();
287
+ const input = (args.input || args.arguments) || {};
288
+ return engine.checkToolPolicy(ctx, { toolSlug, input });
289
+ }
290
+ if (action === "kill_switch") {
291
+ const enabled = typeof args.enabled === "boolean"
292
+ ? args.enabled
293
+ : typeof args.active === "boolean"
294
+ ? args.active
295
+ : !/\b(resume|unpause|disable|off|false)\b/i.test(prompt || query || "");
296
+ const reason = prompt ||
297
+ query ||
298
+ (enabled ? "Paused via MCP get_run_context" : undefined);
299
+ const updated = engine.setKillSwitch(ctx, enabled, reason);
300
+ const govOverview = engine.getGovernanceOverview(ctx);
301
+ return {
302
+ ok: true,
303
+ action: "kill_switch",
304
+ killSwitchActive: Boolean(updated.policy.killSwitchActive),
305
+ killSwitchReason: updated.policy.killSwitchReason || null,
306
+ policy: updated.policy,
307
+ llmPolicyBrief: govOverview.llmPolicyBrief,
308
+ explanation: govOverview.explanation,
309
+ };
310
+ }
276
311
  if (action === "scan_context") {
277
312
  const textToScan = String(args.content || prompt || query || "");
278
313
  return engine.scanForContextPoisoning(ctx.workspace.id, textToScan);
@@ -403,6 +438,39 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
403
438
  source: rawParamRules ? "mcp_harness" : "deterministic",
404
439
  });
405
440
  }
441
+ case "reset_guardrails":
442
+ return engine.resetWorkspaceGuardrails(ctx);
443
+ case "check_policy":
444
+ case "simulate_policy":
445
+ return engine.checkToolPolicy(ctx, {
446
+ toolSlug: String(args.tool_slug || args.slug || args.tool_id || args.query || "instant.web.search"),
447
+ input: (args.input || args.arguments) || {},
448
+ });
449
+ case "kill_switch": {
450
+ const enabled = typeof args.enabled === "boolean"
451
+ ? args.enabled
452
+ : typeof args.active === "boolean"
453
+ ? args.active
454
+ : true;
455
+ const reason = args.reason
456
+ ? String(args.reason)
457
+ : args.prompt
458
+ ? String(args.prompt)
459
+ : undefined;
460
+ const updated = engine.setKillSwitch(ctx, enabled, reason);
461
+ const govOverview = engine.getGovernanceOverview(ctx);
462
+ return {
463
+ ok: true,
464
+ action: "kill_switch",
465
+ killSwitchActive: Boolean(updated.policy.killSwitchActive),
466
+ killSwitchReason: updated.policy.killSwitchReason || null,
467
+ policy: updated.policy,
468
+ llmPolicyBrief: govOverview.llmPolicyBrief,
469
+ explanation: govOverview.explanation,
470
+ };
471
+ }
472
+ case "scan_context":
473
+ return engine.scanForContextPoisoning(ctx.workspace.id, String(args.content || args.prompt || args.query || ""));
406
474
  case "governance_status":
407
475
  return engine.getGovernanceOverview(ctx);
408
476
  case "verify_receipt_chain":
@@ -424,7 +492,7 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
424
492
  const toolHits = toolsRes.tools.map((t) => ({
425
493
  id: `tool:${t.slug}`,
426
494
  title: `${t.name} (${t.slug})`,
427
- url: t.providerUrl || `https://docs.muxo.ai/tools/${encodeURIComponent(t.slug)}`,
495
+ url: t.providerUrl || `https://docs.muxo.ai/catalogue#${encodeURIComponent(t.providerSlug || t.slug)}`,
428
496
  snippet: `${t.description} [lane=${t.lane}, risk=${t.riskLevel}, cost=${t.creditCost}cr]`,
429
497
  }));
430
498
  const memHits = (memRes.memories || []).slice(0, 5).map((m) => ({
@@ -464,7 +532,7 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
464
532
  title: tool.name,
465
533
  text: JSON.stringify(tool, null, 2),
466
534
  url: tool.providerUrl ||
467
- `https://docs.muxo.ai/tools/${encodeURIComponent(tool.slug)}`,
535
+ `https://docs.muxo.ai/catalogue#${encodeURIComponent(tool.providerSlug || tool.slug)}`,
468
536
  metadata: {
469
537
  slug: tool.slug,
470
538
  lane: tool.lane,
@@ -485,41 +553,90 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
485
553
  method.startsWith("notifications/")) {
486
554
  return null;
487
555
  }
556
+ const headerAndMetaCheck = validateMcpHttpHeadersAndMeta({}, rpc);
557
+ if (!headerAndMetaCheck.ok) {
558
+ return {
559
+ jsonrpc: "2.0",
560
+ id,
561
+ error: headerAndMetaCheck.error,
562
+ };
563
+ }
488
564
  try {
565
+ if (method === "server/discover") {
566
+ return {
567
+ jsonrpc: "2.0",
568
+ id,
569
+ result: buildMcpDiscoverResult(MUXO_VERSION),
570
+ };
571
+ }
489
572
  if (method === "initialize") {
490
- const requestedProtocol = typeof params.protocolVersion === "string" &&
491
- params.protocolVersion.trim()
492
- ? params.protocolVersion.trim()
493
- : "2025-06-18";
573
+ const requestedProtocol = headerAndMetaCheck.protocolVersion;
574
+ const serverInfo = {
575
+ name: "muxo-mcp-server",
576
+ title: "Muxo Unified Agent Runtime & Governance MCP Server",
577
+ version: MUXO_VERSION,
578
+ };
494
579
  return {
495
580
  jsonrpc: "2.0",
496
581
  id,
497
582
  result: {
583
+ resultType: "complete",
498
584
  protocolVersion: requestedProtocol,
585
+ supportedVersions: [...SUPPORTED_MCP_PROTOCOL_VERSIONS],
499
586
  instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
500
- serverInfo: {
501
- name: "muxo-mcp-server",
502
- version: MUXO_VERSION,
503
- },
587
+ serverInfo,
504
588
  capabilities: {
505
589
  tools: { listChanged: false },
506
- resources: { listChanged: false },
590
+ resources: { listChanged: false, subscribe: false },
507
591
  prompts: { listChanged: false },
592
+ completions: {},
508
593
  extensions: {
509
594
  "io.modelcontextprotocol/skills": {},
595
+ "io.modelcontextprotocol/apps": {},
510
596
  },
511
597
  },
598
+ _meta: {
599
+ "io.modelcontextprotocol/serverInfo": serverInfo,
600
+ "io.modelcontextprotocol/instructions": MUXO_MCP_SERVER_INSTRUCTIONS,
601
+ },
512
602
  },
513
603
  };
514
604
  }
515
605
  if (method === "ping") {
516
- return { jsonrpc: "2.0", id, result: {} };
606
+ return { jsonrpc: "2.0", id, result: { resultType: "complete" } };
607
+ }
608
+ if (method === "completion/complete") {
609
+ const catalogTools = await engine.searchTools({ lane: "all", limit: 100 });
610
+ const completion = completeMcpArgument(params, catalogTools.tools.map((t) => t.slug));
611
+ return {
612
+ jsonrpc: "2.0",
613
+ id,
614
+ result: {
615
+ resultType: "complete",
616
+ completion,
617
+ },
618
+ };
619
+ }
620
+ if (method === "subscriptions/listen") {
621
+ return {
622
+ jsonrpc: "2.0",
623
+ id,
624
+ result: {
625
+ resultType: "complete",
626
+ events: [],
627
+ ttlMs: 30_000,
628
+ cacheScope: "private",
629
+ },
630
+ };
517
631
  }
518
632
  if (method === "prompts/list") {
519
633
  return {
520
634
  jsonrpc: "2.0",
521
635
  id,
522
636
  result: {
637
+ resultType: "complete",
638
+ ttlMs: 300_000,
639
+ cacheScope: "public",
523
640
  prompts: [
524
641
  {
525
642
  name: "context",
@@ -551,6 +668,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
551
668
  description: "Inspect the workspace's 9-module Microsoft Agent Governance posture, Bi-Temporal Knowledge Graph, and Ed25519 AgenticReceipt hash chain.",
552
669
  arguments: [],
553
670
  },
671
+ {
672
+ name: "policy_guardrails",
673
+ title: "Workspace Policy, Parameter Guardrails & Risk Matrix",
674
+ description: "Load the structured LLM Policy & Governance Brief (riskLaneMatrix, conditional parameterRules with compliance guidance, budget caps, kill switch status, and control-plane commands).",
675
+ arguments: [],
676
+ },
554
677
  ],
555
678
  },
556
679
  };
@@ -565,6 +688,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
565
688
  jsonrpc: "2.0",
566
689
  id,
567
690
  result: {
691
+ resultType: "complete",
568
692
  description: "Ready-to-attach Muxo workspace memory, active defaults, and safety guardrails.",
569
693
  messages: [
570
694
  {
@@ -578,6 +702,36 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
578
702
  },
579
703
  };
580
704
  }
705
+ if (promptName === "policy_guardrails") {
706
+ const gov = engine.getGovernanceOverview(ctx);
707
+ const sections = [
708
+ gov.llmPolicyBrief.llmSystemDirective,
709
+ `### Structured LLM Policy Brief (JSON)\n\`\`\`json\n${JSON.stringify(gov.llmPolicyBrief, null, 2)}\n\`\`\``,
710
+ ];
711
+ if (promptArgs.tool_slug) {
712
+ const sim = await engine.checkToolPolicy(ctx, {
713
+ toolSlug: String(promptArgs.tool_slug),
714
+ });
715
+ sections.push(`### Dry-Run Policy Check for \`${sim.toolSlug}\`\n\`\`\`json\n${JSON.stringify(sim, null, 2)}\n\`\`\``);
716
+ }
717
+ return {
718
+ jsonrpc: "2.0",
719
+ id,
720
+ result: {
721
+ resultType: "complete",
722
+ description: "Workspace policy, conditional parameter guardrails, and risk-lane matrix for AI agents",
723
+ messages: [
724
+ {
725
+ role: "user",
726
+ content: {
727
+ type: "text",
728
+ text: sections.join("\n\n"),
729
+ },
730
+ },
731
+ ],
732
+ },
733
+ };
734
+ }
581
735
  if (promptName === "governed_execution") {
582
736
  const task = String(promptArgs.task || "the user's requested operation");
583
737
  const runCtx = await engine.getRunContext(ctx);
@@ -585,6 +739,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
585
739
  jsonrpc: "2.0",
586
740
  id,
587
741
  result: {
742
+ resultType: "complete",
588
743
  description: "Governed Muxo execution workflow prompt",
589
744
  messages: [
590
745
  {
@@ -608,6 +763,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
608
763
  jsonrpc: "2.0",
609
764
  id,
610
765
  result: {
766
+ resultType: "complete",
611
767
  description: "Workspace governance, bi-temporal graph, and receipt chain audit",
612
768
  messages: [
613
769
  {
@@ -640,10 +796,10 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
640
796
  jsonrpc: "2.0",
641
797
  id,
642
798
  result: {
643
- tools: MUXO_MCP_TOOLS.map((t) => ({
644
- ...t,
645
- securitySchemes: securitySchemesForTool(t.name),
646
- })),
799
+ resultType: "complete",
800
+ ttlMs: 300_000,
801
+ cacheScope: "public",
802
+ tools: MUXO_MCP_TOOLS.map((t) => buildMcpToolDescriptor(t)),
647
803
  },
648
804
  };
649
805
  }
@@ -655,10 +811,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
655
811
  const structuredContent = output && typeof output === "object" && !Array.isArray(output)
656
812
  ? output
657
813
  : { data: output };
814
+ const resultMeta = buildMcpToolResultMeta(toolName, params);
658
815
  return {
659
816
  jsonrpc: "2.0",
660
817
  id,
661
818
  result: {
819
+ resultType: "complete",
662
820
  structuredContent,
663
821
  content: [
664
822
  {
@@ -666,6 +824,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
666
824
  text: JSON.stringify(output, null, 2),
667
825
  },
668
826
  ],
827
+ ...(resultMeta ? { _meta: resultMeta } : {}),
669
828
  isError: false,
670
829
  },
671
830
  };
@@ -688,7 +847,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
688
847
  return {
689
848
  jsonrpc: "2.0",
690
849
  id,
691
- result: { skills },
850
+ result: {
851
+ resultType: "complete",
852
+ ttlMs: 300_000,
853
+ cacheScope: "public",
854
+ skills,
855
+ },
692
856
  };
693
857
  }
694
858
  if (method === "skills/get") {
@@ -711,6 +875,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
711
875
  jsonrpc: "2.0",
712
876
  id,
713
877
  result: {
878
+ resultType: "complete",
879
+ ttlMs: 300_000,
880
+ cacheScope: "public",
714
881
  skill: {
715
882
  uri: skill.uri,
716
883
  frontmatter: skill.frontmatter,
@@ -733,6 +900,18 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
733
900
  },
734
901
  };
735
902
  }
903
+ if (method === "resources/templates/list") {
904
+ return {
905
+ jsonrpc: "2.0",
906
+ id,
907
+ result: {
908
+ resultType: "complete",
909
+ ttlMs: 300_000,
910
+ cacheScope: "public",
911
+ resourceTemplates: MUXO_MCP_RESOURCE_TEMPLATES,
912
+ },
913
+ };
914
+ }
736
915
  if (method === "resources/list") {
737
916
  const skillResources = getMuxoMcpSkills().flatMap((s) => s.files.map((f) => ({
738
917
  uri: f.uri,
@@ -777,6 +956,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
777
956
  description: "9-module Microsoft Agent Governance status, plain-English guardrails, Bayesian trust score, and OWASP ASI-06 scan status.",
778
957
  mimeType: "application/json",
779
958
  },
959
+ {
960
+ uri: "muxo://policy/brief",
961
+ name: "LLM Policy, Risk Matrix & Parameter Guardrails Brief",
962
+ description: "Structured LLM policy digest with riskLaneMatrix, conditional parameterRules compliance guidance, learned memory defaults, and control-plane commands.",
963
+ mimeType: "application/json",
964
+ },
780
965
  {
781
966
  uri: "muxo://receipts/chain",
782
967
  name: "Cryptographic AgenticReceipt Hash Chain",
@@ -787,11 +972,36 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
787
972
  return {
788
973
  jsonrpc: "2.0",
789
974
  id,
790
- result: { resources: [...skillResources, ...dynamicResources] },
975
+ result: {
976
+ resultType: "complete",
977
+ ttlMs: 60_000,
978
+ cacheScope: "private",
979
+ resources: [...MUXO_UI_RESOURCES, ...skillResources, ...dynamicResources],
980
+ },
791
981
  };
792
982
  }
793
983
  if (method === "resources/read") {
794
984
  const uri = String(params.uri || "").trim();
985
+ const uiResource = MUXO_UI_RESOURCES.find((r) => r.uri === uri);
986
+ if (uiResource) {
987
+ return {
988
+ jsonrpc: "2.0",
989
+ id,
990
+ result: {
991
+ resultType: "complete",
992
+ ttlMs: 300_000,
993
+ cacheScope: "public",
994
+ contents: [
995
+ {
996
+ uri: uiResource.uri,
997
+ mimeType: uiResource.mimeType,
998
+ text: renderMuxoUiWidgetHtml(),
999
+ _meta: uiResource._meta,
1000
+ },
1001
+ ],
1002
+ },
1003
+ };
1004
+ }
795
1005
  if (uri === "muxo://profile" || uri === "supermemory://profile") {
796
1006
  const overview = await engine.getMemoryOverview(ctx);
797
1007
  const profile = engine.getProfile(ctx);
@@ -810,6 +1020,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
810
1020
  jsonrpc: "2.0",
811
1021
  id,
812
1022
  result: {
1023
+ resultType: "complete",
1024
+ ttlMs: 60_000,
1025
+ cacheScope: "private",
813
1026
  contents: [
814
1027
  {
815
1028
  uri,
@@ -838,6 +1051,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
838
1051
  jsonrpc: "2.0",
839
1052
  id,
840
1053
  result: {
1054
+ resultType: "complete",
1055
+ ttlMs: 60_000,
1056
+ cacheScope: "private",
841
1057
  contents: [
842
1058
  {
843
1059
  uri,
@@ -854,6 +1070,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
854
1070
  jsonrpc: "2.0",
855
1071
  id,
856
1072
  result: {
1073
+ resultType: "complete",
1074
+ ttlMs: 60_000,
1075
+ cacheScope: "private",
857
1076
  contents: [
858
1077
  {
859
1078
  uri,
@@ -870,6 +1089,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
870
1089
  jsonrpc: "2.0",
871
1090
  id,
872
1091
  result: {
1092
+ resultType: "complete",
1093
+ ttlMs: 60_000,
1094
+ cacheScope: "private",
873
1095
  contents: [
874
1096
  {
875
1097
  uri,
@@ -886,6 +1108,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
886
1108
  jsonrpc: "2.0",
887
1109
  id,
888
1110
  result: {
1111
+ resultType: "complete",
1112
+ ttlMs: 60_000,
1113
+ cacheScope: "private",
889
1114
  contents: [
890
1115
  {
891
1116
  uri,
@@ -896,12 +1121,34 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
896
1121
  },
897
1122
  };
898
1123
  }
1124
+ if (uri === "muxo://policy/brief") {
1125
+ const gov = engine.getGovernanceOverview(ctx);
1126
+ return {
1127
+ jsonrpc: "2.0",
1128
+ id,
1129
+ result: {
1130
+ resultType: "complete",
1131
+ ttlMs: 60_000,
1132
+ cacheScope: "private",
1133
+ contents: [
1134
+ {
1135
+ uri,
1136
+ mimeType: "application/json",
1137
+ text: JSON.stringify(gov.llmPolicyBrief, null, 2),
1138
+ },
1139
+ ],
1140
+ },
1141
+ };
1142
+ }
899
1143
  if (uri === "muxo://receipts/chain") {
900
1144
  const chain = engine.verifyReceiptChain(ctx);
901
1145
  return {
902
1146
  jsonrpc: "2.0",
903
1147
  id,
904
1148
  result: {
1149
+ resultType: "complete",
1150
+ ttlMs: 60_000,
1151
+ cacheScope: "private",
905
1152
  contents: [
906
1153
  {
907
1154
  uri,
@@ -912,6 +1159,142 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
912
1159
  },
913
1160
  };
914
1161
  }
1162
+ if (uri.startsWith("muxo://tools/")) {
1163
+ const slug = decodeURIComponent(uri.slice("muxo://tools/".length)).trim();
1164
+ try {
1165
+ const inspected = await dispatchMcpToolCall(engine, ctx, "inspect_tool", {
1166
+ tool_slug: slug,
1167
+ });
1168
+ return {
1169
+ jsonrpc: "2.0",
1170
+ id,
1171
+ result: {
1172
+ resultType: "complete",
1173
+ ttlMs: 300_000,
1174
+ cacheScope: "public",
1175
+ contents: [
1176
+ {
1177
+ uri,
1178
+ mimeType: "application/json",
1179
+ text: JSON.stringify(inspected, null, 2),
1180
+ },
1181
+ ],
1182
+ },
1183
+ };
1184
+ }
1185
+ catch {
1186
+ return {
1187
+ jsonrpc: "2.0",
1188
+ id,
1189
+ error: {
1190
+ code: -32602,
1191
+ message: `Resource not found: ${uri}`,
1192
+ },
1193
+ };
1194
+ }
1195
+ }
1196
+ if (uri.startsWith("muxo://plans/")) {
1197
+ const planId = decodeURIComponent(uri.slice("muxo://plans/".length)).trim();
1198
+ try {
1199
+ const planRecord = await dispatchMcpToolCall(engine, ctx, "get_plan", {
1200
+ plan_id: planId,
1201
+ });
1202
+ return {
1203
+ jsonrpc: "2.0",
1204
+ id,
1205
+ result: {
1206
+ resultType: "complete",
1207
+ ttlMs: 30_000,
1208
+ cacheScope: "private",
1209
+ contents: [
1210
+ {
1211
+ uri,
1212
+ mimeType: "application/json",
1213
+ text: JSON.stringify(planRecord, null, 2),
1214
+ },
1215
+ ],
1216
+ },
1217
+ };
1218
+ }
1219
+ catch {
1220
+ return {
1221
+ jsonrpc: "2.0",
1222
+ id,
1223
+ error: {
1224
+ code: -32602,
1225
+ message: `Resource not found: ${uri}`,
1226
+ },
1227
+ };
1228
+ }
1229
+ }
1230
+ if (uri.startsWith("muxo://runs/")) {
1231
+ const runId = decodeURIComponent(uri.slice("muxo://runs/".length)).trim();
1232
+ try {
1233
+ const runRecord = await dispatchMcpToolCall(engine, ctx, "get_run", {
1234
+ run_id: runId,
1235
+ });
1236
+ return {
1237
+ jsonrpc: "2.0",
1238
+ id,
1239
+ result: {
1240
+ resultType: "complete",
1241
+ ttlMs: 30_000,
1242
+ cacheScope: "private",
1243
+ contents: [
1244
+ {
1245
+ uri,
1246
+ mimeType: "application/json",
1247
+ text: JSON.stringify(runRecord, null, 2),
1248
+ },
1249
+ ],
1250
+ },
1251
+ };
1252
+ }
1253
+ catch {
1254
+ return {
1255
+ jsonrpc: "2.0",
1256
+ id,
1257
+ error: {
1258
+ code: -32602,
1259
+ message: `Resource not found: ${uri}`,
1260
+ },
1261
+ };
1262
+ }
1263
+ }
1264
+ if (uri.startsWith("muxo://receipts/")) {
1265
+ const receiptId = decodeURIComponent(uri.slice("muxo://receipts/".length)).trim();
1266
+ try {
1267
+ const receiptRecord = await dispatchMcpToolCall(engine, ctx, "get_receipt", {
1268
+ receipt_id: receiptId,
1269
+ });
1270
+ return {
1271
+ jsonrpc: "2.0",
1272
+ id,
1273
+ result: {
1274
+ resultType: "complete",
1275
+ ttlMs: 60_000,
1276
+ cacheScope: "private",
1277
+ contents: [
1278
+ {
1279
+ uri,
1280
+ mimeType: "application/json",
1281
+ text: JSON.stringify(receiptRecord, null, 2),
1282
+ },
1283
+ ],
1284
+ },
1285
+ };
1286
+ }
1287
+ catch {
1288
+ return {
1289
+ jsonrpc: "2.0",
1290
+ id,
1291
+ error: {
1292
+ code: -32602,
1293
+ message: `Resource not found: ${uri}`,
1294
+ },
1295
+ };
1296
+ }
1297
+ }
915
1298
  const allFiles = getMuxoMcpSkills().flatMap((s) => s.files);
916
1299
  const found = allFiles.find((f) => f.uri === uri);
917
1300
  if (!found) {
@@ -928,6 +1311,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
928
1311
  jsonrpc: "2.0",
929
1312
  id,
930
1313
  result: {
1314
+ resultType: "complete",
1315
+ ttlMs: 300_000,
1316
+ cacheScope: "public",
931
1317
  contents: [
932
1318
  {
933
1319
  uri: found.uri,
@@ -949,10 +1335,12 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
949
1335
  }
950
1336
  catch (err) {
951
1337
  const errPayload = errorPayloadFrom(err, "MCP tool execution failed");
1338
+ const errMeta = buildMcpErrorResultMeta(err, engine?.config?.baseUrl || "https://api.muxo.ai");
952
1339
  return {
953
1340
  jsonrpc: "2.0",
954
1341
  id,
955
1342
  result: {
1343
+ resultType: "complete",
956
1344
  structuredContent: errPayload,
957
1345
  content: [
958
1346
  {
@@ -960,6 +1348,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
960
1348
  text: JSON.stringify(errPayload, null, 2),
961
1349
  },
962
1350
  ],
1351
+ ...(errMeta ? { _meta: errMeta } : {}),
963
1352
  isError: true,
964
1353
  },
965
1354
  };