@muxoai/sdk 1.3.0 → 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 +2 -2
- package/.claude-plugin/marketplace.json +19 -4
- package/.codex/config.toml +9 -2
- package/ARCHITECTURE.md +16 -6
- package/README.md +69 -24
- package/dist/clerk.d.ts +35 -0
- package/dist/clerk.js +201 -0
- package/dist/cli.js +1677 -103
- package/dist/composio-catalog.d.ts +234 -0
- package/dist/composio-catalog.js +1894 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.js +27 -1
- package/dist/durable-workflow.d.ts +112 -0
- package/dist/durable-workflow.js +284 -0
- package/dist/engine.d.ts +377 -6
- package/dist/engine.js +1919 -94
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/mcp-schema.d.ts +286 -0
- package/dist/mcp-schema.js +2580 -0
- package/dist/mcp.d.ts +2 -25
- package/dist/mcp.js +1008 -507
- package/dist/memory-graph.d.ts +45 -0
- package/dist/memory-graph.js +293 -0
- package/dist/nl.js +214 -35
- package/dist/oauth.d.ts +32 -0
- package/dist/oauth.js +134 -0
- package/dist/oss-suite.d.ts +217 -0
- package/dist/oss-suite.js +836 -0
- package/dist/policy.d.ts +190 -0
- package/dist/policy.js +1597 -0
- package/dist/providers/composio-instant.d.ts +4 -0
- package/dist/providers/composio-instant.js +890 -535
- package/dist/providers/composio-sdk.d.ts +126 -5
- package/dist/providers/composio-sdk.js +902 -79
- package/dist/providers/microsoft-governance.d.ts +89 -3
- package/dist/providers/microsoft-governance.js +673 -26
- package/dist/providers/stripe-billing.d.ts +42 -0
- package/dist/providers/stripe-billing.js +244 -5
- package/dist/providers/stripe-projects.d.ts +459 -4
- package/dist/providers/stripe-projects.js +2674 -122
- package/dist/providers/supermemory.d.ts +102 -6
- package/dist/providers/supermemory.js +609 -55
- package/dist/provisioning-managed.d.ts +50 -0
- package/dist/provisioning-managed.js +155 -0
- package/dist/sdk.d.ts +728 -7
- package/dist/sdk.js +539 -10
- package/dist/server.js +2744 -321
- package/dist/store.d.ts +138 -6
- package/dist/store.js +932 -58
- package/dist/types.d.ts +330 -4
- package/dist/ui/console-html.d.ts +62 -0
- package/dist/ui/console-html.js +3742 -2228
- package/dist/ui/design-tokens.d.ts +177 -0
- package/dist/ui/design-tokens.js +210 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/package.json +6 -5
- package/plugins/muxo/.app.json +1 -1
- package/plugins/muxo/.claude-plugin/plugin.json +3 -3
- package/plugins/muxo/.codex-plugin/plugin.json +19 -10
- package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
- package/plugins/muxo/.mcp.json +1 -33
- package/plugins/muxo/assets/logo.png +0 -0
- package/plugins/muxo/hooks/session-start.sh +16 -4
- package/plugins/muxo/hooks/user-prompt-submit.sh +14 -1
- package/plugins/muxo/mcp.json +0 -10
- package/plugins/muxo/plugin.json +65 -8
- package/plugins/muxo/skills/muxo/SKILL.md +142 -14
- package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
- package/plugins/muxo/skills/muxo/references/cli.md +9 -3
- package/plugins/muxo/skills/muxo/references/mcp.md +22 -10
- package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
- package/plugins/muxo/skills/setup/SKILL.md +17 -3
- package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
- package/src/catalogues/stripe-projects-catalog.json +140 -0
package/dist/mcp.js
CHANGED
|
@@ -2,474 +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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*/
|
|
9
|
-
export const MUXO_MCP_SERVER_INSTRUCTIONS = "Muxo governs SaaS actions (Composio app.*), Instant tools (instant.*), Cloud Infrastructure (Stripe Projects resource.*), Supermemory v5 recall, and Microsoft Agent Governance Ed25519 receipts. Workflow: 1) search_tools & inspect_tool. 2) plan_action to get a plan_*. 3) If authHandoff.required is true, show redirectUrl and call wait_for_connection. 4) Execute via the matching risk tool (execute_read/write/admin/financial/provisioning/destructive). 5) Verify via get_receipt.";
|
|
10
|
-
export const MUXO_MCP_TOOLS = [
|
|
11
|
-
{
|
|
12
|
-
name: "get_profile",
|
|
13
|
-
title: "Get Authenticated Profile",
|
|
14
|
-
description: "Get the authenticated actor profile, user ID, email, workspace ID, and subscription tier.",
|
|
15
|
-
inputSchema: {
|
|
16
|
-
type: "object",
|
|
17
|
-
properties: {},
|
|
18
|
-
additionalProperties: false,
|
|
19
|
-
},
|
|
20
|
-
outputSchema: {
|
|
21
|
-
type: "object",
|
|
22
|
-
properties: {
|
|
23
|
-
id: { type: "string", description: "Unique user identifier" },
|
|
24
|
-
name: { type: "string", description: "Display name" },
|
|
25
|
-
email: { type: "string", description: "Email address" },
|
|
26
|
-
workspaceId: { type: "string", description: "Active workspace ID" },
|
|
27
|
-
workspaceName: { type: "string", description: "Active workspace name" },
|
|
28
|
-
tier: { type: "string", description: "Workspace subscription tier" },
|
|
29
|
-
},
|
|
30
|
-
required: ["id"],
|
|
31
|
-
},
|
|
32
|
-
annotations: {
|
|
33
|
-
readOnlyHint: true,
|
|
34
|
-
destructiveHint: false,
|
|
35
|
-
openWorldHint: false,
|
|
36
|
-
},
|
|
37
|
-
_meta: {
|
|
38
|
-
"openai/profile": true,
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: "get_organization",
|
|
43
|
-
title: "Get Organization & Billing Summary",
|
|
44
|
-
description: "Get workspace governance policy, monthly action usage, credit balance, Merchant-of-Record supplier settlement summary, and active connection/resource counts.",
|
|
45
|
-
inputSchema: {
|
|
46
|
-
type: "object",
|
|
47
|
-
properties: {},
|
|
48
|
-
additionalProperties: false,
|
|
49
|
-
},
|
|
50
|
-
annotations: {
|
|
51
|
-
readOnlyHint: true,
|
|
52
|
-
destructiveHint: false,
|
|
53
|
-
openWorldHint: false,
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: "search_tools",
|
|
58
|
-
title: "Search Unified Tool Catalog",
|
|
59
|
-
description: "Search the unified Muxo catalog across Connected Apps (Composio SDK: app.*), Instant Tools (Composio Instant: instant.*), and Cloud Infrastructure (Stripe Projects: resource.*).",
|
|
60
|
-
inputSchema: {
|
|
61
|
-
type: "object",
|
|
62
|
-
properties: {
|
|
63
|
-
query: {
|
|
64
|
-
type: "string",
|
|
65
|
-
description: "Search keywords (e.g. 'postgres', 'github issue', 'web search', 'seo audit', 'redis')",
|
|
66
|
-
},
|
|
67
|
-
lane: {
|
|
68
|
-
type: "string",
|
|
69
|
-
enum: ["all", "composio_sdk", "composio_instant", "stripe_projects"],
|
|
70
|
-
default: "all",
|
|
71
|
-
},
|
|
72
|
-
risk_level: {
|
|
73
|
-
type: "string",
|
|
74
|
-
enum: [
|
|
75
|
-
"read",
|
|
76
|
-
"write",
|
|
77
|
-
"admin",
|
|
78
|
-
"financial",
|
|
79
|
-
"provisioning",
|
|
80
|
-
"destructive",
|
|
81
|
-
],
|
|
82
|
-
},
|
|
83
|
-
limit: { type: "number", default: 20 },
|
|
84
|
-
},
|
|
85
|
-
additionalProperties: false,
|
|
86
|
-
},
|
|
87
|
-
annotations: {
|
|
88
|
-
readOnlyHint: true,
|
|
89
|
-
destructiveHint: false,
|
|
90
|
-
openWorldHint: true,
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
name: "inspect_tool",
|
|
95
|
-
title: "Inspect Tool Schema & Risk",
|
|
96
|
-
description: "Inspect a tool's full input JSON schema, risk classification, provider lane, LLM context URL, and credit cost before planning.",
|
|
97
|
-
inputSchema: {
|
|
98
|
-
type: "object",
|
|
99
|
-
required: ["tool_slug"],
|
|
100
|
-
properties: {
|
|
101
|
-
tool_slug: {
|
|
102
|
-
type: "string",
|
|
103
|
-
description: "Canonical Muxo tool slug (e.g. 'instant.seo.audit', 'app.gmail.send_email', or 'resource.turso.database')",
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
additionalProperties: false,
|
|
107
|
-
},
|
|
108
|
-
annotations: {
|
|
109
|
-
readOnlyHint: true,
|
|
110
|
-
destructiveHint: false,
|
|
111
|
-
openWorldHint: false,
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
name: "connection_status",
|
|
116
|
-
title: "Check Connection Status",
|
|
117
|
-
description: "Check connection status across Composio OAuth apps, Instant wallet, and linked Stripe Projects cloud providers.",
|
|
118
|
-
inputSchema: {
|
|
119
|
-
type: "object",
|
|
120
|
-
properties: {
|
|
121
|
-
provider: {
|
|
122
|
-
type: "string",
|
|
123
|
-
description: "Optional provider filter (e.g. 'github', 'gmail', 'slack', 'neon', 'turso')",
|
|
124
|
-
},
|
|
125
|
-
sync_live: {
|
|
126
|
-
type: "boolean",
|
|
127
|
-
default: true,
|
|
128
|
-
description: "Whether to sync live status from upstream Composio and Stripe Projects",
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
additionalProperties: false,
|
|
132
|
-
},
|
|
133
|
-
annotations: {
|
|
134
|
-
readOnlyHint: true,
|
|
135
|
-
destructiveHint: false,
|
|
136
|
-
openWorldHint: true,
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
name: "start_connection",
|
|
141
|
-
title: "Start OAuth Connection Handoff",
|
|
142
|
-
description: "Initiate a managed OAuth connection handoff for a Connected App (Composio) or link a cloud provider (Stripe Projects).",
|
|
143
|
-
inputSchema: {
|
|
144
|
-
type: "object",
|
|
145
|
-
required: ["provider"],
|
|
146
|
-
properties: {
|
|
147
|
-
provider: {
|
|
148
|
-
type: "string",
|
|
149
|
-
description: "Provider or toolkit slug (e.g. 'github', 'gmail', 'slack', 'neon')",
|
|
150
|
-
},
|
|
151
|
-
lane: {
|
|
152
|
-
type: "string",
|
|
153
|
-
enum: ["composio_sdk", "stripe_projects"],
|
|
154
|
-
description: "Provider lane (defaults to composio_sdk unless prefixed with resource.)",
|
|
155
|
-
},
|
|
156
|
-
callback_url: {
|
|
157
|
-
type: "string",
|
|
158
|
-
description: "Optional OAuth callback URL",
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
additionalProperties: false,
|
|
162
|
-
},
|
|
163
|
-
annotations: {
|
|
164
|
-
readOnlyHint: false,
|
|
165
|
-
destructiveHint: false,
|
|
166
|
-
openWorldHint: true,
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
name: "wait_for_connection",
|
|
171
|
-
title: "Wait for OAuth Connection Handoff",
|
|
172
|
-
description: "Poll and wait for an external user's pending OAuth connection handoff to become active before resuming a planned operation.",
|
|
173
|
-
inputSchema: {
|
|
174
|
-
type: "object",
|
|
175
|
-
required: ["provider"],
|
|
176
|
-
properties: {
|
|
177
|
-
provider: {
|
|
178
|
-
type: "string",
|
|
179
|
-
description: "Provider or toolkit slug (e.g. 'github', 'gmail', 'slack', 'notion', 'linear')",
|
|
180
|
-
},
|
|
181
|
-
timeout_seconds: {
|
|
182
|
-
type: "number",
|
|
183
|
-
default: 15,
|
|
184
|
-
description: "Maximum seconds to poll for OAuth completion (0-120, default 15)",
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
additionalProperties: false,
|
|
188
|
-
},
|
|
189
|
-
annotations: {
|
|
190
|
-
readOnlyHint: true,
|
|
191
|
-
destructiveHint: false,
|
|
192
|
-
openWorldHint: true,
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
name: "plan_action",
|
|
197
|
-
title: "Create Governed Action Plan",
|
|
198
|
-
description: "Create a governed execution plan (plan_*) for any tool, billing operation, or infrastructure provisioning operation. Accepts either an exact tool_slug (e.g. 'instant.seo.audit', 'billing.credits.topup', 'resource.turso.database') or a natural-language instruction (e.g. 'audit seo for https://muxo.ai'). Evaluates workspace policy, risk level, Supermemory v5 recall, Ed25519 signature, BYOK vs Muxo-funded mode, and credit balance.",
|
|
199
|
-
inputSchema: {
|
|
200
|
-
type: "object",
|
|
201
|
-
required: ["tool_slug"],
|
|
202
|
-
properties: {
|
|
203
|
-
tool_slug: {
|
|
204
|
-
type: "string",
|
|
205
|
-
description: "Muxo tool slug (e.g. 'instant.seo.audit', 'billing.credits.topup') or natural-language request",
|
|
206
|
-
},
|
|
207
|
-
input: {
|
|
208
|
-
type: "object",
|
|
209
|
-
description: "Arguments matching the tool's inputSchema (auto-extracted when tool_slug is natural language)",
|
|
210
|
-
},
|
|
211
|
-
reason: {
|
|
212
|
-
type: "string",
|
|
213
|
-
description: "Audit reason explaining why this action is being planned",
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
additionalProperties: false,
|
|
217
|
-
},
|
|
218
|
-
annotations: {
|
|
219
|
-
readOnlyHint: false,
|
|
220
|
-
destructiveHint: false,
|
|
221
|
-
openWorldHint: false,
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
name: "get_plan",
|
|
226
|
-
title: "Get Action Plan",
|
|
227
|
-
description: "Inspect the status, risk level, governance decision record, and approval state of a planned action.",
|
|
228
|
-
inputSchema: {
|
|
229
|
-
type: "object",
|
|
230
|
-
required: ["plan_id"],
|
|
231
|
-
properties: {
|
|
232
|
-
plan_id: { type: "string", description: "Plan ID (plan_*)" },
|
|
233
|
-
},
|
|
234
|
-
additionalProperties: false,
|
|
235
|
-
},
|
|
236
|
-
annotations: {
|
|
237
|
-
readOnlyHint: true,
|
|
238
|
-
destructiveHint: false,
|
|
239
|
-
openWorldHint: false,
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
{
|
|
243
|
-
name: "get_run_context",
|
|
244
|
-
title: "Get Workspace Context & Memory",
|
|
245
|
-
description: "Get the workspace runtime context, Supermemory v5 contextual brain (static/dynamic profile + hybrid search recall), Microsoft Agent Governance status, active provisioned Stripe Projects resources, and redacted environment variable keys.",
|
|
246
|
-
inputSchema: {
|
|
247
|
-
type: "object",
|
|
248
|
-
properties: {
|
|
249
|
-
query: {
|
|
250
|
-
type: "string",
|
|
251
|
-
description: "Optional semantic search query to recall relevant workspace memories from Supermemory v5",
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
additionalProperties: false,
|
|
255
|
-
},
|
|
256
|
-
annotations: {
|
|
257
|
-
readOnlyHint: true,
|
|
258
|
-
destructiveHint: false,
|
|
259
|
-
openWorldHint: false,
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
name: "execute_read",
|
|
264
|
-
title: "Execute Read Plan",
|
|
265
|
-
description: "Execute an approved plan with riskLevel = 'read'.",
|
|
266
|
-
inputSchema: {
|
|
267
|
-
type: "object",
|
|
268
|
-
required: ["plan_id"],
|
|
269
|
-
properties: {
|
|
270
|
-
plan_id: { type: "string", description: "Plan ID (plan_*)" },
|
|
271
|
-
},
|
|
272
|
-
additionalProperties: false,
|
|
273
|
-
},
|
|
274
|
-
annotations: {
|
|
275
|
-
readOnlyHint: true,
|
|
276
|
-
destructiveHint: false,
|
|
277
|
-
openWorldHint: true,
|
|
278
|
-
},
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
name: "execute_write",
|
|
282
|
-
title: "Execute Write Plan",
|
|
283
|
-
description: "Execute an approved plan with riskLevel = 'write'.",
|
|
284
|
-
inputSchema: {
|
|
285
|
-
type: "object",
|
|
286
|
-
required: ["plan_id"],
|
|
287
|
-
properties: {
|
|
288
|
-
plan_id: { type: "string", description: "Plan ID (plan_*)" },
|
|
289
|
-
},
|
|
290
|
-
additionalProperties: false,
|
|
291
|
-
},
|
|
292
|
-
annotations: {
|
|
293
|
-
readOnlyHint: false,
|
|
294
|
-
destructiveHint: false,
|
|
295
|
-
openWorldHint: true,
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
name: "execute_admin",
|
|
300
|
-
title: "Execute Admin Plan",
|
|
301
|
-
description: "Execute an approved plan with riskLevel = 'admin'.",
|
|
302
|
-
inputSchema: {
|
|
303
|
-
type: "object",
|
|
304
|
-
required: ["plan_id"],
|
|
305
|
-
properties: {
|
|
306
|
-
plan_id: { type: "string", description: "Plan ID (plan_*)" },
|
|
307
|
-
},
|
|
308
|
-
additionalProperties: false,
|
|
309
|
-
},
|
|
310
|
-
annotations: {
|
|
311
|
-
readOnlyHint: false,
|
|
312
|
-
destructiveHint: false,
|
|
313
|
-
openWorldHint: true,
|
|
314
|
-
},
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
name: "execute_financial",
|
|
318
|
-
title: "Execute Financial Plan",
|
|
319
|
-
description: "Execute an approved plan with riskLevel = 'financial'.",
|
|
320
|
-
inputSchema: {
|
|
321
|
-
type: "object",
|
|
322
|
-
required: ["plan_id"],
|
|
323
|
-
properties: {
|
|
324
|
-
plan_id: { type: "string", description: "Plan ID (plan_*)" },
|
|
325
|
-
},
|
|
326
|
-
additionalProperties: false,
|
|
327
|
-
},
|
|
328
|
-
annotations: {
|
|
329
|
-
readOnlyHint: false,
|
|
330
|
-
destructiveHint: false,
|
|
331
|
-
openWorldHint: true,
|
|
332
|
-
},
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
name: "execute_provisioning",
|
|
336
|
-
title: "Execute Infrastructure Provisioning Plan",
|
|
337
|
-
description: "Execute an approved infrastructure provisioning plan with riskLevel = 'provisioning' via Stripe Projects.",
|
|
338
|
-
inputSchema: {
|
|
339
|
-
type: "object",
|
|
340
|
-
required: ["plan_id"],
|
|
341
|
-
properties: {
|
|
342
|
-
plan_id: { type: "string", description: "Plan ID (plan_*)" },
|
|
343
|
-
},
|
|
344
|
-
additionalProperties: false,
|
|
345
|
-
},
|
|
346
|
-
annotations: {
|
|
347
|
-
readOnlyHint: false,
|
|
348
|
-
destructiveHint: false,
|
|
349
|
-
openWorldHint: true,
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
{
|
|
353
|
-
name: "execute_destructive",
|
|
354
|
-
title: "Execute Destructive Plan",
|
|
355
|
-
description: "Execute an approved plan with riskLevel = 'destructive'.",
|
|
356
|
-
inputSchema: {
|
|
357
|
-
type: "object",
|
|
358
|
-
required: ["plan_id"],
|
|
359
|
-
properties: {
|
|
360
|
-
plan_id: { type: "string", description: "Plan ID (plan_*)" },
|
|
361
|
-
},
|
|
362
|
-
additionalProperties: false,
|
|
363
|
-
},
|
|
364
|
-
annotations: {
|
|
365
|
-
readOnlyHint: false,
|
|
366
|
-
destructiveHint: true,
|
|
367
|
-
openWorldHint: true,
|
|
368
|
-
},
|
|
369
|
-
},
|
|
370
|
-
{
|
|
371
|
-
name: "get_run",
|
|
372
|
-
title: "Get Execution Run",
|
|
373
|
-
description: "Get the execution status, output, duration, and metered cost of a run (run_*).",
|
|
374
|
-
inputSchema: {
|
|
375
|
-
type: "object",
|
|
376
|
-
required: ["run_id"],
|
|
377
|
-
properties: {
|
|
378
|
-
run_id: { type: "string", description: "Run ID (run_*)" },
|
|
379
|
-
},
|
|
380
|
-
additionalProperties: false,
|
|
381
|
-
},
|
|
382
|
-
annotations: {
|
|
383
|
-
readOnlyHint: true,
|
|
384
|
-
destructiveHint: false,
|
|
385
|
-
openWorldHint: false,
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
{
|
|
389
|
-
name: "cancel_run",
|
|
390
|
-
title: "Cancel Execution Run",
|
|
391
|
-
description: "Cancel an in-progress run and issue a cancellation receipt.",
|
|
392
|
-
inputSchema: {
|
|
393
|
-
type: "object",
|
|
394
|
-
required: ["run_id"],
|
|
395
|
-
properties: {
|
|
396
|
-
run_id: { type: "string", description: "Run ID (run_*)" },
|
|
397
|
-
},
|
|
398
|
-
additionalProperties: false,
|
|
399
|
-
},
|
|
400
|
-
annotations: {
|
|
401
|
-
readOnlyHint: false,
|
|
402
|
-
destructiveHint: true,
|
|
403
|
-
openWorldHint: false,
|
|
404
|
-
},
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
name: "get_receipt",
|
|
408
|
-
title: "Verify Execution Receipt",
|
|
409
|
-
description: "Fetch and cryptographically verify the HMAC-SHA256 + Ed25519 chained execution receipt (rcpt_*) for a run.",
|
|
410
|
-
inputSchema: {
|
|
411
|
-
type: "object",
|
|
412
|
-
required: ["receipt_id"],
|
|
413
|
-
properties: {
|
|
414
|
-
receipt_id: {
|
|
415
|
-
type: "string",
|
|
416
|
-
description: "Receipt ID (rcpt_*) or Run ID (run_*)",
|
|
417
|
-
},
|
|
418
|
-
},
|
|
419
|
-
additionalProperties: false,
|
|
420
|
-
},
|
|
421
|
-
annotations: {
|
|
422
|
-
readOnlyHint: true,
|
|
423
|
-
destructiveHint: false,
|
|
424
|
-
openWorldHint: false,
|
|
425
|
-
},
|
|
426
|
-
},
|
|
427
|
-
];
|
|
428
|
-
/**
|
|
429
|
-
* OpenAI Company Knowledge standard `search` and `fetch` tool definitions
|
|
430
|
-
* per https://developers.openai.com/plugins/build/mcp-server#company-knowledge-compatibility
|
|
431
|
-
*/
|
|
432
|
-
export const OPENAI_COMPANY_KNOWLEDGE_TOOLS = [
|
|
433
|
-
{
|
|
434
|
-
name: "search",
|
|
435
|
-
title: "Search Muxo Tools & Workspace Memory",
|
|
436
|
-
description: "Search across Muxo tools, provisioned cloud resources, and Supermemory v5 workspace knowledge.",
|
|
437
|
-
inputSchema: {
|
|
438
|
-
type: "object",
|
|
439
|
-
required: ["query"],
|
|
440
|
-
properties: {
|
|
441
|
-
query: { type: "string", description: "Search query string." },
|
|
442
|
-
},
|
|
443
|
-
additionalProperties: false,
|
|
444
|
-
},
|
|
445
|
-
annotations: {
|
|
446
|
-
readOnlyHint: true,
|
|
447
|
-
destructiveHint: false,
|
|
448
|
-
openWorldHint: false,
|
|
449
|
-
},
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
name: "fetch",
|
|
453
|
-
title: "Fetch Muxo Tool or Memory Record",
|
|
454
|
-
description: "Retrieve complete details for a Muxo tool, resource, or workspace memory record by ID.",
|
|
455
|
-
inputSchema: {
|
|
456
|
-
type: "object",
|
|
457
|
-
required: ["id"],
|
|
458
|
-
properties: {
|
|
459
|
-
id: {
|
|
460
|
-
type: "string",
|
|
461
|
-
description: "Identifier returned by search (e.g. 'tool:instant.seo.audit' or 'memory:mem_123').",
|
|
462
|
-
},
|
|
463
|
-
},
|
|
464
|
-
additionalProperties: false,
|
|
465
|
-
},
|
|
466
|
-
annotations: {
|
|
467
|
-
readOnlyHint: true,
|
|
468
|
-
destructiveHint: false,
|
|
469
|
-
openWorldHint: false,
|
|
470
|
-
},
|
|
471
|
-
},
|
|
472
|
-
];
|
|
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
|
+
import { MUXO_VERSION } from "./version.js";
|
|
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, };
|
|
473
8
|
function sha256Digest(content) {
|
|
474
9
|
const hash = crypto
|
|
475
10
|
.createHash("sha256")
|
|
@@ -508,7 +43,7 @@ function readSkillFileOrDefault(relPath, fallback) {
|
|
|
508
43
|
export function getMuxoMcpSkills() {
|
|
509
44
|
const muxoSkillMd = readSkillFileOrDefault("muxo/SKILL.md", `---
|
|
510
45
|
name: muxo
|
|
511
|
-
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.
|
|
512
47
|
---
|
|
513
48
|
|
|
514
49
|
# Muxo
|
|
@@ -526,6 +61,8 @@ description: Guided onboarding skill for setting up the Muxo plugin in OpenAI Ch
|
|
|
526
61
|
|
|
527
62
|
Call \`get_profile\` and \`get_organization\` to verify your workspace connection, or run \`npx -y @muxoai/cli@latest login --signup\` in a terminal.
|
|
528
63
|
`);
|
|
64
|
+
const muxoOpenaiYaml = readSkillFileOrDefault("muxo/agents/openai.yaml", `interface:\n display_name: "Muxo"\n short_description: "Governed SaaS, Instant Web/SEO tools, Cloud Infrastructure, and Workspace Memory"\n default_prompt: "Audit https://muxo.ai for technical SEO and crawl its top pages."\n\ndependencies:\n tools:\n - type: "mcp"\n value: "muxo"\n description: "Muxo Governed Execution, Instant Web/SEO Tools, Connected Apps, and Cloud Infrastructure MCP Server"\n transport: "streamable_http"\n url: "https://api.muxo.ai/mcp"\n`);
|
|
65
|
+
const setupOpenaiYaml = readSkillFileOrDefault("setup/agents/openai.yaml", `interface:\n display_name: "Muxo Setup"\n short_description: "Guided onboarding and connection verification for Muxo in ChatGPT and Codex"\n default_prompt: "Check my Muxo profile and organization status."\n\ndependencies:\n tools:\n - type: "mcp"\n value: "muxo"\n description: "Muxo Governed Execution, Instant Web/SEO Tools, Connected Apps, and Cloud Infrastructure MCP Server"\n transport: "streamable_http"\n url: "https://api.muxo.ai/mcp"\n`);
|
|
529
66
|
const muxoFm = parseFrontmatter(muxoSkillMd);
|
|
530
67
|
const setupFm = parseFrontmatter(setupSkillMd);
|
|
531
68
|
const muxoFiles = [
|
|
@@ -537,6 +74,14 @@ Call \`get_profile\` and \`get_organization\` to verify your workspace connectio
|
|
|
537
74
|
mimeType: "text/markdown",
|
|
538
75
|
content: muxoSkillMd,
|
|
539
76
|
},
|
|
77
|
+
{
|
|
78
|
+
path: "agents/openai.yaml",
|
|
79
|
+
uri: "skill://muxo/muxo/agents/openai.yaml",
|
|
80
|
+
size: Buffer.byteLength(muxoOpenaiYaml, "utf8"),
|
|
81
|
+
digest: sha256Digest(muxoOpenaiYaml),
|
|
82
|
+
mimeType: "application/yaml",
|
|
83
|
+
content: muxoOpenaiYaml,
|
|
84
|
+
},
|
|
540
85
|
{
|
|
541
86
|
path: "references/cli.md",
|
|
542
87
|
uri: "skill://muxo/muxo/references/cli.md",
|
|
@@ -563,6 +108,14 @@ Call \`get_profile\` and \`get_organization\` to verify your workspace connectio
|
|
|
563
108
|
mimeType: "text/markdown",
|
|
564
109
|
content: setupSkillMd,
|
|
565
110
|
},
|
|
111
|
+
{
|
|
112
|
+
path: "agents/openai.yaml",
|
|
113
|
+
uri: "skill://muxo/setup/agents/openai.yaml",
|
|
114
|
+
size: Buffer.byteLength(setupOpenaiYaml, "utf8"),
|
|
115
|
+
digest: sha256Digest(setupOpenaiYaml),
|
|
116
|
+
mimeType: "application/yaml",
|
|
117
|
+
content: setupOpenaiYaml,
|
|
118
|
+
},
|
|
566
119
|
];
|
|
567
120
|
const muxoName = muxoFm.name || "muxo";
|
|
568
121
|
const muxoDesc = muxoFm.description ||
|
|
@@ -615,18 +168,22 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
615
168
|
provider: args.provider ? String(args.provider) : undefined,
|
|
616
169
|
syncLive: args.sync_live !== false,
|
|
617
170
|
});
|
|
618
|
-
case "start_connection":
|
|
619
|
-
|
|
171
|
+
case "start_connection": {
|
|
172
|
+
const conn = await engine.startConnection(ctx, {
|
|
620
173
|
provider: String(args.provider || ""),
|
|
621
174
|
lane: args.lane,
|
|
622
175
|
callbackUrl: args.callback_url ? String(args.callback_url) : undefined,
|
|
623
176
|
});
|
|
177
|
+
return {
|
|
178
|
+
ok: true,
|
|
179
|
+
...conn,
|
|
180
|
+
connection: conn,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
624
183
|
case "wait_for_connection":
|
|
625
184
|
return engine.waitForConnection(ctx, {
|
|
626
185
|
provider: String(args.provider || ""),
|
|
627
|
-
timeoutSeconds: args.timeout_seconds
|
|
628
|
-
? Number(args.timeout_seconds)
|
|
629
|
-
: 15,
|
|
186
|
+
timeoutSeconds: clampWaitSeconds(args.timeout_seconds),
|
|
630
187
|
});
|
|
631
188
|
case "plan_action":
|
|
632
189
|
return engine.planAction(ctx, {
|
|
@@ -640,9 +197,207 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
640
197
|
reason: args.reason ? String(args.reason) : undefined,
|
|
641
198
|
});
|
|
642
199
|
case "get_plan":
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
200
|
+
if (args.wait_for_approval === true || args.wait === true) {
|
|
201
|
+
return engine.waitForPlanApproval(ctx, {
|
|
202
|
+
planId: String(args.plan_id || ""),
|
|
203
|
+
timeoutSeconds: clampWaitSeconds(args.timeout_seconds, 15, 60),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
{
|
|
207
|
+
const plan = engine.getPlan(ctx, String(args.plan_id || ""));
|
|
208
|
+
return {
|
|
209
|
+
ok: true,
|
|
210
|
+
approved: APPROVED_PLAN_STATUSES.has(plan.approvalStatus),
|
|
211
|
+
timedOut: false,
|
|
212
|
+
plan,
|
|
213
|
+
approvalStatus: plan.approvalStatus,
|
|
214
|
+
approvalUrl: buildApprovalUrl(engine.config.baseUrl, plan.id),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
case "get_run_context": {
|
|
218
|
+
const action = String(args.action || "").trim().toLowerCase();
|
|
219
|
+
const prompt = String(args.prompt || "").trim();
|
|
220
|
+
const query = args.query ? String(args.query) : undefined;
|
|
221
|
+
const rawParamRules = Array.isArray(args.parameter_rules)
|
|
222
|
+
? args.parameter_rules
|
|
223
|
+
: Array.isArray(args.parameterRules)
|
|
224
|
+
? args.parameterRules
|
|
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;
|
|
234
|
+
if (action === "memory_graph") {
|
|
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
|
+
});
|
|
273
|
+
}
|
|
274
|
+
if (action === "governance_status") {
|
|
275
|
+
return engine.getGovernanceOverview(ctx);
|
|
276
|
+
}
|
|
277
|
+
if (action === "list_workspaces") {
|
|
278
|
+
const workspaces = engine.store.listUserWorkspaces(ctx.user.id, ctx.workspace.id);
|
|
279
|
+
return {
|
|
280
|
+
ok: true,
|
|
281
|
+
action,
|
|
282
|
+
currentWorkspaceId: ctx.workspace.id,
|
|
283
|
+
activeWorkspace: workspaces.find((w) => w.id === ctx.workspace.id) || {
|
|
284
|
+
id: ctx.workspace.id,
|
|
285
|
+
name: ctx.workspace.name,
|
|
286
|
+
slug: ctx.workspace.slug,
|
|
287
|
+
tier: ctx.workspace.tier,
|
|
288
|
+
},
|
|
289
|
+
workspaces,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
if (action === "switch_workspace") {
|
|
293
|
+
const targetWsId = String(args.workspace_id || query || prompt || "").trim();
|
|
294
|
+
if (!targetWsId) {
|
|
295
|
+
throw new Error("workspace_id is required when action='switch_workspace'");
|
|
296
|
+
}
|
|
297
|
+
const switched = engine.store.switchUserWorkspace(ctx.user.id, targetWsId);
|
|
298
|
+
if (!switched) {
|
|
299
|
+
throw new Error(`Workspace ${targetWsId} not found or not linked to your account. Call get_run_context with action='list_workspaces' to see accessible workspaces.`);
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
ok: true,
|
|
303
|
+
action,
|
|
304
|
+
switched: true,
|
|
305
|
+
workspaceId: switched.workspace.id,
|
|
306
|
+
workspace: switched.workspace,
|
|
307
|
+
workspaces: engine.store.listUserWorkspaces(ctx.user.id, switched.workspace.id),
|
|
308
|
+
message: `Active workspace for your session is now ${switched.workspace.name} (${switched.workspace.id}). API keys stay bound to their own workspace; use a key minted for ${switched.workspace.id} to target it over MCP.`,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
if (action === "onboard_team") {
|
|
312
|
+
return buildOnboardTeamGuide({
|
|
313
|
+
baseUrl: engine.config.baseUrl,
|
|
314
|
+
workspaceId: ctx.workspace.id,
|
|
315
|
+
workspaceName: ctx.workspace.name,
|
|
316
|
+
teamName: String(args.team_name || args.teamName || query || prompt || "").trim(),
|
|
317
|
+
workspaces: engine.store.listUserWorkspaces(ctx.user.id, ctx.workspace.id),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
if (action === "set_guardrail" &&
|
|
321
|
+
(prompt || (rawParamRules && rawParamRules.length > 0))) {
|
|
322
|
+
return engine.applyNaturalLanguageGuardrail(ctx, prompt, {
|
|
323
|
+
parameterRules: rawParamRules,
|
|
324
|
+
source: rawParamRules ? "mcp_harness" : "deterministic",
|
|
325
|
+
});
|
|
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
|
+
}
|
|
356
|
+
if (action === "scan_context") {
|
|
357
|
+
const textToScan = String(args.content || prompt || query || "");
|
|
358
|
+
return engine.scanForContextPoisoning(ctx.workspace.id, textToScan);
|
|
359
|
+
}
|
|
360
|
+
if (action === "forget") {
|
|
361
|
+
if (!(query || prompt)) {
|
|
362
|
+
throw new Error("query is required when action='forget'");
|
|
363
|
+
}
|
|
364
|
+
return engine.forgetWorkspaceMemoryMatching(ctx, query || prompt);
|
|
365
|
+
}
|
|
366
|
+
if (action === "recall") {
|
|
367
|
+
return engine.getMemoryOverview(ctx, query);
|
|
368
|
+
}
|
|
369
|
+
if (action === "remember") {
|
|
370
|
+
if (prompt && !args.content) {
|
|
371
|
+
return engine.doNaturalLanguage(ctx, { prompt });
|
|
372
|
+
}
|
|
373
|
+
const record = await engine.addWorkspaceMemory(ctx, {
|
|
374
|
+
title: String(args.title || prompt.slice(0, 60) || "Workspace Fact"),
|
|
375
|
+
content: String(args.content || prompt || query || ""),
|
|
376
|
+
kind: "fact",
|
|
377
|
+
});
|
|
378
|
+
const overview = await engine.getMemoryOverview(ctx);
|
|
379
|
+
return {
|
|
380
|
+
ok: true,
|
|
381
|
+
memory: record,
|
|
382
|
+
activeDefaults: overview.activeDefaults,
|
|
383
|
+
explanation: overview.explanation,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
if (prompt && !action) {
|
|
387
|
+
return engine.doNaturalLanguage(ctx, { prompt });
|
|
388
|
+
}
|
|
389
|
+
const runCtx = await engine.getRunContext(ctx, query);
|
|
390
|
+
if (args.include_graph === true) {
|
|
391
|
+
const memoryGraph = await engine.getMemoryGraph(ctx, {
|
|
392
|
+
query,
|
|
393
|
+
asOf,
|
|
394
|
+
focalEntity,
|
|
395
|
+
maxHops,
|
|
396
|
+
});
|
|
397
|
+
return { ...runCtx, memoryGraph };
|
|
398
|
+
}
|
|
399
|
+
return runCtx;
|
|
400
|
+
}
|
|
646
401
|
case "execute_read":
|
|
647
402
|
return engine.executePlanForRisk(ctx, String(args.plan_id || ""), "read");
|
|
648
403
|
case "execute_write":
|
|
@@ -658,9 +413,134 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
658
413
|
case "get_run":
|
|
659
414
|
return engine.getRun(ctx, String(args.run_id || ""));
|
|
660
415
|
case "cancel_run":
|
|
661
|
-
return engine.cancelRun(ctx, String(args.run_id || ""));
|
|
662
|
-
case "get_receipt":
|
|
663
|
-
|
|
416
|
+
return engine.cancelRun(ctx, String(args.run_id || ""), args.reason ? String(args.reason) : undefined);
|
|
417
|
+
case "get_receipt": {
|
|
418
|
+
const targetId = String(args.receipt_id || args.run_id || "latest").trim();
|
|
419
|
+
if (targetId === "chain") {
|
|
420
|
+
return engine.verifyReceiptChain(ctx);
|
|
421
|
+
}
|
|
422
|
+
const verified = engine.getReceipt(ctx, targetId);
|
|
423
|
+
if (args.verify_chain === true) {
|
|
424
|
+
const receiptChain = engine.verifyReceiptChain(ctx);
|
|
425
|
+
return { ...verified, receiptChain };
|
|
426
|
+
}
|
|
427
|
+
return verified;
|
|
428
|
+
}
|
|
429
|
+
// Supermemory MCP & Governance direct tool aliases for agent harness interoperability
|
|
430
|
+
case "who_am_i":
|
|
431
|
+
return engine.getProfile(ctx);
|
|
432
|
+
case "list_spaces": {
|
|
433
|
+
const overview = await engine.getMemoryOverview(ctx);
|
|
434
|
+
return {
|
|
435
|
+
activeSpace: overview.namespace,
|
|
436
|
+
spaces: [
|
|
437
|
+
{
|
|
438
|
+
id: overview.namespace,
|
|
439
|
+
containerTag: overview.namespace,
|
|
440
|
+
workspaceId: ctx.workspace.id,
|
|
441
|
+
workspaceName: ctx.workspace.name,
|
|
442
|
+
active: true,
|
|
443
|
+
},
|
|
444
|
+
],
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
case "search_memory":
|
|
448
|
+
case "list_memories":
|
|
449
|
+
return engine.getMemoryOverview(ctx, args.query ? String(args.query) : undefined);
|
|
450
|
+
case "add_memory":
|
|
451
|
+
case "remember": {
|
|
452
|
+
const prompt = String(args.prompt || "").trim();
|
|
453
|
+
if (prompt && !args.content) {
|
|
454
|
+
return engine.doNaturalLanguage(ctx, { prompt });
|
|
455
|
+
}
|
|
456
|
+
const content = String(args.content || args.memory || prompt || "");
|
|
457
|
+
const title = String(args.title || content.slice(0, 60) || "Workspace Memory");
|
|
458
|
+
const record = await engine.addWorkspaceMemory(ctx, {
|
|
459
|
+
title,
|
|
460
|
+
content,
|
|
461
|
+
kind: args.kind || "fact",
|
|
462
|
+
});
|
|
463
|
+
const overview = await engine.getMemoryOverview(ctx);
|
|
464
|
+
return {
|
|
465
|
+
ok: true,
|
|
466
|
+
memory: record,
|
|
467
|
+
activeDefaults: overview.activeDefaults,
|
|
468
|
+
explanation: overview.explanation,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
case "forget_memory": {
|
|
472
|
+
const query = String(args.query || args.id || args.memory || "").trim();
|
|
473
|
+
if (!query)
|
|
474
|
+
throw new Error("query is required to forget a memory");
|
|
475
|
+
return engine.forgetWorkspaceMemoryMatching(ctx, query);
|
|
476
|
+
}
|
|
477
|
+
case "memory_graph":
|
|
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
|
+
});
|
|
488
|
+
case "set_guardrail":
|
|
489
|
+
case "configure_guardrails": {
|
|
490
|
+
const rawParamRules = Array.isArray(args.parameter_rules)
|
|
491
|
+
? args.parameter_rules
|
|
492
|
+
: Array.isArray(args.parameterRules)
|
|
493
|
+
? args.parameterRules
|
|
494
|
+
: undefined;
|
|
495
|
+
return engine.applyNaturalLanguageGuardrail(ctx, String(args.prompt || args.rule || args.instruction || ""), {
|
|
496
|
+
parameterRules: rawParamRules,
|
|
497
|
+
source: rawParamRules ? "mcp_harness" : "deterministic",
|
|
498
|
+
});
|
|
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 || ""));
|
|
533
|
+
case "governance_status":
|
|
534
|
+
return engine.getGovernanceOverview(ctx);
|
|
535
|
+
case "verify_receipt_chain":
|
|
536
|
+
return engine.verifyReceiptChain(ctx, args.limit ? Number(args.limit) : 100);
|
|
537
|
+
case "do":
|
|
538
|
+
return engine.doNaturalLanguage(ctx, {
|
|
539
|
+
prompt: String(args.prompt || args.instruction || args.query || ""),
|
|
540
|
+
input: args.input || undefined,
|
|
541
|
+
dryRun: Boolean(args.dry_run || args.dryRun),
|
|
542
|
+
autoApprove: args.auto_approve !== false && args.autoApprove !== false,
|
|
543
|
+
});
|
|
664
544
|
// OpenAI Company Knowledge standard `search` and `fetch` tool support
|
|
665
545
|
case "search": {
|
|
666
546
|
const q = String(args.query || "").trim();
|
|
@@ -671,7 +551,7 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
671
551
|
const toolHits = toolsRes.tools.map((t) => ({
|
|
672
552
|
id: `tool:${t.slug}`,
|
|
673
553
|
title: `${t.name} (${t.slug})`,
|
|
674
|
-
url: t.providerUrl || `https://docs.muxo.ai/
|
|
554
|
+
url: t.providerUrl || `https://docs.muxo.ai/catalogue#${encodeURIComponent(t.providerSlug || t.slug)}`,
|
|
675
555
|
snippet: `${t.description} [lane=${t.lane}, risk=${t.riskLevel}, cost=${t.creditCost}cr]`,
|
|
676
556
|
}));
|
|
677
557
|
const memHits = (memRes.memories || []).slice(0, 5).map((m) => ({
|
|
@@ -711,7 +591,7 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
711
591
|
title: tool.name,
|
|
712
592
|
text: JSON.stringify(tool, null, 2),
|
|
713
593
|
url: tool.providerUrl ||
|
|
714
|
-
`https://docs.muxo.ai/
|
|
594
|
+
`https://docs.muxo.ai/catalogue#${encodeURIComponent(tool.providerSlug || tool.slug)}`,
|
|
715
595
|
metadata: {
|
|
716
596
|
slug: tool.slug,
|
|
717
597
|
lane: tool.lane,
|
|
@@ -721,7 +601,7 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
|
|
|
721
601
|
};
|
|
722
602
|
}
|
|
723
603
|
default:
|
|
724
|
-
throw new
|
|
604
|
+
throw new MuxoToolError(`Unknown MCP tool: '${toolName}'. Call tools/list for the canonical Muxo MCP tools.`, { code: "unknown_mcp_tool", statusCode: 404, payload: { toolName } });
|
|
725
605
|
}
|
|
726
606
|
}
|
|
727
607
|
export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
@@ -732,55 +612,270 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
732
612
|
method.startsWith("notifications/")) {
|
|
733
613
|
return null;
|
|
734
614
|
}
|
|
615
|
+
const headerAndMetaCheck = validateMcpHttpHeadersAndMeta({}, rpc);
|
|
616
|
+
if (!headerAndMetaCheck.ok) {
|
|
617
|
+
return {
|
|
618
|
+
jsonrpc: "2.0",
|
|
619
|
+
id,
|
|
620
|
+
error: headerAndMetaCheck.error,
|
|
621
|
+
};
|
|
622
|
+
}
|
|
735
623
|
try {
|
|
624
|
+
if (method === "server/discover") {
|
|
625
|
+
return {
|
|
626
|
+
jsonrpc: "2.0",
|
|
627
|
+
id,
|
|
628
|
+
result: buildMcpDiscoverResult(MUXO_VERSION),
|
|
629
|
+
};
|
|
630
|
+
}
|
|
736
631
|
if (method === "initialize") {
|
|
737
|
-
const requestedProtocol =
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
: "
|
|
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
|
+
};
|
|
741
638
|
return {
|
|
742
639
|
jsonrpc: "2.0",
|
|
743
640
|
id,
|
|
744
641
|
result: {
|
|
642
|
+
resultType: "complete",
|
|
745
643
|
protocolVersion: requestedProtocol,
|
|
644
|
+
supportedVersions: [...SUPPORTED_MCP_PROTOCOL_VERSIONS],
|
|
746
645
|
instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
747
|
-
serverInfo
|
|
748
|
-
name: "muxo-mcp-server",
|
|
749
|
-
version: "1.3.0",
|
|
750
|
-
},
|
|
646
|
+
serverInfo,
|
|
751
647
|
capabilities: {
|
|
752
648
|
tools: { listChanged: false },
|
|
753
|
-
resources: { listChanged: false },
|
|
649
|
+
resources: { listChanged: false, subscribe: false },
|
|
650
|
+
prompts: { listChanged: false },
|
|
651
|
+
completions: {},
|
|
754
652
|
extensions: {
|
|
755
653
|
"io.modelcontextprotocol/skills": {},
|
|
654
|
+
"io.modelcontextprotocol/apps": {},
|
|
756
655
|
},
|
|
757
656
|
},
|
|
657
|
+
_meta: {
|
|
658
|
+
"io.modelcontextprotocol/serverInfo": serverInfo,
|
|
659
|
+
"io.modelcontextprotocol/instructions": MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
660
|
+
},
|
|
758
661
|
},
|
|
759
662
|
};
|
|
760
663
|
}
|
|
761
664
|
if (method === "ping") {
|
|
762
|
-
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
|
+
};
|
|
690
|
+
}
|
|
691
|
+
if (method === "prompts/list") {
|
|
692
|
+
return {
|
|
693
|
+
jsonrpc: "2.0",
|
|
694
|
+
id,
|
|
695
|
+
result: {
|
|
696
|
+
resultType: "complete",
|
|
697
|
+
ttlMs: 300_000,
|
|
698
|
+
cacheScope: "public",
|
|
699
|
+
prompts: [
|
|
700
|
+
{
|
|
701
|
+
name: "context",
|
|
702
|
+
title: "Workspace Memory & Governance Context",
|
|
703
|
+
description: "Ready-to-attach workspace context (Supermemory v5 profile, bi-temporal facts, learned parameter defaults, and active Microsoft Governance guardrails).",
|
|
704
|
+
arguments: [
|
|
705
|
+
{
|
|
706
|
+
name: "query",
|
|
707
|
+
description: "Optional topic or task query to focus memory recall",
|
|
708
|
+
required: false,
|
|
709
|
+
},
|
|
710
|
+
],
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
name: "governed_execution",
|
|
714
|
+
title: "Governed Tool Execution Workflow",
|
|
715
|
+
description: "Step-by-step assistant prompt for discovering, planning, approving, executing, and verifying a governed Muxo action.",
|
|
716
|
+
arguments: [
|
|
717
|
+
{
|
|
718
|
+
name: "task",
|
|
719
|
+
description: "Natural-language task to plan and execute",
|
|
720
|
+
required: false,
|
|
721
|
+
},
|
|
722
|
+
],
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
name: "security_audit",
|
|
726
|
+
title: "Workspace Governance, Memory Graph & Receipt Chain Audit",
|
|
727
|
+
description: "Inspect the workspace's 9-module Microsoft Agent Governance posture, Bi-Temporal Knowledge Graph, and Ed25519 AgenticReceipt hash chain.",
|
|
728
|
+
arguments: [],
|
|
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
|
+
},
|
|
736
|
+
],
|
|
737
|
+
},
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
if (method === "prompts/get") {
|
|
741
|
+
const promptName = String(params.name || "context").trim();
|
|
742
|
+
const promptArgs = (params.arguments || {});
|
|
743
|
+
if (promptName === "context") {
|
|
744
|
+
const query = promptArgs.query ? String(promptArgs.query) : undefined;
|
|
745
|
+
const runCtx = await engine.getRunContext(ctx, query);
|
|
746
|
+
return {
|
|
747
|
+
jsonrpc: "2.0",
|
|
748
|
+
id,
|
|
749
|
+
result: {
|
|
750
|
+
resultType: "complete",
|
|
751
|
+
description: "Ready-to-attach Muxo workspace memory, active defaults, and safety guardrails.",
|
|
752
|
+
messages: [
|
|
753
|
+
{
|
|
754
|
+
role: "user",
|
|
755
|
+
content: {
|
|
756
|
+
type: "text",
|
|
757
|
+
text: String(runCtx.llmSystemPrompt || runCtx.explanation.preferred),
|
|
758
|
+
},
|
|
759
|
+
},
|
|
760
|
+
],
|
|
761
|
+
},
|
|
762
|
+
};
|
|
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
|
+
}
|
|
794
|
+
if (promptName === "governed_execution") {
|
|
795
|
+
const task = String(promptArgs.task || "the user's requested operation");
|
|
796
|
+
const runCtx = await engine.getRunContext(ctx);
|
|
797
|
+
return {
|
|
798
|
+
jsonrpc: "2.0",
|
|
799
|
+
id,
|
|
800
|
+
result: {
|
|
801
|
+
resultType: "complete",
|
|
802
|
+
description: "Governed Muxo execution workflow prompt",
|
|
803
|
+
messages: [
|
|
804
|
+
{
|
|
805
|
+
role: "user",
|
|
806
|
+
content: {
|
|
807
|
+
type: "text",
|
|
808
|
+
text: `${runCtx.llmSystemPrompt}\n\n## Task\nExecute "${task}" safely using Muxo:\n1. Call \`search_tools\` and \`inspect_tool\` (or pass a natural-language request to \`plan_action\`).\n2. Call \`plan_action\` and inspect \`plan.approvalStatus\`, \`authHandoff\`, and \`llmGuidance.nextToolCalls\`.\n3. If \`authHandoff.required\` is true, present \`humanHandoff.markdownForUser\` and call \`wait_for_connection\`.\n4. If \`approvalStatus === "pending_approval"\`, present \`humanHandoff.markdownForUser\` and call \`get_plan\` with \`wait_for_approval: true\`.\n5. Execute with \`execute_<riskLevel>\` and verify the cryptographic receipt with \`get_receipt\`.`,
|
|
809
|
+
},
|
|
810
|
+
},
|
|
811
|
+
],
|
|
812
|
+
},
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
if (promptName === "security_audit") {
|
|
816
|
+
const [gov, graph, chain] = await Promise.all([
|
|
817
|
+
Promise.resolve(engine.getGovernanceOverview(ctx)),
|
|
818
|
+
engine.getMemoryGraph(ctx),
|
|
819
|
+
Promise.resolve(engine.verifyReceiptChain(ctx)),
|
|
820
|
+
]);
|
|
821
|
+
return {
|
|
822
|
+
jsonrpc: "2.0",
|
|
823
|
+
id,
|
|
824
|
+
result: {
|
|
825
|
+
resultType: "complete",
|
|
826
|
+
description: "Workspace governance, bi-temporal graph, and receipt chain audit",
|
|
827
|
+
messages: [
|
|
828
|
+
{
|
|
829
|
+
role: "user",
|
|
830
|
+
content: {
|
|
831
|
+
type: "text",
|
|
832
|
+
text: [
|
|
833
|
+
`# Muxo Security, Memory & Cryptographic Audit`,
|
|
834
|
+
`## 1. Microsoft Agent Governance (9 Modules)\n${gov.explanation.preferred}`,
|
|
835
|
+
`## 2. Bi-Temporal Knowledge Graph\n${graph.explanation.preferred}\n\`\`\`mermaid\n${graph.mermaid}\n\`\`\``,
|
|
836
|
+
`## 3. Portable Ed25519 AgenticReceipt Chain\n${chain.explanation.preferred}`,
|
|
837
|
+
].join("\n\n"),
|
|
838
|
+
},
|
|
839
|
+
},
|
|
840
|
+
],
|
|
841
|
+
},
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
jsonrpc: "2.0",
|
|
846
|
+
id,
|
|
847
|
+
error: {
|
|
848
|
+
code: -32602,
|
|
849
|
+
message: `Prompt not found: ${promptName}`,
|
|
850
|
+
},
|
|
851
|
+
};
|
|
763
852
|
}
|
|
764
853
|
if (method === "tools/list") {
|
|
765
854
|
return {
|
|
766
855
|
jsonrpc: "2.0",
|
|
767
856
|
id,
|
|
768
857
|
result: {
|
|
769
|
-
|
|
858
|
+
resultType: "complete",
|
|
859
|
+
ttlMs: 300_000,
|
|
860
|
+
cacheScope: "public",
|
|
861
|
+
tools: MUXO_MCP_TOOLS.map((t) => buildMcpToolDescriptor(t)),
|
|
770
862
|
},
|
|
771
863
|
};
|
|
772
864
|
}
|
|
773
865
|
if (method === "tools/call") {
|
|
774
866
|
const toolName = String(params.name || "");
|
|
775
867
|
const toolArgs = (params.arguments || {});
|
|
776
|
-
const
|
|
868
|
+
const rawOutput = await dispatchMcpToolCall(engine, ctx, toolName, toolArgs);
|
|
869
|
+
const output = attachMcpHarnessGuidance(toolName, toolArgs, rawOutput);
|
|
777
870
|
const structuredContent = output && typeof output === "object" && !Array.isArray(output)
|
|
778
871
|
? output
|
|
779
872
|
: { data: output };
|
|
873
|
+
const resultMeta = buildMcpToolResultMeta(toolName, params);
|
|
780
874
|
return {
|
|
781
875
|
jsonrpc: "2.0",
|
|
782
876
|
id,
|
|
783
877
|
result: {
|
|
878
|
+
resultType: "complete",
|
|
784
879
|
structuredContent,
|
|
785
880
|
content: [
|
|
786
881
|
{
|
|
@@ -788,6 +883,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
788
883
|
text: JSON.stringify(output, null, 2),
|
|
789
884
|
},
|
|
790
885
|
],
|
|
886
|
+
...(resultMeta ? { _meta: resultMeta } : {}),
|
|
791
887
|
isError: false,
|
|
792
888
|
},
|
|
793
889
|
};
|
|
@@ -795,9 +891,14 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
795
891
|
// SEP-2640 Skills Import Extension (`io.modelcontextprotocol/skills`)
|
|
796
892
|
if (method === "skills/list") {
|
|
797
893
|
const skills = getMuxoMcpSkills().map((s) => ({
|
|
894
|
+
uri: s.uri,
|
|
895
|
+
frontmatter: s.frontmatter,
|
|
896
|
+
resources: s.files.map((f) => ({
|
|
897
|
+
uri: f.uri,
|
|
898
|
+
digest: f.digest,
|
|
899
|
+
})),
|
|
798
900
|
name: s.name,
|
|
799
901
|
description: s.description,
|
|
800
|
-
uri: s.uri,
|
|
801
902
|
version: s.version,
|
|
802
903
|
digest: s.files[0]?.digest || "",
|
|
803
904
|
files: s.files.length,
|
|
@@ -805,34 +906,49 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
805
906
|
return {
|
|
806
907
|
jsonrpc: "2.0",
|
|
807
908
|
id,
|
|
808
|
-
result: {
|
|
909
|
+
result: {
|
|
910
|
+
resultType: "complete",
|
|
911
|
+
ttlMs: 300_000,
|
|
912
|
+
cacheScope: "public",
|
|
913
|
+
skills,
|
|
914
|
+
},
|
|
809
915
|
};
|
|
810
916
|
}
|
|
811
917
|
if (method === "skills/get") {
|
|
812
|
-
const
|
|
813
|
-
const skill = getMuxoMcpSkills().find((s) => s.name === requestedName);
|
|
918
|
+
const { skill, requested } = findMcpSkill(getMuxoMcpSkills(), params);
|
|
814
919
|
if (!skill) {
|
|
815
920
|
return {
|
|
816
921
|
jsonrpc: "2.0",
|
|
817
922
|
id,
|
|
818
923
|
error: {
|
|
819
924
|
code: -32602,
|
|
820
|
-
message: `Skill not found: ${
|
|
925
|
+
message: `Skill not found: ${requested}`,
|
|
821
926
|
},
|
|
822
927
|
};
|
|
823
928
|
}
|
|
929
|
+
const resources = skill.files.map((f) => ({
|
|
930
|
+
uri: f.uri,
|
|
931
|
+
digest: f.digest,
|
|
932
|
+
}));
|
|
824
933
|
return {
|
|
825
934
|
jsonrpc: "2.0",
|
|
826
935
|
id,
|
|
827
936
|
result: {
|
|
937
|
+
resultType: "complete",
|
|
938
|
+
ttlMs: 300_000,
|
|
939
|
+
cacheScope: "public",
|
|
828
940
|
skill: {
|
|
941
|
+
uri: skill.uri,
|
|
942
|
+
frontmatter: skill.frontmatter,
|
|
943
|
+
resources,
|
|
829
944
|
name: skill.name,
|
|
830
945
|
description: skill.description,
|
|
831
|
-
uri: skill.uri,
|
|
832
946
|
version: skill.version,
|
|
833
947
|
digest: skill.files[0]?.digest || "",
|
|
834
948
|
},
|
|
949
|
+
uri: skill.uri,
|
|
835
950
|
frontmatter: skill.frontmatter,
|
|
951
|
+
resources,
|
|
836
952
|
files: skill.files.map((f) => ({
|
|
837
953
|
path: f.path,
|
|
838
954
|
uri: f.uri,
|
|
@@ -843,21 +959,401 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
843
959
|
},
|
|
844
960
|
};
|
|
845
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
|
+
}
|
|
846
974
|
if (method === "resources/list") {
|
|
847
|
-
const
|
|
975
|
+
const skillResources = getMuxoMcpSkills().flatMap((s) => s.files.map((f) => ({
|
|
848
976
|
uri: f.uri,
|
|
849
977
|
name: `${s.name}/${f.path}`,
|
|
850
978
|
description: s.description,
|
|
851
979
|
mimeType: f.mimeType,
|
|
852
980
|
})));
|
|
981
|
+
const dynamicResources = [
|
|
982
|
+
{
|
|
983
|
+
uri: "muxo://profile",
|
|
984
|
+
name: "Workspace Profile & Active Memory Defaults",
|
|
985
|
+
description: "Stable and recent Supermemory v5 profile context, active auto-fill defaults, and Ed25519 Agent DID for the active workspace.",
|
|
986
|
+
mimeType: "application/json",
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
uri: "supermemory://profile",
|
|
990
|
+
name: "Supermemory Active Space Profile",
|
|
991
|
+
description: "Supermemory MCP compatible profile resource (static + dynamic facts and preferences) for the active workspace.",
|
|
992
|
+
mimeType: "application/json",
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
uri: "supermemory://spaces",
|
|
996
|
+
name: "Supermemory Accessible Spaces",
|
|
997
|
+
description: "Compact list of accessible workspace memory spaces with the active containerTag marked.",
|
|
998
|
+
mimeType: "application/json",
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
uri: "muxo://context",
|
|
1002
|
+
name: "Governed Workspace Run Context",
|
|
1003
|
+
description: "Ready-to-inject workspace context including guardrails, learned defaults, provisioned cloud resources, and Supermemory recall.",
|
|
1004
|
+
mimeType: "application/json",
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
uri: "muxo://memory/graph",
|
|
1008
|
+
name: "Bi-Temporal Knowledge Graph",
|
|
1009
|
+
description: "Entity & relationship graph with active facts, superseded historical facts (validFrom/validTo), and Mermaid topology.",
|
|
1010
|
+
mimeType: "application/json",
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
uri: "muxo://governance/policy",
|
|
1014
|
+
name: "Microsoft Agent Governance & Guardrails",
|
|
1015
|
+
description: "9-module Microsoft Agent Governance status, plain-English guardrails, Bayesian trust score, and OWASP ASI-06 scan status.",
|
|
1016
|
+
mimeType: "application/json",
|
|
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
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
uri: "muxo://receipts/chain",
|
|
1026
|
+
name: "Cryptographic AgenticReceipt Hash Chain",
|
|
1027
|
+
description: "Tamper-evident SHA-256 + portable Ed25519 AgenticReceipt chain verification report.",
|
|
1028
|
+
mimeType: "application/json",
|
|
1029
|
+
},
|
|
1030
|
+
];
|
|
853
1031
|
return {
|
|
854
1032
|
jsonrpc: "2.0",
|
|
855
1033
|
id,
|
|
856
|
-
result: {
|
|
1034
|
+
result: {
|
|
1035
|
+
resultType: "complete",
|
|
1036
|
+
ttlMs: 60_000,
|
|
1037
|
+
cacheScope: "private",
|
|
1038
|
+
resources: [...MUXO_UI_RESOURCES, ...skillResources, ...dynamicResources],
|
|
1039
|
+
},
|
|
857
1040
|
};
|
|
858
1041
|
}
|
|
859
1042
|
if (method === "resources/read") {
|
|
860
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
|
+
}
|
|
1064
|
+
if (uri === "muxo://profile" || uri === "supermemory://profile") {
|
|
1065
|
+
const overview = await engine.getMemoryOverview(ctx);
|
|
1066
|
+
const profile = engine.getProfile(ctx);
|
|
1067
|
+
const payload = {
|
|
1068
|
+
uri,
|
|
1069
|
+
workspaceId: ctx.workspace.id,
|
|
1070
|
+
workspaceSlug: ctx.workspace.slug,
|
|
1071
|
+
namespace: overview.namespace,
|
|
1072
|
+
profile: overview.context.profile,
|
|
1073
|
+
activeDefaults: overview.activeDefaults,
|
|
1074
|
+
activeGuardrails: overview.activeGuardrails,
|
|
1075
|
+
actor: profile,
|
|
1076
|
+
explanation: overview.explanation,
|
|
1077
|
+
};
|
|
1078
|
+
return {
|
|
1079
|
+
jsonrpc: "2.0",
|
|
1080
|
+
id,
|
|
1081
|
+
result: {
|
|
1082
|
+
resultType: "complete",
|
|
1083
|
+
ttlMs: 60_000,
|
|
1084
|
+
cacheScope: "private",
|
|
1085
|
+
contents: [
|
|
1086
|
+
{
|
|
1087
|
+
uri,
|
|
1088
|
+
mimeType: "application/json",
|
|
1089
|
+
text: JSON.stringify(payload, null, 2),
|
|
1090
|
+
},
|
|
1091
|
+
],
|
|
1092
|
+
},
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
if (uri === "muxo://spaces" || uri === "supermemory://spaces") {
|
|
1096
|
+
const overview = await engine.getMemoryOverview(ctx);
|
|
1097
|
+
const payload = {
|
|
1098
|
+
activeSpace: overview.namespace,
|
|
1099
|
+
spaces: [
|
|
1100
|
+
{
|
|
1101
|
+
id: overview.namespace,
|
|
1102
|
+
containerTag: overview.namespace,
|
|
1103
|
+
workspaceId: ctx.workspace.id,
|
|
1104
|
+
workspaceName: ctx.workspace.name,
|
|
1105
|
+
active: true,
|
|
1106
|
+
},
|
|
1107
|
+
],
|
|
1108
|
+
};
|
|
1109
|
+
return {
|
|
1110
|
+
jsonrpc: "2.0",
|
|
1111
|
+
id,
|
|
1112
|
+
result: {
|
|
1113
|
+
resultType: "complete",
|
|
1114
|
+
ttlMs: 60_000,
|
|
1115
|
+
cacheScope: "private",
|
|
1116
|
+
contents: [
|
|
1117
|
+
{
|
|
1118
|
+
uri,
|
|
1119
|
+
mimeType: "application/json",
|
|
1120
|
+
text: JSON.stringify(payload, null, 2),
|
|
1121
|
+
},
|
|
1122
|
+
],
|
|
1123
|
+
},
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
if (uri === "muxo://context") {
|
|
1127
|
+
const runCtx = await engine.getRunContext(ctx);
|
|
1128
|
+
return {
|
|
1129
|
+
jsonrpc: "2.0",
|
|
1130
|
+
id,
|
|
1131
|
+
result: {
|
|
1132
|
+
resultType: "complete",
|
|
1133
|
+
ttlMs: 60_000,
|
|
1134
|
+
cacheScope: "private",
|
|
1135
|
+
contents: [
|
|
1136
|
+
{
|
|
1137
|
+
uri,
|
|
1138
|
+
mimeType: "application/json",
|
|
1139
|
+
text: JSON.stringify(runCtx, null, 2),
|
|
1140
|
+
},
|
|
1141
|
+
],
|
|
1142
|
+
},
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
if (uri === "muxo://memory/graph") {
|
|
1146
|
+
const graph = await engine.getMemoryGraph(ctx);
|
|
1147
|
+
return {
|
|
1148
|
+
jsonrpc: "2.0",
|
|
1149
|
+
id,
|
|
1150
|
+
result: {
|
|
1151
|
+
resultType: "complete",
|
|
1152
|
+
ttlMs: 60_000,
|
|
1153
|
+
cacheScope: "private",
|
|
1154
|
+
contents: [
|
|
1155
|
+
{
|
|
1156
|
+
uri,
|
|
1157
|
+
mimeType: "application/json",
|
|
1158
|
+
text: JSON.stringify(graph, null, 2),
|
|
1159
|
+
},
|
|
1160
|
+
],
|
|
1161
|
+
},
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
if (uri === "muxo://governance/policy") {
|
|
1165
|
+
const gov = engine.getGovernanceOverview(ctx);
|
|
1166
|
+
return {
|
|
1167
|
+
jsonrpc: "2.0",
|
|
1168
|
+
id,
|
|
1169
|
+
result: {
|
|
1170
|
+
resultType: "complete",
|
|
1171
|
+
ttlMs: 60_000,
|
|
1172
|
+
cacheScope: "private",
|
|
1173
|
+
contents: [
|
|
1174
|
+
{
|
|
1175
|
+
uri,
|
|
1176
|
+
mimeType: "application/json",
|
|
1177
|
+
text: JSON.stringify(gov, null, 2),
|
|
1178
|
+
},
|
|
1179
|
+
],
|
|
1180
|
+
},
|
|
1181
|
+
};
|
|
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
|
+
}
|
|
1202
|
+
if (uri === "muxo://receipts/chain") {
|
|
1203
|
+
const chain = engine.verifyReceiptChain(ctx);
|
|
1204
|
+
return {
|
|
1205
|
+
jsonrpc: "2.0",
|
|
1206
|
+
id,
|
|
1207
|
+
result: {
|
|
1208
|
+
resultType: "complete",
|
|
1209
|
+
ttlMs: 60_000,
|
|
1210
|
+
cacheScope: "private",
|
|
1211
|
+
contents: [
|
|
1212
|
+
{
|
|
1213
|
+
uri,
|
|
1214
|
+
mimeType: "application/json",
|
|
1215
|
+
text: JSON.stringify(chain, null, 2),
|
|
1216
|
+
},
|
|
1217
|
+
],
|
|
1218
|
+
},
|
|
1219
|
+
};
|
|
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
|
+
}
|
|
861
1357
|
const allFiles = getMuxoMcpSkills().flatMap((s) => s.files);
|
|
862
1358
|
const found = allFiles.find((f) => f.uri === uri);
|
|
863
1359
|
if (!found) {
|
|
@@ -874,6 +1370,9 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
874
1370
|
jsonrpc: "2.0",
|
|
875
1371
|
id,
|
|
876
1372
|
result: {
|
|
1373
|
+
resultType: "complete",
|
|
1374
|
+
ttlMs: 300_000,
|
|
1375
|
+
cacheScope: "public",
|
|
877
1376
|
contents: [
|
|
878
1377
|
{
|
|
879
1378
|
uri: found.uri,
|
|
@@ -894,19 +1393,21 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
894
1393
|
};
|
|
895
1394
|
}
|
|
896
1395
|
catch (err) {
|
|
1396
|
+
const errPayload = errorPayloadFrom(err, "MCP tool execution failed");
|
|
1397
|
+
const errMeta = buildMcpErrorResultMeta(err, engine?.config?.baseUrl || "https://api.muxo.ai");
|
|
897
1398
|
return {
|
|
898
1399
|
jsonrpc: "2.0",
|
|
899
1400
|
id,
|
|
900
1401
|
result: {
|
|
1402
|
+
resultType: "complete",
|
|
1403
|
+
structuredContent: errPayload,
|
|
901
1404
|
content: [
|
|
902
1405
|
{
|
|
903
1406
|
type: "text",
|
|
904
|
-
text: JSON.stringify(
|
|
905
|
-
ok: false,
|
|
906
|
-
error: String(err?.message || err || "MCP tool execution failed"),
|
|
907
|
-
}, null, 2),
|
|
1407
|
+
text: JSON.stringify(errPayload, null, 2),
|
|
908
1408
|
},
|
|
909
1409
|
],
|
|
1410
|
+
...(errMeta ? { _meta: errMeta } : {}),
|
|
910
1411
|
isError: true,
|
|
911
1412
|
},
|
|
912
1413
|
};
|