@muxoai/platform 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.js CHANGED
@@ -1,23 +1,68 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { ROOT_DIR } from "./config.js";
5
+ /**
6
+ * Concise server instructions (<512 chars) per OpenAI Plugin MCP Server specification:
7
+ * https://developers.openai.com/plugins/build/mcp-server
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.";
1
10
  export const MUXO_MCP_TOOLS = [
2
11
  {
3
12
  name: "get_profile",
4
- description: "Get the authenticated actor profile, workspace ID, and subscription tier.",
5
- inputSchema: { type: "object", properties: {} },
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
+ },
6
40
  },
7
41
  {
8
42
  name: "get_organization",
9
- description: "Get workspace governance policy, monthly action usage, credit balance, and active connection/resource counts.",
10
- inputSchema: { type: "object", properties: {} },
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
+ },
11
55
  },
12
56
  {
13
57
  name: "search_tools",
58
+ title: "Search Unified Tool Catalog",
14
59
  description: "Search the unified Muxo catalog across Connected Apps (Composio SDK: app.*), Instant Tools (Composio Instant: instant.*), and Cloud Infrastructure (Stripe Projects: resource.*).",
15
60
  inputSchema: {
16
61
  type: "object",
17
62
  properties: {
18
63
  query: {
19
64
  type: "string",
20
- description: "Search keywords (e.g. 'postgres', 'github issue', 'web search', 'redis')",
65
+ description: "Search keywords (e.g. 'postgres', 'github issue', 'web search', 'seo audit', 'redis')",
21
66
  },
22
67
  lane: {
23
68
  type: "string",
@@ -26,35 +71,56 @@ export const MUXO_MCP_TOOLS = [
26
71
  },
27
72
  risk_level: {
28
73
  type: "string",
29
- enum: ["read", "write", "admin", "financial", "provisioning", "destructive"],
74
+ enum: [
75
+ "read",
76
+ "write",
77
+ "admin",
78
+ "financial",
79
+ "provisioning",
80
+ "destructive",
81
+ ],
30
82
  },
31
83
  limit: { type: "number", default: 20 },
32
84
  },
85
+ additionalProperties: false,
86
+ },
87
+ annotations: {
88
+ readOnlyHint: true,
89
+ destructiveHint: false,
90
+ openWorldHint: true,
33
91
  },
34
92
  },
35
93
  {
36
94
  name: "inspect_tool",
37
- description: "Inspect a tool's full input JSON schema, risk classification, provider lane, and credit cost before planning.",
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.",
38
97
  inputSchema: {
39
98
  type: "object",
40
99
  required: ["tool_slug"],
41
100
  properties: {
42
101
  tool_slug: {
43
102
  type: "string",
44
- description: "Canonical Muxo tool slug (e.g. 'instant.hackernews.top_stories' or 'resource.neon.launch')",
103
+ description: "Canonical Muxo tool slug (e.g. 'instant.seo.audit', 'app.gmail.send_email', or 'resource.turso.database')",
45
104
  },
46
105
  },
106
+ additionalProperties: false,
107
+ },
108
+ annotations: {
109
+ readOnlyHint: true,
110
+ destructiveHint: false,
111
+ openWorldHint: false,
47
112
  },
48
113
  },
49
114
  {
50
115
  name: "connection_status",
116
+ title: "Check Connection Status",
51
117
  description: "Check connection status across Composio OAuth apps, Instant wallet, and linked Stripe Projects cloud providers.",
52
118
  inputSchema: {
53
119
  type: "object",
54
120
  properties: {
55
121
  provider: {
56
122
  type: "string",
57
- description: "Optional provider filter (e.g. 'github', 'slack', 'neon', 'supabase')",
123
+ description: "Optional provider filter (e.g. 'github', 'gmail', 'slack', 'neon', 'turso')",
58
124
  },
59
125
  sync_live: {
60
126
  type: "boolean",
@@ -62,11 +128,18 @@ export const MUXO_MCP_TOOLS = [
62
128
  description: "Whether to sync live status from upstream Composio and Stripe Projects",
63
129
  },
64
130
  },
131
+ additionalProperties: false,
132
+ },
133
+ annotations: {
134
+ readOnlyHint: true,
135
+ destructiveHint: false,
136
+ openWorldHint: true,
65
137
  },
66
138
  },
67
139
  {
68
140
  name: "start_connection",
69
- description: "Initiate an OAuth connection for a Connected App (Composio) or link a cloud provider (Stripe Projects).",
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).",
70
143
  inputSchema: {
71
144
  type: "object",
72
145
  required: ["provider"],
@@ -85,10 +158,17 @@ export const MUXO_MCP_TOOLS = [
85
158
  description: "Optional OAuth callback URL",
86
159
  },
87
160
  },
161
+ additionalProperties: false,
162
+ },
163
+ annotations: {
164
+ readOnlyHint: false,
165
+ destructiveHint: false,
166
+ openWorldHint: true,
88
167
  },
89
168
  },
90
169
  {
91
170
  name: "wait_for_connection",
171
+ title: "Wait for OAuth Connection Handoff",
92
172
  description: "Poll and wait for an external user's pending OAuth connection handoff to become active before resuming a planned operation.",
93
173
  inputSchema: {
94
174
  type: "object",
@@ -104,40 +184,64 @@ export const MUXO_MCP_TOOLS = [
104
184
  description: "Maximum seconds to poll for OAuth completion (0-120, default 15)",
105
185
  },
106
186
  },
187
+ additionalProperties: false,
188
+ },
189
+ annotations: {
190
+ readOnlyHint: true,
191
+ destructiveHint: false,
192
+ openWorldHint: true,
107
193
  },
108
194
  },
109
195
  {
110
196
  name: "plan_action",
111
- description: "Create a governed execution plan (plan_*) for any tool or infrastructure provisioning operation. Evaluates workspace policy, risk level, and credit balance.",
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.",
112
199
  inputSchema: {
113
200
  type: "object",
114
201
  required: ["tool_slug"],
115
202
  properties: {
116
- tool_slug: { type: "string", description: "Muxo tool slug to plan" },
203
+ tool_slug: {
204
+ type: "string",
205
+ description: "Muxo tool slug (e.g. 'instant.seo.audit', 'billing.credits.topup') or natural-language request",
206
+ },
117
207
  input: {
118
208
  type: "object",
119
- description: "Arguments matching the tool's inputSchema",
209
+ description: "Arguments matching the tool's inputSchema (auto-extracted when tool_slug is natural language)",
120
210
  },
121
211
  reason: {
122
212
  type: "string",
123
213
  description: "Audit reason explaining why this action is being planned",
124
214
  },
125
215
  },
216
+ additionalProperties: false,
217
+ },
218
+ annotations: {
219
+ readOnlyHint: false,
220
+ destructiveHint: false,
221
+ openWorldHint: false,
126
222
  },
127
223
  },
128
224
  {
129
225
  name: "get_plan",
130
- description: "Inspect the status, risk level, and approval state of a planned action.",
226
+ title: "Get Action Plan",
227
+ description: "Inspect the status, risk level, governance decision record, and approval state of a planned action.",
131
228
  inputSchema: {
132
229
  type: "object",
133
230
  required: ["plan_id"],
134
231
  properties: {
135
232
  plan_id: { type: "string", description: "Plan ID (plan_*)" },
136
233
  },
234
+ additionalProperties: false,
235
+ },
236
+ annotations: {
237
+ readOnlyHint: true,
238
+ destructiveHint: false,
239
+ openWorldHint: false,
137
240
  },
138
241
  },
139
242
  {
140
243
  name: "get_run_context",
244
+ title: "Get Workspace Context & Memory",
141
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.",
142
246
  inputSchema: {
143
247
  type: "object",
@@ -147,10 +251,17 @@ export const MUXO_MCP_TOOLS = [
147
251
  description: "Optional semantic search query to recall relevant workspace memories from Supermemory v5",
148
252
  },
149
253
  },
254
+ additionalProperties: false,
255
+ },
256
+ annotations: {
257
+ readOnlyHint: true,
258
+ destructiveHint: false,
259
+ openWorldHint: false,
150
260
  },
151
261
  },
152
262
  {
153
263
  name: "execute_read",
264
+ title: "Execute Read Plan",
154
265
  description: "Execute an approved plan with riskLevel = 'read'.",
155
266
  inputSchema: {
156
267
  type: "object",
@@ -158,10 +269,17 @@ export const MUXO_MCP_TOOLS = [
158
269
  properties: {
159
270
  plan_id: { type: "string", description: "Plan ID (plan_*)" },
160
271
  },
272
+ additionalProperties: false,
273
+ },
274
+ annotations: {
275
+ readOnlyHint: true,
276
+ destructiveHint: false,
277
+ openWorldHint: true,
161
278
  },
162
279
  },
163
280
  {
164
281
  name: "execute_write",
282
+ title: "Execute Write Plan",
165
283
  description: "Execute an approved plan with riskLevel = 'write'.",
166
284
  inputSchema: {
167
285
  type: "object",
@@ -169,10 +287,17 @@ export const MUXO_MCP_TOOLS = [
169
287
  properties: {
170
288
  plan_id: { type: "string", description: "Plan ID (plan_*)" },
171
289
  },
290
+ additionalProperties: false,
291
+ },
292
+ annotations: {
293
+ readOnlyHint: false,
294
+ destructiveHint: false,
295
+ openWorldHint: true,
172
296
  },
173
297
  },
174
298
  {
175
299
  name: "execute_admin",
300
+ title: "Execute Admin Plan",
176
301
  description: "Execute an approved plan with riskLevel = 'admin'.",
177
302
  inputSchema: {
178
303
  type: "object",
@@ -180,10 +305,17 @@ export const MUXO_MCP_TOOLS = [
180
305
  properties: {
181
306
  plan_id: { type: "string", description: "Plan ID (plan_*)" },
182
307
  },
308
+ additionalProperties: false,
309
+ },
310
+ annotations: {
311
+ readOnlyHint: false,
312
+ destructiveHint: false,
313
+ openWorldHint: true,
183
314
  },
184
315
  },
185
316
  {
186
317
  name: "execute_financial",
318
+ title: "Execute Financial Plan",
187
319
  description: "Execute an approved plan with riskLevel = 'financial'.",
188
320
  inputSchema: {
189
321
  type: "object",
@@ -191,10 +323,17 @@ export const MUXO_MCP_TOOLS = [
191
323
  properties: {
192
324
  plan_id: { type: "string", description: "Plan ID (plan_*)" },
193
325
  },
326
+ additionalProperties: false,
327
+ },
328
+ annotations: {
329
+ readOnlyHint: false,
330
+ destructiveHint: false,
331
+ openWorldHint: true,
194
332
  },
195
333
  },
196
334
  {
197
335
  name: "execute_provisioning",
336
+ title: "Execute Infrastructure Provisioning Plan",
198
337
  description: "Execute an approved infrastructure provisioning plan with riskLevel = 'provisioning' via Stripe Projects.",
199
338
  inputSchema: {
200
339
  type: "object",
@@ -202,10 +341,17 @@ export const MUXO_MCP_TOOLS = [
202
341
  properties: {
203
342
  plan_id: { type: "string", description: "Plan ID (plan_*)" },
204
343
  },
344
+ additionalProperties: false,
345
+ },
346
+ annotations: {
347
+ readOnlyHint: false,
348
+ destructiveHint: false,
349
+ openWorldHint: true,
205
350
  },
206
351
  },
207
352
  {
208
353
  name: "execute_destructive",
354
+ title: "Execute Destructive Plan",
209
355
  description: "Execute an approved plan with riskLevel = 'destructive'.",
210
356
  inputSchema: {
211
357
  type: "object",
@@ -213,10 +359,17 @@ export const MUXO_MCP_TOOLS = [
213
359
  properties: {
214
360
  plan_id: { type: "string", description: "Plan ID (plan_*)" },
215
361
  },
362
+ additionalProperties: false,
363
+ },
364
+ annotations: {
365
+ readOnlyHint: false,
366
+ destructiveHint: true,
367
+ openWorldHint: true,
216
368
  },
217
369
  },
218
370
  {
219
371
  name: "get_run",
372
+ title: "Get Execution Run",
220
373
  description: "Get the execution status, output, duration, and metered cost of a run (run_*).",
221
374
  inputSchema: {
222
375
  type: "object",
@@ -224,10 +377,17 @@ export const MUXO_MCP_TOOLS = [
224
377
  properties: {
225
378
  run_id: { type: "string", description: "Run ID (run_*)" },
226
379
  },
380
+ additionalProperties: false,
381
+ },
382
+ annotations: {
383
+ readOnlyHint: true,
384
+ destructiveHint: false,
385
+ openWorldHint: false,
227
386
  },
228
387
  },
229
388
  {
230
389
  name: "cancel_run",
390
+ title: "Cancel Execution Run",
231
391
  description: "Cancel an in-progress run and issue a cancellation receipt.",
232
392
  inputSchema: {
233
393
  type: "object",
@@ -235,11 +395,18 @@ export const MUXO_MCP_TOOLS = [
235
395
  properties: {
236
396
  run_id: { type: "string", description: "Run ID (run_*)" },
237
397
  },
398
+ additionalProperties: false,
399
+ },
400
+ annotations: {
401
+ readOnlyHint: false,
402
+ destructiveHint: true,
403
+ openWorldHint: false,
238
404
  },
239
405
  },
240
406
  {
241
407
  name: "get_receipt",
242
- description: "Fetch and cryptographically verify the HMAC-SHA256 chained execution receipt (rcpt_*) for a run.",
408
+ title: "Verify Execution Receipt",
409
+ description: "Fetch and cryptographically verify the HMAC-SHA256 + Ed25519 chained execution receipt (rcpt_*) for a run.",
243
410
  inputSchema: {
244
411
  type: "object",
245
412
  required: ["receipt_id"],
@@ -249,9 +416,185 @@ export const MUXO_MCP_TOOLS = [
249
416
  description: "Receipt ID (rcpt_*) or Run ID (run_*)",
250
417
  },
251
418
  },
419
+ additionalProperties: false,
420
+ },
421
+ annotations: {
422
+ readOnlyHint: true,
423
+ destructiveHint: false,
424
+ openWorldHint: false,
252
425
  },
253
426
  },
254
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
+ ];
473
+ function sha256Digest(content) {
474
+ const hash = crypto
475
+ .createHash("sha256")
476
+ .update(Buffer.from(content, "utf8"))
477
+ .digest("hex");
478
+ return `sha256:${hash}`;
479
+ }
480
+ function parseFrontmatter(markdown) {
481
+ const match = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/);
482
+ if (!match)
483
+ return {};
484
+ const result = {};
485
+ for (const line of match[1].split(/\r?\n/)) {
486
+ const idx = line.indexOf(":");
487
+ if (idx > 0) {
488
+ const k = line.slice(0, idx).trim();
489
+ const v = line.slice(idx + 1).trim();
490
+ if (k && v)
491
+ result[k] = v;
492
+ }
493
+ }
494
+ return result;
495
+ }
496
+ function readSkillFileOrDefault(relPath, fallback) {
497
+ try {
498
+ const absPath = path.join(ROOT_DIR, "plugins", "muxo", "skills", relPath);
499
+ if (fs.existsSync(absPath)) {
500
+ return fs.readFileSync(absPath, "utf8");
501
+ }
502
+ }
503
+ catch {
504
+ // Fallback to embedded markdown
505
+ }
506
+ return fallback;
507
+ }
508
+ export function getMuxoMcpSkills() {
509
+ const muxoSkillMd = readSkillFileOrDefault("muxo/SKILL.md", `---
510
+ name: muxo
511
+ 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.
512
+ ---
513
+
514
+ # Muxo
515
+
516
+ Use \`search_tools\`, \`inspect_tool\`, \`plan_action\`, \`wait_for_connection\`, and \`execute_<risk>\` to run governed actions across Connected Apps (\`app.*\`), Instant Tools (\`instant.*\`), and Cloud Infrastructure (\`resource.*\`).
517
+ `);
518
+ const muxoCliMd = readSkillFileOrDefault("muxo/references/cli.md", `# Local Muxo CLI\n\nRun \`muxo login --signup\`, \`muxo search\`, \`muxo link <provider> --wait\`, \`muxo exec\`, and \`muxo env pull\`.`);
519
+ const muxoMcpMd = readSkillFileOrDefault("muxo/references/mcp.md", `# Hosted Muxo MCP App\n\nFollow \`search_tools\` -> \`inspect_tool\` -> \`plan_action\` -> \`wait_for_connection\` -> \`execute_<risk>\` -> \`get_receipt\`.`);
520
+ const setupSkillMd = readSkillFileOrDefault("setup/SKILL.md", `---
521
+ name: setup
522
+ description: Guided onboarding skill for setting up the Muxo plugin in OpenAI ChatGPT and Codex. Helps users verify workspace authorization, connect external SaaS apps via OAuth handoff, provision cloud infrastructure, or install the local Muxo CLI.
523
+ ---
524
+
525
+ # Muxo Onboarding & Setup
526
+
527
+ Call \`get_profile\` and \`get_organization\` to verify your workspace connection, or run \`npx -y @muxoai/cli@latest login --signup\` in a terminal.
528
+ `);
529
+ const muxoFm = parseFrontmatter(muxoSkillMd);
530
+ const setupFm = parseFrontmatter(setupSkillMd);
531
+ const muxoFiles = [
532
+ {
533
+ path: "SKILL.md",
534
+ uri: "skill://muxo/muxo/SKILL.md",
535
+ size: Buffer.byteLength(muxoSkillMd, "utf8"),
536
+ digest: sha256Digest(muxoSkillMd),
537
+ mimeType: "text/markdown",
538
+ content: muxoSkillMd,
539
+ },
540
+ {
541
+ path: "references/cli.md",
542
+ uri: "skill://muxo/muxo/references/cli.md",
543
+ size: Buffer.byteLength(muxoCliMd, "utf8"),
544
+ digest: sha256Digest(muxoCliMd),
545
+ mimeType: "text/markdown",
546
+ content: muxoCliMd,
547
+ },
548
+ {
549
+ path: "references/mcp.md",
550
+ uri: "skill://muxo/muxo/references/mcp.md",
551
+ size: Buffer.byteLength(muxoMcpMd, "utf8"),
552
+ digest: sha256Digest(muxoMcpMd),
553
+ mimeType: "text/markdown",
554
+ content: muxoMcpMd,
555
+ },
556
+ ];
557
+ const setupFiles = [
558
+ {
559
+ path: "SKILL.md",
560
+ uri: "skill://muxo/setup/SKILL.md",
561
+ size: Buffer.byteLength(setupSkillMd, "utf8"),
562
+ digest: sha256Digest(setupSkillMd),
563
+ mimeType: "text/markdown",
564
+ content: setupSkillMd,
565
+ },
566
+ ];
567
+ const muxoName = muxoFm.name || "muxo";
568
+ const muxoDesc = muxoFm.description ||
569
+ "Route governed Muxo work between the hosted MCP-backed app and the local Muxo CLI.";
570
+ const setupName = setupFm.name || "setup";
571
+ const setupDesc = setupFm.description ||
572
+ "Guided onboarding skill for setting up the Muxo plugin in OpenAI ChatGPT and Codex.";
573
+ return [
574
+ {
575
+ name: muxoName,
576
+ description: muxoDesc,
577
+ uri: "skill://muxo/muxo/SKILL.md",
578
+ version: muxoFiles[0].digest,
579
+ frontmatter: {
580
+ name: muxoName,
581
+ description: muxoDesc,
582
+ },
583
+ files: muxoFiles,
584
+ },
585
+ {
586
+ name: setupName,
587
+ description: setupDesc,
588
+ uri: "skill://muxo/setup/SKILL.md",
589
+ version: setupFiles[0].digest,
590
+ frontmatter: {
591
+ name: setupName,
592
+ description: setupDesc,
593
+ },
594
+ files: setupFiles,
595
+ },
596
+ ];
597
+ }
255
598
  export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
256
599
  switch (toolName) {
257
600
  case "get_profile":
@@ -287,8 +630,13 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
287
630
  });
288
631
  case "plan_action":
289
632
  return engine.planAction(ctx, {
290
- toolSlug: String(args.tool_slug || args.slug || ""),
291
- input: args.input || {},
633
+ toolSlug: String(args.tool_slug ||
634
+ args.slug ||
635
+ args.tool_id ||
636
+ args.prompt ||
637
+ args.instruction ||
638
+ ""),
639
+ input: (args.input || args.arguments) || {},
292
640
  reason: args.reason ? String(args.reason) : undefined,
293
641
  });
294
642
  case "get_plan":
@@ -313,6 +661,65 @@ export async function dispatchMcpToolCall(engine, ctx, toolName, args = {}) {
313
661
  return engine.cancelRun(ctx, String(args.run_id || ""));
314
662
  case "get_receipt":
315
663
  return engine.getReceipt(ctx, String(args.receipt_id || args.run_id || ""));
664
+ // OpenAI Company Knowledge standard `search` and `fetch` tool support
665
+ case "search": {
666
+ const q = String(args.query || "").trim();
667
+ const [toolsRes, memRes] = await Promise.all([
668
+ engine.searchTools({ query: q, limit: 10 }),
669
+ engine.getMemoryOverview(ctx, q),
670
+ ]);
671
+ const toolHits = toolsRes.tools.map((t) => ({
672
+ id: `tool:${t.slug}`,
673
+ title: `${t.name} (${t.slug})`,
674
+ url: t.providerUrl || `https://docs.muxo.ai/tools/${encodeURIComponent(t.slug)}`,
675
+ snippet: `${t.description} [lane=${t.lane}, risk=${t.riskLevel}, cost=${t.creditCost}cr]`,
676
+ }));
677
+ const memHits = (memRes.memories || []).slice(0, 5).map((m) => ({
678
+ id: `memory:${m.id}`,
679
+ title: m.title,
680
+ url: `https://app.muxo.ai/?memory=${encodeURIComponent(m.id)}`,
681
+ snippet: m.content.slice(0, 240),
682
+ }));
683
+ return {
684
+ results: [...toolHits, ...memHits],
685
+ };
686
+ }
687
+ case "fetch": {
688
+ const rawId = String(args.id || "").trim();
689
+ const slug = rawId.startsWith("tool:") ? rawId.slice(5) : rawId;
690
+ if (rawId.startsWith("memory:")) {
691
+ const memId = rawId.slice(7);
692
+ const memRes = await engine.getMemoryOverview(ctx);
693
+ const found = (memRes.memories || []).find((m) => m.id === memId);
694
+ if (!found)
695
+ throw new Error(`Memory record not found: ${rawId}`);
696
+ return {
697
+ id: rawId,
698
+ title: found.title,
699
+ text: found.content,
700
+ url: `https://app.muxo.ai/?memory=${encodeURIComponent(found.id)}`,
701
+ metadata: {
702
+ namespace: found.namespace,
703
+ kind: found.kind,
704
+ createdAt: found.createdAt,
705
+ },
706
+ };
707
+ }
708
+ const tool = await engine.inspectTool(slug);
709
+ return {
710
+ id: `tool:${tool.slug}`,
711
+ title: tool.name,
712
+ text: JSON.stringify(tool, null, 2),
713
+ url: tool.providerUrl ||
714
+ `https://docs.muxo.ai/tools/${encodeURIComponent(tool.slug)}`,
715
+ metadata: {
716
+ slug: tool.slug,
717
+ lane: tool.lane,
718
+ riskLevel: tool.riskLevel,
719
+ creditCost: String(tool.creditCost),
720
+ },
721
+ };
722
+ }
316
723
  default:
317
724
  throw new Error(`Unknown MCP tool: ${toolName}`);
318
725
  }
@@ -321,22 +728,32 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
321
728
  const id = rpc.id ?? null;
322
729
  const method = String(rpc.method || "");
323
730
  const params = (rpc.params || {});
324
- if (method === "notifications/initialized") {
731
+ if (method === "notifications/initialized" ||
732
+ method.startsWith("notifications/")) {
325
733
  return null;
326
734
  }
327
735
  try {
328
736
  if (method === "initialize") {
737
+ const requestedProtocol = typeof params.protocolVersion === "string" &&
738
+ params.protocolVersion.trim()
739
+ ? params.protocolVersion.trim()
740
+ : "2025-06-18";
329
741
  return {
330
742
  jsonrpc: "2.0",
331
743
  id,
332
744
  result: {
333
- protocolVersion: "2024-11-05",
745
+ protocolVersion: requestedProtocol,
746
+ instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
334
747
  serverInfo: {
335
748
  name: "muxo-mcp-server",
336
- version: "1.0.0",
749
+ version: "1.3.0",
337
750
  },
338
751
  capabilities: {
339
- tools: {},
752
+ tools: { listChanged: false },
753
+ resources: { listChanged: false },
754
+ extensions: {
755
+ "io.modelcontextprotocol/skills": {},
756
+ },
340
757
  },
341
758
  },
342
759
  };
@@ -357,10 +774,14 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
357
774
  const toolName = String(params.name || "");
358
775
  const toolArgs = (params.arguments || {});
359
776
  const output = await dispatchMcpToolCall(engine, ctx, toolName, toolArgs);
777
+ const structuredContent = output && typeof output === "object" && !Array.isArray(output)
778
+ ? output
779
+ : { data: output };
360
780
  return {
361
781
  jsonrpc: "2.0",
362
782
  id,
363
783
  result: {
784
+ structuredContent,
364
785
  content: [
365
786
  {
366
787
  type: "text",
@@ -371,6 +792,98 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
371
792
  },
372
793
  };
373
794
  }
795
+ // SEP-2640 Skills Import Extension (`io.modelcontextprotocol/skills`)
796
+ if (method === "skills/list") {
797
+ const skills = getMuxoMcpSkills().map((s) => ({
798
+ name: s.name,
799
+ description: s.description,
800
+ uri: s.uri,
801
+ version: s.version,
802
+ digest: s.files[0]?.digest || "",
803
+ files: s.files.length,
804
+ }));
805
+ return {
806
+ jsonrpc: "2.0",
807
+ id,
808
+ result: { skills },
809
+ };
810
+ }
811
+ if (method === "skills/get") {
812
+ const requestedName = String(params.name || "muxo").trim();
813
+ const skill = getMuxoMcpSkills().find((s) => s.name === requestedName);
814
+ if (!skill) {
815
+ return {
816
+ jsonrpc: "2.0",
817
+ id,
818
+ error: {
819
+ code: -32602,
820
+ message: `Skill not found: ${requestedName}`,
821
+ },
822
+ };
823
+ }
824
+ return {
825
+ jsonrpc: "2.0",
826
+ id,
827
+ result: {
828
+ skill: {
829
+ name: skill.name,
830
+ description: skill.description,
831
+ uri: skill.uri,
832
+ version: skill.version,
833
+ digest: skill.files[0]?.digest || "",
834
+ },
835
+ frontmatter: skill.frontmatter,
836
+ files: skill.files.map((f) => ({
837
+ path: f.path,
838
+ uri: f.uri,
839
+ size: f.size,
840
+ digest: f.digest,
841
+ mimeType: f.mimeType,
842
+ })),
843
+ },
844
+ };
845
+ }
846
+ if (method === "resources/list") {
847
+ const resources = getMuxoMcpSkills().flatMap((s) => s.files.map((f) => ({
848
+ uri: f.uri,
849
+ name: `${s.name}/${f.path}`,
850
+ description: s.description,
851
+ mimeType: f.mimeType,
852
+ })));
853
+ return {
854
+ jsonrpc: "2.0",
855
+ id,
856
+ result: { resources },
857
+ };
858
+ }
859
+ if (method === "resources/read") {
860
+ const uri = String(params.uri || "").trim();
861
+ const allFiles = getMuxoMcpSkills().flatMap((s) => s.files);
862
+ const found = allFiles.find((f) => f.uri === uri);
863
+ if (!found) {
864
+ return {
865
+ jsonrpc: "2.0",
866
+ id,
867
+ error: {
868
+ code: -32602,
869
+ message: `Resource not found: ${uri}`,
870
+ },
871
+ };
872
+ }
873
+ return {
874
+ jsonrpc: "2.0",
875
+ id,
876
+ result: {
877
+ contents: [
878
+ {
879
+ uri: found.uri,
880
+ mimeType: found.mimeType,
881
+ text: found.content,
882
+ },
883
+ ],
884
+ },
885
+ };
886
+ }
374
887
  return {
375
888
  jsonrpc: "2.0",
376
889
  id,