@mushi-mushi/mcp 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +201 -16
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -83,6 +83,55 @@ var TOOL_CATALOG = [
|
|
|
83
83
|
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
84
84
|
useCase: "Which components had the most critical bugs this week?"
|
|
85
85
|
},
|
|
86
|
+
// --- Inventory v2 (whitepaper §6.8) -------------------------------------
|
|
87
|
+
{
|
|
88
|
+
name: "inventory_get",
|
|
89
|
+
title: "Inventory snapshot",
|
|
90
|
+
description: "Current inventory.yaml snapshot for a project (latest ingest, validation errors, per-action status summary). Requires inventory_v2 on the project plan.",
|
|
91
|
+
scope: "mcp:read",
|
|
92
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
93
|
+
useCase: "What does the live inventory claim for this repo right now?"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "inventory_diff",
|
|
97
|
+
title: "Inventory diff",
|
|
98
|
+
description: "Diff two ingested inventory commits (fromSha \u2192 toSha) \u2014 added/removed nodes and edges. Use before merging a PR that touches inventory.yaml.",
|
|
99
|
+
scope: "mcp:read",
|
|
100
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
101
|
+
useCase: "What changed in inventory between these two SHAs?"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "inventory_findings",
|
|
105
|
+
title: "Gate findings",
|
|
106
|
+
description: "Latest gate runs + findings (dead-handler, mock-leak, crawl, status-claim, \u2026). Filter by gate name or severity.",
|
|
107
|
+
scope: "mcp:read",
|
|
108
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
109
|
+
useCase: "Show me what CI gates failed on the last run."
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "graph_neighborhood",
|
|
113
|
+
title: "Graph neighborhood",
|
|
114
|
+
description: 'BFS neighborhood around a graph node id or label \u2014 nodes + edges within a depth budget (max 4). Same backend as knowledge-graph traversal, tuned for "what touches this action?".',
|
|
115
|
+
scope: "mcp:read",
|
|
116
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
117
|
+
useCase: "What nodes connect to this inventory Action within 2 hops?"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "graph_node_status",
|
|
121
|
+
title: "Graph node detail",
|
|
122
|
+
description: "Fetch a single graph node row (label, type, metadata \u2014 includes v2 derived status on Action nodes).",
|
|
123
|
+
scope: "mcp:read",
|
|
124
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
125
|
+
useCase: "What status does the graph store on this node id?"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: "fix_suggest",
|
|
129
|
+
title: "Suggested fix (from triage)",
|
|
130
|
+
description: "Read-only slice of a report focused on Stage 2 suggested fix + root cause + reproduction \u2014 faster than pulling the full blob when you only need the human-readable hint.",
|
|
131
|
+
scope: "mcp:read",
|
|
132
|
+
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
133
|
+
useCase: "What did Stage 2 say we should try for this report?"
|
|
134
|
+
},
|
|
86
135
|
// --- Write / agentic ----------------------------------------------------
|
|
87
136
|
{
|
|
88
137
|
name: "submit_fix_result",
|
|
@@ -109,6 +158,14 @@ var TOOL_CATALOG = [
|
|
|
109
158
|
hints: { readOnly: false, destructive: false, idempotent: true, openWorld: true },
|
|
110
159
|
useCase: "Grade the latest batch of fixes before I ship."
|
|
111
160
|
},
|
|
161
|
+
{
|
|
162
|
+
name: "test_gen_from_report",
|
|
163
|
+
title: "Generate Playwright test from report",
|
|
164
|
+
description: "POST to inventory test-gen: uses the project BYOK LLM to author a Playwright spec from a classified report and opens a draft PR (internal service orchestration). Requires inventory_v2 + GitHub + LLM keys.",
|
|
165
|
+
scope: "mcp:write",
|
|
166
|
+
hints: { readOnly: false, destructive: false, idempotent: false, openWorld: true },
|
|
167
|
+
useCase: "Turn this regression report into an E2E test PR."
|
|
168
|
+
},
|
|
112
169
|
{
|
|
113
170
|
name: "transition_status",
|
|
114
171
|
title: "Move report between states",
|
|
@@ -347,6 +404,129 @@ function createMushiServer(config) {
|
|
|
347
404
|
return jsonText(await apiCall(`/v1/admin/graph/traverse?${params}`));
|
|
348
405
|
}
|
|
349
406
|
);
|
|
407
|
+
server.registerTool(
|
|
408
|
+
"graph_neighborhood",
|
|
409
|
+
{
|
|
410
|
+
title: titleOf("graph_neighborhood"),
|
|
411
|
+
description: descOf("graph_neighborhood"),
|
|
412
|
+
annotations: annotationsFor("graph_neighborhood"),
|
|
413
|
+
inputSchema: {
|
|
414
|
+
seed: z.string().describe("Starting node id or label"),
|
|
415
|
+
depth: z.number().optional().describe("Traversal depth (default 2, max 4)")
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
async (args) => {
|
|
419
|
+
const params = new URLSearchParams({
|
|
420
|
+
seed: args.seed,
|
|
421
|
+
depth: String(Math.min(args.depth ?? 2, 4))
|
|
422
|
+
});
|
|
423
|
+
return jsonText(await apiCall(`/v1/admin/graph/traverse?${params}`));
|
|
424
|
+
}
|
|
425
|
+
);
|
|
426
|
+
server.registerTool(
|
|
427
|
+
"graph_node_status",
|
|
428
|
+
{
|
|
429
|
+
title: titleOf("graph_node_status"),
|
|
430
|
+
description: descOf("graph_node_status"),
|
|
431
|
+
annotations: annotationsFor("graph_node_status"),
|
|
432
|
+
inputSchema: { nodeId: z.string().describe("graph_nodes.id") }
|
|
433
|
+
},
|
|
434
|
+
async (args) => jsonText(await apiCall(`/v1/admin/graph/node/${args.nodeId}`))
|
|
435
|
+
);
|
|
436
|
+
server.registerTool(
|
|
437
|
+
"inventory_get",
|
|
438
|
+
{
|
|
439
|
+
title: titleOf("inventory_get"),
|
|
440
|
+
description: descOf("inventory_get"),
|
|
441
|
+
annotations: annotationsFor("inventory_get"),
|
|
442
|
+
inputSchema: {
|
|
443
|
+
projectId: z.string().optional().describe("Project UUID \u2014 defaults to the server-configured project when omitted")
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
async (args) => {
|
|
447
|
+
const pid = args.projectId ?? projectId;
|
|
448
|
+
if (!pid) throw new MushiApiError(400, "MISSING_PROJECT", "projectId is required for inventory_get");
|
|
449
|
+
return jsonText(await apiCall(`/v1/admin/inventory/${pid}`));
|
|
450
|
+
}
|
|
451
|
+
);
|
|
452
|
+
server.registerTool(
|
|
453
|
+
"inventory_diff",
|
|
454
|
+
{
|
|
455
|
+
title: titleOf("inventory_diff"),
|
|
456
|
+
description: descOf("inventory_diff"),
|
|
457
|
+
annotations: annotationsFor("inventory_diff"),
|
|
458
|
+
inputSchema: {
|
|
459
|
+
projectId: z.string().optional().describe("Project UUID \u2014 defaults to configured project"),
|
|
460
|
+
fromSha: z.string().describe("Older commit SHA (baseline)"),
|
|
461
|
+
toSha: z.string().describe("Newer commit SHA (candidate)")
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
async (args) => {
|
|
465
|
+
const pid = args.projectId ?? projectId;
|
|
466
|
+
if (!pid) throw new MushiApiError(400, "MISSING_PROJECT", "projectId is required for inventory_diff");
|
|
467
|
+
const q = new URLSearchParams({ from: args.fromSha, to: args.toSha });
|
|
468
|
+
return jsonText(await apiCall(`/v1/admin/inventory/${pid}/diff?${q}`));
|
|
469
|
+
}
|
|
470
|
+
);
|
|
471
|
+
server.registerTool(
|
|
472
|
+
"inventory_findings",
|
|
473
|
+
{
|
|
474
|
+
title: titleOf("inventory_findings"),
|
|
475
|
+
description: descOf("inventory_findings"),
|
|
476
|
+
annotations: annotationsFor("inventory_findings"),
|
|
477
|
+
inputSchema: {
|
|
478
|
+
projectId: z.string().optional().describe("Project UUID \u2014 defaults to configured project"),
|
|
479
|
+
gate: z.string().optional().describe("Filter by gate id (e.g. dead_handler, status_claim)"),
|
|
480
|
+
severity: z.string().optional().describe("Filter findings by severity")
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
async (args) => {
|
|
484
|
+
const pid = args.projectId ?? projectId;
|
|
485
|
+
if (!pid) throw new MushiApiError(400, "MISSING_PROJECT", "projectId is required for inventory_findings");
|
|
486
|
+
const q = new URLSearchParams();
|
|
487
|
+
if (args.gate) q.set("gate", args.gate);
|
|
488
|
+
if (args.severity) q.set("severity", args.severity);
|
|
489
|
+
const suffix = q.toString() ? `?${q}` : "";
|
|
490
|
+
return jsonText(await apiCall(`/v1/admin/inventory/${pid}/findings${suffix}`));
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
server.registerTool(
|
|
494
|
+
"fix_suggest",
|
|
495
|
+
{
|
|
496
|
+
title: titleOf("fix_suggest"),
|
|
497
|
+
description: descOf("fix_suggest"),
|
|
498
|
+
annotations: annotationsFor("fix_suggest"),
|
|
499
|
+
inputSchema: { reportId: z.string().describe("Report UUID") }
|
|
500
|
+
},
|
|
501
|
+
async (args) => {
|
|
502
|
+
const report = await apiCall(`/v1/admin/reports/${args.reportId}`);
|
|
503
|
+
const s2 = report.stage2_analysis;
|
|
504
|
+
return jsonText({
|
|
505
|
+
reportId: args.reportId,
|
|
506
|
+
rootCause: s2?.rootCause ?? null,
|
|
507
|
+
suggestedFix: s2?.suggestedFix ?? null,
|
|
508
|
+
reproductionSteps: report.reproduction_steps ?? [],
|
|
509
|
+
summary: report.summary ?? null,
|
|
510
|
+
component: report.component ?? null
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
);
|
|
514
|
+
server.registerTool(
|
|
515
|
+
"run_nl_query",
|
|
516
|
+
{
|
|
517
|
+
title: titleOf("run_nl_query"),
|
|
518
|
+
description: descOf("run_nl_query"),
|
|
519
|
+
annotations: annotationsFor("run_nl_query"),
|
|
520
|
+
inputSchema: { question: z.string().describe('Question in plain English, e.g. "Which components had the most critical bugs this week?"') }
|
|
521
|
+
},
|
|
522
|
+
async (args) => {
|
|
523
|
+
const data = await apiCall("/v1/admin/query", {
|
|
524
|
+
method: "POST",
|
|
525
|
+
body: JSON.stringify({ question: args.question })
|
|
526
|
+
});
|
|
527
|
+
return jsonText(data);
|
|
528
|
+
}
|
|
529
|
+
);
|
|
350
530
|
server.registerTool(
|
|
351
531
|
"submit_fix_result",
|
|
352
532
|
{
|
|
@@ -441,6 +621,27 @@ function createMushiServer(config) {
|
|
|
441
621
|
return jsonText(data);
|
|
442
622
|
}
|
|
443
623
|
);
|
|
624
|
+
server.registerTool(
|
|
625
|
+
"test_gen_from_report",
|
|
626
|
+
{
|
|
627
|
+
title: titleOf("test_gen_from_report"),
|
|
628
|
+
description: descOf("test_gen_from_report"),
|
|
629
|
+
annotations: annotationsFor("test_gen_from_report"),
|
|
630
|
+
inputSchema: {
|
|
631
|
+
reportId: z.string().describe("Report UUID to turn into a Playwright PR"),
|
|
632
|
+
projectId: z.string().optional().describe("Project UUID \u2014 defaults to configured project")
|
|
633
|
+
}
|
|
634
|
+
},
|
|
635
|
+
async (args) => {
|
|
636
|
+
const pid = args.projectId ?? projectId;
|
|
637
|
+
if (!pid) throw new MushiApiError(400, "MISSING_PROJECT", "projectId is required for test_gen_from_report");
|
|
638
|
+
const data = await apiCall(`/v1/admin/inventory/${pid}/test-gen/from-report/${args.reportId}`, {
|
|
639
|
+
method: "POST",
|
|
640
|
+
body: JSON.stringify({})
|
|
641
|
+
});
|
|
642
|
+
return jsonText(data);
|
|
643
|
+
}
|
|
644
|
+
);
|
|
444
645
|
server.registerTool(
|
|
445
646
|
"transition_status",
|
|
446
647
|
{
|
|
@@ -461,22 +662,6 @@ function createMushiServer(config) {
|
|
|
461
662
|
return jsonText(data);
|
|
462
663
|
}
|
|
463
664
|
);
|
|
464
|
-
server.registerTool(
|
|
465
|
-
"run_nl_query",
|
|
466
|
-
{
|
|
467
|
-
title: titleOf("run_nl_query"),
|
|
468
|
-
description: descOf("run_nl_query"),
|
|
469
|
-
annotations: annotationsFor("run_nl_query"),
|
|
470
|
-
inputSchema: { question: z.string().describe('Question in plain English, e.g. "Which components had the most critical bugs this week?"') }
|
|
471
|
-
},
|
|
472
|
-
async (args) => {
|
|
473
|
-
const data = await apiCall("/v1/admin/query", {
|
|
474
|
-
method: "POST",
|
|
475
|
-
body: JSON.stringify({ question: args.question })
|
|
476
|
-
});
|
|
477
|
-
return jsonText(data);
|
|
478
|
-
}
|
|
479
|
-
);
|
|
480
665
|
server.resource(
|
|
481
666
|
"project_stats",
|
|
482
667
|
"project://stats",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mushi-mushi/mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "MCP server exposing Mushi Mushi reports to coding agents",
|
|
6
6
|
"type": "module",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
28
28
|
"zod": "^4.3.6",
|
|
29
|
-
"@mushi-mushi/core": "^0.
|
|
29
|
+
"@mushi-mushi/core": "^0.9.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.0.0",
|