mcp-walkthrough 0.2.0 → 0.2.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 CHANGED
@@ -19,7 +19,7 @@ Text in a terminal isn't enough when you want Claude to explain a solution. MCP
19
19
  - **Selection Reading** — Claude can see what you've highlighted to discuss it further
20
20
  - **Focus Preservation** — Opens files without stealing focus from your terminal
21
21
 
22
- > **Note:** This MCP server requires VS Code. It includes a companion VS Code extension that is automatically installed when you `npm install`.
22
+ > **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
23
 
24
24
  ## Installation
25
25
 
@@ -153,7 +153,7 @@ Claude Code → MCP Server (stdio) → Unix socket → VS Code Extension
153
153
  4. Each VS Code window gets its own socket — multiple windows work independently
154
154
  5. Focus stays in your terminal — code appears in the editor beside it
155
155
 
156
- The VS Code extension is bundled with the npm package and automatically installed on first run.
156
+ 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
157
 
158
158
  ## Development
159
159
 
@@ -164,15 +164,20 @@ mcp-walkthrough/
164
164
  ├── src/
165
165
  │ ├── index.ts # MCP server entry point, tool registration
166
166
  │ ├── bridge.ts # Unix socket client to VS Code extension
167
+ │ ├── code-cli.ts # Cross-platform VS Code CLI discovery
167
168
  │ ├── socket.ts # Socket path computation and discovery
168
169
  │ └── utils/
169
170
  │ └── logger.ts # Pino logger (stderr only)
171
+ ├── scripts/
172
+ │ └── postinstall.cjs # Auto-installs extension on npm install
170
173
  ├── vscode-extension/
171
174
  │ ├── src/
172
175
  │ │ └── extension.ts # VS Code extension (HTTP server, Comments API)
173
176
  │ └── package.json
174
177
  ├── tests/
175
178
  │ ├── bridge.test.ts
179
+ │ ├── code-cli.test.ts
180
+ │ ├── postinstall.test.ts
176
181
  │ └── socket.test.ts
177
182
  └── docs/
178
183
  ```
@@ -207,10 +212,16 @@ The MCP server discovers the VS Code extension via a Unix socket. If the socket
207
212
 
208
213
  ### Extension not installed
209
214
 
210
- The MCP server auto-installs the extension on first run via `code --install-extension`. If this fails:
215
+ The MCP server auto-discovers VS Code, VS Code Insiders, and Cursor CLIs — even when `code` isn't in your PATH. It searches:
211
216
 
212
- 1. Verify the `code` CLI is available in your terminal
213
- 2. Manually install: `code --install-extension path/to/walkthrough-bridge.vsix`
217
+ - **macOS**: `/Applications/*.app/Contents/Resources/app/bin/`
218
+ - **Linux**: `/usr/bin/`, `/usr/local/bin/`, `/snap/bin/`, `/opt/*/bin/`
219
+ - **Windows**: `%LOCALAPPDATA%\Programs\*\bin\`
220
+
221
+ The extension is installed into **all** found editors. If auto-install still fails:
222
+
223
+ 1. Manually install: `code --install-extension path/to/walkthrough-bridge.vsix`
224
+ 2. Or reload the VS Code window after installing the npm package
214
225
 
215
226
  ## Contributing
216
227
 
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAiBA,wBAAgB,wBAAwB,IAAI,IAAI,CAsB/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"}
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
- try {
14
- const installed = execSync("code --list-extensions", { encoding: "utf-8" });
15
- if (installed.includes(EXTENSION_ID)) {
16
- logger.info("Walkthrough bridge extension already installed");
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
- try {
28
- execSync(`code --install-extension "${VSIX_PATH}"`, { encoding: "utf-8" });
29
- logger.info("Installed walkthrough bridge extension");
30
- }
31
- catch (error) {
32
- logger.error({ err: error }, "Failed to install extension");
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;
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
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"}
@@ -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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-walkthrough",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
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 -e \"try{require('child_process').execSync('code --install-extension '+require('path').join(__dirname,'vscode-extension','walkthrough-bridge.vsix')+' --force',{stdio:'ignore'})}catch{}\"",
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",
@@ -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
+ }