mcp-walkthrough 0.1.0
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 +221 -0
- package/dist/bridge.d.ts +22 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +96 -0
- package/dist/bridge.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +151 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +9 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +53 -0
- package/vscode-extension/walkthrough-bridge.vsix +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/mcp-walkthrough)
|
|
2
|
+
[](https://www.npmjs.com/package/mcp-walkthrough)
|
|
3
|
+
[](https://github.com/Stefan-Nitu/mcp-walkthrough/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/Stefan-Nitu/mcp-walkthrough/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
# MCP Walkthrough
|
|
7
|
+
|
|
8
|
+
An MCP server for interactive code walkthroughs. Claude drives the narrative — opens files, highlights code, shows inline explanations, and navigates step by step.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
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, and show rich markdown explanations right next to the code. Navigate at your own pace — forward, back, or let it autoplay.
|
|
13
|
+
|
|
14
|
+
**Key Features:**
|
|
15
|
+
- **Inline Explanations** — Markdown comment bubbles appear right next to highlighted code
|
|
16
|
+
- **Multi-Step Walkthroughs** — Claude sends all steps at once, you navigate with keyboard shortcuts
|
|
17
|
+
- **Autoplay** — Optional auto-advance with reading-speed-based timing
|
|
18
|
+
- **Keyboard Navigation** — `Cmd+Shift+Right` / `Cmd+Shift+Left` to navigate steps
|
|
19
|
+
- **Selection Reading** — Claude can see what you've highlighted to discuss it further
|
|
20
|
+
- **Focus Preservation** — Opens files without stealing focus from your terminal
|
|
21
|
+
|
|
22
|
+
> **Note:** This MCP server requires VS Code. It includes a companion VS Code extension that is automatically installed on first run.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
### Via npm (Recommended)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install -g mcp-walkthrough
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### From Source
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/Stefan-Nitu/mcp-walkthrough.git
|
|
36
|
+
cd mcp-walkthrough
|
|
37
|
+
bun install
|
|
38
|
+
bun run build
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
> Requires Bun v1.3.8+ (development) and Node.js v18+ (runtime)
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
### With Claude Code
|
|
46
|
+
|
|
47
|
+
Add to `~/.claude.json`:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"mcp-walkthrough": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["-y", "mcp-walkthrough"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or if installed globally:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"mcp-walkthrough": {
|
|
66
|
+
"command": "mcp-walkthrough"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Restart Claude Code to pick up the new server.
|
|
73
|
+
|
|
74
|
+
### Add a CLAUDE.md hint
|
|
75
|
+
|
|
76
|
+
MCP tools are deferred (loaded on-demand), so Claude may not use them automatically. Add this to your project's `CLAUDE.md`:
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
## Walkthrough MCP
|
|
80
|
+
|
|
81
|
+
You have access to walkthrough tools via MCP. Use them to visually walk the user through code — open files, highlight lines, and show inline explanations in VS Code.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Available Tools
|
|
85
|
+
|
|
86
|
+
| Tool | Description |
|
|
87
|
+
|------|-------------|
|
|
88
|
+
| **show_code** | Open a file and highlight specific lines |
|
|
89
|
+
| **explain_code** | Highlight lines + show an inline markdown explanation bubble |
|
|
90
|
+
| **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
|
+
| **get_selection** | Read the currently highlighted code in VS Code |
|
|
95
|
+
|
|
96
|
+
### walkthrough
|
|
97
|
+
|
|
98
|
+
The main tool. Claude generates all steps and sends them at once. The VS Code extension handles navigation.
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"steps": [
|
|
103
|
+
{
|
|
104
|
+
"file": "/absolute/path/to/file.ts",
|
|
105
|
+
"line": 10,
|
|
106
|
+
"endLine": 25,
|
|
107
|
+
"explanation": "## Auth Middleware\n\nThis validates the JWT token on every request.",
|
|
108
|
+
"title": "Token Validation"
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"autoplay": false,
|
|
112
|
+
"delayMs": 5000
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Parameters:**
|
|
117
|
+
- `steps` — Array of `{ file, line, endLine?, explanation, title? }`
|
|
118
|
+
- `autoplay` — Auto-advance through steps (default: `false`)
|
|
119
|
+
- `delayMs` — Delay between steps in ms when autoplay is on (default: calculated from reading speed)
|
|
120
|
+
|
|
121
|
+
### walkthrough_navigate
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{ "action": "next" }
|
|
125
|
+
{ "action": "prev" }
|
|
126
|
+
{ "action": "goto", "step": 3 }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Keyboard Shortcuts
|
|
130
|
+
|
|
131
|
+
During an active walkthrough:
|
|
132
|
+
- **Cmd+Shift+Right** — Next step
|
|
133
|
+
- **Cmd+Shift+Left** — Previous step
|
|
134
|
+
- **Status bar** — Shows current step, click to stop
|
|
135
|
+
|
|
136
|
+
## How It Works
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
Claude Code → MCP Server (stdio) → HTTP localhost:7890 → VS Code Extension → Editor API
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
1. Claude calls walkthrough tools via MCP
|
|
143
|
+
2. The MCP server forwards requests to a companion VS Code extension over HTTP
|
|
144
|
+
3. The extension uses the VS Code API to open files, select ranges, and create comment threads
|
|
145
|
+
4. Focus stays in your terminal — code appears in the editor beside it
|
|
146
|
+
|
|
147
|
+
The VS Code extension is bundled with the npm package and automatically installed on first run.
|
|
148
|
+
|
|
149
|
+
## Development
|
|
150
|
+
|
|
151
|
+
### Project Structure
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
mcp-walkthrough/
|
|
155
|
+
├── src/
|
|
156
|
+
│ ├── index.ts # MCP server entry point, tool registration
|
|
157
|
+
│ ├── bridge.ts # HTTP client to VS Code extension
|
|
158
|
+
│ └── utils/
|
|
159
|
+
│ └── logger.ts # Pino logger (stderr only)
|
|
160
|
+
├── vscode-extension/
|
|
161
|
+
│ ├── src/
|
|
162
|
+
│ │ └── extension.ts # VS Code extension (HTTP server, Comments API)
|
|
163
|
+
│ └── package.json
|
|
164
|
+
├── tests/
|
|
165
|
+
│ └── bridge.test.ts
|
|
166
|
+
└── docs/
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Testing
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
bun test # Run all tests
|
|
173
|
+
bun test --watch # Watch mode
|
|
174
|
+
bun run typecheck # Type checking
|
|
175
|
+
bun run lint # Linting
|
|
176
|
+
bun run check # Full check (typecheck + lint)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Building
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
bun run build # Builds MCP server + VS Code extension
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The build script syncs the version from root `package.json` into the extension before packaging.
|
|
186
|
+
|
|
187
|
+
## Troubleshooting
|
|
188
|
+
|
|
189
|
+
### Tools return "This MCP server only works from VS Code."
|
|
190
|
+
|
|
191
|
+
The MCP server pings the VS Code extension on startup. If the extension isn't running:
|
|
192
|
+
|
|
193
|
+
1. Make sure you're running Claude Code inside VS Code (not a standalone terminal)
|
|
194
|
+
2. The extension activates on VS Code startup — try reloading the window (`Cmd+Shift+P` → "Reload Window")
|
|
195
|
+
|
|
196
|
+
### Extension not installed
|
|
197
|
+
|
|
198
|
+
The MCP server auto-installs the extension on first run via `code --install-extension`. If this fails:
|
|
199
|
+
|
|
200
|
+
1. Verify the `code` CLI is available in your terminal
|
|
201
|
+
2. Manually install: `code --install-extension path/to/walkthrough-bridge.vsix`
|
|
202
|
+
|
|
203
|
+
## Contributing
|
|
204
|
+
|
|
205
|
+
1. Fork the repository
|
|
206
|
+
2. Create a feature branch
|
|
207
|
+
3. **Write tests first** (TDD approach)
|
|
208
|
+
4. Implement the feature
|
|
209
|
+
5. Ensure all tests pass (`bun test`)
|
|
210
|
+
6. Run linting (`bun run lint`)
|
|
211
|
+
7. Submit a pull request
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
MIT
|
|
216
|
+
|
|
217
|
+
## Related Projects
|
|
218
|
+
|
|
219
|
+
- [Model Context Protocol](https://modelcontextprotocol.io) - MCP specification and documentation
|
|
220
|
+
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) - SDK used by this server
|
|
221
|
+
- [MCP Claude Code Conversation History](https://github.com/Stefan-Nitu/mcp-claude-code-conversation-history) - MCP server for searching Claude Code conversations
|
package/dist/bridge.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare function ensureExtensionInstalled(): void;
|
|
2
|
+
type BridgeResult = Record<string, unknown>;
|
|
3
|
+
export declare let bridgeAvailable: boolean | null;
|
|
4
|
+
export declare function resetBridgeState(): void;
|
|
5
|
+
export declare function checkBridge(): Promise<boolean>;
|
|
6
|
+
export declare function isBridgeAvailable(): boolean;
|
|
7
|
+
export declare function openFile(file: string, line: number, endLine?: number): Promise<BridgeResult>;
|
|
8
|
+
export declare function showExplanation(file: string, line: number, endLine: number | undefined, explanation: string, title?: string): Promise<BridgeResult>;
|
|
9
|
+
export declare function clearExplanations(): Promise<BridgeResult>;
|
|
10
|
+
export interface WalkthroughStep {
|
|
11
|
+
file: string;
|
|
12
|
+
line: number;
|
|
13
|
+
endLine?: number;
|
|
14
|
+
explanation: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function startWalkthrough(steps: WalkthroughStep[], autoplay?: boolean, delayMs?: number): Promise<BridgeResult>;
|
|
18
|
+
export declare function navigateWalkthrough(action: string, step?: number): Promise<BridgeResult>;
|
|
19
|
+
export declare function getWalkthroughStatus(): Promise<BridgeResult>;
|
|
20
|
+
export declare function getSelection(): Promise<BridgeResult>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAgBA,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;AAElD,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAcpD;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAyBD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,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,GACb,OAAO,CAAC,YAAY,CAAC,CAEvB;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
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { logger } from "./utils/logger.js";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
const EXTENSION_ID = "undefined_publisher.walkthrough-bridge";
|
|
9
|
+
const VSIX_PATH = join(__dirname, "../vscode-extension/walkthrough-bridge.vsix");
|
|
10
|
+
const BRIDGE_URL = "http://127.0.0.1:7890";
|
|
11
|
+
export function ensureExtensionInstalled() {
|
|
12
|
+
try {
|
|
13
|
+
const installed = execSync("code --list-extensions", { encoding: "utf-8" });
|
|
14
|
+
if (installed.includes(EXTENSION_ID)) {
|
|
15
|
+
logger.info("Walkthrough bridge extension already installed");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
logger.warn("Could not check installed extensions");
|
|
21
|
+
}
|
|
22
|
+
if (!existsSync(VSIX_PATH)) {
|
|
23
|
+
logger.error({ path: VSIX_PATH }, "Extension .vsix not found");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
execSync(`code --install-extension "${VSIX_PATH}"`, { encoding: "utf-8" });
|
|
28
|
+
logger.info("Installed walkthrough bridge extension");
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
logger.error({ err: error }, "Failed to install extension");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export let bridgeAvailable = null;
|
|
35
|
+
export function resetBridgeState() {
|
|
36
|
+
bridgeAvailable = null;
|
|
37
|
+
}
|
|
38
|
+
export async function checkBridge() {
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(`${BRIDGE_URL}/ping`, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: { "Content-Type": "application/json" },
|
|
43
|
+
body: "{}",
|
|
44
|
+
});
|
|
45
|
+
const data = (await res.json());
|
|
46
|
+
bridgeAvailable = data.ok === true;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
bridgeAvailable = false;
|
|
50
|
+
}
|
|
51
|
+
logger.info({ bridgeAvailable }, "Bridge status");
|
|
52
|
+
return bridgeAvailable;
|
|
53
|
+
}
|
|
54
|
+
export function isBridgeAvailable() {
|
|
55
|
+
return bridgeAvailable === true;
|
|
56
|
+
}
|
|
57
|
+
const BRIDGE_UNAVAILABLE_ERROR = "This MCP server only works from VS Code.";
|
|
58
|
+
async function bridgeRequest(endpoint, data = {}) {
|
|
59
|
+
if (bridgeAvailable === false) {
|
|
60
|
+
return { ok: false, error: BRIDGE_UNAVAILABLE_ERROR };
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const res = await fetch(`${BRIDGE_URL}${endpoint}`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
body: JSON.stringify(data),
|
|
67
|
+
});
|
|
68
|
+
return (await res.json());
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
bridgeAvailable = false;
|
|
72
|
+
return { ok: false, error: BRIDGE_UNAVAILABLE_ERROR };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export async function openFile(file, line, endLine) {
|
|
76
|
+
return bridgeRequest("/open", { file, line, endLine });
|
|
77
|
+
}
|
|
78
|
+
export async function showExplanation(file, line, endLine, explanation, title) {
|
|
79
|
+
return bridgeRequest("/explain", { file, line, endLine, explanation, title });
|
|
80
|
+
}
|
|
81
|
+
export async function clearExplanations() {
|
|
82
|
+
return bridgeRequest("/clear");
|
|
83
|
+
}
|
|
84
|
+
export async function startWalkthrough(steps, autoplay, delayMs) {
|
|
85
|
+
return bridgeRequest("/walkthrough", { steps, autoplay, delayMs });
|
|
86
|
+
}
|
|
87
|
+
export async function navigateWalkthrough(action, step) {
|
|
88
|
+
return bridgeRequest("/walkthrough/navigate", { action, step });
|
|
89
|
+
}
|
|
90
|
+
export async function getWalkthroughStatus() {
|
|
91
|
+
return bridgeRequest("/walkthrough/status");
|
|
92
|
+
}
|
|
93
|
+
export async function getSelection() {
|
|
94
|
+
return bridgeRequest("/selection");
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { checkBridge, clearExplanations, ensureExtensionInstalled, getSelection, getWalkthroughStatus, navigateWalkthrough, openFile, showExplanation, startWalkthrough, } from "./bridge.js";
|
|
9
|
+
import { flushLogs, logger } from "./utils/logger.js";
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
|
|
13
|
+
const server = new McpServer({
|
|
14
|
+
name: "mcp-walkthrough",
|
|
15
|
+
version: packageJson.version,
|
|
16
|
+
});
|
|
17
|
+
server.registerTool("show_code", {
|
|
18
|
+
description: "Open a file in VS Code and highlight specific lines. Use this to walk the user through code.",
|
|
19
|
+
inputSchema: {
|
|
20
|
+
file: z.string().describe("Absolute path to the file"),
|
|
21
|
+
line: z.number().describe("Start line (1-based)"),
|
|
22
|
+
endLine: z.number().optional().describe("End line (1-based)"),
|
|
23
|
+
},
|
|
24
|
+
}, async (args) => {
|
|
25
|
+
const result = await openFile(args.file, args.line, args.endLine);
|
|
26
|
+
return {
|
|
27
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
server.registerTool("explain_code", {
|
|
31
|
+
description: "Open a file in VS Code, highlight lines, and show an inline markdown explanation bubble. Use this to walk the user through code with rich annotations.",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
file: z.string().describe("Absolute path to the file"),
|
|
34
|
+
line: z.number().describe("Start line (1-based)"),
|
|
35
|
+
endLine: z.number().optional().describe("End line (1-based)"),
|
|
36
|
+
explanation: z.string().describe("Markdown explanation to display"),
|
|
37
|
+
title: z.string().optional().describe("Title for the explanation"),
|
|
38
|
+
},
|
|
39
|
+
}, async (args) => {
|
|
40
|
+
const result = await showExplanation(args.file, args.line, args.endLine, args.explanation, args.title);
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
server.registerTool("clear_explanations", {
|
|
46
|
+
description: "Remove all walkthrough explanation bubbles from the editor.",
|
|
47
|
+
}, async () => {
|
|
48
|
+
const result = await clearExplanations();
|
|
49
|
+
return {
|
|
50
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
const stepSchema = z.object({
|
|
54
|
+
file: z.string().describe("Absolute path to the file"),
|
|
55
|
+
line: z.number().describe("Start line (1-based)"),
|
|
56
|
+
endLine: z.number().optional().describe("End line (1-based)"),
|
|
57
|
+
explanation: z.string().describe("Markdown explanation"),
|
|
58
|
+
title: z.string().optional().describe("Step title"),
|
|
59
|
+
});
|
|
60
|
+
server.registerTool("walkthrough", {
|
|
61
|
+
description: "Start a multi-step code walkthrough. Sends all steps to VS Code at once. The extension handles navigation — user clicks prev/next or uses Cmd+Shift+Left/Right. Optional autoplay with delay between steps. Returns current step state so you can navigate with walkthrough_navigate.",
|
|
62
|
+
inputSchema: {
|
|
63
|
+
steps: z.array(stepSchema).describe("Array of walkthrough steps"),
|
|
64
|
+
autoplay: z
|
|
65
|
+
.boolean()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("Auto-advance through steps (default: false)"),
|
|
68
|
+
delayMs: z
|
|
69
|
+
.number()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe("Delay between steps in ms when autoplay is on (default: 5000)"),
|
|
72
|
+
},
|
|
73
|
+
}, async (args) => {
|
|
74
|
+
const result = await startWalkthrough(args.steps, args.autoplay, args.delayMs);
|
|
75
|
+
return {
|
|
76
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
server.registerTool("walkthrough_navigate", {
|
|
80
|
+
description: "Navigate an active walkthrough. Use when the user says next, back, or asks to jump to a step. Returns the current step state.",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
action: z.enum(["next", "prev", "goto"]).describe("Navigation action"),
|
|
83
|
+
step: z
|
|
84
|
+
.number()
|
|
85
|
+
.optional()
|
|
86
|
+
.describe("Step index (0-based) for goto action"),
|
|
87
|
+
},
|
|
88
|
+
}, async (args) => {
|
|
89
|
+
const result = await navigateWalkthrough(args.action, args.step);
|
|
90
|
+
return {
|
|
91
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
server.registerTool("walkthrough_status", {
|
|
95
|
+
description: "Get the current state of an active walkthrough — which step, total steps, step details.",
|
|
96
|
+
}, async () => {
|
|
97
|
+
const result = await getWalkthroughStatus();
|
|
98
|
+
return {
|
|
99
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
server.registerTool("get_selection", {
|
|
103
|
+
description: "Get the currently selected/highlighted code in VS Code. Returns the file path, line range, and selected text. Use when the user wants to discuss specific code they've highlighted.",
|
|
104
|
+
}, async () => {
|
|
105
|
+
const result = await getSelection();
|
|
106
|
+
return {
|
|
107
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
async function main() {
|
|
111
|
+
ensureExtensionInstalled();
|
|
112
|
+
await checkBridge();
|
|
113
|
+
const transport = new StdioServerTransport();
|
|
114
|
+
let cleanupStarted = false;
|
|
115
|
+
const cleanup = async () => {
|
|
116
|
+
if (cleanupStarted)
|
|
117
|
+
return;
|
|
118
|
+
cleanupStarted = true;
|
|
119
|
+
logger.info("Shutting down...");
|
|
120
|
+
flushLogs();
|
|
121
|
+
const timeoutId = setTimeout(() => {
|
|
122
|
+
logger.error("Cleanup timeout - forcing exit after 5 seconds");
|
|
123
|
+
flushLogs();
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}, 5000);
|
|
126
|
+
try {
|
|
127
|
+
await server.close();
|
|
128
|
+
clearTimeout(timeoutId);
|
|
129
|
+
logger.info("Cleanup completed");
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
clearTimeout(timeoutId);
|
|
134
|
+
logger.error({ err: error }, "Error during cleanup");
|
|
135
|
+
flushLogs();
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
process.once("SIGINT", cleanup);
|
|
140
|
+
process.once("SIGTERM", cleanup);
|
|
141
|
+
await server.connect(transport);
|
|
142
|
+
process.stdin.once("end", cleanup);
|
|
143
|
+
process.stdin.once("close", cleanup);
|
|
144
|
+
logger.info("mcp-walkthrough server started");
|
|
145
|
+
}
|
|
146
|
+
main().catch((error) => {
|
|
147
|
+
logger.error({ err: error }, "Fatal error");
|
|
148
|
+
flushLogs();
|
|
149
|
+
process.exit(1);
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,QAAQ,EACR,eAAe,EACf,gBAAgB,GAEjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC1D,CAAC;AAEF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,WAAW,CAAC,OAAO;CAC7B,CAAC,CAAC;AAEH,MAAM,CAAC,YAAY,CACjB,WAAW,EACX;IACE,WAAW,EACT,8FAA8F;IAChG,WAAW,EAAE;QACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACtD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;KAC9D;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAClE,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;IACE,WAAW,EACT,wJAAwJ;IAC1J,WAAW,EAAE;QACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACtD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAC7D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;QACnE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACnE;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,MAAM,MAAM,GAAG,MAAM,eAAe,CAClC,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,KAAK,CACX,CAAC;IACF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;IACE,WAAW,EAAE,6DAA6D;CAC3E,EACD,KAAK,IAAI,EAAE;IACT,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;IACtD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IAC7D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IACxD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;CACpD,CAAC,CAAC;AAEH,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;IACE,WAAW,EACT,uRAAuR;IACzR,WAAW,EAAE;QACX,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,4BAA4B,CAAC;QACjE,QAAQ,EAAE,CAAC;aACR,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,6CAA6C,CAAC;QAC1D,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,+DAA+D,CAChE;KACJ;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,IAAI,CAAC,KAA0B,EAC/B,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAO,CACb,CAAC;IACF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;IACE,WAAW,EACT,+HAA+H;IACjI,WAAW,EAAE;QACX,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACtE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,sCAAsC,CAAC;KACpD;CACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACjE,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;IACE,WAAW,EACT,yFAAyF;CAC5F,EACD,KAAK,IAAI,EAAE;IACT,MAAM,MAAM,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAC5C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;IACE,WAAW,EACT,qLAAqL;CACxL,EACD,KAAK,IAAI,EAAE;IACT,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IACpC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,wBAAwB,EAAE,CAAC;IAE3B,MAAM,WAAW,EAAE,CAAC;IAEpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,IAAI,cAAc;YAAE,OAAO;QAC3B,cAAc,GAAG,IAAI,CAAC;QAEtB,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChC,SAAS,EAAE,CAAC;QAEZ,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;YAC/D,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,EAAE,IAAI,CAAC,CAAC;QAET,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,sBAAsB,CAAC,CAAC;YACrD,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAEjC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAErC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,aAAa,CAAC,CAAC;IAC5C,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,eAAO,MAAM,MAAM,6BAKlB,CAAC;AAEF,wBAAgB,SAAS,IAAI,IAAI,CAEhC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import pino from "pino";
|
|
2
|
+
const destination = pino.destination({ dest: 2, sync: false });
|
|
3
|
+
export const logger = pino({
|
|
4
|
+
level: process.env.LOG_LEVEL || "info",
|
|
5
|
+
}, destination);
|
|
6
|
+
export function flushLogs() {
|
|
7
|
+
destination.flushSync();
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAE/D,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CACxB;IACE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;CACvC,EACD,WAAW,CACZ,CAAC;AAEF,MAAM,UAAU,SAAS;IACvB,WAAW,CAAC,SAAS,EAAE,CAAC;AAC1B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-walkthrough",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for interactive code walkthroughs - Claude-driven code tours",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-walkthrough": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"vscode-extension/walkthrough-bridge.vsix",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"author": "Stefan Nitu",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"walkthrough",
|
|
22
|
+
"code-tour",
|
|
23
|
+
"claude-code"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "npm run build:extension && tsc -p tsconfig.build.json",
|
|
27
|
+
"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",
|
|
28
|
+
"postinstall": "node -e \"try{require('child_process').execSync('code --install-extension '+require('path').join(__dirname,'vscode-extension','walkthrough-bridge.vsix')+' --force',{stdio:'ignore'})}catch{}\"",
|
|
29
|
+
"dev": "bun --watch src/index.ts",
|
|
30
|
+
"start": "node dist/index.js",
|
|
31
|
+
"test": "bun test",
|
|
32
|
+
"test:watch": "bun test --watch",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"lint": "biome check",
|
|
35
|
+
"lint:fix": "biome check --write",
|
|
36
|
+
"check": "bun run typecheck && bun run lint",
|
|
37
|
+
"prepare": "husky"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.18.1",
|
|
41
|
+
"pino": "^10.0.0",
|
|
42
|
+
"zod": "^3.25.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@biomejs/biome": "^2.4.9",
|
|
46
|
+
"@types/bun": "latest",
|
|
47
|
+
"husky": "^9.1.7",
|
|
48
|
+
"typescript": "^6.0.2"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
Binary file
|