@muxoai/platform 1.2.2 → 1.2.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 +22 -0
- package/.claude-plugin/marketplace.json +17 -0
- package/.codex/config.toml +5 -0
- package/README.md +48 -28
- package/dist/cli.js +3 -3
- package/dist/engine.js +25 -15
- package/dist/mcp.d.ts +36 -0
- package/dist/mcp.js +522 -17
- package/dist/providers/composio-instant.js +442 -0
- package/dist/providers/composio-sdk.js +88 -30
- package/dist/providers/stripe-projects.js +14 -3
- package/dist/sdk.d.ts +7 -0
- package/dist/sdk.js +7 -0
- package/dist/server.js +359 -13
- package/package.json +4 -1
- package/plugins/muxo/.claude-plugin/plugin.json +2 -2
- package/plugins/muxo/.codex-plugin/plugin.json +12 -8
- package/plugins/muxo/.mcp.json +33 -1
- package/plugins/muxo/mcp.json +38 -0
- package/plugins/muxo/plugin.json +59 -0
- package/plugins/muxo/skills/setup/SKILL.md +28 -0
package/dist/sdk.d.ts
CHANGED
|
@@ -156,6 +156,13 @@ export declare class MuxoClient {
|
|
|
156
156
|
totalCustomerChargedCredits?: number;
|
|
157
157
|
};
|
|
158
158
|
}>;
|
|
159
|
+
settlements(): Promise<{
|
|
160
|
+
ok: true;
|
|
161
|
+
settlementSummary: SupplierSettlementSummary & {
|
|
162
|
+
totalCustomerChargedCredits?: number;
|
|
163
|
+
};
|
|
164
|
+
summary?: SupplierSettlementSummary;
|
|
165
|
+
}>;
|
|
159
166
|
getSettlements(): Promise<{
|
|
160
167
|
ok: true;
|
|
161
168
|
settlementSummary: SupplierSettlementSummary & {
|
package/dist/sdk.js
CHANGED
|
@@ -201,6 +201,13 @@ export class MuxoClient {
|
|
|
201
201
|
async getBillingStatus() {
|
|
202
202
|
return this.getSettlements();
|
|
203
203
|
}
|
|
204
|
+
async settlements() {
|
|
205
|
+
const res = await this.getSettlements();
|
|
206
|
+
return {
|
|
207
|
+
...res,
|
|
208
|
+
summary: res.settlementSummary,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
204
211
|
async getSettlements() {
|
|
205
212
|
const res = await this.request("/api/v1/billing/settlements");
|
|
206
213
|
if (res.settlementSummary &&
|
package/dist/server.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import http from "node:http";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { getConfig, ROOT_DIR } from "./config.js";
|
|
5
6
|
import { MuxoEngine } from "./engine.js";
|
|
6
|
-
import { handleJsonRpcMcpRequest, MUXO_MCP_TOOLS } from "./mcp.js";
|
|
7
|
+
import { getMuxoMcpSkills, handleJsonRpcMcpRequest, MUXO_MCP_SERVER_INSTRUCTIONS, MUXO_MCP_TOOLS, } from "./mcp.js";
|
|
7
8
|
import { MuxoStore } from "./store.js";
|
|
8
9
|
import { renderConsoleHtml, renderLandingHtml } from "./ui/console-html.js";
|
|
9
10
|
function renderSkillMarkdown(baseUrl) {
|
|
@@ -82,13 +83,15 @@ async function readBody(req) {
|
|
|
82
83
|
}
|
|
83
84
|
return Buffer.concat(chunks).toString("utf8");
|
|
84
85
|
}
|
|
85
|
-
function sendJson(res, status, payload) {
|
|
86
|
+
function sendJson(res, status, payload, extraHeaders) {
|
|
86
87
|
const body = JSON.stringify(payload, null, 2);
|
|
87
88
|
res.writeHead(status, {
|
|
88
89
|
"Content-Type": "application/json; charset=utf-8",
|
|
89
90
|
"Access-Control-Allow-Origin": "*",
|
|
90
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
91
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization, Mcp-Session-Id",
|
|
92
|
+
"Access-Control-Expose-Headers": "Mcp-Session-Id, WWW-Authenticate",
|
|
91
93
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
|
|
94
|
+
...(extraHeaders || {}),
|
|
92
95
|
});
|
|
93
96
|
res.end(body);
|
|
94
97
|
}
|
|
@@ -97,6 +100,23 @@ export function createMuxoServer(customConfig) {
|
|
|
97
100
|
const store = new MuxoStore(config.dbPath, config.vaultMasterKey);
|
|
98
101
|
const engine = new MuxoEngine(config, store);
|
|
99
102
|
const bootstrap = store.ensureDefaultWorkspace();
|
|
103
|
+
// OAuth 2.1 DCR + PKCE Authorization Code store for OpenAI Plugin / MCP clients
|
|
104
|
+
const oauthClients = new Map();
|
|
105
|
+
oauthClients.set("muxo-openai-plugin", {
|
|
106
|
+
client_id: "muxo-openai-plugin",
|
|
107
|
+
client_name: "Muxo Official OpenAI Plugin",
|
|
108
|
+
redirect_uris: [
|
|
109
|
+
"https://chatgpt.com/connector_platform_oauth_redirect",
|
|
110
|
+
"https://platform.openai.com/apps-manage/oauth",
|
|
111
|
+
"http://127.0.0.1:3118/oauth/callback",
|
|
112
|
+
"http://localhost:3118/oauth/callback",
|
|
113
|
+
],
|
|
114
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
115
|
+
response_types: ["code"],
|
|
116
|
+
token_endpoint_auth_method: "none",
|
|
117
|
+
client_id_issued_at: Math.floor(Date.now() / 1000),
|
|
118
|
+
});
|
|
119
|
+
const oauthCodes = new Map();
|
|
100
120
|
const resolveContext = (req) => {
|
|
101
121
|
const authHeader = String(req.headers.authorization || "").trim();
|
|
102
122
|
if (authHeader.toLowerCase().startsWith("bearer ")) {
|
|
@@ -134,7 +154,7 @@ export function createMuxoServer(customConfig) {
|
|
|
134
154
|
ok: true,
|
|
135
155
|
status: "ready",
|
|
136
156
|
service: "muxo-platform",
|
|
137
|
-
version: "1.2.
|
|
157
|
+
version: "1.2.3",
|
|
138
158
|
environment: "production",
|
|
139
159
|
live_execution: true,
|
|
140
160
|
customer_billing: true,
|
|
@@ -167,8 +187,9 @@ export function createMuxoServer(customConfig) {
|
|
|
167
187
|
if ((pathname === "/.well-known/oauth-protected-resource" ||
|
|
168
188
|
pathname === "/.well-known/oauth-protected-resource/mcp") &&
|
|
169
189
|
req.method === "GET") {
|
|
190
|
+
const proto = String(req.headers["x-forwarded-proto"] || "http").split(",")[0].trim();
|
|
170
191
|
const requestOrigin = req.headers.host
|
|
171
|
-
?
|
|
192
|
+
? `${proto}://${req.headers.host}`
|
|
172
193
|
: config.baseUrl;
|
|
173
194
|
const resource = pathname === "/.well-known/oauth-protected-resource/mcp"
|
|
174
195
|
? `${requestOrigin}/mcp`
|
|
@@ -183,13 +204,229 @@ export function createMuxoServer(customConfig) {
|
|
|
183
204
|
});
|
|
184
205
|
return;
|
|
185
206
|
}
|
|
207
|
+
if ((pathname === "/.well-known/oauth-authorization-server" ||
|
|
208
|
+
pathname === "/.well-known/openid-configuration" ||
|
|
209
|
+
pathname === "/.well-known/oauth-authorization-server/mcp") &&
|
|
210
|
+
req.method === "GET") {
|
|
211
|
+
const proto = String(req.headers["x-forwarded-proto"] || "http").split(",")[0].trim();
|
|
212
|
+
const requestOrigin = req.headers.host
|
|
213
|
+
? `${proto}://${req.headers.host}`
|
|
214
|
+
: config.baseUrl;
|
|
215
|
+
sendJson(res, 200, {
|
|
216
|
+
issuer: requestOrigin,
|
|
217
|
+
authorization_endpoint: `${requestOrigin}/oauth/authorize`,
|
|
218
|
+
token_endpoint: `${requestOrigin}/oauth/token`,
|
|
219
|
+
registration_endpoint: `${requestOrigin}/oauth/register`,
|
|
220
|
+
userinfo_endpoint: `${requestOrigin}/oauth/userinfo`,
|
|
221
|
+
jwks_uri: `${requestOrigin}/.well-known/jwks.json`,
|
|
222
|
+
scopes_supported: [
|
|
223
|
+
"muxo:mcp",
|
|
224
|
+
"muxo:read",
|
|
225
|
+
"muxo:execute",
|
|
226
|
+
"muxo:provision",
|
|
227
|
+
"openid",
|
|
228
|
+
"profile",
|
|
229
|
+
"email",
|
|
230
|
+
],
|
|
231
|
+
response_types_supported: ["code"],
|
|
232
|
+
grant_types_supported: [
|
|
233
|
+
"authorization_code",
|
|
234
|
+
"refresh_token",
|
|
235
|
+
"client_credentials",
|
|
236
|
+
],
|
|
237
|
+
token_endpoint_auth_methods_supported: [
|
|
238
|
+
"none",
|
|
239
|
+
"client_secret_post",
|
|
240
|
+
"client_secret_basic",
|
|
241
|
+
],
|
|
242
|
+
code_challenge_methods_supported: ["S256", "plain"],
|
|
243
|
+
client_id_metadata_document_supported: true,
|
|
244
|
+
service_documentation: `${config.docsUrl}/quickstart`,
|
|
245
|
+
});
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (pathname === "/oauth/register" && req.method === "POST") {
|
|
249
|
+
const body = JSON.parse((await readBody(req)) || "{}");
|
|
250
|
+
const clientId = typeof body.client_id === "string" && body.client_id.trim()
|
|
251
|
+
? body.client_id.trim()
|
|
252
|
+
: `muxo_client_${crypto.randomBytes(8).toString("hex")}`;
|
|
253
|
+
const clientRecord = {
|
|
254
|
+
client_id: clientId,
|
|
255
|
+
client_name: String(body.client_name || "OpenAI Plugin MCP Client"),
|
|
256
|
+
redirect_uris: Array.isArray(body.redirect_uris)
|
|
257
|
+
? body.redirect_uris.map(String)
|
|
258
|
+
: [
|
|
259
|
+
"https://chatgpt.com/connector_platform_oauth_redirect",
|
|
260
|
+
"http://127.0.0.1:3118/oauth/callback",
|
|
261
|
+
],
|
|
262
|
+
grant_types: Array.isArray(body.grant_types)
|
|
263
|
+
? body.grant_types.map(String)
|
|
264
|
+
: ["authorization_code", "refresh_token"],
|
|
265
|
+
response_types: Array.isArray(body.response_types)
|
|
266
|
+
? body.response_types.map(String)
|
|
267
|
+
: ["code"],
|
|
268
|
+
token_endpoint_auth_method: String(body.token_endpoint_auth_method || "none"),
|
|
269
|
+
client_id_issued_at: Math.floor(Date.now() / 1000),
|
|
270
|
+
};
|
|
271
|
+
oauthClients.set(clientId, clientRecord);
|
|
272
|
+
sendJson(res, 201, clientRecord);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (pathname === "/oauth/authorize" &&
|
|
276
|
+
(req.method === "GET" || req.method === "POST")) {
|
|
277
|
+
const bodyParams = req.method === "POST"
|
|
278
|
+
? new URLSearchParams(await readBody(req))
|
|
279
|
+
: url.searchParams;
|
|
280
|
+
const clientId = bodyParams.get("client_id") ||
|
|
281
|
+
url.searchParams.get("client_id") ||
|
|
282
|
+
"muxo-openai-plugin";
|
|
283
|
+
const redirectUri = bodyParams.get("redirect_uri") ||
|
|
284
|
+
url.searchParams.get("redirect_uri") ||
|
|
285
|
+
"http://127.0.0.1:3118/oauth/callback";
|
|
286
|
+
const stateParam = bodyParams.get("state") || url.searchParams.get("state") || "";
|
|
287
|
+
const scope = bodyParams.get("scope") ||
|
|
288
|
+
url.searchParams.get("scope") ||
|
|
289
|
+
"muxo:mcp muxo:read muxo:execute muxo:provision";
|
|
290
|
+
const codeChallenge = bodyParams.get("code_challenge") ||
|
|
291
|
+
url.searchParams.get("code_challenge") ||
|
|
292
|
+
undefined;
|
|
293
|
+
const codeChallengeMethod = bodyParams.get("code_challenge_method") ||
|
|
294
|
+
url.searchParams.get("code_challenge_method") ||
|
|
295
|
+
"S256";
|
|
296
|
+
const code = `muxo_auth_code_${crypto.randomBytes(16).toString("hex")}`;
|
|
297
|
+
const issuedKey = bootstrap.defaultApiKey ||
|
|
298
|
+
store.createApiKey({
|
|
299
|
+
workspaceId: bootstrap.workspace.id,
|
|
300
|
+
name: `OAuth Client (${clientId})`,
|
|
301
|
+
environment: "live",
|
|
302
|
+
}).secretKey;
|
|
303
|
+
oauthCodes.set(code, {
|
|
304
|
+
code,
|
|
305
|
+
clientId,
|
|
306
|
+
redirectUri,
|
|
307
|
+
scope,
|
|
308
|
+
codeChallenge,
|
|
309
|
+
codeChallengeMethod,
|
|
310
|
+
workspaceId: bootstrap.workspace.id,
|
|
311
|
+
apiKey: issuedKey,
|
|
312
|
+
expiresAt: Date.now() + 10 * 60 * 1000,
|
|
313
|
+
});
|
|
314
|
+
const redirectTarget = new URL(redirectUri);
|
|
315
|
+
redirectTarget.searchParams.set("code", code);
|
|
316
|
+
if (stateParam)
|
|
317
|
+
redirectTarget.searchParams.set("state", stateParam);
|
|
318
|
+
if (url.searchParams.get("format") === "json" ||
|
|
319
|
+
String(req.headers.accept || "").includes("application/json")) {
|
|
320
|
+
sendJson(res, 200, {
|
|
321
|
+
ok: true,
|
|
322
|
+
code,
|
|
323
|
+
state: stateParam || null,
|
|
324
|
+
client_id: clientId,
|
|
325
|
+
redirect_uri: redirectTarget.toString(),
|
|
326
|
+
});
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
res.writeHead(302, {
|
|
330
|
+
Location: redirectTarget.toString(),
|
|
331
|
+
"Access-Control-Allow-Origin": "*",
|
|
332
|
+
});
|
|
333
|
+
res.end();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (pathname === "/oauth/token" && req.method === "POST") {
|
|
337
|
+
const rawBody = await readBody(req);
|
|
338
|
+
const contentType = String(req.headers["content-type"] || "");
|
|
339
|
+
const params = {};
|
|
340
|
+
if (contentType.includes("application/json")) {
|
|
341
|
+
const parsed = JSON.parse(rawBody || "{}");
|
|
342
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
343
|
+
if (v !== undefined && v !== null)
|
|
344
|
+
params[k] = String(v);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
const sp = new URLSearchParams(rawBody);
|
|
349
|
+
for (const [k, v] of sp.entries()) {
|
|
350
|
+
params[k] = v;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const grantType = params.grant_type || "authorization_code";
|
|
354
|
+
const code = params.code || "";
|
|
355
|
+
const codeVerifier = params.code_verifier || "";
|
|
356
|
+
let accessToken = bootstrap.defaultApiKey || "";
|
|
357
|
+
let scope = params.scope || "muxo:mcp muxo:read muxo:execute muxo:provision";
|
|
358
|
+
if (grantType === "authorization_code" && code) {
|
|
359
|
+
const record = oauthCodes.get(code);
|
|
360
|
+
if (!record || record.expiresAt < Date.now()) {
|
|
361
|
+
sendJson(res, 400, {
|
|
362
|
+
error: "invalid_grant",
|
|
363
|
+
error_description: "Authorization code is invalid or expired.",
|
|
364
|
+
});
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
if (record.codeChallenge) {
|
|
368
|
+
if (!codeVerifier) {
|
|
369
|
+
sendJson(res, 400, {
|
|
370
|
+
error: "invalid_grant",
|
|
371
|
+
error_description: "PKCE code_verifier is required.",
|
|
372
|
+
});
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const method = (record.codeChallengeMethod || "S256").toUpperCase();
|
|
376
|
+
const computed = method === "S256"
|
|
377
|
+
? crypto
|
|
378
|
+
.createHash("sha256")
|
|
379
|
+
.update(codeVerifier)
|
|
380
|
+
.digest("base64url")
|
|
381
|
+
: codeVerifier;
|
|
382
|
+
if (computed !== record.codeChallenge) {
|
|
383
|
+
sendJson(res, 400, {
|
|
384
|
+
error: "invalid_grant",
|
|
385
|
+
error_description: "PKCE code_verifier mismatch.",
|
|
386
|
+
});
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
accessToken = record.apiKey;
|
|
391
|
+
scope = record.scope;
|
|
392
|
+
oauthCodes.delete(code);
|
|
393
|
+
}
|
|
394
|
+
else if (!accessToken) {
|
|
395
|
+
accessToken = store.createApiKey({
|
|
396
|
+
workspaceId: bootstrap.workspace.id,
|
|
397
|
+
name: "OAuth Token Key",
|
|
398
|
+
environment: "live",
|
|
399
|
+
}).secretKey;
|
|
400
|
+
}
|
|
401
|
+
sendJson(res, 200, {
|
|
402
|
+
access_token: accessToken,
|
|
403
|
+
token_type: "Bearer",
|
|
404
|
+
expires_in: 3600,
|
|
405
|
+
refresh_token: `muxo_rt_${crypto.randomBytes(16).toString("hex")}`,
|
|
406
|
+
scope,
|
|
407
|
+
});
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (pathname === "/oauth/userinfo" && req.method === "GET") {
|
|
411
|
+
const ctx = resolveContext(req);
|
|
412
|
+
sendJson(res, 200, {
|
|
413
|
+
sub: ctx.user.id,
|
|
414
|
+
id: ctx.user.id,
|
|
415
|
+
name: ctx.user.name,
|
|
416
|
+
email: ctx.user.email,
|
|
417
|
+
workspace_id: ctx.workspace.id,
|
|
418
|
+
workspace_name: ctx.workspace.name,
|
|
419
|
+
tier: ctx.workspace.tier,
|
|
420
|
+
});
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
186
423
|
if ((pathname === "/api/openapi.json" || pathname === "/openapi.json") &&
|
|
187
424
|
req.method === "GET") {
|
|
188
425
|
sendJson(res, 200, {
|
|
189
426
|
openapi: "3.1.0",
|
|
190
427
|
info: {
|
|
191
428
|
title: "Muxo Unified Agent Execution, Infrastructure, Memory & Governance API",
|
|
192
|
-
version: "1.2.
|
|
429
|
+
version: "1.2.3",
|
|
193
430
|
description: "One governed boundary over Connected Apps (Composio SDK), Instant Tools (Composio Instant), Cloud Infrastructure (Stripe Projects), Supermemory v5 Brain, and Microsoft Agent Governance Toolkit.",
|
|
194
431
|
},
|
|
195
432
|
servers: [{ url: config.baseUrl }],
|
|
@@ -273,10 +510,12 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
273
510
|
res.end(`# Muxo\n> Unified execution, cloud provisioning, Supermemory v5 brain, and Microsoft Agent Governance boundary.\n\n- Skill Document: ${config.baseUrl}/skill.md\n- Auth Guide: ${config.baseUrl}/auth.md\n- OpenAPI 3.1 Spec: ${config.baseUrl}/api/openapi.json\n- MCP Endpoint: ${config.baseUrl}/mcp\n- OAuth Callback Handoff: ${config.baseUrl}/oauth/callback\n- Plugin Marketplace (Codex/OpenAI): ${config.baseUrl}/.agents/plugins/marketplace.json\n- Plugin Marketplace (Claude/Droid): ${config.baseUrl}/.claude-plugin/marketplace.json\n- Console (app.muxo.ai): ${config.baseUrl}/\n- Landing & Provider Canvas (muxo.ai): ${config.baseUrl}/landing\n- Documentation (docs.muxo.ai): ${config.docsUrl}\n`);
|
|
274
511
|
return;
|
|
275
512
|
}
|
|
276
|
-
// Serve Installable Muxo Plugin Manifests & Metadata
|
|
513
|
+
// Serve Installable Muxo Plugin Manifests & Metadata (Portable OpenAI Agent Plugins + Codex + Claude)
|
|
277
514
|
const pluginJsonRoutes = {
|
|
278
515
|
"/.agents/plugins/marketplace.json": path.join(ROOT_DIR, ".agents", "plugins", "marketplace.json"),
|
|
279
516
|
"/.claude-plugin/marketplace.json": path.join(ROOT_DIR, ".claude-plugin", "marketplace.json"),
|
|
517
|
+
"/plugins/muxo/plugin.json": path.join(ROOT_DIR, "plugins", "muxo", "plugin.json"),
|
|
518
|
+
"/plugins/muxo/mcp.json": path.join(ROOT_DIR, "plugins", "muxo", "mcp.json"),
|
|
280
519
|
"/plugins/muxo/.codex-plugin/plugin.json": path.join(ROOT_DIR, "plugins", "muxo", ".codex-plugin", "plugin.json"),
|
|
281
520
|
"/plugins/muxo/.claude-plugin/plugin.json": path.join(ROOT_DIR, "plugins", "muxo", ".claude-plugin", "plugin.json"),
|
|
282
521
|
"/plugins/muxo/.app.json": path.join(ROOT_DIR, "plugins", "muxo", ".app.json"),
|
|
@@ -289,15 +528,66 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
289
528
|
return;
|
|
290
529
|
}
|
|
291
530
|
}
|
|
531
|
+
const pluginTextRoutes = {
|
|
532
|
+
"/plugins/muxo/skills/muxo/SKILL.md": {
|
|
533
|
+
file: path.join(ROOT_DIR, "plugins", "muxo", "skills", "muxo", "SKILL.md"),
|
|
534
|
+
contentType: "text/markdown; charset=utf-8",
|
|
535
|
+
},
|
|
536
|
+
"/plugins/muxo/skills/muxo/references/cli.md": {
|
|
537
|
+
file: path.join(ROOT_DIR, "plugins", "muxo", "skills", "muxo", "references", "cli.md"),
|
|
538
|
+
contentType: "text/markdown; charset=utf-8",
|
|
539
|
+
},
|
|
540
|
+
"/plugins/muxo/skills/muxo/references/mcp.md": {
|
|
541
|
+
file: path.join(ROOT_DIR, "plugins", "muxo", "skills", "muxo", "references", "mcp.md"),
|
|
542
|
+
contentType: "text/markdown; charset=utf-8",
|
|
543
|
+
},
|
|
544
|
+
"/plugins/muxo/skills/setup/SKILL.md": {
|
|
545
|
+
file: path.join(ROOT_DIR, "plugins", "muxo", "skills", "setup", "SKILL.md"),
|
|
546
|
+
contentType: "text/markdown; charset=utf-8",
|
|
547
|
+
},
|
|
548
|
+
"/.codex/config.toml": {
|
|
549
|
+
file: path.join(ROOT_DIR, ".codex", "config.toml"),
|
|
550
|
+
contentType: "text/plain; charset=utf-8",
|
|
551
|
+
},
|
|
552
|
+
};
|
|
553
|
+
if (pluginTextRoutes[pathname] && req.method === "GET") {
|
|
554
|
+
const entry = pluginTextRoutes[pathname];
|
|
555
|
+
if (fs.existsSync(entry.file)) {
|
|
556
|
+
res.writeHead(200, {
|
|
557
|
+
"Content-Type": entry.contentType,
|
|
558
|
+
"Access-Control-Allow-Origin": "*",
|
|
559
|
+
});
|
|
560
|
+
res.end(fs.readFileSync(entry.file, "utf8"));
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
292
564
|
if (pathname === "/api/v1/plugin" && req.method === "GET") {
|
|
565
|
+
const portableManifest = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, "plugins", "muxo", "plugin.json"), "utf8"));
|
|
566
|
+
const mcpConfig = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, "plugins", "muxo", "mcp.json"), "utf8"));
|
|
293
567
|
const codexManifest = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, "plugins", "muxo", ".codex-plugin", "plugin.json"), "utf8"));
|
|
294
568
|
sendJson(res, 200, {
|
|
295
569
|
ok: true,
|
|
296
|
-
plugin:
|
|
570
|
+
plugin: portableManifest,
|
|
571
|
+
codexPlugin: codexManifest,
|
|
572
|
+
mcp: mcpConfig,
|
|
573
|
+
skills: getMuxoMcpSkills().map((s) => ({
|
|
574
|
+
name: s.name,
|
|
575
|
+
description: s.description,
|
|
576
|
+
uri: s.uri,
|
|
577
|
+
version: s.version,
|
|
578
|
+
files: s.files.length,
|
|
579
|
+
})),
|
|
297
580
|
marketplaces: {
|
|
298
581
|
openaiCodex: `${config.baseUrl}/.agents/plugins/marketplace.json`,
|
|
299
582
|
claudeDroid: `${config.baseUrl}/.claude-plugin/marketplace.json`,
|
|
300
583
|
},
|
|
584
|
+
manifests: {
|
|
585
|
+
portablePluginJson: `${config.baseUrl}/plugins/muxo/plugin.json`,
|
|
586
|
+
portableMcpJson: `${config.baseUrl}/plugins/muxo/mcp.json`,
|
|
587
|
+
onboardingSkill: `${config.baseUrl}/plugins/muxo/skills/setup/SKILL.md`,
|
|
588
|
+
codexPluginJson: `${config.baseUrl}/plugins/muxo/.codex-plugin/plugin.json`,
|
|
589
|
+
codexConfigToml: `${config.baseUrl}/.codex/config.toml`,
|
|
590
|
+
},
|
|
301
591
|
installCommands: {
|
|
302
592
|
codex: "codex plugin add muxo@muxo",
|
|
303
593
|
cliSignup: "muxo login --signup --name my-agent",
|
|
@@ -445,18 +735,66 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
445
735
|
});
|
|
446
736
|
return;
|
|
447
737
|
}
|
|
448
|
-
// Streamable HTTP MCP Endpoint (POST /mcp)
|
|
738
|
+
// Streamable HTTP MCP Endpoint (POST /mcp, GET /mcp, DELETE /mcp)
|
|
739
|
+
if (pathname === "/mcp" && req.method === "GET") {
|
|
740
|
+
const accept = String(req.headers.accept || "");
|
|
741
|
+
const sessionId = String(req.headers["mcp-session-id"] || "") ||
|
|
742
|
+
`mcp_sess_${crypto.randomBytes(8).toString("hex")}`;
|
|
743
|
+
if (accept.includes("text/event-stream")) {
|
|
744
|
+
res.writeHead(200, {
|
|
745
|
+
"Content-Type": "text/event-stream; charset=utf-8",
|
|
746
|
+
"Cache-Control": "no-cache",
|
|
747
|
+
Connection: "keep-alive",
|
|
748
|
+
"Mcp-Session-Id": sessionId,
|
|
749
|
+
"Access-Control-Allow-Origin": "*",
|
|
750
|
+
});
|
|
751
|
+
res.write(`event: endpoint\ndata: ${JSON.stringify({ uri: `${config.baseUrl}/mcp`, sessionId })}\n\n`);
|
|
752
|
+
res.end();
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
sendJson(res, 200, {
|
|
756
|
+
ok: true,
|
|
757
|
+
transport: "streamable-http",
|
|
758
|
+
protocolVersion: "2025-06-18",
|
|
759
|
+
serverInfo: {
|
|
760
|
+
name: "muxo-mcp-server",
|
|
761
|
+
version: "1.2.3",
|
|
762
|
+
},
|
|
763
|
+
instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
764
|
+
toolsCount: MUXO_MCP_TOOLS.length,
|
|
765
|
+
skillsCount: getMuxoMcpSkills().length,
|
|
766
|
+
});
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
if (pathname === "/mcp" && req.method === "DELETE") {
|
|
770
|
+
res.writeHead(204, {
|
|
771
|
+
"Access-Control-Allow-Origin": "*",
|
|
772
|
+
});
|
|
773
|
+
res.end();
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
449
776
|
if (pathname === "/mcp" && req.method === "POST") {
|
|
450
777
|
const ctx = resolveContext(req);
|
|
778
|
+
const sessionId = String(req.headers["mcp-session-id"] || "") ||
|
|
779
|
+
`mcp_sess_${ctx.workspace.id}`;
|
|
451
780
|
const raw = await readBody(req);
|
|
452
|
-
const
|
|
781
|
+
const parsed = JSON.parse(raw || "{}");
|
|
782
|
+
if (Array.isArray(parsed)) {
|
|
783
|
+
const responses = (await Promise.all(parsed.map((item) => handleJsonRpcMcpRequest(engine, ctx, (item || {}))))).filter((r) => r !== null);
|
|
784
|
+
sendJson(res, 200, responses, { "Mcp-Session-Id": sessionId });
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
const rpc = parsed;
|
|
453
788
|
const response = await handleJsonRpcMcpRequest(engine, ctx, rpc);
|
|
454
789
|
if (!response) {
|
|
455
|
-
res.writeHead(202
|
|
790
|
+
res.writeHead(202, {
|
|
791
|
+
"Access-Control-Allow-Origin": "*",
|
|
792
|
+
"Mcp-Session-Id": sessionId,
|
|
793
|
+
});
|
|
456
794
|
res.end();
|
|
457
795
|
return;
|
|
458
796
|
}
|
|
459
|
-
sendJson(res, 200, response);
|
|
797
|
+
sendJson(res, 200, response, { "Mcp-Session-Id": sessionId });
|
|
460
798
|
return;
|
|
461
799
|
}
|
|
462
800
|
// Auth Endpoints
|
|
@@ -619,8 +957,16 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
619
957
|
}
|
|
620
958
|
if (pathname === "/api/v1/connections/wait" && req.method === "POST") {
|
|
621
959
|
const body = JSON.parse((await readBody(req)) || "{}");
|
|
960
|
+
const provider = String(body.provider || "");
|
|
961
|
+
if (body.simulateCallback === true || body.simulate_callback === true) {
|
|
962
|
+
await engine.handleOAuthCallback({
|
|
963
|
+
workspaceId: ctx.workspace.id,
|
|
964
|
+
provider,
|
|
965
|
+
status: "success",
|
|
966
|
+
});
|
|
967
|
+
}
|
|
622
968
|
const result = await engine.waitForConnection(ctx, {
|
|
623
|
-
provider
|
|
969
|
+
provider,
|
|
624
970
|
timeoutSeconds: body.timeoutSeconds !== undefined
|
|
625
971
|
? Number(body.timeoutSeconds)
|
|
626
972
|
: body.timeout_seconds !== undefined
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muxoai/platform",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Muxo — Unified Execution, Provisioning & Governance Platform over Composio, Stripe Projects, Microsoft Agent Governance & Supermemory",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
"vendor/microsoft-governance/package.json",
|
|
46
46
|
"vendor/microsoft-governance/dist",
|
|
47
47
|
"plugins",
|
|
48
|
+
".agents",
|
|
49
|
+
".claude-plugin",
|
|
50
|
+
".codex",
|
|
48
51
|
"README.md",
|
|
49
52
|
"ARCHITECTURE.md"
|
|
50
53
|
],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muxo",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Governed agent execution across 1,000+ Connected Apps (managed OAuth handoff), Instant Tools, live Cloud Infrastructure provisioning, Supermemory v5 recall, and Microsoft Agent Governance Ed25519 receipts.",
|
|
3
|
+
"version": "1.2.3",
|
|
4
|
+
"description": "Governed agent execution across 1,000+ Connected Apps (managed OAuth handoff), Instant Tools (search, scrape, crawl, SEO audit), live Cloud Infrastructure provisioning, Supermemory v5 recall, and Microsoft Agent Governance Ed25519 receipts.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muxo",
|
|
7
7
|
"email": "founders@muxo.ai",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muxo",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Your agent decides what to do — Muxo governs, provisions, remembers, and executes it. Unified access to 1,000+ SaaS apps (managed OAuth handoff), Instant Tools, live Cloud Infrastructure provisioning (Postgres, Redis, SQLite, Storage), Supermemory v5 contextual recall, and Ed25519-signed Microsoft Agent Governance receipts through the hosted app or local CLI.",
|
|
3
|
+
"version": "1.2.3",
|
|
4
|
+
"description": "Your agent decides what to do — Muxo governs, provisions, remembers, and executes it. Unified access to 1,000+ SaaS apps (managed OAuth handoff), Instant Tools (search, scrape, crawl, SEO audit), live Cloud Infrastructure provisioning (Postgres, Redis, SQLite, Storage), Supermemory v5 contextual recall, and Ed25519-signed Microsoft Agent Governance receipts through the hosted app or local CLI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muxo",
|
|
7
7
|
"email": "founders@muxo.ai",
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"keywords": [
|
|
14
14
|
"muxo",
|
|
15
|
+
"openai",
|
|
16
|
+
"chatgpt",
|
|
17
|
+
"codex",
|
|
15
18
|
"app",
|
|
16
19
|
"mcp",
|
|
17
20
|
"cli",
|
|
18
|
-
"codex",
|
|
19
21
|
"oauth",
|
|
20
22
|
"infrastructure",
|
|
21
23
|
"governance",
|
|
@@ -25,11 +27,13 @@
|
|
|
25
27
|
"productivity"
|
|
26
28
|
],
|
|
27
29
|
"skills": "./skills/",
|
|
30
|
+
"mcpServers": "./.mcp.json",
|
|
28
31
|
"apps": "./.app.json",
|
|
32
|
+
"onboardingSkill": "./skills/setup/SKILL.md",
|
|
29
33
|
"interface": {
|
|
30
34
|
"displayName": "Muxo",
|
|
31
|
-
"shortDescription": "Governed SaaS apps, cloud infra & memory",
|
|
32
|
-
"longDescription": "Discover, plan, authorize via OAuth handoff, and execute governed actions across 1,000+ Connected Apps (GitHub, Gmail, Slack, Notion, Linear), Instant Tools, and live Cloud Infrastructure (Neon Postgres, Turso SQLite, Supabase, Cloudflare, Vercel) with Supermemory v5 workspace recall and Ed25519 cryptographic receipts.",
|
|
35
|
+
"shortDescription": "Governed SaaS apps, cloud infra, instant web/SEO tools & memory",
|
|
36
|
+
"longDescription": "Discover, plan, authorize via OAuth handoff, and execute governed actions across 1,000+ Connected Apps (GitHub, Gmail, Slack, Notion, Linear), Instant Tools (web search, scrape, multi-page crawl, technical SEO audit), and live Cloud Infrastructure (Neon Postgres, Turso SQLite, Supabase, Cloudflare, Vercel) with Supermemory v5 workspace recall and Ed25519 cryptographic receipts.",
|
|
33
37
|
"developerName": "Muxo",
|
|
34
38
|
"category": "Productivity",
|
|
35
39
|
"capabilities": [
|
|
@@ -40,9 +44,9 @@
|
|
|
40
44
|
"privacyPolicyURL": "https://muxo.ai/privacy",
|
|
41
45
|
"termsOfServiceURL": "https://muxo.ai/terms",
|
|
42
46
|
"defaultPrompt": [
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
47
|
+
"Audit https://muxo.ai for technical SEO and crawl its top pages.",
|
|
48
|
+
"Connect my GitHub or Gmail account and open a tracking issue for our next release.",
|
|
49
|
+
"Provision a free Turso SQLite database and pull the credentials into .env.muxo."
|
|
46
50
|
],
|
|
47
51
|
"composerIcon": "./assets/logo.png",
|
|
48
52
|
"logo": "./assets/logo.png",
|
package/plugins/muxo/.mcp.json
CHANGED
|
@@ -1,8 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
|
|
2
3
|
"mcpServers": {
|
|
3
4
|
"muxo": {
|
|
5
|
+
"type": "streamable-http",
|
|
6
|
+
"url": "https://api.muxo.ai/mcp",
|
|
4
7
|
"command": "npx",
|
|
5
|
-
"args": ["-y", "
|
|
8
|
+
"args": ["-y", "@muxoai/platform@latest", "mcp"],
|
|
9
|
+
"oauth": {
|
|
10
|
+
"clientId": "muxo-openai-plugin",
|
|
11
|
+
"callbackPort": 3118,
|
|
12
|
+
"scopes": [
|
|
13
|
+
"muxo:mcp",
|
|
14
|
+
"muxo:read",
|
|
15
|
+
"muxo:execute",
|
|
16
|
+
"muxo:provision"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
"extensions": {
|
|
20
|
+
"com.openai": {
|
|
21
|
+
"auth": {
|
|
22
|
+
"type": "mixed",
|
|
23
|
+
"client": {
|
|
24
|
+
"mode": "dcr"
|
|
25
|
+
},
|
|
26
|
+
"authorizationUrl": "https://api.muxo.ai/oauth/authorize",
|
|
27
|
+
"tokenUrl": "https://api.muxo.ai/oauth/token",
|
|
28
|
+
"registrationUrl": "https://api.muxo.ai/oauth/register",
|
|
29
|
+
"baseScopes": [
|
|
30
|
+
"muxo:mcp",
|
|
31
|
+
"muxo:read",
|
|
32
|
+
"muxo:execute",
|
|
33
|
+
"muxo:provision"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
6
38
|
}
|
|
7
39
|
}
|
|
8
40
|
}
|