@muxoai/platform 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +19 -4
- package/.codex/config.toml +9 -2
- package/README.md +54 -19
- package/dist/cli.js +780 -94
- package/dist/engine.d.ts +1 -0
- package/dist/engine.js +52 -4
- package/dist/mcp.d.ts +6 -1
- package/dist/mcp.js +108 -22
- package/dist/nl.js +60 -36
- package/dist/providers/composio-instant.d.ts +1 -0
- package/dist/providers/composio-instant.js +6 -5
- package/dist/providers/composio-sdk.d.ts +1 -0
- package/dist/providers/composio-sdk.js +6 -2
- package/dist/providers/stripe-billing.js +14 -4
- package/dist/providers/stripe-projects.js +61 -4
- package/dist/providers/supermemory.d.ts +2 -0
- package/dist/providers/supermemory.js +58 -40
- package/dist/server.js +85 -27
- package/dist/store.d.ts +1 -0
- package/dist/store.js +20 -4
- package/dist/ui/console-html.js +134 -114
- package/package.json +1 -1
- package/plugins/muxo/.app.json +1 -1
- package/plugins/muxo/.claude-plugin/plugin.json +2 -2
- package/plugins/muxo/.codex-plugin/plugin.json +7 -5
- package/plugins/muxo/.mcp.json +1 -33
- package/plugins/muxo/assets/logo.png +0 -0
- package/plugins/muxo/hooks/session-start.sh +1 -1
- package/plugins/muxo/plugin.json +63 -6
- package/plugins/muxo/skills/muxo/SKILL.md +92 -14
- package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
- package/plugins/muxo/skills/muxo/references/cli.md +4 -2
- package/plugins/muxo/skills/muxo/references/mcp.md +15 -9
- package/plugins/muxo/skills/setup/SKILL.md +8 -2
- package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
package/dist/engine.d.ts
CHANGED
|
@@ -95,6 +95,7 @@ export declare class MuxoEngine {
|
|
|
95
95
|
}>;
|
|
96
96
|
getPlan(ctx: ExecutionContext, planId: string): ActionPlan;
|
|
97
97
|
approvePlan(ctx: ExecutionContext, planId: string, decision?: "approved" | "rejected"): ActionPlan;
|
|
98
|
+
private enrichMemoryContext;
|
|
98
99
|
getRunContext(ctx: ExecutionContext, query?: string): Promise<Record<string, unknown>>;
|
|
99
100
|
getMemoryOverview(ctx: ExecutionContext, query?: string): Promise<{
|
|
100
101
|
enabled: boolean;
|
package/dist/engine.js
CHANGED
|
@@ -26,10 +26,14 @@ export class MuxoEngine {
|
|
|
26
26
|
}
|
|
27
27
|
// 1. get_profile
|
|
28
28
|
getProfile(ctx) {
|
|
29
|
+
const nickname = (ctx.user.email || "").split("@")[0] ||
|
|
30
|
+
ctx.user.name.toLowerCase().replace(/\s+/g, ".") ||
|
|
31
|
+
ctx.user.id;
|
|
29
32
|
return {
|
|
30
33
|
id: ctx.user.id,
|
|
31
34
|
name: ctx.user.name,
|
|
32
35
|
email: ctx.user.email,
|
|
36
|
+
nickname,
|
|
33
37
|
user: ctx.user,
|
|
34
38
|
actorId: ctx.actorId,
|
|
35
39
|
authType: ctx.authType,
|
|
@@ -417,7 +421,7 @@ export class MuxoEngine {
|
|
|
417
421
|
}
|
|
418
422
|
// 2. Recall Supermemory v5 contextual brain for this workspace + tool intent
|
|
419
423
|
const memoryQuery = `${tool.slug} ${tool.name} ${resolvedReason}`.trim();
|
|
420
|
-
const memoryContext = await this.supermemory.getContextForWorkspace(ws.id, memoryQuery);
|
|
424
|
+
const memoryContext = await this.enrichMemoryContext(ws.id, await this.supermemory.getContextForWorkspace(ws.id, memoryQuery));
|
|
421
425
|
const requiresHumanApproval = decisionRecord.verdict === "escalate" ||
|
|
422
426
|
(ws.policy.mode === "enforce" &&
|
|
423
427
|
ws.policy.requireApprovalFor.includes(tool.riskLevel));
|
|
@@ -506,6 +510,38 @@ export class MuxoEngine {
|
|
|
506
510
|
approvedBy: ctx.user.email,
|
|
507
511
|
});
|
|
508
512
|
}
|
|
513
|
+
async enrichMemoryContext(workspaceId, ctx) {
|
|
514
|
+
if (ctx.recalledMemories.length > 0 && ctx.staticFacts.length > 0) {
|
|
515
|
+
return ctx;
|
|
516
|
+
}
|
|
517
|
+
const localRecords = this.store.listMemoryRecords(workspaceId, 8);
|
|
518
|
+
if (localRecords.length === 0)
|
|
519
|
+
return ctx;
|
|
520
|
+
const recalled = ctx.recalledMemories.length > 0
|
|
521
|
+
? ctx.recalledMemories
|
|
522
|
+
: localRecords.slice(0, 5).map((r) => ({
|
|
523
|
+
documentId: r.documentId,
|
|
524
|
+
title: r.title,
|
|
525
|
+
snippet: r.content.slice(0, 240),
|
|
526
|
+
similarity: 1,
|
|
527
|
+
}));
|
|
528
|
+
const staticFacts = ctx.staticFacts.length > 0
|
|
529
|
+
? ctx.staticFacts
|
|
530
|
+
: localRecords
|
|
531
|
+
.filter((r) => r.kind === "fact" || r.kind === "preference")
|
|
532
|
+
.slice(0, 5)
|
|
533
|
+
.map((r) => `${r.title}: ${r.content.slice(0, 140)}`);
|
|
534
|
+
return {
|
|
535
|
+
...ctx,
|
|
536
|
+
staticFacts,
|
|
537
|
+
recalledMemories: recalled,
|
|
538
|
+
relevantMemories: recalled,
|
|
539
|
+
profile: {
|
|
540
|
+
...ctx.profile,
|
|
541
|
+
static: staticFacts,
|
|
542
|
+
},
|
|
543
|
+
};
|
|
544
|
+
}
|
|
509
545
|
// 9. get_run_context
|
|
510
546
|
async getRunContext(ctx, query) {
|
|
511
547
|
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
@@ -516,7 +552,7 @@ export class MuxoEngine {
|
|
|
516
552
|
redactedEnv[k] =
|
|
517
553
|
v.length > 8 ? `${v.slice(0, 4)}••••${v.slice(-3)}` : "••••••••";
|
|
518
554
|
}
|
|
519
|
-
const memoryContext = await this.supermemory.getContextForWorkspace(ws.id, query);
|
|
555
|
+
const memoryContext = await this.enrichMemoryContext(ws.id, await this.supermemory.getContextForWorkspace(ws.id, query));
|
|
520
556
|
return {
|
|
521
557
|
workspaceId: ws.id,
|
|
522
558
|
workspaceSlug: ws.slug,
|
|
@@ -533,7 +569,7 @@ export class MuxoEngine {
|
|
|
533
569
|
}
|
|
534
570
|
// Supermemory Workspace Brain Operations
|
|
535
571
|
async getMemoryOverview(ctx, query) {
|
|
536
|
-
const context = await this.supermemory.getContextForWorkspace(ctx.workspace.id, query);
|
|
572
|
+
const context = await this.enrichMemoryContext(ctx.workspace.id, await this.supermemory.getContextForWorkspace(ctx.workspace.id, query));
|
|
537
573
|
const recentMemories = this.store.listMemoryRecords(ctx.workspace.id, 25);
|
|
538
574
|
return {
|
|
539
575
|
enabled: context.enabled,
|
|
@@ -596,6 +632,14 @@ export class MuxoEngine {
|
|
|
596
632
|
}
|
|
597
633
|
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
598
634
|
const tool = await this.inspectTool(plan.toolSlug);
|
|
635
|
+
const byokActive = this.store.hasByokForLane(ws.id, tool.lane, tool.slug);
|
|
636
|
+
const effectiveCreditCost = byokActive ? 0 : plan.creditCost;
|
|
637
|
+
if (ws.monthlyActionsUsed >= ws.monthlyActionsLimit) {
|
|
638
|
+
throw new Error(`Monthly action limit reached (${ws.monthlyActionsUsed}/${ws.monthlyActionsLimit}). Upgrade to Starter ($29/mo) to unlock 5,000 actions/mo.`);
|
|
639
|
+
}
|
|
640
|
+
if (effectiveCreditCost > ws.creditsBalance) {
|
|
641
|
+
throw new Error(`Insufficient workspace credits to execute plan '${plan.id}' for ${tool.slug} (requires ${effectiveCreditCost}, available ${ws.creditsBalance}). Top up credits or configure a BYOK key.`);
|
|
642
|
+
}
|
|
599
643
|
const execDecisionRecord = this.governance.evaluateExecution({
|
|
600
644
|
workspace: ws,
|
|
601
645
|
actorId: ctx.actorId,
|
|
@@ -639,18 +683,22 @@ export class MuxoEngine {
|
|
|
639
683
|
});
|
|
640
684
|
}
|
|
641
685
|
else if (plan.lane === "composio_instant") {
|
|
686
|
+
const composioByok = this.store.getByokKey(ctx.workspace.id, "composio");
|
|
642
687
|
output = await this.composioInstant.executeTool({
|
|
643
688
|
workspaceId: ctx.workspace.id,
|
|
644
689
|
tool,
|
|
645
690
|
input: plan.input,
|
|
691
|
+
composioApiKey: composioByok,
|
|
646
692
|
});
|
|
647
693
|
}
|
|
648
694
|
else if (plan.lane === "composio_sdk") {
|
|
695
|
+
const composioByok = this.store.getByokKey(ctx.workspace.id, "composio");
|
|
649
696
|
output = await this.composioSdk.executeTool({
|
|
650
697
|
workspaceId: ctx.workspace.id,
|
|
651
698
|
tool,
|
|
652
699
|
input: plan.input,
|
|
653
700
|
connectedAccountId: activeConnId,
|
|
701
|
+
composioApiKey: composioByok,
|
|
654
702
|
});
|
|
655
703
|
}
|
|
656
704
|
else if (plan.lane === "stripe_projects") {
|
|
@@ -677,7 +725,7 @@ export class MuxoEngine {
|
|
|
677
725
|
status: "succeeded",
|
|
678
726
|
output,
|
|
679
727
|
actionsMetered: 1,
|
|
680
|
-
creditsMetered:
|
|
728
|
+
creditsMetered: effectiveCreditCost,
|
|
681
729
|
durationMs,
|
|
682
730
|
decisionRecord: execDecisionRecord,
|
|
683
731
|
});
|
package/dist/mcp.d.ts
CHANGED
|
@@ -4,12 +4,17 @@ export interface McpToolAnnotations {
|
|
|
4
4
|
destructiveHint: boolean;
|
|
5
5
|
openWorldHint: boolean;
|
|
6
6
|
}
|
|
7
|
+
export interface McpToolSecurityScheme {
|
|
8
|
+
type: "noauth" | "oauth2";
|
|
9
|
+
scopes?: string[];
|
|
10
|
+
}
|
|
7
11
|
export interface McpToolDefinition {
|
|
8
12
|
name: string;
|
|
9
13
|
title: string;
|
|
10
14
|
description: string;
|
|
11
15
|
inputSchema: Record<string, unknown>;
|
|
12
16
|
outputSchema?: Record<string, unknown>;
|
|
17
|
+
securitySchemes?: McpToolSecurityScheme[];
|
|
13
18
|
annotations: McpToolAnnotations;
|
|
14
19
|
_meta?: Record<string, unknown>;
|
|
15
20
|
}
|
|
@@ -17,7 +22,7 @@ export interface McpToolDefinition {
|
|
|
17
22
|
* Concise server instructions (<512 chars) per OpenAI Plugin MCP Server specification:
|
|
18
23
|
* https://developers.openai.com/plugins/build/mcp-server
|
|
19
24
|
*/
|
|
20
|
-
export declare const MUXO_MCP_SERVER_INSTRUCTIONS = "Muxo governs SaaS actions (
|
|
25
|
+
export declare const MUXO_MCP_SERVER_INSTRUCTIONS = "Muxo governs SaaS actions (Connected Apps: app.*), Instant tools (instant.*), Cloud Infrastructure (resource.*), Workspace Memory recall, and verifiable audit records. 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.";
|
|
21
26
|
export declare const MUXO_MCP_TOOLS: McpToolDefinition[];
|
|
22
27
|
/**
|
|
23
28
|
* OpenAI Company Knowledge standard `search` and `fetch` tool definitions
|
package/dist/mcp.js
CHANGED
|
@@ -2,11 +2,18 @@ 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
|
+
const DEFAULT_TOOL_SECURITY_SCHEMES = [
|
|
6
|
+
{ type: "noauth" },
|
|
7
|
+
{
|
|
8
|
+
type: "oauth2",
|
|
9
|
+
scopes: ["muxo:mcp", "muxo:read", "muxo:execute", "muxo:provision"],
|
|
10
|
+
},
|
|
11
|
+
];
|
|
5
12
|
/**
|
|
6
13
|
* Concise server instructions (<512 chars) per OpenAI Plugin MCP Server specification:
|
|
7
14
|
* https://developers.openai.com/plugins/build/mcp-server
|
|
8
15
|
*/
|
|
9
|
-
export const MUXO_MCP_SERVER_INSTRUCTIONS = "Muxo governs SaaS actions (
|
|
16
|
+
export const MUXO_MCP_SERVER_INSTRUCTIONS = "Muxo governs SaaS actions (Connected Apps: app.*), Instant tools (instant.*), Cloud Infrastructure (resource.*), Workspace Memory recall, and verifiable audit records. 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
17
|
export const MUXO_MCP_TOOLS = [
|
|
11
18
|
{
|
|
12
19
|
name: "get_profile",
|
|
@@ -18,17 +25,59 @@ export const MUXO_MCP_TOOLS = [
|
|
|
18
25
|
additionalProperties: false,
|
|
19
26
|
},
|
|
20
27
|
outputSchema: {
|
|
28
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
21
29
|
type: "object",
|
|
22
30
|
properties: {
|
|
23
|
-
id: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
id: {
|
|
32
|
+
type: "string",
|
|
33
|
+
minLength: 1,
|
|
34
|
+
pattern: "\\S",
|
|
35
|
+
description: "Unique identifier for the user.",
|
|
36
|
+
},
|
|
37
|
+
name: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "Full name of the user.",
|
|
40
|
+
},
|
|
41
|
+
email: {
|
|
42
|
+
type: "string",
|
|
43
|
+
description: "Email address of the user.",
|
|
44
|
+
},
|
|
45
|
+
nickname: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description: "Handle or username of the user.",
|
|
48
|
+
},
|
|
49
|
+
workspaceId: {
|
|
50
|
+
type: "string",
|
|
51
|
+
description: "Active workspace ID.",
|
|
52
|
+
},
|
|
53
|
+
workspaceName: {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "Active workspace name.",
|
|
56
|
+
},
|
|
57
|
+
tier: {
|
|
58
|
+
type: "string",
|
|
59
|
+
description: "Workspace subscription tier.",
|
|
60
|
+
},
|
|
61
|
+
authType: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "Authentication type (session or api_key).",
|
|
64
|
+
},
|
|
65
|
+
actorId: {
|
|
66
|
+
type: "string",
|
|
67
|
+
description: "Actor identifier.",
|
|
68
|
+
},
|
|
69
|
+
user: {
|
|
70
|
+
type: "object",
|
|
71
|
+
description: "User profile record.",
|
|
72
|
+
},
|
|
29
73
|
},
|
|
30
74
|
required: ["id"],
|
|
75
|
+
additionalProperties: false,
|
|
31
76
|
},
|
|
77
|
+
securitySchemes: [
|
|
78
|
+
{ type: "noauth" },
|
|
79
|
+
{ type: "oauth2", scopes: ["muxo:read"] },
|
|
80
|
+
],
|
|
32
81
|
annotations: {
|
|
33
82
|
readOnlyHint: true,
|
|
34
83
|
destructiveHint: false,
|
|
@@ -56,7 +105,7 @@ export const MUXO_MCP_TOOLS = [
|
|
|
56
105
|
{
|
|
57
106
|
name: "search_tools",
|
|
58
107
|
title: "Search Unified Tool Catalog",
|
|
59
|
-
description: "Search the unified Muxo catalog across Connected Apps (
|
|
108
|
+
description: "Search the unified Muxo catalog across Connected Apps (app.*), Instant Tools (instant.*), and Cloud Infrastructure (resource.*).",
|
|
60
109
|
inputSchema: {
|
|
61
110
|
type: "object",
|
|
62
111
|
properties: {
|
|
@@ -114,7 +163,7 @@ export const MUXO_MCP_TOOLS = [
|
|
|
114
163
|
{
|
|
115
164
|
name: "connection_status",
|
|
116
165
|
title: "Check Connection Status",
|
|
117
|
-
description: "Check connection status across
|
|
166
|
+
description: "Check connection status across Connected Apps, Instant Tools, and linked Cloud Infrastructure providers.",
|
|
118
167
|
inputSchema: {
|
|
119
168
|
type: "object",
|
|
120
169
|
properties: {
|
|
@@ -125,7 +174,7 @@ export const MUXO_MCP_TOOLS = [
|
|
|
125
174
|
sync_live: {
|
|
126
175
|
type: "boolean",
|
|
127
176
|
default: true,
|
|
128
|
-
description: "Whether to sync live status from upstream
|
|
177
|
+
description: "Whether to sync live connection status from upstream providers",
|
|
129
178
|
},
|
|
130
179
|
},
|
|
131
180
|
additionalProperties: false,
|
|
@@ -139,7 +188,7 @@ export const MUXO_MCP_TOOLS = [
|
|
|
139
188
|
{
|
|
140
189
|
name: "start_connection",
|
|
141
190
|
title: "Start OAuth Connection Handoff",
|
|
142
|
-
description: "Initiate a managed OAuth connection handoff for a Connected App
|
|
191
|
+
description: "Initiate a managed OAuth connection handoff for a Connected App or link a Cloud Infrastructure provider.",
|
|
143
192
|
inputSchema: {
|
|
144
193
|
type: "object",
|
|
145
194
|
required: ["provider"],
|
|
@@ -195,7 +244,7 @@ export const MUXO_MCP_TOOLS = [
|
|
|
195
244
|
{
|
|
196
245
|
name: "plan_action",
|
|
197
246
|
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,
|
|
247
|
+
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, Workspace Memory recall, safety guardrails, BYOK vs Muxo-funded mode, and credit balance.",
|
|
199
248
|
inputSchema: {
|
|
200
249
|
type: "object",
|
|
201
250
|
required: ["tool_slug"],
|
|
@@ -526,6 +575,8 @@ description: Guided onboarding skill for setting up the Muxo plugin in OpenAI Ch
|
|
|
526
575
|
|
|
527
576
|
Call \`get_profile\` and \`get_organization\` to verify your workspace connection, or run \`npx -y @muxoai/cli@latest login --signup\` in a terminal.
|
|
528
577
|
`);
|
|
578
|
+
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`);
|
|
579
|
+
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
580
|
const muxoFm = parseFrontmatter(muxoSkillMd);
|
|
530
581
|
const setupFm = parseFrontmatter(setupSkillMd);
|
|
531
582
|
const muxoFiles = [
|
|
@@ -537,6 +588,14 @@ Call \`get_profile\` and \`get_organization\` to verify your workspace connectio
|
|
|
537
588
|
mimeType: "text/markdown",
|
|
538
589
|
content: muxoSkillMd,
|
|
539
590
|
},
|
|
591
|
+
{
|
|
592
|
+
path: "agents/openai.yaml",
|
|
593
|
+
uri: "skill://muxo/muxo/agents/openai.yaml",
|
|
594
|
+
size: Buffer.byteLength(muxoOpenaiYaml, "utf8"),
|
|
595
|
+
digest: sha256Digest(muxoOpenaiYaml),
|
|
596
|
+
mimeType: "application/yaml",
|
|
597
|
+
content: muxoOpenaiYaml,
|
|
598
|
+
},
|
|
540
599
|
{
|
|
541
600
|
path: "references/cli.md",
|
|
542
601
|
uri: "skill://muxo/muxo/references/cli.md",
|
|
@@ -563,6 +622,14 @@ Call \`get_profile\` and \`get_organization\` to verify your workspace connectio
|
|
|
563
622
|
mimeType: "text/markdown",
|
|
564
623
|
content: setupSkillMd,
|
|
565
624
|
},
|
|
625
|
+
{
|
|
626
|
+
path: "agents/openai.yaml",
|
|
627
|
+
uri: "skill://muxo/setup/agents/openai.yaml",
|
|
628
|
+
size: Buffer.byteLength(setupOpenaiYaml, "utf8"),
|
|
629
|
+
digest: sha256Digest(setupOpenaiYaml),
|
|
630
|
+
mimeType: "application/yaml",
|
|
631
|
+
content: setupOpenaiYaml,
|
|
632
|
+
},
|
|
566
633
|
];
|
|
567
634
|
const muxoName = muxoFm.name || "muxo";
|
|
568
635
|
const muxoDesc = muxoFm.description ||
|
|
@@ -746,7 +813,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
746
813
|
instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
747
814
|
serverInfo: {
|
|
748
815
|
name: "muxo-mcp-server",
|
|
749
|
-
version: "1.3.
|
|
816
|
+
version: "1.3.1",
|
|
750
817
|
},
|
|
751
818
|
capabilities: {
|
|
752
819
|
tools: { listChanged: false },
|
|
@@ -766,7 +833,10 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
766
833
|
jsonrpc: "2.0",
|
|
767
834
|
id,
|
|
768
835
|
result: {
|
|
769
|
-
tools: MUXO_MCP_TOOLS
|
|
836
|
+
tools: MUXO_MCP_TOOLS.map((t) => ({
|
|
837
|
+
...t,
|
|
838
|
+
securitySchemes: t.securitySchemes || DEFAULT_TOOL_SECURITY_SCHEMES,
|
|
839
|
+
})),
|
|
770
840
|
},
|
|
771
841
|
};
|
|
772
842
|
}
|
|
@@ -795,9 +865,14 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
795
865
|
// SEP-2640 Skills Import Extension (`io.modelcontextprotocol/skills`)
|
|
796
866
|
if (method === "skills/list") {
|
|
797
867
|
const skills = getMuxoMcpSkills().map((s) => ({
|
|
868
|
+
uri: s.uri,
|
|
869
|
+
frontmatter: s.frontmatter,
|
|
870
|
+
resources: s.files.map((f) => ({
|
|
871
|
+
uri: f.uri,
|
|
872
|
+
digest: f.digest,
|
|
873
|
+
})),
|
|
798
874
|
name: s.name,
|
|
799
875
|
description: s.description,
|
|
800
|
-
uri: s.uri,
|
|
801
876
|
version: s.version,
|
|
802
877
|
digest: s.files[0]?.digest || "",
|
|
803
878
|
files: s.files.length,
|
|
@@ -809,30 +884,39 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
809
884
|
};
|
|
810
885
|
}
|
|
811
886
|
if (method === "skills/get") {
|
|
887
|
+
const requestedUri = String(params.uri || "").trim();
|
|
812
888
|
const requestedName = String(params.name || "muxo").trim();
|
|
813
|
-
const skill = getMuxoMcpSkills().find((s) => s.name === requestedName);
|
|
889
|
+
const skill = getMuxoMcpSkills().find((s) => s.uri === requestedUri || s.name === requestedName);
|
|
814
890
|
if (!skill) {
|
|
815
891
|
return {
|
|
816
892
|
jsonrpc: "2.0",
|
|
817
893
|
id,
|
|
818
894
|
error: {
|
|
819
895
|
code: -32602,
|
|
820
|
-
message: `Skill not found: ${requestedName}`,
|
|
896
|
+
message: `Skill not found: ${requestedUri || requestedName}`,
|
|
821
897
|
},
|
|
822
898
|
};
|
|
823
899
|
}
|
|
900
|
+
const resources = skill.files.map((f) => ({
|
|
901
|
+
uri: f.uri,
|
|
902
|
+
digest: f.digest,
|
|
903
|
+
}));
|
|
824
904
|
return {
|
|
825
905
|
jsonrpc: "2.0",
|
|
826
906
|
id,
|
|
827
907
|
result: {
|
|
828
908
|
skill: {
|
|
909
|
+
uri: skill.uri,
|
|
910
|
+
frontmatter: skill.frontmatter,
|
|
911
|
+
resources,
|
|
829
912
|
name: skill.name,
|
|
830
913
|
description: skill.description,
|
|
831
|
-
uri: skill.uri,
|
|
832
914
|
version: skill.version,
|
|
833
915
|
digest: skill.files[0]?.digest || "",
|
|
834
916
|
},
|
|
917
|
+
uri: skill.uri,
|
|
835
918
|
frontmatter: skill.frontmatter,
|
|
919
|
+
resources,
|
|
836
920
|
files: skill.files.map((f) => ({
|
|
837
921
|
path: f.path,
|
|
838
922
|
uri: f.uri,
|
|
@@ -894,17 +978,19 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
894
978
|
};
|
|
895
979
|
}
|
|
896
980
|
catch (err) {
|
|
981
|
+
const errPayload = {
|
|
982
|
+
ok: false,
|
|
983
|
+
error: String(err?.message || err || "MCP tool execution failed"),
|
|
984
|
+
};
|
|
897
985
|
return {
|
|
898
986
|
jsonrpc: "2.0",
|
|
899
987
|
id,
|
|
900
988
|
result: {
|
|
989
|
+
structuredContent: errPayload,
|
|
901
990
|
content: [
|
|
902
991
|
{
|
|
903
992
|
type: "text",
|
|
904
|
-
text: JSON.stringify(
|
|
905
|
-
ok: false,
|
|
906
|
-
error: String(err?.message || err || "MCP tool execution failed"),
|
|
907
|
-
}, null, 2),
|
|
993
|
+
text: JSON.stringify(errPayload, null, 2),
|
|
908
994
|
},
|
|
909
995
|
],
|
|
910
996
|
isError: true,
|
package/dist/nl.js
CHANGED
|
@@ -80,23 +80,39 @@ export function extractParametersFromNaturalLanguage(prompt, tool, explicitInput
|
|
|
80
80
|
input.numResults = extractNumberAfterKeyword(text, ["results", "limit", "top"], 5);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
else if (slug === "instant.code.execute") {
|
|
84
|
-
if (!input.language) {
|
|
83
|
+
else if (slug === "instant.code.execute" || slug === "instant.composio.workbench") {
|
|
84
|
+
if (!input.language && slug === "instant.code.execute") {
|
|
85
85
|
input.language = /\b(javascript|js|node|typescript|ts)\b/i.test(text)
|
|
86
86
|
? "javascript"
|
|
87
87
|
: "python";
|
|
88
88
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
const codeBlock = text.match(/```(?:\w+)?\n([\s\S]*?)```/);
|
|
90
|
+
const inlineCode = text.match(/`([^`]+)`/);
|
|
91
|
+
const extractedCode = codeBlock
|
|
92
|
+
? codeBlock[1].trim()
|
|
93
|
+
: inlineCode
|
|
94
|
+
? inlineCode[1].trim()
|
|
95
|
+
: text;
|
|
96
|
+
if (slug === "instant.composio.workbench") {
|
|
97
|
+
if (!input.code_to_execute) {
|
|
98
|
+
input.code_to_execute = String(input.code || extractedCode);
|
|
93
99
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (inlineCode)
|
|
97
|
-
input.code = inlineCode[1].trim();
|
|
100
|
+
if (!input.thought) {
|
|
101
|
+
input.thought = `Natural language workbench execution: ${text.slice(0, 80)}`;
|
|
98
102
|
}
|
|
99
103
|
}
|
|
104
|
+
else if (!input.code) {
|
|
105
|
+
input.code = extractedCode;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (slug === "instant.github.repo_intel") {
|
|
109
|
+
const repoMatch = text.match(/\b([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)\b/);
|
|
110
|
+
if (repoMatch && !repoMatch[0].includes(".ai") && !repoMatch[0].includes(".com")) {
|
|
111
|
+
if (!input.owner)
|
|
112
|
+
input.owner = repoMatch[1];
|
|
113
|
+
if (!input.repo)
|
|
114
|
+
input.repo = repoMatch[2];
|
|
115
|
+
}
|
|
100
116
|
}
|
|
101
117
|
else if (slug.startsWith("resource.")) {
|
|
102
118
|
if (!input.resource_name && !input.name) {
|
|
@@ -235,13 +251,19 @@ function scoreToolForPrompt(prompt, tool) {
|
|
|
235
251
|
if (slug === "instant.web.scrape")
|
|
236
252
|
score += 110;
|
|
237
253
|
}
|
|
238
|
-
|
|
254
|
+
const isExplicitWebSearch = /\b(search\s+(?:the\s+)?web|web\s+search|search\s+online|search\s+(?:for|about)|look\s+up|find\s+(?:news|info|information|articles)|exa|google)\b/i.test(q);
|
|
255
|
+
const hasProvisionVerb = /\b(provision|create|deploy|spin\s+up|setup|set\s+up|add\s+resource|new\s+db|new\s+database|database|db)\b/i.test(q);
|
|
256
|
+
if (isExplicitWebSearch) {
|
|
239
257
|
if (slug === "instant.web.search")
|
|
240
|
-
score +=
|
|
258
|
+
score += 155;
|
|
259
|
+
}
|
|
260
|
+
if (/\b(run\s+python|execute\s+code|run\s+script|sandbox|workbench|calculate|e2b)\b/i.test(q)) {
|
|
261
|
+
if (slug === "instant.code.execute" || slug === "instant.composio.workbench")
|
|
262
|
+
score += 125;
|
|
241
263
|
}
|
|
242
|
-
if (/\b(
|
|
243
|
-
if (slug === "instant.
|
|
244
|
-
score +=
|
|
264
|
+
if (/\b(repo\s+intel|github\s+repo|inspect\s+repo|repository\s+intel|stars\s+and\s+forks)\b/i.test(q)) {
|
|
265
|
+
if (slug === "instant.github.repo_intel")
|
|
266
|
+
score += 135;
|
|
245
267
|
}
|
|
246
268
|
if (/\b(top\s*up|add\s+credits|buy\s+credits|refill\s+credits|more\s+credits|\d+\s+credits)\b/i.test(q)) {
|
|
247
269
|
if (slug === "billing.credits.topup")
|
|
@@ -255,27 +277,29 @@ function scoreToolForPrompt(prompt, tool) {
|
|
|
255
277
|
if (slug === "billing.checkout.create")
|
|
256
278
|
score += 125;
|
|
257
279
|
}
|
|
258
|
-
if (
|
|
259
|
-
if (
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if (
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
280
|
+
if (!isExplicitWebSearch || hasProvisionVerb) {
|
|
281
|
+
if (/\b(turso|libsql|sqlite\s+database|sqlite\s+db)\b/i.test(q)) {
|
|
282
|
+
if (slug.startsWith("resource.turso."))
|
|
283
|
+
score += 120;
|
|
284
|
+
if (slug.includes("database"))
|
|
285
|
+
score += 15;
|
|
286
|
+
}
|
|
287
|
+
if (/\b(neon|postgres|postgresql|pg\s+database)\b/i.test(q)) {
|
|
288
|
+
if (slug.startsWith("resource.neon."))
|
|
289
|
+
score += 120;
|
|
290
|
+
}
|
|
291
|
+
if (/\b(upstash|redis|cache\s+store|kv\s+store)\b/i.test(q)) {
|
|
292
|
+
if (slug.startsWith("resource.upstash."))
|
|
293
|
+
score += 120;
|
|
294
|
+
}
|
|
295
|
+
if (/\b(supabase)\b/i.test(q)) {
|
|
296
|
+
if (slug.startsWith("resource.supabase."))
|
|
297
|
+
score += 120;
|
|
298
|
+
}
|
|
299
|
+
if (/\b(mongodb|mongo)\b/i.test(q)) {
|
|
300
|
+
if (slug.startsWith("resource.mongodb."))
|
|
301
|
+
score += 120;
|
|
302
|
+
}
|
|
279
303
|
}
|
|
280
304
|
if (/\b(hacker\s*news|hn\s+stories|top\s+stories)\b/i.test(q)) {
|
|
281
305
|
if (slug === "instant.hackernews.top_stories")
|
|
@@ -163,11 +163,11 @@ const INSTANT_TOOLS = [
|
|
|
163
163
|
{
|
|
164
164
|
slug: "instant.composio.workbench",
|
|
165
165
|
upstreamSlug: "COMPOSIO_REMOTE_WORKBENCH",
|
|
166
|
-
name: "
|
|
167
|
-
description: "Execute isolated data processing, JSON transformation, or Python/JS analysis in
|
|
166
|
+
name: "Instant: Remote Sandbox Workbench",
|
|
167
|
+
description: "Execute isolated data processing, JSON transformation, or Python/JS analysis in Muxo's remote sandbox workbench without OAuth.",
|
|
168
168
|
lane: "composio_instant",
|
|
169
169
|
providerSlug: "composio",
|
|
170
|
-
providerName: "
|
|
170
|
+
providerName: "Muxo Workbench",
|
|
171
171
|
categories: ["sandbox", "compute", "analysis", "instant"],
|
|
172
172
|
riskLevel: "write",
|
|
173
173
|
requiresAuth: false,
|
|
@@ -211,13 +211,14 @@ export class ComposioInstantAdapter {
|
|
|
211
211
|
}
|
|
212
212
|
async executeTool(params) {
|
|
213
213
|
const { tool, input } = params;
|
|
214
|
+
const activeComposioKey = params.composioApiKey || this.config.composioApiKey;
|
|
214
215
|
// 1. Try Composio Instant / No-Auth tool execution first if applicable
|
|
215
|
-
if (
|
|
216
|
+
if (activeComposioKey && tool.upstreamSlug.startsWith("COMPOSIO_")) {
|
|
216
217
|
try {
|
|
217
218
|
const res = await fetch(`${this.config.composioBaseUrl}/tools/execute/${encodeURIComponent(tool.upstreamSlug)}`, {
|
|
218
219
|
method: "POST",
|
|
219
220
|
headers: {
|
|
220
|
-
"x-api-key":
|
|
221
|
+
"x-api-key": activeComposioKey,
|
|
221
222
|
"Content-Type": "application/json",
|
|
222
223
|
},
|
|
223
224
|
body: JSON.stringify({
|
|
@@ -536,7 +536,8 @@ export class ComposioSdkAdapter {
|
|
|
536
536
|
},
|
|
537
537
|
};
|
|
538
538
|
};
|
|
539
|
-
|
|
539
|
+
const effectiveApiKey = params.composioApiKey || this.config.composioApiKey;
|
|
540
|
+
if (!effectiveApiKey) {
|
|
540
541
|
return buildConnectedAccountFallback();
|
|
541
542
|
}
|
|
542
543
|
const body = {
|
|
@@ -549,7 +550,10 @@ export class ComposioSdkAdapter {
|
|
|
549
550
|
try {
|
|
550
551
|
const res = await fetch(`${this.config.composioBaseUrl}/tools/execute/${encodeURIComponent(params.tool.upstreamSlug)}`, {
|
|
551
552
|
method: "POST",
|
|
552
|
-
headers:
|
|
553
|
+
headers: {
|
|
554
|
+
...this.headers,
|
|
555
|
+
"x-api-key": effectiveApiKey,
|
|
556
|
+
},
|
|
553
557
|
body: JSON.stringify(body),
|
|
554
558
|
signal: AbortSignal.timeout(25000),
|
|
555
559
|
});
|