@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.
Files changed (36) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/marketplace.json +19 -4
  3. package/.codex/config.toml +9 -2
  4. package/README.md +54 -19
  5. package/dist/cli.js +780 -94
  6. package/dist/engine.d.ts +1 -0
  7. package/dist/engine.js +52 -4
  8. package/dist/mcp.d.ts +6 -1
  9. package/dist/mcp.js +108 -22
  10. package/dist/nl.js +60 -36
  11. package/dist/providers/composio-instant.d.ts +1 -0
  12. package/dist/providers/composio-instant.js +6 -5
  13. package/dist/providers/composio-sdk.d.ts +1 -0
  14. package/dist/providers/composio-sdk.js +6 -2
  15. package/dist/providers/stripe-billing.js +14 -4
  16. package/dist/providers/stripe-projects.js +61 -4
  17. package/dist/providers/supermemory.d.ts +2 -0
  18. package/dist/providers/supermemory.js +58 -40
  19. package/dist/server.js +85 -27
  20. package/dist/store.d.ts +1 -0
  21. package/dist/store.js +20 -4
  22. package/dist/ui/console-html.js +134 -114
  23. package/package.json +1 -1
  24. package/plugins/muxo/.app.json +1 -1
  25. package/plugins/muxo/.claude-plugin/plugin.json +2 -2
  26. package/plugins/muxo/.codex-plugin/plugin.json +7 -5
  27. package/plugins/muxo/.mcp.json +1 -33
  28. package/plugins/muxo/assets/logo.png +0 -0
  29. package/plugins/muxo/hooks/session-start.sh +1 -1
  30. package/plugins/muxo/plugin.json +63 -6
  31. package/plugins/muxo/skills/muxo/SKILL.md +92 -14
  32. package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
  33. package/plugins/muxo/skills/muxo/references/cli.md +4 -2
  34. package/plugins/muxo/skills/muxo/references/mcp.md +15 -9
  35. package/plugins/muxo/skills/setup/SKILL.md +8 -2
  36. 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: plan.creditCost,
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 (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.";
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 (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.";
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: { 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" },
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 (Composio SDK: app.*), Instant Tools (Composio Instant: instant.*), and Cloud Infrastructure (Stripe Projects: resource.*).",
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 Composio OAuth apps, Instant wallet, and linked Stripe Projects cloud providers.",
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 Composio and Stripe Projects",
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 (Composio) or link a cloud provider (Stripe Projects).",
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, Supermemory v5 recall, Ed25519 signature, BYOK vs Muxo-funded mode, and credit balance.",
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.0",
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
- if (!input.code) {
90
- const codeBlock = text.match(/```(?:\w+)?\n([\s\S]*?)```/);
91
- if (codeBlock) {
92
- input.code = codeBlock[1].trim();
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
- else {
95
- const inlineCode = text.match(/`([^`]+)`/);
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
- if (/\b(search\s+the\s+web|web\s+search|search\s+for|look\s+up|find\s+news|exa|google)\b/i.test(q)) {
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 += 105;
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(run\s+python|execute\s+code|run\s+script|sandbox|calculate|e2b)\b/i.test(q)) {
243
- if (slug === "instant.code.execute")
244
- score += 105;
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 (/\b(turso|libsql|sqlite\s+database|sqlite\s+db)\b/i.test(q)) {
259
- if (slug.startsWith("resource.turso."))
260
- score += 120;
261
- if (slug.includes("database"))
262
- score += 15;
263
- }
264
- if (/\b(neon|postgres|postgresql|pg\s+database)\b/i.test(q)) {
265
- if (slug.startsWith("resource.neon."))
266
- score += 120;
267
- }
268
- if (/\b(upstash|redis|cache\s+store|kv\s+store)\b/i.test(q)) {
269
- if (slug.startsWith("resource.upstash."))
270
- score += 120;
271
- }
272
- if (/\b(supabase)\b/i.test(q)) {
273
- if (slug.startsWith("resource.supabase."))
274
- score += 120;
275
- }
276
- if (/\b(mongodb|mongo)\b/i.test(q)) {
277
- if (slug.startsWith("resource.mongodb."))
278
- score += 120;
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")
@@ -10,5 +10,6 @@ export declare class ComposioInstantAdapter {
10
10
  workspaceId: string;
11
11
  tool: MuxoTool;
12
12
  input: Record<string, unknown>;
13
+ composioApiKey?: string | null;
13
14
  }): Promise<Record<string, unknown>>;
14
15
  }
@@ -163,11 +163,11 @@ const INSTANT_TOOLS = [
163
163
  {
164
164
  slug: "instant.composio.workbench",
165
165
  upstreamSlug: "COMPOSIO_REMOTE_WORKBENCH",
166
- name: "Composio Instant: Remote Sandbox Workbench",
167
- description: "Execute isolated data processing, JSON transformation, or Python/JS analysis in Composio's remote sandbox workbench without OAuth.",
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: "Composio Workbench",
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 (this.config.composioApiKey && tool.upstreamSlug.startsWith("COMPOSIO_")) {
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": this.config.composioApiKey,
221
+ "x-api-key": activeComposioKey,
221
222
  "Content-Type": "application/json",
222
223
  },
223
224
  body: JSON.stringify({
@@ -37,5 +37,6 @@ export declare class ComposioSdkAdapter {
37
37
  tool: MuxoTool;
38
38
  input: Record<string, unknown>;
39
39
  connectedAccountId?: string | null;
40
+ composioApiKey?: string | null;
40
41
  }): Promise<Record<string, unknown>>;
41
42
  }
@@ -536,7 +536,8 @@ export class ComposioSdkAdapter {
536
536
  },
537
537
  };
538
538
  };
539
- if (!this.config.composioApiKey) {
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: this.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
  });