mcp-walkthrough 0.2.0 → 0.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/README.md +67 -29
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +27 -15
- package/dist/bridge.js.map +1 -1
- package/dist/code-cli.d.ts +4 -0
- package/dist/code-cli.d.ts.map +1 -0
- package/dist/code-cli.js +86 -0
- package/dist/code-cli.js.map +1 -0
- package/dist/index.js +231 -13
- package/dist/index.js.map +1 -1
- package/dist/tts.d.ts +14 -0
- package/dist/tts.d.ts.map +1 -0
- package/dist/tts.js +182 -0
- package/dist/tts.js.map +1 -0
- package/package.json +4 -2
- package/scripts/postinstall.cjs +98 -0
- package/vscode-extension/walkthrough-bridge.vsix +0 -0
package/README.md
CHANGED
|
@@ -5,21 +5,24 @@
|
|
|
5
5
|
|
|
6
6
|
# MCP Walkthrough
|
|
7
7
|
|
|
8
|
-
An MCP server for interactive code walkthroughs. Claude drives the narrative — opens files, highlights code,
|
|
8
|
+
An MCP server for interactive code walkthroughs with voice narration. Claude drives the narrative — opens files, highlights code, explains inline, and reads each step aloud using neural text-to-speech.
|
|
9
9
|
|
|
10
10
|
## Overview
|
|
11
11
|
|
|
12
|
-
Text in a terminal isn't enough when you want Claude to explain a solution. MCP Walkthrough lets Claude open files in VS Code, highlight specific lines,
|
|
12
|
+
Text in a terminal isn't enough when you want Claude to explain a solution. MCP Walkthrough lets Claude open files in VS Code, highlight specific lines, show rich markdown explanations, and **narrate each step with a natural-sounding voice**. Navigate at your own pace — forward, back, pause, or let the voice guide you.
|
|
13
13
|
|
|
14
14
|
**Key Features:**
|
|
15
|
+
- **Voice Narration** — Neural text-to-speech reads each step aloud (400+ voices via Microsoft Edge TTS)
|
|
15
16
|
- **Inline Explanations** — Markdown comment bubbles appear right next to highlighted code
|
|
16
|
-
- **Multi-Step Walkthroughs** — Claude sends all steps at once,
|
|
17
|
-
- **
|
|
17
|
+
- **Multi-Step Walkthroughs** — Claude sends all steps at once, voice auto-advances through them
|
|
18
|
+
- **Live Controls** — Pause, resume, skip, stop, toggle voice/bubbles on the fly
|
|
19
|
+
- **Voice Selection** — Choose your narrator, audition voices, preference persisted across sessions
|
|
18
20
|
- **Keyboard Navigation** — `Cmd+Shift+Right` / `Cmd+Shift+Left` to navigate steps
|
|
19
21
|
- **Selection Reading** — Claude can see what you've highlighted to discuss it further
|
|
20
22
|
- **Focus Preservation** — Opens files without stealing focus from your terminal
|
|
23
|
+
- **Offline Fallback** — Falls back to native TTS (`say`/`espeak`) when offline
|
|
21
24
|
|
|
22
|
-
> **Note:** This MCP server requires VS Code. It includes a companion VS Code extension that is automatically installed when you `npm install`.
|
|
25
|
+
> **Note:** This MCP server requires VS Code, VS Code Insiders, or Cursor. It includes a companion VS Code extension that is automatically installed when you `npm install`. The CLI is auto-discovered even if `code` is not in your PATH.
|
|
23
26
|
|
|
24
27
|
## Installation
|
|
25
28
|
|
|
@@ -78,24 +81,25 @@ MCP tools are deferred (loaded on-demand), so Claude may not use them automatica
|
|
|
78
81
|
```markdown
|
|
79
82
|
## Walkthrough MCP
|
|
80
83
|
|
|
81
|
-
You have access to walkthrough tools via MCP. Use them to visually walk the user through code — open files, highlight lines,
|
|
84
|
+
You have access to walkthrough tools via MCP. Use them to visually walk the user through code with voice narration — open files, highlight lines, show inline explanations, and read each step aloud in VS Code.
|
|
82
85
|
```
|
|
83
86
|
|
|
84
87
|
## Available Tools
|
|
85
88
|
|
|
86
89
|
| Tool | Description |
|
|
87
90
|
|------|-------------|
|
|
91
|
+
| **walkthrough** | Start a voiced, multi-step code walkthrough |
|
|
92
|
+
| **walkthrough_control** | Pause, resume, next, prev, stop, toggle voice/bubbles |
|
|
93
|
+
| **walkthrough_voice** | Change narrator voice, audition voices, list available |
|
|
94
|
+
| **walkthrough_status** | Get current walkthrough state |
|
|
88
95
|
| **show_code** | Open a file and highlight specific lines |
|
|
89
|
-
| **explain_code** | Highlight lines + show
|
|
96
|
+
| **explain_code** | Highlight lines + show explanation bubble (+ voice if enabled) |
|
|
90
97
|
| **clear_explanations** | Remove all explanation bubbles |
|
|
91
|
-
| **walkthrough** | Start a multi-step walkthrough with all steps at once |
|
|
92
|
-
| **walkthrough_navigate** | Navigate an active walkthrough (next/prev/goto) |
|
|
93
|
-
| **walkthrough_status** | Get current walkthrough state |
|
|
94
98
|
| **get_selection** | Read the currently highlighted code in VS Code |
|
|
95
99
|
|
|
96
100
|
### walkthrough
|
|
97
101
|
|
|
98
|
-
The main tool. Claude generates all steps and sends them at once.
|
|
102
|
+
The main tool. Claude generates all steps and sends them at once. Voice narration and explanation bubbles are on by default. Returns immediately — narration runs in the background.
|
|
99
103
|
|
|
100
104
|
```json
|
|
101
105
|
{
|
|
@@ -104,42 +108,63 @@ The main tool. Claude generates all steps and sends them at once. The VS Code ex
|
|
|
104
108
|
"file": "/absolute/path/to/file.ts",
|
|
105
109
|
"line": 10,
|
|
106
110
|
"endLine": 25,
|
|
107
|
-
"explanation": "This validates the JWT token on every request
|
|
111
|
+
"explanation": "This validates the JWT token on every request. The secret is loaded from environment variables.",
|
|
108
112
|
"title": "Token Validation"
|
|
109
113
|
}
|
|
110
114
|
],
|
|
111
|
-
"
|
|
112
|
-
"
|
|
115
|
+
"voice": true,
|
|
116
|
+
"showBubbles": true
|
|
113
117
|
}
|
|
114
118
|
```
|
|
115
119
|
|
|
116
120
|
**Parameters:**
|
|
117
121
|
- `steps` — Array of `{ file, line, endLine?, explanation, title? }`
|
|
118
|
-
- `
|
|
119
|
-
- `
|
|
122
|
+
- `voice` — Enable voice narration (default: `true`)
|
|
123
|
+
- `showBubbles` — Show inline explanation bubbles (default: `true`)
|
|
124
|
+
|
|
125
|
+
Write explanations as **natural spoken language** — markdown is stripped before narration.
|
|
120
126
|
|
|
121
|
-
###
|
|
127
|
+
### walkthrough_control
|
|
128
|
+
|
|
129
|
+
Control an active walkthrough on the fly:
|
|
122
130
|
|
|
123
131
|
```json
|
|
124
132
|
{ "action": "next" }
|
|
125
133
|
{ "action": "prev" }
|
|
126
|
-
{ "action": "
|
|
134
|
+
{ "action": "pause" }
|
|
135
|
+
{ "action": "resume" }
|
|
136
|
+
{ "action": "stop" }
|
|
137
|
+
{ "voice": false }
|
|
138
|
+
{ "showBubbles": false }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### walkthrough_voice
|
|
142
|
+
|
|
143
|
+
Change the narrator voice. Speaks a sample so you hear the difference. Persisted across sessions.
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{ "voice": "en-US-GuyNeural" }
|
|
147
|
+
{ "list": true, "locale": "en-US" }
|
|
148
|
+
{ "audition": true, "locale": "en-US", "gender": "Female" }
|
|
127
149
|
```
|
|
128
150
|
|
|
151
|
+
Popular voices: `en-US-AriaNeural`, `en-US-MichelleNeural`, `en-US-AndrewNeural`, `en-US-GuyNeural`
|
|
152
|
+
|
|
129
153
|
### Keyboard Shortcuts
|
|
130
154
|
|
|
131
|
-
During an active walkthrough:
|
|
132
|
-
- **Cmd+Shift+Right** — Next step
|
|
133
|
-
- **Cmd+Shift+Left** — Previous step
|
|
155
|
+
During an active walkthrough (shown in the explanation bubble):
|
|
156
|
+
- **Cmd+Shift+Right** (macOS) / **Ctrl+Shift+Right** (Linux/Windows) — Next step
|
|
157
|
+
- **Cmd+Shift+Left** (macOS) / **Ctrl+Shift+Left** (Linux/Windows) — Previous step
|
|
134
158
|
- **Status bar** — Shows current step, click to stop
|
|
135
159
|
|
|
136
160
|
### Writing Explanations
|
|
137
161
|
|
|
138
|
-
Explanations render as markdown in VS Code comment bubbles. Tips:
|
|
162
|
+
Explanations render as markdown in VS Code comment bubbles and are also narrated as speech. Tips:
|
|
139
163
|
|
|
164
|
+
- **Write as natural speech** — the voice reads it aloud, so avoid heavy markdown
|
|
140
165
|
- **Use actual newlines** for paragraphs, not `\n` escape sequences
|
|
141
|
-
- **Avoid `##` headers** — they render
|
|
142
|
-
- Inline code
|
|
166
|
+
- **Avoid `##` headers** — they render too large in the comment bubble. Use **bold** instead
|
|
167
|
+
- Inline code, code blocks, lists, and links all work in bubbles
|
|
143
168
|
|
|
144
169
|
## How It Works
|
|
145
170
|
|
|
@@ -153,7 +178,7 @@ Claude Code → MCP Server (stdio) → Unix socket → VS Code Extension
|
|
|
153
178
|
4. Each VS Code window gets its own socket — multiple windows work independently
|
|
154
179
|
5. Focus stays in your terminal — code appears in the editor beside it
|
|
155
180
|
|
|
156
|
-
The VS Code extension is bundled with the npm package and automatically installed on first
|
|
181
|
+
The VS Code extension is bundled with the npm package and automatically installed on `npm install` and on first server start. The CLI is auto-discovered across VS Code, VS Code Insiders, and Cursor on all platforms.
|
|
157
182
|
|
|
158
183
|
## Development
|
|
159
184
|
|
|
@@ -164,16 +189,23 @@ mcp-walkthrough/
|
|
|
164
189
|
├── src/
|
|
165
190
|
│ ├── index.ts # MCP server entry point, tool registration
|
|
166
191
|
│ ├── bridge.ts # Unix socket client to VS Code extension
|
|
192
|
+
│ ├── code-cli.ts # Cross-platform VS Code CLI discovery
|
|
193
|
+
│ ├── tts.ts # Text-to-speech (Edge TTS + native fallback)
|
|
167
194
|
│ ├── socket.ts # Socket path computation and discovery
|
|
168
195
|
│ └── utils/
|
|
169
196
|
│ └── logger.ts # Pino logger (stderr only)
|
|
197
|
+
├── scripts/
|
|
198
|
+
│ └── postinstall.cjs # Auto-installs extension on npm install
|
|
170
199
|
├── vscode-extension/
|
|
171
200
|
│ ├── src/
|
|
172
201
|
│ │ └── extension.ts # VS Code extension (HTTP server, Comments API)
|
|
173
202
|
│ └── package.json
|
|
174
203
|
├── tests/
|
|
175
204
|
│ ├── bridge.test.ts
|
|
176
|
-
│
|
|
205
|
+
│ ├── code-cli.test.ts
|
|
206
|
+
│ ├── postinstall.test.ts
|
|
207
|
+
│ ├── socket.test.ts
|
|
208
|
+
│ └── tts.test.ts
|
|
177
209
|
└── docs/
|
|
178
210
|
```
|
|
179
211
|
|
|
@@ -207,10 +239,16 @@ The MCP server discovers the VS Code extension via a Unix socket. If the socket
|
|
|
207
239
|
|
|
208
240
|
### Extension not installed
|
|
209
241
|
|
|
210
|
-
The MCP server auto-
|
|
242
|
+
The MCP server auto-discovers VS Code, VS Code Insiders, and Cursor CLIs — even when `code` isn't in your PATH. It searches:
|
|
243
|
+
|
|
244
|
+
- **macOS**: `/Applications/*.app/Contents/Resources/app/bin/`
|
|
245
|
+
- **Linux**: `/usr/bin/`, `/usr/local/bin/`, `/snap/bin/`, `/opt/*/bin/`
|
|
246
|
+
- **Windows**: `%LOCALAPPDATA%\Programs\*\bin\`
|
|
247
|
+
|
|
248
|
+
The extension is installed into **all** found editors. If auto-install still fails:
|
|
211
249
|
|
|
212
|
-
1.
|
|
213
|
-
2.
|
|
250
|
+
1. Manually install: `code --install-extension path/to/walkthrough-bridge.vsix`
|
|
251
|
+
2. Or reload the VS Code window after installing the npm package
|
|
214
252
|
|
|
215
253
|
## Contributing
|
|
216
254
|
|
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAkBA,wBAAgB,wBAAwB,IAAI,IAAI,CAoC/C;AAED,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5C,eAAO,IAAI,eAAe,EAAE,OAAO,GAAG,IAAW,CAAC;AAGlD,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAGD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjD;AA+DD,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAKpD;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAUvB;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,YAAY,CAAC,CAE/D;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,CAAC,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAElE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,CAE1D"}
|
package/dist/bridge.js
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync } from "node:fs";
|
|
|
3
3
|
import * as http from "node:http";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { resolveAllCodeClis } from "./code-cli.js";
|
|
6
7
|
import { discoverSocket } from "./socket.js";
|
|
7
8
|
import { logger } from "./utils/logger.js";
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -10,26 +11,37 @@ const __dirname = dirname(__filename);
|
|
|
10
11
|
const EXTENSION_ID = "undefined_publisher.walkthrough-bridge";
|
|
11
12
|
const VSIX_PATH = join(__dirname, "../vscode-extension/walkthrough-bridge.vsix");
|
|
12
13
|
export function ensureExtensionInstalled() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
logger.warn("Could not check installed extensions");
|
|
14
|
+
const clis = resolveAllCodeClis();
|
|
15
|
+
if (clis.length === 0) {
|
|
16
|
+
logger.warn("Could not find VS Code CLI (code, code-insiders, or cursor). Install one or add it to PATH.");
|
|
17
|
+
return;
|
|
22
18
|
}
|
|
23
19
|
if (!existsSync(VSIX_PATH)) {
|
|
24
20
|
logger.error({ path: VSIX_PATH }, "Extension .vsix not found");
|
|
25
21
|
return;
|
|
26
22
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
for (const cli of clis) {
|
|
24
|
+
try {
|
|
25
|
+
const installed = execSync(`"${cli}" --list-extensions`, {
|
|
26
|
+
encoding: "utf-8",
|
|
27
|
+
});
|
|
28
|
+
if (installed.includes(EXTENSION_ID)) {
|
|
29
|
+
logger.info({ cli }, "Walkthrough bridge extension already installed");
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
logger.warn({ cli }, "Could not check installed extensions");
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
execSync(`"${cli}" --install-extension "${VSIX_PATH}"`, {
|
|
38
|
+
encoding: "utf-8",
|
|
39
|
+
});
|
|
40
|
+
logger.info({ cli }, "Installed walkthrough bridge extension");
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
logger.error({ cli, err: error }, "Failed to install extension");
|
|
44
|
+
}
|
|
33
45
|
}
|
|
34
46
|
}
|
|
35
47
|
export let bridgeAvailable = null;
|
package/dist/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,YAAY,GAAG,wCAAwC,CAAC;AAC9D,MAAM,SAAS,GAAG,IAAI,CACpB,SAAS,EACT,6CAA6C,CAC9C,CAAC;AAEF,MAAM,UAAU,wBAAwB;IACtC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function _findAllCodeClis(platform: NodeJS.Platform, findInPath: (name: string) => string | null, fileExists: (path: string) => boolean, listDir: (path: string) => string[], localAppData?: string): string[];
|
|
2
|
+
export declare function resolveAllCodeClis(): string[];
|
|
3
|
+
export declare function resetCodeCliCache(): void;
|
|
4
|
+
//# sourceMappingURL=code-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-cli.d.ts","sourceRoot":"","sources":["../src/code-cli.ts"],"names":[],"mappings":"AAkBA,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,EAC3C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,EACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,EACnC,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,EAAE,CAiEV;AAgBD,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAS7C;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
package/dist/code-cli.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
const CLI_NAMES = ["code", "code-insiders", "cursor"];
|
|
6
|
+
function safeListDir(listDir, path) {
|
|
7
|
+
try {
|
|
8
|
+
return listDir(path);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function _findAllCodeClis(platform, findInPath, fileExists, listDir, localAppData) {
|
|
15
|
+
const found = [];
|
|
16
|
+
for (const name of CLI_NAMES) {
|
|
17
|
+
const p = findInPath(name);
|
|
18
|
+
if (p)
|
|
19
|
+
found.push(p);
|
|
20
|
+
}
|
|
21
|
+
if (platform === "darwin") {
|
|
22
|
+
for (const entry of safeListDir(listDir, "/Applications")) {
|
|
23
|
+
if (!entry.endsWith(".app"))
|
|
24
|
+
continue;
|
|
25
|
+
for (const name of CLI_NAMES) {
|
|
26
|
+
const bin = join("/Applications", entry, "Contents", "Resources", "app", "bin", name);
|
|
27
|
+
if (fileExists(bin))
|
|
28
|
+
found.push(bin);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (platform === "linux") {
|
|
33
|
+
for (const dir of ["/usr/bin", "/usr/local/bin", "/snap/bin"]) {
|
|
34
|
+
for (const name of CLI_NAMES) {
|
|
35
|
+
const bin = join(dir, name);
|
|
36
|
+
if (fileExists(bin))
|
|
37
|
+
found.push(bin);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const entry of safeListDir(listDir, "/opt")) {
|
|
41
|
+
for (const name of CLI_NAMES) {
|
|
42
|
+
const bin = join("/opt", entry, "bin", name);
|
|
43
|
+
if (fileExists(bin))
|
|
44
|
+
found.push(bin);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (platform === "win32") {
|
|
49
|
+
const appData = localAppData ||
|
|
50
|
+
process.env.LOCALAPPDATA ||
|
|
51
|
+
join(homedir(), "AppData", "Local");
|
|
52
|
+
const programsDir = join(appData, "Programs");
|
|
53
|
+
for (const entry of safeListDir(listDir, programsDir)) {
|
|
54
|
+
for (const name of CLI_NAMES) {
|
|
55
|
+
const std = join(programsDir, entry, "bin", `${name}.cmd`);
|
|
56
|
+
if (fileExists(std))
|
|
57
|
+
found.push(std);
|
|
58
|
+
const electron = join(programsDir, entry, "resources", "app", "bin", `${name}.cmd`);
|
|
59
|
+
if (fileExists(electron))
|
|
60
|
+
found.push(electron);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return [...new Set(found)];
|
|
65
|
+
}
|
|
66
|
+
function defaultFindInPath(name) {
|
|
67
|
+
try {
|
|
68
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
69
|
+
return (execSync(`${cmd} ${name}`, { encoding: "utf-8", stdio: "pipe" }).trim() ||
|
|
70
|
+
null);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
let cached;
|
|
77
|
+
export function resolveAllCodeClis() {
|
|
78
|
+
if (cached !== undefined)
|
|
79
|
+
return cached;
|
|
80
|
+
cached = _findAllCodeClis(process.platform, defaultFindInPath, existsSync, (p) => readdirSync(p));
|
|
81
|
+
return cached;
|
|
82
|
+
}
|
|
83
|
+
export function resetCodeCliCache() {
|
|
84
|
+
cached = undefined;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=code-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-cli.js","sourceRoot":"","sources":["../src/code-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;AAEtD,SAAS,WAAW,CAClB,OAAmC,EACnC,IAAY;IAEZ,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAAyB,EACzB,UAA2C,EAC3C,UAAqC,EACrC,OAAmC,EACnC,YAAqB;IAErB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,SAAS;YACtC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,IAAI,CACd,eAAe,EACf,KAAK,EACL,UAAU,EACV,WAAW,EACX,KAAK,EACL,KAAK,EACL,IAAI,CACL,CAAC;gBACF,IAAI,UAAU,CAAC,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,gBAAgB,EAAE,WAAW,CAAC,EAAE,CAAC;YAC9D,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC5B,IAAI,UAAU,CAAC,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;YACjD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC7C,IAAI,UAAU,CAAC,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,OAAO,GACX,YAAY;YACZ,OAAO,CAAC,GAAG,CAAC,YAAY;YACxB,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;YACtD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;gBAC3D,IAAI,UAAU,CAAC,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrC,MAAM,QAAQ,GAAG,IAAI,CACnB,WAAW,EACX,KAAK,EACL,WAAW,EACX,KAAK,EACL,KAAK,EACL,GAAG,IAAI,MAAM,CACd,CAAC;gBACF,IAAI,UAAU,CAAC,QAAQ,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7D,OAAO,CACL,QAAQ,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE;YACvE,IAAI,CACL,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,IAAI,MAA4B,CAAC;AAEjC,MAAM,UAAU,kBAAkB;IAChC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,GAAG,gBAAgB,CACvB,OAAO,CAAC,QAAQ,EAChB,iBAAiB,EACjB,UAAU,EACV,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CACtB,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,SAAS,CAAC;AACrB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { checkBridge, clearExplanations, ensureExtensionInstalled, getSelection, getWalkthroughStatus, navigateWalkthrough, openFile, showExplanation, startWalkthrough, } from "./bridge.js";
|
|
9
|
+
import { cleanupTts, getVoice, listVoices, setVoice, speak, stopSpeaking, stripMarkdown, } from "./tts.js";
|
|
9
10
|
import { flushLogs, logger } from "./utils/logger.js";
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = dirname(__filename);
|
|
@@ -42,6 +43,9 @@ server.registerTool("explain_code", {
|
|
|
42
43
|
},
|
|
43
44
|
}, async (args) => {
|
|
44
45
|
const result = await showExplanation(args.file, args.line, args.endLine, args.explanation, args.title, args.startChar, args.endChar);
|
|
46
|
+
if (playback.voice) {
|
|
47
|
+
speak(stripMarkdown(args.explanation)).catch((err) => logger.warn({ err }, "TTS failed for explain_code"));
|
|
48
|
+
}
|
|
45
49
|
return {
|
|
46
50
|
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
47
51
|
};
|
|
@@ -61,38 +65,250 @@ const stepSchema = z.object({
|
|
|
61
65
|
explanation: z.string().describe("Markdown explanation"),
|
|
62
66
|
title: z.string().optional().describe("Step title"),
|
|
63
67
|
});
|
|
68
|
+
// --- Walkthrough state ---
|
|
69
|
+
let activeSteps = [];
|
|
70
|
+
let narrationAbort = null;
|
|
71
|
+
let paused = false;
|
|
72
|
+
let pauseResolve = null;
|
|
73
|
+
const playback = { voice: true, showBubbles: true };
|
|
74
|
+
async function runNarration(startIndex) {
|
|
75
|
+
narrationAbort = new AbortController();
|
|
76
|
+
const signal = narrationAbort.signal;
|
|
77
|
+
for (let i = startIndex; i < activeSteps.length; i++) {
|
|
78
|
+
if (signal.aborted)
|
|
79
|
+
break;
|
|
80
|
+
while (paused && !signal.aborted) {
|
|
81
|
+
await new Promise((r) => {
|
|
82
|
+
pauseResolve = r;
|
|
83
|
+
});
|
|
84
|
+
pauseResolve = null;
|
|
85
|
+
}
|
|
86
|
+
if (signal.aborted)
|
|
87
|
+
break;
|
|
88
|
+
if (i > startIndex) {
|
|
89
|
+
await navigateWalkthrough("next");
|
|
90
|
+
}
|
|
91
|
+
if (playback.voice) {
|
|
92
|
+
const step = activeSteps[i];
|
|
93
|
+
if (step) {
|
|
94
|
+
const text = stripMarkdown(step.explanation);
|
|
95
|
+
await speak(text);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
narrationAbort = null;
|
|
100
|
+
if (!signal.aborted) {
|
|
101
|
+
await navigateWalkthrough("next");
|
|
102
|
+
activeSteps = [];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function stopNarration() {
|
|
106
|
+
paused = false;
|
|
107
|
+
pauseResolve?.();
|
|
108
|
+
stopSpeaking();
|
|
109
|
+
narrationAbort?.abort();
|
|
110
|
+
narrationAbort = null;
|
|
111
|
+
}
|
|
64
112
|
server.registerTool("walkthrough", {
|
|
65
|
-
description: "Start a multi-step code walkthrough
|
|
113
|
+
description: "Start a multi-step code walkthrough with voice narration. Opens files, highlights code, shows inline explanation bubbles, and reads each step aloud. Voice and bubbles are on by default. Returns immediately — narration runs in background. Control with walkthrough_control (next, prev, stop, pause, resume, toggle voice/bubbles). Write explanations as natural spoken language.",
|
|
66
114
|
inputSchema: {
|
|
67
115
|
steps: z.array(stepSchema).describe("Array of walkthrough steps"),
|
|
68
|
-
|
|
116
|
+
voice: z
|
|
69
117
|
.boolean()
|
|
70
118
|
.optional()
|
|
71
|
-
.describe("
|
|
72
|
-
|
|
73
|
-
.
|
|
119
|
+
.describe("Enable voice narration (default: true)"),
|
|
120
|
+
showBubbles: z
|
|
121
|
+
.boolean()
|
|
74
122
|
.optional()
|
|
75
|
-
.describe("
|
|
123
|
+
.describe("Show explanation bubbles (default: true)"),
|
|
76
124
|
},
|
|
77
125
|
}, async (args) => {
|
|
78
|
-
|
|
126
|
+
stopNarration();
|
|
127
|
+
activeSteps = args.steps;
|
|
128
|
+
if (args.voice !== undefined)
|
|
129
|
+
playback.voice = args.voice;
|
|
130
|
+
if (args.showBubbles !== undefined)
|
|
131
|
+
playback.showBubbles = args.showBubbles;
|
|
132
|
+
paused = false;
|
|
133
|
+
const result = await startWalkthrough(activeSteps, false);
|
|
134
|
+
runNarration(0).catch((err) => logger.error({ err }, "Narration failed"));
|
|
79
135
|
return {
|
|
80
|
-
content: [
|
|
136
|
+
content: [
|
|
137
|
+
{ type: "text", text: JSON.stringify(result) },
|
|
138
|
+
{
|
|
139
|
+
type: "text",
|
|
140
|
+
text: "Controls: next | prev | pause | resume | stop — use walkthrough_control. Toggle voice/bubbles on the fly.",
|
|
141
|
+
},
|
|
142
|
+
],
|
|
81
143
|
};
|
|
82
144
|
});
|
|
83
|
-
server.registerTool("
|
|
84
|
-
description: "
|
|
145
|
+
server.registerTool("walkthrough_control", {
|
|
146
|
+
description: "Control an active walkthrough. Navigate (next/prev/goto), stop, pause, resume, or toggle voice and bubbles on the fly. Changes take effect immediately.",
|
|
85
147
|
inputSchema: {
|
|
86
|
-
action: z
|
|
148
|
+
action: z
|
|
149
|
+
.enum(["next", "prev", "goto", "stop", "pause", "resume"])
|
|
150
|
+
.optional()
|
|
151
|
+
.describe("Navigation or playback action"),
|
|
87
152
|
step: z
|
|
88
153
|
.number()
|
|
89
154
|
.optional()
|
|
90
155
|
.describe("Step index (0-based) for goto action"),
|
|
156
|
+
voice: z.boolean().optional().describe("Toggle voice narration on/off"),
|
|
157
|
+
showBubbles: z
|
|
158
|
+
.boolean()
|
|
159
|
+
.optional()
|
|
160
|
+
.describe("Toggle explanation bubbles on/off"),
|
|
91
161
|
},
|
|
92
162
|
}, async (args) => {
|
|
93
|
-
|
|
163
|
+
if (args.voice !== undefined)
|
|
164
|
+
playback.voice = args.voice;
|
|
165
|
+
if (args.showBubbles !== undefined)
|
|
166
|
+
playback.showBubbles = args.showBubbles;
|
|
167
|
+
if (args.action === "stop") {
|
|
168
|
+
stopNarration();
|
|
169
|
+
activeSteps = [];
|
|
170
|
+
return {
|
|
171
|
+
content: [
|
|
172
|
+
{ type: "text", text: JSON.stringify({ ok: true, stopped: true }) },
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (args.action === "pause") {
|
|
177
|
+
paused = true;
|
|
178
|
+
stopSpeaking();
|
|
179
|
+
return {
|
|
180
|
+
content: [
|
|
181
|
+
{ type: "text", text: JSON.stringify({ ok: true, paused: true }) },
|
|
182
|
+
],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (args.action === "resume") {
|
|
186
|
+
paused = false;
|
|
187
|
+
pauseResolve?.();
|
|
188
|
+
return {
|
|
189
|
+
content: [
|
|
190
|
+
{ type: "text", text: JSON.stringify({ ok: true, resumed: true }) },
|
|
191
|
+
],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
if (args.action === "next" ||
|
|
195
|
+
args.action === "prev" ||
|
|
196
|
+
args.action === "goto") {
|
|
197
|
+
stopNarration();
|
|
198
|
+
const result = await navigateWalkthrough(args.action, args.step);
|
|
199
|
+
if (result.active &&
|
|
200
|
+
playback.voice &&
|
|
201
|
+
typeof result.currentStep === "number") {
|
|
202
|
+
runNarration(result.currentStep).catch((err) => logger.error({ err }, "Narration failed"));
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
206
|
+
};
|
|
207
|
+
}
|
|
94
208
|
return {
|
|
95
|
-
content: [
|
|
209
|
+
content: [
|
|
210
|
+
{ type: "text", text: JSON.stringify({ ok: true, ...playback }) },
|
|
211
|
+
],
|
|
212
|
+
};
|
|
213
|
+
});
|
|
214
|
+
server.registerTool("walkthrough_voice", {
|
|
215
|
+
description: "Change the narration voice. Speaks a sample so you hear the difference. Persisted across sessions. Use audition=true to hear voices back-to-back. Filter by locale and gender.",
|
|
216
|
+
inputSchema: {
|
|
217
|
+
voice: z
|
|
218
|
+
.string()
|
|
219
|
+
.optional()
|
|
220
|
+
.describe("Voice name (e.g. en-US-GuyNeural, en-US-AriaNeural)"),
|
|
221
|
+
list: z
|
|
222
|
+
.boolean()
|
|
223
|
+
.optional()
|
|
224
|
+
.describe("List available voices without playing them"),
|
|
225
|
+
audition: z
|
|
226
|
+
.boolean()
|
|
227
|
+
.optional()
|
|
228
|
+
.describe("Play voices back-to-back so you can compare"),
|
|
229
|
+
locale: z
|
|
230
|
+
.string()
|
|
231
|
+
.optional()
|
|
232
|
+
.describe("Filter by locale prefix (e.g. 'en-US', 'en', 'de')"),
|
|
233
|
+
gender: z
|
|
234
|
+
.enum(["Male", "Female"])
|
|
235
|
+
.optional()
|
|
236
|
+
.describe("Filter by gender"),
|
|
237
|
+
},
|
|
238
|
+
}, async (args, extra) => {
|
|
239
|
+
const voices = await listVoices();
|
|
240
|
+
let filtered = args.locale
|
|
241
|
+
? voices.filter((v) => v.locale.toLowerCase().startsWith(args.locale.toLowerCase()))
|
|
242
|
+
: voices;
|
|
243
|
+
if (args.gender) {
|
|
244
|
+
filtered = filtered.filter((v) => v.gender === args.gender);
|
|
245
|
+
}
|
|
246
|
+
if (args.list) {
|
|
247
|
+
return {
|
|
248
|
+
content: [{ type: "text", text: JSON.stringify(filtered) }],
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
if (args.audition) {
|
|
252
|
+
const toAudition = args.locale
|
|
253
|
+
? filtered
|
|
254
|
+
: filtered.filter((v) => v.locale === "en-US");
|
|
255
|
+
const originalVoice = getVoice();
|
|
256
|
+
const played = [];
|
|
257
|
+
const onAbort = () => stopSpeaking();
|
|
258
|
+
extra.signal?.addEventListener("abort", onAbort);
|
|
259
|
+
for (const v of toAudition) {
|
|
260
|
+
if (extra.signal?.aborted)
|
|
261
|
+
break;
|
|
262
|
+
if (v.name.includes("Multilingual"))
|
|
263
|
+
continue;
|
|
264
|
+
setVoice(v.name);
|
|
265
|
+
const name = v.name
|
|
266
|
+
.replace(/Neural$/, "")
|
|
267
|
+
.replace(/^[\w]+-[\w]+-/, "")
|
|
268
|
+
.replace(/-/g, " ");
|
|
269
|
+
await speak(`I'm ${name}. Here's how I sound narrating a code walkthrough for you.`);
|
|
270
|
+
played.push(v.name);
|
|
271
|
+
}
|
|
272
|
+
extra.signal?.removeEventListener("abort", onAbort);
|
|
273
|
+
setVoice(originalVoice);
|
|
274
|
+
stopSpeaking();
|
|
275
|
+
return {
|
|
276
|
+
content: [
|
|
277
|
+
{
|
|
278
|
+
type: "text",
|
|
279
|
+
text: JSON.stringify({
|
|
280
|
+
ok: true,
|
|
281
|
+
auditioned: played,
|
|
282
|
+
currentVoice: originalVoice,
|
|
283
|
+
}),
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
if (args.voice) {
|
|
289
|
+
setVoice(args.voice);
|
|
290
|
+
const name = args.voice.replace(/Neural$/, "").replace(/-/g, " ");
|
|
291
|
+
await speak(`Hi, I'm ${name}. This is how I sound when narrating a code walkthrough.`);
|
|
292
|
+
return {
|
|
293
|
+
content: [
|
|
294
|
+
{
|
|
295
|
+
type: "text",
|
|
296
|
+
text: JSON.stringify({
|
|
297
|
+
ok: true,
|
|
298
|
+
voice: args.voice,
|
|
299
|
+
persisted: true,
|
|
300
|
+
}),
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
content: [
|
|
307
|
+
{
|
|
308
|
+
type: "text",
|
|
309
|
+
text: JSON.stringify({ currentVoice: getVoice() }),
|
|
310
|
+
},
|
|
311
|
+
],
|
|
96
312
|
};
|
|
97
313
|
});
|
|
98
314
|
server.registerTool("walkthrough_status", {
|
|
@@ -120,6 +336,8 @@ async function main() {
|
|
|
120
336
|
if (cleanupStarted)
|
|
121
337
|
return;
|
|
122
338
|
cleanupStarted = true;
|
|
339
|
+
stopNarration();
|
|
340
|
+
cleanupTts();
|
|
123
341
|
logger.info("Shutting down...");
|
|
124
342
|
flushLogs();
|
|
125
343
|
const timeoutId = setTimeout(() => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tts.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function getVoice(): string;
|
|
2
|
+
export declare function setVoice(voice: string): void;
|
|
3
|
+
export declare function listVoices(): Promise<{
|
|
4
|
+
name: string;
|
|
5
|
+
locale: string;
|
|
6
|
+
gender: string;
|
|
7
|
+
}[]>;
|
|
8
|
+
export declare function stripMarkdown(text: string): string;
|
|
9
|
+
export declare function speak(text: string): Promise<void>;
|
|
10
|
+
export declare function _speak(text: string, cmd: string, args: string[]): Promise<void>;
|
|
11
|
+
export declare function stopSpeaking(): void;
|
|
12
|
+
export declare function isSpeaking(): boolean;
|
|
13
|
+
export declare function cleanupTts(): void;
|
|
14
|
+
//# sourceMappingURL=tts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts.d.ts","sourceRoot":"","sources":["../src/tts.ts"],"names":[],"mappings":"AAoDA,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI5C;AAED,wBAAsB,UAAU,IAAI,OAAO,CACzC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CACnD,CAUA;AAID,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAalD;AAwFD,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvD;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAgB,YAAY,IAAI,IAAI,CAKnC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,UAAU,IAAI,IAAI,CAOjC"}
|
package/dist/tts.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { homedir, tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { MsEdgeTTS, OUTPUT_FORMAT } from "msedge-tts";
|
|
6
|
+
import { logger } from "./utils/logger.js";
|
|
7
|
+
let currentProcess = null;
|
|
8
|
+
let edgeTts = null;
|
|
9
|
+
let edgeTtsDir = null;
|
|
10
|
+
let cachedVoices = null;
|
|
11
|
+
const DEFAULT_VOICE = "en-US-AriaNeural";
|
|
12
|
+
const CONFIG_DIR = join(homedir(), ".walkthrough");
|
|
13
|
+
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
14
|
+
function loadConfig() {
|
|
15
|
+
try {
|
|
16
|
+
if (existsSync(CONFIG_PATH)) {
|
|
17
|
+
const parsed = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
18
|
+
if (typeof parsed?.voice === "string")
|
|
19
|
+
return parsed;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
logger.warn({ err }, "Failed to load TTS config");
|
|
24
|
+
}
|
|
25
|
+
return { voice: DEFAULT_VOICE };
|
|
26
|
+
}
|
|
27
|
+
function saveConfig(cfg) {
|
|
28
|
+
try {
|
|
29
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
30
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
logger.warn({ err }, "Failed to save TTS config");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const config = loadConfig();
|
|
37
|
+
export function getVoice() {
|
|
38
|
+
return config.voice;
|
|
39
|
+
}
|
|
40
|
+
export function setVoice(voice) {
|
|
41
|
+
config.voice = voice;
|
|
42
|
+
saveConfig(config);
|
|
43
|
+
edgeTts = null;
|
|
44
|
+
}
|
|
45
|
+
export async function listVoices() {
|
|
46
|
+
if (cachedVoices)
|
|
47
|
+
return cachedVoices;
|
|
48
|
+
const tts = new MsEdgeTTS();
|
|
49
|
+
const voices = await tts.getVoices();
|
|
50
|
+
cachedVoices = voices.map((v) => ({
|
|
51
|
+
name: v.ShortName ?? "",
|
|
52
|
+
locale: v.Locale ?? "",
|
|
53
|
+
gender: v.Gender ?? "",
|
|
54
|
+
}));
|
|
55
|
+
return cachedVoices;
|
|
56
|
+
}
|
|
57
|
+
// --- Markdown stripping ---
|
|
58
|
+
export function stripMarkdown(text) {
|
|
59
|
+
return text
|
|
60
|
+
.replace(/```[\s\S]*?```/g, "")
|
|
61
|
+
.replace(/`([^`]+)`/g, "$1")
|
|
62
|
+
.replace(/\*\*([^*]+)\*\*/g, "$1")
|
|
63
|
+
.replace(/\*([^*]+)\*/g, "$1")
|
|
64
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
|
|
65
|
+
.replace(/^#{1,6}\s+/gm, "")
|
|
66
|
+
.replace(/^[-*+]\s+/gm, "")
|
|
67
|
+
.replace(/^\d+\.\s+/gm, "")
|
|
68
|
+
.replace(/^>\s+/gm, "")
|
|
69
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
70
|
+
.trim();
|
|
71
|
+
}
|
|
72
|
+
// --- Process runner (shared by playFile and _speak) ---
|
|
73
|
+
function runProcess(cmd, args) {
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
stopSpeaking();
|
|
76
|
+
try {
|
|
77
|
+
const proc = spawn(cmd, args, { stdio: "ignore" });
|
|
78
|
+
currentProcess = proc;
|
|
79
|
+
proc.on("close", () => {
|
|
80
|
+
if (currentProcess === proc)
|
|
81
|
+
currentProcess = null;
|
|
82
|
+
resolve();
|
|
83
|
+
});
|
|
84
|
+
proc.on("error", () => {
|
|
85
|
+
if (currentProcess === proc)
|
|
86
|
+
currentProcess = null;
|
|
87
|
+
resolve();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
resolve();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// --- Edge TTS ---
|
|
96
|
+
async function getEdgeTts() {
|
|
97
|
+
if (!edgeTts) {
|
|
98
|
+
edgeTts = new MsEdgeTTS();
|
|
99
|
+
await edgeTts.setMetadata(config.voice, OUTPUT_FORMAT.AUDIO_24KHZ_48KBITRATE_MONO_MP3);
|
|
100
|
+
edgeTtsDir = join(tmpdir(), `walkthrough-tts-${process.pid}`);
|
|
101
|
+
mkdirSync(edgeTtsDir, { recursive: true });
|
|
102
|
+
}
|
|
103
|
+
return edgeTts;
|
|
104
|
+
}
|
|
105
|
+
function getPlayerArgs(filePath) {
|
|
106
|
+
if (process.platform === "darwin")
|
|
107
|
+
return ["afplay", [filePath]];
|
|
108
|
+
if (process.platform === "linux")
|
|
109
|
+
return ["mpg123", ["-q", filePath]];
|
|
110
|
+
if (process.platform === "win32") {
|
|
111
|
+
const escaped = filePath.replace(/'/g, "''");
|
|
112
|
+
return [
|
|
113
|
+
"powershell",
|
|
114
|
+
[
|
|
115
|
+
"-Command",
|
|
116
|
+
`Add-Type -AssemblyName presentationCore; $p = New-Object System.Windows.Media.MediaPlayer; $p.Open([Uri]'${escaped}'); $p.Play(); Start-Sleep -Seconds 300`,
|
|
117
|
+
],
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
async function speakEdgeTts(text) {
|
|
123
|
+
const tts = await getEdgeTts();
|
|
124
|
+
if (!edgeTtsDir)
|
|
125
|
+
throw new Error("Edge TTS dir not initialized");
|
|
126
|
+
const result = await tts.toFile(edgeTtsDir, text);
|
|
127
|
+
const playerArgs = getPlayerArgs(result.audioFilePath);
|
|
128
|
+
if (playerArgs) {
|
|
129
|
+
await runProcess(...playerArgs);
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
rmSync(result.audioFilePath, { force: true });
|
|
133
|
+
}
|
|
134
|
+
catch { }
|
|
135
|
+
}
|
|
136
|
+
// --- Native TTS fallback ---
|
|
137
|
+
function speakNative(text) {
|
|
138
|
+
if (process.platform === "darwin")
|
|
139
|
+
return runProcess("say", [text]);
|
|
140
|
+
if (process.platform === "linux")
|
|
141
|
+
return runProcess("espeak", [text]);
|
|
142
|
+
if (process.platform === "win32") {
|
|
143
|
+
const escaped = text.replace(/'/g, "''");
|
|
144
|
+
return runProcess("powershell", [
|
|
145
|
+
"-Command",
|
|
146
|
+
`Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('${escaped}')`,
|
|
147
|
+
]);
|
|
148
|
+
}
|
|
149
|
+
return Promise.resolve();
|
|
150
|
+
}
|
|
151
|
+
// --- Public API ---
|
|
152
|
+
export async function speak(text) {
|
|
153
|
+
try {
|
|
154
|
+
await speakEdgeTts(text);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
logger.warn({ err }, "Edge TTS failed, falling back to native");
|
|
158
|
+
await speakNative(text);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export function _speak(text, cmd, args) {
|
|
162
|
+
return runProcess(cmd, [...args, text]);
|
|
163
|
+
}
|
|
164
|
+
export function stopSpeaking() {
|
|
165
|
+
if (currentProcess) {
|
|
166
|
+
currentProcess.kill();
|
|
167
|
+
currentProcess = null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
export function isSpeaking() {
|
|
171
|
+
return currentProcess !== null;
|
|
172
|
+
}
|
|
173
|
+
export function cleanupTts() {
|
|
174
|
+
stopSpeaking();
|
|
175
|
+
if (edgeTtsDir) {
|
|
176
|
+
try {
|
|
177
|
+
rmSync(edgeTtsDir, { recursive: true, force: true });
|
|
178
|
+
}
|
|
179
|
+
catch { }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=tts.js.map
|
package/dist/tts.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts.js","sourceRoot":"","sources":["../src/tts.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-walkthrough",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "MCP server for interactive code walkthroughs - Claude-driven code tours",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
|
+
"scripts/postinstall.cjs",
|
|
12
13
|
"vscode-extension/walkthrough-bridge.vsix",
|
|
13
14
|
"README.md",
|
|
14
15
|
"LICENSE"
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
"scripts": {
|
|
30
31
|
"build": "npm run build:extension && tsc -p tsconfig.build.json",
|
|
31
32
|
"build:extension": "node -e \"const fs=require('fs');const v=require('./package.json').version;const p=JSON.parse(fs.readFileSync('vscode-extension/package.json','utf-8'));p.version=v;fs.writeFileSync('vscode-extension/package.json',JSON.stringify(p,null,2)+'\\n')\" && cd vscode-extension && npm install && npx tsc -p ./ && npx @vscode/vsce package --allow-missing-repository -o walkthrough-bridge.vsix",
|
|
32
|
-
"postinstall": "node
|
|
33
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
33
34
|
"dev": "bun --watch src/index.ts",
|
|
34
35
|
"start": "node dist/index.js",
|
|
35
36
|
"test": "bun test",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
},
|
|
43
44
|
"dependencies": {
|
|
44
45
|
"@modelcontextprotocol/sdk": "^1.18.1",
|
|
46
|
+
"msedge-tts": "^2.0.4",
|
|
45
47
|
"pino": "^10.0.0",
|
|
46
48
|
"zod": "^3.25.0"
|
|
47
49
|
},
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const { execSync } = require("node:child_process");
|
|
2
|
+
const { existsSync, readdirSync } = require("node:fs");
|
|
3
|
+
const { join } = require("node:path");
|
|
4
|
+
|
|
5
|
+
const vsixPath = join(
|
|
6
|
+
__dirname,
|
|
7
|
+
"..",
|
|
8
|
+
"vscode-extension",
|
|
9
|
+
"walkthrough-bridge.vsix",
|
|
10
|
+
);
|
|
11
|
+
if (!existsSync(vsixPath)) process.exit(0);
|
|
12
|
+
|
|
13
|
+
const cliNames = ["code", "code-insiders", "cursor"];
|
|
14
|
+
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
15
|
+
|
|
16
|
+
function safeReaddir(dir) {
|
|
17
|
+
try {
|
|
18
|
+
return readdirSync(dir);
|
|
19
|
+
} catch {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const found = [];
|
|
25
|
+
|
|
26
|
+
for (const name of cliNames) {
|
|
27
|
+
try {
|
|
28
|
+
const p = execSync(`${whichCmd} ${name}`, {
|
|
29
|
+
encoding: "utf-8",
|
|
30
|
+
stdio: "pipe",
|
|
31
|
+
}).trim();
|
|
32
|
+
if (p) found.push(p);
|
|
33
|
+
} catch {}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (process.platform === "darwin") {
|
|
37
|
+
for (const entry of safeReaddir("/Applications")) {
|
|
38
|
+
if (!entry.endsWith(".app")) continue;
|
|
39
|
+
for (const name of cliNames) {
|
|
40
|
+
const bin = join(
|
|
41
|
+
"/Applications",
|
|
42
|
+
entry,
|
|
43
|
+
"Contents",
|
|
44
|
+
"Resources",
|
|
45
|
+
"app",
|
|
46
|
+
"bin",
|
|
47
|
+
name,
|
|
48
|
+
);
|
|
49
|
+
if (existsSync(bin)) found.push(bin);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (process.platform === "linux") {
|
|
55
|
+
for (const dir of ["/usr/bin", "/usr/local/bin", "/snap/bin"]) {
|
|
56
|
+
for (const name of cliNames) {
|
|
57
|
+
const bin = join(dir, name);
|
|
58
|
+
if (existsSync(bin)) found.push(bin);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const entry of safeReaddir("/opt")) {
|
|
62
|
+
for (const name of cliNames) {
|
|
63
|
+
const bin = join("/opt", entry, "bin", name);
|
|
64
|
+
if (existsSync(bin)) found.push(bin);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (process.platform === "win32") {
|
|
70
|
+
const appData =
|
|
71
|
+
process.env.LOCALAPPDATA ||
|
|
72
|
+
join(require("node:os").homedir(), "AppData", "Local");
|
|
73
|
+
const programsDir = join(appData, "Programs");
|
|
74
|
+
for (const entry of safeReaddir(programsDir)) {
|
|
75
|
+
for (const name of cliNames) {
|
|
76
|
+
const std = join(programsDir, entry, "bin", `${name}.cmd`);
|
|
77
|
+
if (existsSync(std)) found.push(std);
|
|
78
|
+
const electron = join(
|
|
79
|
+
programsDir,
|
|
80
|
+
entry,
|
|
81
|
+
"resources",
|
|
82
|
+
"app",
|
|
83
|
+
"bin",
|
|
84
|
+
`${name}.cmd`,
|
|
85
|
+
);
|
|
86
|
+
if (existsSync(electron)) found.push(electron);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const unique = [...new Set(found)];
|
|
92
|
+
for (const cli of unique) {
|
|
93
|
+
try {
|
|
94
|
+
execSync(`"${cli}" --install-extension "${vsixPath}" --force`, {
|
|
95
|
+
stdio: "ignore",
|
|
96
|
+
});
|
|
97
|
+
} catch {}
|
|
98
|
+
}
|
|
Binary file
|