@mushi-mushi/mcp 0.16.0 → 0.16.2
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/CONTRIBUTING.md +51 -8
- package/README.md +4 -9
- package/SECURITY.md +1 -1
- package/dist/catalog.js +1 -1
- package/dist/{chunk-PZEGN4XD.js → chunk-MM3IMFM4.js} +10 -1
- package/dist/{chunk-B2QEG35D.js → chunk-ZX3XIJ7S.js} +3 -0
- package/dist/feature-groups.d.ts +1 -1
- package/dist/feature-groups.js +1 -1
- package/dist/index.js +61 -1
- package/dist/server.js +50 -2
- package/package.json +13 -8
package/CONTRIBUTING.md
CHANGED
|
@@ -27,12 +27,24 @@ pnpm build
|
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
pnpm dev # Start all dev servers (admin on :6464)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
| Surface | URL |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| Admin console | http://localhost:6464 |
|
|
35
|
+
| Docs site | http://localhost:3000 |
|
|
36
|
+
| CLI console override | `MUSHI_CONSOLE_URL=http://localhost:6464` |
|
|
37
|
+
|
|
38
|
+
```bash
|
|
30
39
|
pnpm test # Run Vitest across all packages
|
|
31
40
|
pnpm typecheck # TypeScript checks
|
|
32
41
|
pnpm lint # ESLint
|
|
33
42
|
pnpm format # Prettier
|
|
43
|
+
pnpm smoke:cli-setup # Playwright: onboarding ?setup=cli + success panel (skips headless if unsigned)
|
|
34
44
|
```
|
|
35
45
|
|
|
46
|
+
Set `CLI_SETUP_SMOKE_STRICT=1` to fail the smoke script when Playwright is not signed in (CI gate).
|
|
47
|
+
|
|
36
48
|
Ad-hoc screenshots captured during UI reviews can live temporarily at the repo
|
|
37
49
|
root, but root-level `*.png` files are intentionally ignored. Canonical
|
|
38
50
|
screenshots that should be versioned belong under `docs/screenshots/`.
|
|
@@ -58,9 +70,9 @@ packages/
|
|
|
58
70
|
react-native/ React Native SDK (MIT)
|
|
59
71
|
cli/ CLI tool (MIT)
|
|
60
72
|
mcp/ MCP server for coding agents (MIT)
|
|
61
|
-
server/ Supabase Edge Functions (
|
|
62
|
-
agents/ Agentic fix pipeline (
|
|
63
|
-
verify/ Fix verification (
|
|
73
|
+
server/ Supabase Edge Functions (AGPLv3; ee/ is commercial)
|
|
74
|
+
agents/ Agentic fix pipeline (AGPLv3)
|
|
75
|
+
verify/ Fix verification (AGPLv3)
|
|
64
76
|
apps/
|
|
65
77
|
admin/ Admin dashboard (React + Tailwind)
|
|
66
78
|
docs/ Documentation site (Nextra — apps/docs)
|
|
@@ -69,6 +81,18 @@ tooling/
|
|
|
69
81
|
tsconfig/ Shared TypeScript configs
|
|
70
82
|
```
|
|
71
83
|
|
|
84
|
+
## What we don't accept
|
|
85
|
+
|
|
86
|
+
Knowing this upfront saves everyone time.
|
|
87
|
+
|
|
88
|
+
- **Automated / bulk / AI-slop PRs** — any PR that was opened by a script, an LLM agent acting without meaningful human review, or as part of a parallel bounty-farming sweep is closed on sight. The commit history, branch name, or helper scripts included in the PR make this obvious.
|
|
89
|
+
- **PRs that target the wrong base** — all PRs must branch from and target `master`. PRs targeting `main` or any other branch are closed (and will show an inflated diff that is not your work).
|
|
90
|
+
- **One PR per issue, one issue per PR** — splitting or duplicating work just to collect acknowledgements isn't welcome.
|
|
91
|
+
- **Good-first-issues without claiming first** — comment on the issue to claim it before starting. If two people open PRs for the same issue, the one that commented first is prioritised.
|
|
92
|
+
- **Documentation-only PRs that merely duplicate existing content** — if the information already exists (e.g. in another file in this repo), adding a redundant copy adds noise without value.
|
|
93
|
+
|
|
94
|
+
If a PR violates these policies it will be closed with a brief explanation. No hard feelings — a genuine contribution on the same issue is always welcome.
|
|
95
|
+
|
|
72
96
|
## Making Changes
|
|
73
97
|
|
|
74
98
|
1. Create a feature branch from `master`
|
|
@@ -97,8 +121,10 @@ Guardrails (run locally before pushing):
|
|
|
97
121
|
pnpm check:docs-stats # root README stat badges
|
|
98
122
|
pnpm check:sdk-version-matrix # apps/docs/content/sdks/index.mdx versions
|
|
99
123
|
pnpm check:internal-doc-links # dead /foo links in MDX
|
|
124
|
+
pnpm check:onboarding-drift # phantom MCP env vars / stale tool names
|
|
100
125
|
pnpm check:bundle-docs # @mushi-mushi/web size-limit vs README
|
|
101
126
|
pnpm gen:llms-txt # regenerate apps/docs/public/llms.txt after nav changes
|
|
127
|
+
pnpm gen:mcp-tools-doc # regenerate sdks/mcp-tools.generated.mdx from catalog.ts
|
|
102
128
|
```
|
|
103
129
|
|
|
104
130
|
README changes on npm packages only appear on [npmjs.com](https://www.npmjs.com) after the next **Changesets publish**.
|
|
@@ -115,13 +141,30 @@ Select the affected packages, the semver bump type, and write a summary. The cha
|
|
|
115
141
|
|
|
116
142
|
## Release flow
|
|
117
143
|
|
|
118
|
-
Releases are fully automated. Maintainers don't run
|
|
144
|
+
Releases are fully automated once the version PR is merged. Maintainers don't run
|
|
145
|
+
`npm publish` by hand for routine bumps. See **[`docs/DEPLOYMENT.md`](docs/DEPLOYMENT.md)**
|
|
146
|
+
for the full production runbook (edge functions, admin SPA, docs site, migrations).
|
|
119
147
|
|
|
120
148
|
1. PRs land on `master` with one or more changeset files in `.changeset/`.
|
|
121
|
-
|
|
122
|
-
|
|
149
|
+
Orphaned changesets (only ignored packages) fail `pnpm check:changeset-orphans`.
|
|
150
|
+
2. `release.yml` runs on every push to `master`. It opens (or updates) a
|
|
151
|
+
**`chore: version packages`** PR on `changeset-release/master` that bumps
|
|
152
|
+
affected `package.json` files, rolls up changelogs, and deletes consumed
|
|
153
|
+
changesets.
|
|
154
|
+
3. **Wait for CI on the version PR.** If checks don't appear (bot-branch
|
|
155
|
+
suppression), push an empty commit to `changeset-release/master`. If
|
|
156
|
+
`check:sdk-version-matrix` fails, run `pnpm gen:sdk-version-matrix` on that
|
|
157
|
+
branch and commit `apps/docs/content/sdks/index.mdx`.
|
|
158
|
+
4. Merge the version PR. The publish step uses **OIDC Trusted Publishers** +
|
|
159
|
+
Sigstore provenance (with `NPM_TOKEN` only for brand-new package bootstrap).
|
|
160
|
+
5. **Manually dispatch Release** unless a run starts within ~2 minutes:
|
|
161
|
+
**Actions → Release → Run workflow → `master`**. Squash-merges attributed to
|
|
162
|
+
`github-actions[bot]` usually suppress the auto `push` trigger — manual
|
|
163
|
+
dispatch is the normal path, not a fallback of last resort.
|
|
123
164
|
|
|
124
|
-
|
|
165
|
+
```bash
|
|
166
|
+
gh workflow run release.yml --ref master
|
|
167
|
+
```
|
|
125
168
|
|
|
126
169
|
### Adding a brand-new publishable package
|
|
127
170
|
|
|
@@ -168,7 +211,7 @@ chore: bump dependencies
|
|
|
168
211
|
## License
|
|
169
212
|
|
|
170
213
|
- SDK packages are MIT — your contributions will be MIT-licensed
|
|
171
|
-
- Server/agents/verify are
|
|
214
|
+
- Server/agents/verify are AGPLv3 — contributions to those packages fall under AGPLv3. A [commercial license](./COMMERCIAL-LICENSE.md) is available for hosted-SaaS use cases that cannot publish modifications. The `packages/server/ee/` directory is source-available but commercial (production use needs a license); contributions there are accepted under the same EE terms.
|
|
172
215
|
|
|
173
216
|
## Questions?
|
|
174
217
|
|
package/README.md
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
# @mushi-mushi/mcp
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Your AI wrote it. Mushi tells you why it broke.**
|
|
4
4
|
|
|
5
|
-
[Model Context Protocol](https://spec.modelcontextprotocol.io/) server that wires Mushi
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
User feels a bug → Mushi captures it → AI triages → AI opens a PR
|
|
9
|
-
→ QA verifies → Judge scores → Lesson library remembers → next agent is smarter
|
|
10
|
-
```
|
|
5
|
+
[Model Context Protocol](https://spec.modelcontextprotocol.io/) server that wires Mushi into Cursor, Claude Code, and any MCP client. Pull fix context, run triage, and dispatch fixes without a second LLM vendor key.
|
|
11
6
|
|
|
12
7
|
Wire it into Cursor, Claude Code, or any MCP client in one command:
|
|
13
8
|
|
|
@@ -16,7 +11,7 @@ npx mushi-mushi setup --ide cursor
|
|
|
16
11
|
# or: npx mushi-mushi setup --ide claude
|
|
17
12
|
```
|
|
18
13
|
|
|
19
|
-
That command reads `~/.mushirc
|
|
14
|
+
That command reads CLI config at **`~/.config/mushi/config.json`** (legacy `~/.mushirc` auto-migrates), writes `.cursor/mcp.json` with the `mushi-<slug>` server block, and prints "Done — restart Cursor and ask: `list mushi tools`". No copy-pasting environment variables.
|
|
20
15
|
|
|
21
16
|
### Codebase Understand tools (indexed repos)
|
|
22
17
|
|
|
@@ -146,7 +141,7 @@ The Mushi backend now exposes the same tool catalog over the **Streamable HTTP**
|
|
|
146
141
|
|
|
147
142
|
### Feature groups (`?features=` / `MUSHI_FEATURES`)
|
|
148
143
|
|
|
149
|
-
Full catalog is **
|
|
144
|
+
Full catalog is **71 tools**. New installs default to a lean set via:
|
|
150
145
|
|
|
151
146
|
- **Stdio:** `MUSHI_FEATURES=triage,fixes,inventory,setup,docs`
|
|
152
147
|
- **HTTP:** `?features=triage,fixes,inventory,setup,docs` on the MCP URL
|
package/SECURITY.md
CHANGED
|
@@ -113,7 +113,7 @@ What we treat as in-scope attacker capabilities, and what we don't.
|
|
|
113
113
|
| Compromised Supabase service-role key | ❌ | Treated as a tier-0 incident; would require key rotation and audit-log forensics. Not defendable in software. |
|
|
114
114
|
| Compromise of `kensaurus@gmail.com` | ❌ | Treated as a project-fork event; downstream consumers should pin to the last known-good version and follow the new release channel. |
|
|
115
115
|
| Physical / OS-level attacker on an end-user device | ❌ | Out of scope. |
|
|
116
|
-
| Malicious fork using the Mushi name to ship malware | ❌ (technical) ✅ (legal) | The MIT/
|
|
116
|
+
| Malicious fork using the Mushi name to ship malware | ❌ (technical) ✅ (legal) | The MIT / AGPLv3 grant lets the fork exist; the trademark policy (`TRADEMARK.md`) makes shipping it under the Mushi name an infringement we will pursue. |
|
|
117
117
|
|
|
118
118
|
## Data handling and PII
|
|
119
119
|
|
package/dist/catalog.js
CHANGED
|
@@ -44,7 +44,7 @@ var TOOL_CATALOG = [
|
|
|
44
44
|
{
|
|
45
45
|
name: "get_fix_context",
|
|
46
46
|
title: "Fix context bundle",
|
|
47
|
-
description: "Bundle the full context an agent needs to fix a bug: report detail, reproduction steps, component, root cause, ontology tags. One call instead of several.",
|
|
47
|
+
description: "Bundle the full context an agent needs to fix a bug: a paste-ready fixPrompt (plain-English diagnosis + reproduction + suggested fix + relevant code + blast radius), plus report detail, reproduction steps, component, root cause, and ontology tags. One call instead of several. No second LLM key needed.",
|
|
48
48
|
scope: "mcp:read",
|
|
49
49
|
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
50
50
|
useCase: "Give me everything I need to fix this in one payload."
|
|
@@ -534,6 +534,15 @@ var TDD_TOOL_CATALOG = [
|
|
|
534
534
|
hints: { readOnly: false, destructive: false, idempotent: false, openWorld: true },
|
|
535
535
|
useCase: 'Did "Add to Slack" work? Send a test ping to confirm.'
|
|
536
536
|
},
|
|
537
|
+
// ── Billing / usage tools ─────────────────────────────────────────────────
|
|
538
|
+
{
|
|
539
|
+
name: "get_usage",
|
|
540
|
+
title: "Usage & billing summary",
|
|
541
|
+
description: 'Read-only diagnoses quota and billing summary for the current project: diagnoses used / limit / percentage, spend cap, period start/end, plan name, and whether the project is approaching or over its quota. Use this to answer "how many diagnoses do I have left?" or "am I close to my spend cap?".',
|
|
542
|
+
scope: "mcp:read",
|
|
543
|
+
hints: { readOnly: true, idempotent: true, openWorld: false },
|
|
544
|
+
useCase: "How many diagnoses do I have left this month?"
|
|
545
|
+
},
|
|
537
546
|
// ── Skill Pipeline tools ─────────────────────────────────────────────────────
|
|
538
547
|
{
|
|
539
548
|
name: "list_skills",
|
|
@@ -10,6 +10,7 @@ var FEATURE_GROUPS = [
|
|
|
10
10
|
"admin",
|
|
11
11
|
"audit",
|
|
12
12
|
"docs",
|
|
13
|
+
"usage",
|
|
13
14
|
/** Deprecated aliases kept for one release — hidden unless `legacy` or `all`. */
|
|
14
15
|
"legacy"
|
|
15
16
|
];
|
|
@@ -82,6 +83,8 @@ var TOOL_FEATURE_MAP = {
|
|
|
82
83
|
project_settings: "admin",
|
|
83
84
|
privacy_status: "admin",
|
|
84
85
|
evolution_history: "admin",
|
|
86
|
+
// usage / billing
|
|
87
|
+
get_usage: "usage",
|
|
85
88
|
// qa / tdd
|
|
86
89
|
map_user_stories: "qa",
|
|
87
90
|
get_map_run_status: "qa",
|
package/dist/feature-groups.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* When `features` is omitted → all tools (backward compatible).
|
|
5
5
|
* New installs default to DEFAULT_FEATURE_GROUPS via deeplink / docs.
|
|
6
6
|
*/
|
|
7
|
-
declare const FEATURE_GROUPS: readonly ["triage", "fixes", "inventory", "setup", "qa", "skills", "rewards", "admin", "audit", "docs", "legacy"];
|
|
7
|
+
declare const FEATURE_GROUPS: readonly ["triage", "fixes", "inventory", "setup", "qa", "skills", "rewards", "admin", "audit", "docs", "usage", "legacy"];
|
|
8
8
|
type FeatureGroup = (typeof FEATURE_GROUPS)[number];
|
|
9
9
|
/** Lean default for new Cursor installs (~45 tools vs 70 full). */
|
|
10
10
|
declare const DEFAULT_FEATURE_GROUPS: readonly FeatureGroup[];
|
package/dist/feature-groups.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -51,7 +51,7 @@ var TOOL_CATALOG = [
|
|
|
51
51
|
{
|
|
52
52
|
name: "get_fix_context",
|
|
53
53
|
title: "Fix context bundle",
|
|
54
|
-
description: "Bundle the full context an agent needs to fix a bug: report detail, reproduction steps, component, root cause, ontology tags. One call instead of several.",
|
|
54
|
+
description: "Bundle the full context an agent needs to fix a bug: a paste-ready fixPrompt (plain-English diagnosis + reproduction + suggested fix + relevant code + blast radius), plus report detail, reproduction steps, component, root cause, and ontology tags. One call instead of several. No second LLM key needed.",
|
|
55
55
|
scope: "mcp:read",
|
|
56
56
|
hints: { readOnly: true, idempotent: true, openWorld: true },
|
|
57
57
|
useCase: "Give me everything I need to fix this in one payload."
|
|
@@ -457,6 +457,15 @@ var TDD_TOOL_CATALOG = [
|
|
|
457
457
|
hints: { readOnly: false, destructive: false, idempotent: false, openWorld: true },
|
|
458
458
|
useCase: 'Did "Add to Slack" work? Send a test ping to confirm.'
|
|
459
459
|
},
|
|
460
|
+
// ── Billing / usage tools ─────────────────────────────────────────────────
|
|
461
|
+
{
|
|
462
|
+
name: "get_usage",
|
|
463
|
+
title: "Usage & billing summary",
|
|
464
|
+
description: 'Read-only diagnoses quota and billing summary for the current project: diagnoses used / limit / percentage, spend cap, period start/end, plan name, and whether the project is approaching or over its quota. Use this to answer "how many diagnoses do I have left?" or "am I close to my spend cap?".',
|
|
465
|
+
scope: "mcp:read",
|
|
466
|
+
hints: { readOnly: true, idempotent: true, openWorld: false },
|
|
467
|
+
useCase: "How many diagnoses do I have left this month?"
|
|
468
|
+
},
|
|
460
469
|
// ── Skill Pipeline tools ─────────────────────────────────────────────────────
|
|
461
470
|
{
|
|
462
471
|
name: "list_skills",
|
|
@@ -603,6 +612,7 @@ var FEATURE_GROUPS = [
|
|
|
603
612
|
"admin",
|
|
604
613
|
"audit",
|
|
605
614
|
"docs",
|
|
615
|
+
"usage",
|
|
606
616
|
/** Deprecated aliases kept for one release — hidden unless `legacy` or `all`. */
|
|
607
617
|
"legacy"
|
|
608
618
|
];
|
|
@@ -668,6 +678,8 @@ var TOOL_FEATURE_MAP = {
|
|
|
668
678
|
project_settings: "admin",
|
|
669
679
|
privacy_status: "admin",
|
|
670
680
|
evolution_history: "admin",
|
|
681
|
+
// usage / billing
|
|
682
|
+
get_usage: "usage",
|
|
671
683
|
// qa / tdd
|
|
672
684
|
map_user_stories: "qa",
|
|
673
685
|
get_map_run_status: "qa",
|
|
@@ -1131,6 +1143,7 @@ function createMushiServer(config) {
|
|
|
1131
1143
|
inputSchema: { reportId: z.string().describe("The report UUID to fix") },
|
|
1132
1144
|
outputSchema: {
|
|
1133
1145
|
report: z.unknown(),
|
|
1146
|
+
fixPrompt: z.unknown(),
|
|
1134
1147
|
reproductionSteps: z.unknown(),
|
|
1135
1148
|
component: z.unknown(),
|
|
1136
1149
|
rootCause: z.unknown(),
|
|
@@ -1141,6 +1154,10 @@ function createMushiServer(config) {
|
|
|
1141
1154
|
const report = await apiCall(`/v1/admin/reports/${args.reportId}`);
|
|
1142
1155
|
return jsonResult({
|
|
1143
1156
|
report,
|
|
1157
|
+
// Paste-ready fix prompt composed server-side by composeFixPacket()
|
|
1158
|
+
// (diagnosis + repro + suggested fix + relevant code + blast radius).
|
|
1159
|
+
// Hand this straight to the editing agent — no second LLM key needed.
|
|
1160
|
+
fixPrompt: report.fix_packet ?? null,
|
|
1144
1161
|
reproductionSteps: report.reproduction_steps ?? [],
|
|
1145
1162
|
component: report.component,
|
|
1146
1163
|
rootCause: report.stage2_analysis?.rootCause,
|
|
@@ -2694,6 +2711,23 @@ Be specific. No generic advice.`
|
|
|
2694
2711
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
2695
2712
|
}
|
|
2696
2713
|
);
|
|
2714
|
+
server.registerTool(
|
|
2715
|
+
"get_usage",
|
|
2716
|
+
{
|
|
2717
|
+
title: titleOf("get_usage"),
|
|
2718
|
+
description: descOf("get_usage"),
|
|
2719
|
+
annotations: annotationsFor("get_usage"),
|
|
2720
|
+
inputSchema: {
|
|
2721
|
+
project_id: z.string().optional().describe("Project ID. Defaults to the configured project.")
|
|
2722
|
+
}
|
|
2723
|
+
},
|
|
2724
|
+
async ({ project_id }) => {
|
|
2725
|
+
const pid = project_id ?? config.projectId;
|
|
2726
|
+
const path = pid ? `/v1/admin/billing/stats?project_id=${pid}` : "/v1/admin/billing/stats";
|
|
2727
|
+
const data = await apiCall(path);
|
|
2728
|
+
return jsonText(data);
|
|
2729
|
+
}
|
|
2730
|
+
);
|
|
2697
2731
|
server.registerTool(
|
|
2698
2732
|
"list_skills",
|
|
2699
2733
|
{
|
|
@@ -3015,6 +3049,32 @@ Be specific. No generic advice.`
|
|
|
3015
3049
|
}
|
|
3016
3050
|
}
|
|
3017
3051
|
}
|
|
3052
|
+
const _nativeFetch = globalThis.fetch;
|
|
3053
|
+
let _firstToolCallSignalled = false;
|
|
3054
|
+
const _signalFirstToolCall = () => {
|
|
3055
|
+
if (_firstToolCallSignalled || !projectId) return;
|
|
3056
|
+
_firstToolCallSignalled = true;
|
|
3057
|
+
void _nativeFetch(`${apiEndpoint}/v1/cli/funnel`, {
|
|
3058
|
+
method: "POST",
|
|
3059
|
+
headers: {
|
|
3060
|
+
"Content-Type": "application/json",
|
|
3061
|
+
"X-Mushi-Api-Key": apiKey,
|
|
3062
|
+
"X-Mushi-Project": projectId
|
|
3063
|
+
},
|
|
3064
|
+
body: JSON.stringify({ event: "mcp_first_tool_call" }),
|
|
3065
|
+
signal: AbortSignal.timeout(4e3)
|
|
3066
|
+
}).catch(() => {
|
|
3067
|
+
});
|
|
3068
|
+
};
|
|
3069
|
+
const llServer = server.server;
|
|
3070
|
+
const existingToolsCallHandler = llServer?._requestHandlers?.get("tools/call");
|
|
3071
|
+
if (typeof existingToolsCallHandler === "function") {
|
|
3072
|
+
llServer._requestHandlers.set("tools/call", async (...args) => {
|
|
3073
|
+
const result = await existingToolsCallHandler(...args);
|
|
3074
|
+
_signalFirstToolCall();
|
|
3075
|
+
return result;
|
|
3076
|
+
});
|
|
3077
|
+
}
|
|
3018
3078
|
return server;
|
|
3019
3079
|
}
|
|
3020
3080
|
|
package/dist/server.js
CHANGED
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
CODEBASE_TOOL_CATALOG,
|
|
3
3
|
TDD_TOOL_CATALOG,
|
|
4
4
|
TOOL_CATALOG
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MM3IMFM4.js";
|
|
6
6
|
import {
|
|
7
7
|
MUSHI_SERVER_METADATA
|
|
8
8
|
} from "./chunk-EHB2BGWX.js";
|
|
9
9
|
import {
|
|
10
10
|
toolMatchesFeatures
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZX3XIJ7S.js";
|
|
12
12
|
|
|
13
13
|
// src/server.ts
|
|
14
14
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -409,6 +409,7 @@ function createMushiServer(config) {
|
|
|
409
409
|
inputSchema: { reportId: z.string().describe("The report UUID to fix") },
|
|
410
410
|
outputSchema: {
|
|
411
411
|
report: z.unknown(),
|
|
412
|
+
fixPrompt: z.unknown(),
|
|
412
413
|
reproductionSteps: z.unknown(),
|
|
413
414
|
component: z.unknown(),
|
|
414
415
|
rootCause: z.unknown(),
|
|
@@ -419,6 +420,10 @@ function createMushiServer(config) {
|
|
|
419
420
|
const report = await apiCall(`/v1/admin/reports/${args.reportId}`);
|
|
420
421
|
return jsonResult({
|
|
421
422
|
report,
|
|
423
|
+
// Paste-ready fix prompt composed server-side by composeFixPacket()
|
|
424
|
+
// (diagnosis + repro + suggested fix + relevant code + blast radius).
|
|
425
|
+
// Hand this straight to the editing agent — no second LLM key needed.
|
|
426
|
+
fixPrompt: report.fix_packet ?? null,
|
|
422
427
|
reproductionSteps: report.reproduction_steps ?? [],
|
|
423
428
|
component: report.component,
|
|
424
429
|
rootCause: report.stage2_analysis?.rootCause,
|
|
@@ -1972,6 +1977,23 @@ Be specific. No generic advice.`
|
|
|
1972
1977
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1973
1978
|
}
|
|
1974
1979
|
);
|
|
1980
|
+
server.registerTool(
|
|
1981
|
+
"get_usage",
|
|
1982
|
+
{
|
|
1983
|
+
title: titleOf("get_usage"),
|
|
1984
|
+
description: descOf("get_usage"),
|
|
1985
|
+
annotations: annotationsFor("get_usage"),
|
|
1986
|
+
inputSchema: {
|
|
1987
|
+
project_id: z.string().optional().describe("Project ID. Defaults to the configured project.")
|
|
1988
|
+
}
|
|
1989
|
+
},
|
|
1990
|
+
async ({ project_id }) => {
|
|
1991
|
+
const pid = project_id ?? config.projectId;
|
|
1992
|
+
const path = pid ? `/v1/admin/billing/stats?project_id=${pid}` : "/v1/admin/billing/stats";
|
|
1993
|
+
const data = await apiCall(path);
|
|
1994
|
+
return jsonText(data);
|
|
1995
|
+
}
|
|
1996
|
+
);
|
|
1975
1997
|
server.registerTool(
|
|
1976
1998
|
"list_skills",
|
|
1977
1999
|
{
|
|
@@ -2293,6 +2315,32 @@ Be specific. No generic advice.`
|
|
|
2293
2315
|
}
|
|
2294
2316
|
}
|
|
2295
2317
|
}
|
|
2318
|
+
const _nativeFetch = globalThis.fetch;
|
|
2319
|
+
let _firstToolCallSignalled = false;
|
|
2320
|
+
const _signalFirstToolCall = () => {
|
|
2321
|
+
if (_firstToolCallSignalled || !projectId) return;
|
|
2322
|
+
_firstToolCallSignalled = true;
|
|
2323
|
+
void _nativeFetch(`${apiEndpoint}/v1/cli/funnel`, {
|
|
2324
|
+
method: "POST",
|
|
2325
|
+
headers: {
|
|
2326
|
+
"Content-Type": "application/json",
|
|
2327
|
+
"X-Mushi-Api-Key": apiKey,
|
|
2328
|
+
"X-Mushi-Project": projectId
|
|
2329
|
+
},
|
|
2330
|
+
body: JSON.stringify({ event: "mcp_first_tool_call" }),
|
|
2331
|
+
signal: AbortSignal.timeout(4e3)
|
|
2332
|
+
}).catch(() => {
|
|
2333
|
+
});
|
|
2334
|
+
};
|
|
2335
|
+
const llServer = server.server;
|
|
2336
|
+
const existingToolsCallHandler = llServer?._requestHandlers?.get("tools/call");
|
|
2337
|
+
if (typeof existingToolsCallHandler === "function") {
|
|
2338
|
+
llServer._requestHandlers.set("tools/call", async (...args) => {
|
|
2339
|
+
const result = await existingToolsCallHandler(...args);
|
|
2340
|
+
_signalFirstToolCall();
|
|
2341
|
+
return result;
|
|
2342
|
+
});
|
|
2343
|
+
}
|
|
2296
2344
|
return server;
|
|
2297
2345
|
}
|
|
2298
2346
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mushi-mushi/mcp",
|
|
3
|
-
"
|
|
3
|
+
"mcpName": "io.github.kensaurus/mushi-mushi",
|
|
4
|
+
"version": "0.16.2",
|
|
4
5
|
"license": "MIT",
|
|
5
6
|
"description": "MCP server for Mushi Mushi — triage user-felt bugs, pull evidence (screenshots, console logs, network requests), check blast radius, and dispatch fix PRs, all from your AI coding agent",
|
|
6
7
|
"type": "module",
|
|
@@ -41,15 +42,15 @@
|
|
|
41
42
|
],
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
44
|
-
"zod": "^4.4.
|
|
45
|
-
"@mushi-mushi/core": "^1.
|
|
45
|
+
"zod": "^4.4.3",
|
|
46
|
+
"@mushi-mushi/core": "^1.20.0"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"@types/node": "^22.19.
|
|
49
|
-
"eslint": "^10.
|
|
49
|
+
"@types/node": "^22.19.21",
|
|
50
|
+
"eslint": "^10.4.1",
|
|
50
51
|
"tsup": "^8.5.1",
|
|
51
52
|
"typescript": "^6.0.3",
|
|
52
|
-
"vitest": "^4.1.
|
|
53
|
+
"vitest": "^4.1.8",
|
|
53
54
|
"@mushi-mushi/eslint-config": "0.0.0"
|
|
54
55
|
},
|
|
55
56
|
"repository": {
|
|
@@ -57,8 +58,8 @@
|
|
|
57
58
|
"url": "https://github.com/kensaurus/mushi-mushi.git",
|
|
58
59
|
"directory": "packages/mcp"
|
|
59
60
|
},
|
|
60
|
-
"author": "Kenji Sakuramoto",
|
|
61
|
-
"homepage": "https://
|
|
61
|
+
"author": "Kenji Sakuramoto (https://bsky.app/profile/mushimushi.dev)",
|
|
62
|
+
"homepage": "https://kensaur.us/mushi-mushi",
|
|
62
63
|
"bugs": {
|
|
63
64
|
"url": "https://github.com/kensaurus/mushi-mushi/issues"
|
|
64
65
|
},
|
|
@@ -93,6 +94,10 @@
|
|
|
93
94
|
"engines": {
|
|
94
95
|
"node": ">=20"
|
|
95
96
|
},
|
|
97
|
+
"funding": {
|
|
98
|
+
"type": "github",
|
|
99
|
+
"url": "https://github.com/sponsors/kensaurus"
|
|
100
|
+
},
|
|
96
101
|
"scripts": {
|
|
97
102
|
"build": "tsup",
|
|
98
103
|
"clean:types": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|