@mushi-mushi/mcp 0.13.0 → 0.13.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/README.md +2 -0
- package/dist/index.js +235 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -132,6 +132,8 @@ The endpoint accepts JSON-RPC 2.0 over POST (returns `application/json` or `text
|
|
|
132
132
|
| `get_knowledge_graph` | Traverse the knowledge graph from a seed component or page |
|
|
133
133
|
| `setup_check` | The 4 **dispatch-readiness** checks (GitHub repo, codebase indexed, Anthropic key, autofix enabled) — run before `dispatch_fix` |
|
|
134
134
|
| `ingest_setup_check` | The 4 **required ingest** checks (project, active API key, SDK heartbeat, first report) + `last_sdk_seen_at` diagnostics — run after wiring env vars to confirm the SDK is reporting |
|
|
135
|
+
| `get_activation_status` | Unified setup posture for the active project — required steps, SDK heartbeat, dispatch preflight, and the next best action. Run first when a user says setup is broken |
|
|
136
|
+
| `get_reporter_thread` | Unified report timeline — the reporter/admin comment thread (including verify/reopen signals) plus fix, QA, and status lanes. Use when triaging whether an end user still sees a bug as unfixed |
|
|
135
137
|
|
|
136
138
|
### Write / agentic
|
|
137
139
|
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,14 @@ var TOOL_CATALOG = [
|
|
|
24
24
|
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
25
25
|
useCase: "Show me everything you know about this report."
|
|
26
26
|
},
|
|
27
|
+
{
|
|
28
|
+
name: "get_report_timeline",
|
|
29
|
+
title: "Unified report timeline",
|
|
30
|
+
description: "Ordered timeline merging reporter comments, fix events, QA runs, skill pipeline steps, and Ask Mushi turns for one report.",
|
|
31
|
+
scope: "mcp:read",
|
|
32
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
33
|
+
useCase: "What happened on this report thread end-to-end?"
|
|
34
|
+
},
|
|
27
35
|
{
|
|
28
36
|
name: "search_reports",
|
|
29
37
|
title: "Search reports",
|
|
@@ -146,6 +154,14 @@ var TOOL_CATALOG = [
|
|
|
146
154
|
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
147
155
|
useCase: "Is the SDK installed and ingesting reports? Why is my banner still missing?"
|
|
148
156
|
},
|
|
157
|
+
{
|
|
158
|
+
name: "diagnose_connection",
|
|
159
|
+
title: "Connection diagnose (CLI + MCP + SDK)",
|
|
160
|
+
description: `Validate the MCP server credentials (endpoint, API key, projectId), ping /health, run ingest-setup and dispatch preflight, and return the single best next action when anything fails. Use when the user asks "why aren't my reports showing up?".`,
|
|
161
|
+
scope: "mcp:read",
|
|
162
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
163
|
+
useCase: "Why is my Mushi setup broken \u2014 what exact step should I fix next?"
|
|
164
|
+
},
|
|
149
165
|
// --- Write / agentic ----------------------------------------------------
|
|
150
166
|
{
|
|
151
167
|
name: "submit_fix_result",
|
|
@@ -327,6 +343,14 @@ var TDD_TOOL_CATALOG = [
|
|
|
327
343
|
hints: { readOnly: false, destructive: false, idempotent: false, openWorld: false },
|
|
328
344
|
useCase: "Reply to a reporter asking for more info or confirming a fix."
|
|
329
345
|
},
|
|
346
|
+
{
|
|
347
|
+
name: "get_two_way_comms_health",
|
|
348
|
+
title: "Two-way communication health",
|
|
349
|
+
description: "Summarize SDK \u2194 admin two-way reporter health for a host app: last SDK heartbeat, app version/platform last seen, unread reporter messages, recent reporter replies, and pending QA/TDD follow-ups. Use after wiring @mushi-mushi/web in a Vite/Capacitor app to confirm reports land in the console and admin/MCP replies reach the in-app widget.",
|
|
350
|
+
scope: "mcp:read",
|
|
351
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
352
|
+
useCase: "Is two-way reporter communication working for this host app?"
|
|
353
|
+
},
|
|
330
354
|
{
|
|
331
355
|
name: "list_qa_story_runs",
|
|
332
356
|
title: "Recent QA story runs",
|
|
@@ -392,6 +416,22 @@ var TDD_TOOL_CATALOG = [
|
|
|
392
416
|
hints: { readOnly: false, destructive: false, idempotent: true, openWorld: true },
|
|
393
417
|
useCase: "I just opened the PR \u2014 mark step 2 as passed and link the PR."
|
|
394
418
|
},
|
|
419
|
+
{
|
|
420
|
+
name: "get_activation_status",
|
|
421
|
+
title: "Activation cockpit status",
|
|
422
|
+
description: "Unified setup posture for the active project: required steps, SDK heartbeat, dispatch preflight, and the next best action. Use this first when the user says setup is broken or they cannot connect.",
|
|
423
|
+
scope: "mcp:read",
|
|
424
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
425
|
+
useCase: "What is blocking this project from going live?"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
name: "get_reporter_thread",
|
|
429
|
+
title: "Reporter feedback thread",
|
|
430
|
+
description: "Fetch the unified timeline for a report \u2014 the reporter/admin comment thread (including verify/reopen signals) plus fix, QA, and status lanes. Use when triaging whether an end user still sees a bug as unfixed.",
|
|
431
|
+
scope: "mcp:read",
|
|
432
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
433
|
+
useCase: "What did the reporter say after we marked this fixed?"
|
|
434
|
+
},
|
|
395
435
|
// ── Full-Stack Audit tools (Phase 5) ────────────────────────────────────────
|
|
396
436
|
{
|
|
397
437
|
name: "run_fullstack_audit",
|
|
@@ -545,6 +585,26 @@ function createMushiServer(config) {
|
|
|
545
585
|
},
|
|
546
586
|
async (args) => jsonText(await apiCall(`/v1/admin/reports/${args.reportId}`))
|
|
547
587
|
);
|
|
588
|
+
server.registerTool(
|
|
589
|
+
"get_report_timeline",
|
|
590
|
+
{
|
|
591
|
+
title: titleOf("get_report_timeline"),
|
|
592
|
+
description: descOf("get_report_timeline"),
|
|
593
|
+
annotations: annotationsFor("get_report_timeline"),
|
|
594
|
+
inputSchema: { reportId: z.string().describe("The report UUID") }
|
|
595
|
+
},
|
|
596
|
+
async (args) => jsonText(await apiCall(`/v1/sync/reports/${args.reportId}/timeline`))
|
|
597
|
+
);
|
|
598
|
+
server.registerTool(
|
|
599
|
+
"get_two_way_comms_health",
|
|
600
|
+
{
|
|
601
|
+
title: titleOf("get_two_way_comms_health"),
|
|
602
|
+
description: descOf("get_two_way_comms_health"),
|
|
603
|
+
annotations: annotationsFor("get_two_way_comms_health"),
|
|
604
|
+
inputSchema: {}
|
|
605
|
+
},
|
|
606
|
+
async () => jsonText(await apiCall("/v1/sync/two-way-health"))
|
|
607
|
+
);
|
|
548
608
|
server.registerTool(
|
|
549
609
|
"search_reports",
|
|
550
610
|
{
|
|
@@ -845,6 +905,109 @@ function createMushiServer(config) {
|
|
|
845
905
|
});
|
|
846
906
|
}
|
|
847
907
|
);
|
|
908
|
+
server.registerTool(
|
|
909
|
+
"diagnose_connection",
|
|
910
|
+
{
|
|
911
|
+
title: titleOf("diagnose_connection"),
|
|
912
|
+
description: descOf("diagnose_connection"),
|
|
913
|
+
annotations: annotationsFor("diagnose_connection"),
|
|
914
|
+
inputSchema: {}
|
|
915
|
+
},
|
|
916
|
+
async () => {
|
|
917
|
+
const issues = [];
|
|
918
|
+
if (!apiKey?.startsWith("mushi_")) {
|
|
919
|
+
issues.push({
|
|
920
|
+
check: "mcp_api_key",
|
|
921
|
+
detail: "MCP server API key missing or malformed",
|
|
922
|
+
fix: "Run `mushi connect` to write MUSHI_API_KEY into .cursor/mcp.json, then restart the MCP server."
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
if (!projectId) {
|
|
926
|
+
issues.push({
|
|
927
|
+
check: "mcp_project_id",
|
|
928
|
+
detail: "No projectId configured on the MCP server",
|
|
929
|
+
fix: "Add MUSHI_PROJECT_ID to .cursor/mcp.json (copy UUID from console \u2192 Projects)."
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
if (!apiEndpoint) {
|
|
933
|
+
issues.push({
|
|
934
|
+
check: "mcp_endpoint",
|
|
935
|
+
detail: "No API endpoint configured",
|
|
936
|
+
fix: "Set MUSHI_API_ENDPOINT to your `\u2026/functions/v1/api` URL in .cursor/mcp.json."
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
let healthOk = false;
|
|
940
|
+
if (apiEndpoint) {
|
|
941
|
+
try {
|
|
942
|
+
const healthRes = await doFetch(`${apiEndpoint.replace(/\/$/, "")}/health`, {
|
|
943
|
+
signal: AbortSignal.timeout(5e3)
|
|
944
|
+
});
|
|
945
|
+
healthOk = healthRes.status === 200;
|
|
946
|
+
if (!healthOk) {
|
|
947
|
+
issues.push({
|
|
948
|
+
check: "endpoint_health",
|
|
949
|
+
detail: `GET /health \u2192 HTTP ${healthRes.status}`,
|
|
950
|
+
fix: "Verify MUSHI_API_ENDPOINT and that the Supabase edge function is deployed."
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
} catch (err) {
|
|
954
|
+
issues.push({
|
|
955
|
+
check: "endpoint_health",
|
|
956
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
957
|
+
fix: "Check network connectivity and the endpoint URL in .cursor/mcp.json."
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
let ingestReady = false;
|
|
962
|
+
let dispatchReady = false;
|
|
963
|
+
try {
|
|
964
|
+
const ingest = await apiCall("/v1/sync/ingest-setup");
|
|
965
|
+
ingestReady = ingest.ready;
|
|
966
|
+
if (!ingest.ready) {
|
|
967
|
+
const failed = ingest.steps.filter((s) => s.required && !s.complete);
|
|
968
|
+
issues.push({
|
|
969
|
+
check: "ingest_setup",
|
|
970
|
+
detail: `Incomplete: ${failed.map((s) => s.label).join(", ")}`,
|
|
971
|
+
fix: failed[0]?.hint ?? "Paste the SDK snippet, start your dev server, submit a test report."
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
} catch (err) {
|
|
975
|
+
issues.push({
|
|
976
|
+
check: "ingest_setup",
|
|
977
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
978
|
+
fix: "Confirm API key is active for this project (Projects \u2192 API Keys)."
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
if (projectId) {
|
|
982
|
+
try {
|
|
983
|
+
const preflight = await apiCall(`/v1/admin/projects/${projectId}/preflight`);
|
|
984
|
+
dispatchReady = preflight.ready;
|
|
985
|
+
if (!preflight.ready) {
|
|
986
|
+
const failed = preflight.checks.filter((c) => !c.ready);
|
|
987
|
+
issues.push({
|
|
988
|
+
check: "dispatch_preflight",
|
|
989
|
+
detail: `Blocked: ${failed.map((c) => c.label).join(", ")}`,
|
|
990
|
+
fix: failed[0]?.hint ?? "Open Settings \u2192 Integrations and complete GitHub + BYOK setup."
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
} catch {
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
const ready = issues.length === 0 && healthOk && ingestReady;
|
|
997
|
+
const nextAction = issues[0]?.fix ?? (ready ? "Connection healthy \u2014 SDK ingest is working. Submit a report to confirm end-to-end." : "Run `mushi doctor` in your app repo for a full local checklist.");
|
|
998
|
+
return jsonText({
|
|
999
|
+
ready,
|
|
1000
|
+
healthOk,
|
|
1001
|
+
ingestReady,
|
|
1002
|
+
dispatchReady,
|
|
1003
|
+
endpoint: apiEndpoint ?? null,
|
|
1004
|
+
projectId: projectId ?? null,
|
|
1005
|
+
issues,
|
|
1006
|
+
nextAction,
|
|
1007
|
+
summary: ready ? "MCP credentials valid; ingest pipeline ready." : `Connection issue \u2014 ${issues[0]?.check ?? "unknown"}: ${nextAction}`
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
);
|
|
848
1011
|
server.registerTool(
|
|
849
1012
|
"submit_fix_result",
|
|
850
1013
|
{
|
|
@@ -1215,6 +1378,23 @@ function createMushiServer(config) {
|
|
|
1215
1378
|
};
|
|
1216
1379
|
}
|
|
1217
1380
|
);
|
|
1381
|
+
server.resource(
|
|
1382
|
+
"activation_status",
|
|
1383
|
+
"mushi://activation",
|
|
1384
|
+
{
|
|
1385
|
+
description: "Unified setup posture \u2014 SDK heartbeat, reports, GitHub, MCP readiness, QA stories, and the next best action."
|
|
1386
|
+
},
|
|
1387
|
+
async () => {
|
|
1388
|
+
const qs = projectId ? `?project_id=${encodeURIComponent(projectId)}` : "";
|
|
1389
|
+
return {
|
|
1390
|
+
contents: [{
|
|
1391
|
+
uri: "mushi://activation",
|
|
1392
|
+
mimeType: "application/json",
|
|
1393
|
+
text: JSON.stringify(await apiCall(`/v1/admin/activation${qs}`), null, 2)
|
|
1394
|
+
}]
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
);
|
|
1218
1398
|
server.prompt(
|
|
1219
1399
|
"summarize_report_for_fix",
|
|
1220
1400
|
"Turn a Mushi report into a one-line root cause, smallest file set, repro steps, and blast-radius warnings. Use before asking an agent to write the patch.",
|
|
@@ -1284,6 +1464,31 @@ Prefer items that are bottlenecks or critical severity. Skip filler.`
|
|
|
1284
1464
|
}]
|
|
1285
1465
|
})
|
|
1286
1466
|
);
|
|
1467
|
+
server.prompt(
|
|
1468
|
+
"mushi_setup",
|
|
1469
|
+
"Diagnose why Mushi setup is stuck and return the single next command or console step to unblock it.",
|
|
1470
|
+
{},
|
|
1471
|
+
() => ({
|
|
1472
|
+
messages: [{
|
|
1473
|
+
role: "user",
|
|
1474
|
+
content: {
|
|
1475
|
+
type: "text",
|
|
1476
|
+
text: `You are a Mushi onboarding copilot. Use the MCP tools:
|
|
1477
|
+
1. Read mushi://activation for unified setup posture.
|
|
1478
|
+
2. Read project://integration-health if GitHub or Sentry looks blocked.
|
|
1479
|
+
3. Call get_activation_status if the resource is unavailable.
|
|
1480
|
+
|
|
1481
|
+
Then output:
|
|
1482
|
+
- **Status:** one sentence on what is done vs blocked
|
|
1483
|
+
- **Next step:** the single highest-leverage action (console link or CLI command)
|
|
1484
|
+
- **Prove it:** how the user verifies the step worked
|
|
1485
|
+
- **If still stuck:** one diagnostic command (e.g. mushi doctor --fix)
|
|
1486
|
+
|
|
1487
|
+
Be specific. No generic advice.`
|
|
1488
|
+
}
|
|
1489
|
+
}]
|
|
1490
|
+
})
|
|
1491
|
+
);
|
|
1287
1492
|
server.registerTool(
|
|
1288
1493
|
"map_user_stories",
|
|
1289
1494
|
{
|
|
@@ -1687,6 +1892,36 @@ Prefer items that are bottlenecks or critical severity. Skip filler.`
|
|
|
1687
1892
|
return jsonText({ ok: true, message: `Step ${step_index} \u2192 ${args.status}` });
|
|
1688
1893
|
}
|
|
1689
1894
|
);
|
|
1895
|
+
server.registerTool(
|
|
1896
|
+
"get_activation_status",
|
|
1897
|
+
{
|
|
1898
|
+
title: titleOf("get_activation_status"),
|
|
1899
|
+
description: descOf("get_activation_status"),
|
|
1900
|
+
annotations: annotationsFor("get_activation_status"),
|
|
1901
|
+
inputSchema: {
|
|
1902
|
+
project_id: z.string().optional().describe("Optional project UUID override")
|
|
1903
|
+
}
|
|
1904
|
+
},
|
|
1905
|
+
async (args) => {
|
|
1906
|
+
const qs = args.project_id ? `?project_id=${encodeURIComponent(args.project_id)}` : "";
|
|
1907
|
+
const data = await apiCall(`/v1/admin/activation${qs}`);
|
|
1908
|
+
return jsonText(data);
|
|
1909
|
+
}
|
|
1910
|
+
);
|
|
1911
|
+
server.registerTool(
|
|
1912
|
+
"get_reporter_thread",
|
|
1913
|
+
{
|
|
1914
|
+
title: titleOf("get_reporter_thread"),
|
|
1915
|
+
description: descOf("get_reporter_thread"),
|
|
1916
|
+
annotations: annotationsFor("get_reporter_thread"),
|
|
1917
|
+
inputSchema: { reportId: z.string().describe("The report UUID") }
|
|
1918
|
+
},
|
|
1919
|
+
// The reporter thread is the `comments` lane of the unified report
|
|
1920
|
+
// timeline. There is no standalone admin `/comments` route (only the
|
|
1921
|
+
// reporter-token-gated `/v1/reporter/reports/:id/comments`), so we read the
|
|
1922
|
+
// admin-authed timeline, which also carries fix / QA / status lanes.
|
|
1923
|
+
async (args) => jsonText(await apiCall(`/v1/admin/reports/${args.reportId}/timeline`))
|
|
1924
|
+
);
|
|
1690
1925
|
const grantedScopes = config.scopes;
|
|
1691
1926
|
if (grantedScopes !== void 0) {
|
|
1692
1927
|
const toolRegistry = server._registeredTools;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mushi-mushi/mcp",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "MCP server exposing Mushi Mushi reports to coding agents",
|
|
6
6
|
"type": "module",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
28
|
+
"zod": "^4.4.2",
|
|
29
|
+
"@mushi-mushi/core": "^1.12.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.19.17",
|