@_davideast/stitch-mcp 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -89
- package/dist/cli.js +219 -40
- package/dist/index.js +60 -26
- package/dist/ui/serve-behaviors/handlers.d.ts +9 -0
- package/dist/ui/serve-behaviors/index.d.ts +7 -0
- package/dist/ui/serve-behaviors/registry.d.ts +10 -0
- package/dist/ui/serve-behaviors/server.d.ts +8 -0
- package/dist/ui/serve-behaviors/types.d.ts +18 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,58 +19,14 @@ This single command will:
|
|
|
19
19
|
6. Enable Stitch API
|
|
20
20
|
7. Generate MCP configuration for your client
|
|
21
21
|
|
|
22
|
-
**Example session:**
|
|
23
|
-
```
|
|
24
|
-
Stitch MCP Setup
|
|
25
|
-
|
|
26
|
-
Step 1: Select your MCP client
|
|
27
|
-
✔ Which MCP client are you using? Antigravity
|
|
28
|
-
|
|
29
|
-
Step 2: Setting up Google Cloud CLI
|
|
30
|
-
✔ Google Cloud CLI ready (bundled): v552.0.0
|
|
31
|
-
|
|
32
|
-
Step 3: Setup Authentication
|
|
33
|
-
✔ Check your current setup status? Yes
|
|
34
|
-
|
|
35
|
-
Authenticate with Google Cloud
|
|
36
|
-
|
|
37
|
-
CLOUDSDK_CONFIG="~/.stitch-mcp/config" gcloud auth login
|
|
38
|
-
|
|
39
|
-
(copied to clipboard)
|
|
40
|
-
✔ Press Enter when complete Yes
|
|
41
|
-
✔ Logged in as you@gmail.com
|
|
42
|
-
|
|
43
|
-
Authorize Application Default Credentials
|
|
44
|
-
|
|
45
|
-
CLOUDSDK_CONFIG="~/.stitch-mcp/config" gcloud auth application-default login
|
|
46
|
-
|
|
47
|
-
(copied to clipboard)
|
|
48
|
-
✔ Press Enter when complete Yes
|
|
49
|
-
✔ ADC configured
|
|
50
|
-
|
|
51
|
-
Step 4: Select a Google Cloud project
|
|
52
|
-
✔ Select a project: My Project (my-project-id)
|
|
53
|
-
|
|
54
|
-
Step 5: Configure IAM Permissions
|
|
55
|
-
✔ Required IAM role is already configured.
|
|
56
|
-
|
|
57
|
-
Step 6: Generating MCP Configuration
|
|
58
|
-
✔ Configuration generated
|
|
59
|
-
|
|
60
|
-
Setup Complete! ✔
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
**How it works:** Commands are displayed and automatically copied to your clipboard. Run the command in your terminal, complete the OAuth flow in your browser, then press Enter to continue.
|
|
64
|
-
|
|
65
22
|
**Example output:**
|
|
66
23
|
```json
|
|
67
24
|
{
|
|
68
25
|
"mcpServers": {
|
|
69
26
|
"stitch": {
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
|
|
73
|
-
"STITCH_PROJECT_ID": "your-project-id"
|
|
27
|
+
"serverUrl": "https://stitch.googleapis.com/mcp",
|
|
28
|
+
"headers": {
|
|
29
|
+
"X-Goog-Api-Key": "YOUR-API-KEY"
|
|
74
30
|
}
|
|
75
31
|
}
|
|
76
32
|
}
|
|
@@ -79,46 +35,6 @@ Setup Complete! ✔
|
|
|
79
35
|
|
|
80
36
|
Copy this config into your MCP client settings and you're ready to use the Stitch MCP server.
|
|
81
37
|
|
|
82
|
-
## Quick Start (Existing gcloud Users)
|
|
83
|
-
|
|
84
|
-
If you already have `gcloud` configured, skip `init` and use the proxy directly.
|
|
85
|
-
|
|
86
|
-
**Prerequisites:**
|
|
87
|
-
```bash
|
|
88
|
-
# 1. Application Default Credentials
|
|
89
|
-
gcloud auth application-default login
|
|
90
|
-
|
|
91
|
-
# 2. Set project (if not already set)
|
|
92
|
-
gcloud config set project <PROJECT_ID>
|
|
93
|
-
|
|
94
|
-
# 3. Enable Stitch API (requires beta component)
|
|
95
|
-
gcloud components install beta
|
|
96
|
-
gcloud beta services mcp enable stitch.googleapis.com --project=<PROJECT_ID>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
**MCP Configuration:**
|
|
100
|
-
```json
|
|
101
|
-
{
|
|
102
|
-
"mcpServers": {
|
|
103
|
-
"stitch": {
|
|
104
|
-
"command": "npx",
|
|
105
|
-
"args": ["@_davideast/stitch-mcp", "proxy"],
|
|
106
|
-
"env": {
|
|
107
|
-
"STITCH_USE_SYSTEM_GCLOUD": "1"
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**Environment Variables:**
|
|
115
|
-
| Variable | Description |
|
|
116
|
-
|----------|-------------|
|
|
117
|
-
| `STITCH_USE_SYSTEM_GCLOUD` | Use system gcloud config instead of isolated config |
|
|
118
|
-
| `STITCH_PROJECT_ID` | Override project ID |
|
|
119
|
-
| `GOOGLE_CLOUD_PROJECT` | Alternative project ID variable |
|
|
120
|
-
| `STITCH_HOST` | Custom Stitch API endpoint |
|
|
121
|
-
|
|
122
38
|
## Verify Your Setup
|
|
123
39
|
|
|
124
40
|
```bash
|
|
@@ -217,7 +133,7 @@ Revokes both user authentication and Application Default Credentials. Useful for
|
|
|
217
133
|
- Clearing authentication for testing
|
|
218
134
|
- Resetting state when troubleshooting
|
|
219
135
|
|
|
220
|
-
#### `view` -
|
|
136
|
+
#### `view` - Interactive Resource Viewer
|
|
221
137
|
|
|
222
138
|
```bash
|
|
223
139
|
npx @_davideast/stitch-mcp view [options]
|
|
@@ -230,7 +146,41 @@ npx @_davideast/stitch-mcp view [options]
|
|
|
230
146
|
- `--project <id>` - Project ID
|
|
231
147
|
- `--screen <id>` - Screen ID
|
|
232
148
|
|
|
233
|
-
Interactively
|
|
149
|
+
Interactively browse Stitch resources in a navigable JSON tree. Supports drilling into nested objects and performing actions on selected nodes.
|
|
150
|
+
|
|
151
|
+
**Keyboard Shortcuts:**
|
|
152
|
+
|
|
153
|
+
| Key | Action |
|
|
154
|
+
|-----|--------|
|
|
155
|
+
| `↑` / `↓` | Navigate up/down |
|
|
156
|
+
| `Enter` | Expand/collapse or drill into nested object |
|
|
157
|
+
| `Backspace` | Go back one level |
|
|
158
|
+
| `c` | Copy selected value to clipboard |
|
|
159
|
+
| `cc` | Extended copy (downloads content for URLs) |
|
|
160
|
+
| `s` | **Preview HTML** - serves `htmlCode` in-memory and opens browser |
|
|
161
|
+
| `o` | Open project in Stitch web app |
|
|
162
|
+
| `q` | Quit viewer |
|
|
163
|
+
|
|
164
|
+
**HTML Preview Feature:**
|
|
165
|
+
|
|
166
|
+
When viewing a screen, select the `htmlCode` node and press `s` to:
|
|
167
|
+
1. Download the HTML code from Stitch
|
|
168
|
+
2. Start a local server (auto-closes after 5 minutes)
|
|
169
|
+
3. Open your browser to preview the rendered HTML
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
Selected Path: screen.htmlCode | 'c' copy, 'cc' extended, 's' preview
|
|
173
|
+
🌐 Preview at http://127.0.0.1:54268 (auto-closes in 5 min)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Example Usage:**
|
|
177
|
+
```bash
|
|
178
|
+
# Browse all projects
|
|
179
|
+
npx @_davideast/stitch-mcp view --projects
|
|
180
|
+
|
|
181
|
+
# View a specific screen
|
|
182
|
+
npx @_davideast/stitch-mcp view --project <project-id> --screen <screen-id>
|
|
183
|
+
```
|
|
234
184
|
|
|
235
185
|
#### `proxy` - MCP Proxy Server
|
|
236
186
|
|
|
@@ -249,6 +199,46 @@ This command is typically configured as the entry point in your MCP client setti
|
|
|
249
199
|
- Error handling
|
|
250
200
|
- Debug logging (when `--debug` is enabled to `/tmp/stitch-proxy-debug.log`)
|
|
251
201
|
|
|
202
|
+
## OAuth setup with gcloud
|
|
203
|
+
|
|
204
|
+
If you already have `gcloud` configured, skip `init` and use the proxy directly.
|
|
205
|
+
|
|
206
|
+
**Prerequisites:**
|
|
207
|
+
```bash
|
|
208
|
+
# 1. Application Default Credentials
|
|
209
|
+
gcloud auth application-default login
|
|
210
|
+
|
|
211
|
+
# 2. Set project (if not already set)
|
|
212
|
+
gcloud config set project <PROJECT_ID>
|
|
213
|
+
|
|
214
|
+
# 3. Enable Stitch API (requires beta component)
|
|
215
|
+
gcloud components install beta
|
|
216
|
+
gcloud beta services mcp enable stitch.googleapis.com --project=<PROJECT_ID>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**MCP Configuration:**
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"mcpServers": {
|
|
223
|
+
"stitch": {
|
|
224
|
+
"command": "npx",
|
|
225
|
+
"args": ["@_davideast/stitch-mcp", "proxy"],
|
|
226
|
+
"env": {
|
|
227
|
+
"STITCH_USE_SYSTEM_GCLOUD": "1"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Environment Variables:**
|
|
235
|
+
| Variable | Description |
|
|
236
|
+
|----------|-------------|
|
|
237
|
+
| `STITCH_USE_SYSTEM_GCLOUD` | Use system gcloud config instead of isolated config |
|
|
238
|
+
| `STITCH_PROJECT_ID` | Override project ID |
|
|
239
|
+
| `GOOGLE_CLOUD_PROJECT` | Alternative project ID variable |
|
|
240
|
+
| `STITCH_HOST` | Custom Stitch API endpoint |
|
|
241
|
+
|
|
252
242
|
### How It Works
|
|
253
243
|
|
|
254
244
|
#### Automatic gcloud Management
|
package/dist/cli.js
CHANGED
|
@@ -72134,6 +72134,8 @@ var init_build2 = __esm(async () => {
|
|
|
72134
72134
|
});
|
|
72135
72135
|
|
|
72136
72136
|
// src/ui/copy-behaviors/clipboard.ts
|
|
72137
|
+
import { writeFile, unlink } from "fs/promises";
|
|
72138
|
+
import { spawn as spawn3 } from "child_process";
|
|
72137
72139
|
async function copyText(text) {
|
|
72138
72140
|
await clipboardy_default.write(text);
|
|
72139
72141
|
}
|
|
@@ -72141,6 +72143,19 @@ async function copyJson(value) {
|
|
|
72141
72143
|
const text = typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
72142
72144
|
await clipboardy_default.write(text);
|
|
72143
72145
|
}
|
|
72146
|
+
function spawnAndWait(command, args) {
|
|
72147
|
+
return new Promise((resolve, reject) => {
|
|
72148
|
+
const proc = spawn3(command, args, { stdio: "ignore" });
|
|
72149
|
+
proc.on("close", (code) => {
|
|
72150
|
+
if (code === 0) {
|
|
72151
|
+
resolve();
|
|
72152
|
+
} else {
|
|
72153
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
72154
|
+
}
|
|
72155
|
+
});
|
|
72156
|
+
proc.on("error", reject);
|
|
72157
|
+
});
|
|
72158
|
+
}
|
|
72144
72159
|
async function downloadAndCopyImage(url2) {
|
|
72145
72160
|
const response = await fetch(url2);
|
|
72146
72161
|
if (!response.ok) {
|
|
@@ -72148,19 +72163,21 @@ async function downloadAndCopyImage(url2) {
|
|
|
72148
72163
|
}
|
|
72149
72164
|
const buffer = await response.arrayBuffer();
|
|
72150
72165
|
const tempPath = `/tmp/stitch-clipboard-${Date.now()}.png`;
|
|
72151
|
-
await
|
|
72166
|
+
await writeFile(tempPath, Buffer.from(buffer));
|
|
72152
72167
|
const platform3 = process.platform;
|
|
72153
|
-
|
|
72154
|
-
|
|
72155
|
-
|
|
72156
|
-
|
|
72157
|
-
|
|
72158
|
-
|
|
72159
|
-
|
|
72160
|
-
|
|
72161
|
-
|
|
72162
|
-
|
|
72163
|
-
|
|
72168
|
+
try {
|
|
72169
|
+
if (platform3 === "darwin") {
|
|
72170
|
+
await spawnAndWait("osascript", ["-e", `set the clipboard to (read (POSIX file "${tempPath}") as TIFF picture)`]);
|
|
72171
|
+
} else if (platform3 === "linux") {
|
|
72172
|
+
await spawnAndWait("xclip", ["-selection", "clipboard", "-t", "image/png", "-i", tempPath]);
|
|
72173
|
+
} else if (platform3 === "win32") {
|
|
72174
|
+
await spawnAndWait("powershell", ["-command", `Set-Clipboard -Path "${tempPath}"`]);
|
|
72175
|
+
}
|
|
72176
|
+
} finally {
|
|
72177
|
+
try {
|
|
72178
|
+
await unlink(tempPath);
|
|
72179
|
+
} catch {}
|
|
72180
|
+
}
|
|
72164
72181
|
}
|
|
72165
72182
|
async function downloadAndCopyText(url2) {
|
|
72166
72183
|
const response = await fetch(url2);
|
|
@@ -72319,6 +72336,106 @@ var init_navigation_behaviors = __esm(() => {
|
|
|
72319
72336
|
];
|
|
72320
72337
|
});
|
|
72321
72338
|
|
|
72339
|
+
// src/ui/serve-behaviors/server.ts
|
|
72340
|
+
import { createServer } from "node:http";
|
|
72341
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
72342
|
+
async function serveHtmlInMemory(html, options) {
|
|
72343
|
+
const timeout = options?.timeout ?? 5 * 60 * 1000;
|
|
72344
|
+
const openBrowser = options?.openBrowser ?? true;
|
|
72345
|
+
return new Promise((resolve, reject) => {
|
|
72346
|
+
const server = createServer((req, res) => {
|
|
72347
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
72348
|
+
res.end(html);
|
|
72349
|
+
});
|
|
72350
|
+
server.listen(0, "127.0.0.1", () => {
|
|
72351
|
+
const address = server.address();
|
|
72352
|
+
if (!address || typeof address === "string") {
|
|
72353
|
+
reject(new Error("Failed to get server address"));
|
|
72354
|
+
return;
|
|
72355
|
+
}
|
|
72356
|
+
const url2 = `http://127.0.0.1:${address.port}`;
|
|
72357
|
+
const timer = setTimeout(() => server.close(), timeout);
|
|
72358
|
+
const stop = () => {
|
|
72359
|
+
clearTimeout(timer);
|
|
72360
|
+
server.close();
|
|
72361
|
+
};
|
|
72362
|
+
if (openBrowser) {
|
|
72363
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
72364
|
+
const args = process.platform === "win32" ? ["/c", "start", url2] : [url2];
|
|
72365
|
+
spawn4(cmd, args, { detached: true, stdio: "ignore" }).unref();
|
|
72366
|
+
}
|
|
72367
|
+
resolve({ url: url2, stop });
|
|
72368
|
+
});
|
|
72369
|
+
server.on("error", reject);
|
|
72370
|
+
});
|
|
72371
|
+
}
|
|
72372
|
+
var init_server = () => {};
|
|
72373
|
+
|
|
72374
|
+
// src/ui/serve-behaviors/handlers.ts
|
|
72375
|
+
var deps, htmlCodeServeHandler;
|
|
72376
|
+
var init_handlers2 = __esm(() => {
|
|
72377
|
+
init_server();
|
|
72378
|
+
deps = {
|
|
72379
|
+
serveHtmlInMemory
|
|
72380
|
+
};
|
|
72381
|
+
htmlCodeServeHandler = {
|
|
72382
|
+
async serve(ctx) {
|
|
72383
|
+
try {
|
|
72384
|
+
let url2;
|
|
72385
|
+
if (typeof ctx.value === "string") {
|
|
72386
|
+
url2 = ctx.value;
|
|
72387
|
+
} else if (typeof ctx.value === "object" && ctx.value?.downloadUrl) {
|
|
72388
|
+
url2 = ctx.value.downloadUrl;
|
|
72389
|
+
} else {
|
|
72390
|
+
return { success: false, message: "No download URL found" };
|
|
72391
|
+
}
|
|
72392
|
+
ctx.onProgress?.("\uD83D\uDCE5 Downloading HTML...");
|
|
72393
|
+
const response = await fetch(url2);
|
|
72394
|
+
if (!response.ok) {
|
|
72395
|
+
return { success: false, message: `Download failed: ${response.status} ${response.statusText}` };
|
|
72396
|
+
}
|
|
72397
|
+
const html = await response.text();
|
|
72398
|
+
ctx.onProgress?.("\uD83D\uDE80 Starting local server...");
|
|
72399
|
+
const { url: serveUrl } = await deps.serveHtmlInMemory(html);
|
|
72400
|
+
ctx.onProgress?.("\uD83C\uDF10 Opening browser...");
|
|
72401
|
+
return { success: true, message: `\uD83C\uDF10 Preview at ${serveUrl} (auto-closes in 5 min)`, url: serveUrl };
|
|
72402
|
+
} catch (error2) {
|
|
72403
|
+
return { success: false, message: `Serve failed: ${error2 instanceof Error ? error2.message : String(error2)}` };
|
|
72404
|
+
}
|
|
72405
|
+
}
|
|
72406
|
+
};
|
|
72407
|
+
});
|
|
72408
|
+
|
|
72409
|
+
// src/ui/serve-behaviors/registry.ts
|
|
72410
|
+
function registerServeHandler(matcher, handler2) {
|
|
72411
|
+
registrations2.push({ matcher, handler: handler2 });
|
|
72412
|
+
}
|
|
72413
|
+
function getServeHandler(path10) {
|
|
72414
|
+
for (let i2 = registrations2.length - 1;i2 >= 0; i2--) {
|
|
72415
|
+
const reg = registrations2[i2];
|
|
72416
|
+
if (reg && reg.matcher(path10))
|
|
72417
|
+
return reg.handler;
|
|
72418
|
+
}
|
|
72419
|
+
return null;
|
|
72420
|
+
}
|
|
72421
|
+
function endsWith2(suffix) {
|
|
72422
|
+
return (path10) => path10.endsWith(suffix);
|
|
72423
|
+
}
|
|
72424
|
+
var registrations2;
|
|
72425
|
+
var init_registry2 = __esm(() => {
|
|
72426
|
+
init_handlers2();
|
|
72427
|
+
registrations2 = [];
|
|
72428
|
+
registerServeHandler(endsWith2(".htmlCode"), htmlCodeServeHandler);
|
|
72429
|
+
registerServeHandler(endsWith2(".htmlCode.downloadUrl"), htmlCodeServeHandler);
|
|
72430
|
+
});
|
|
72431
|
+
|
|
72432
|
+
// src/ui/serve-behaviors/index.ts
|
|
72433
|
+
var init_serve_behaviors = __esm(() => {
|
|
72434
|
+
init_server();
|
|
72435
|
+
init_handlers2();
|
|
72436
|
+
init_registry2();
|
|
72437
|
+
});
|
|
72438
|
+
|
|
72322
72439
|
// node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
72323
72440
|
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
72324
72441
|
var React10 = __toESM(require_react(), 1);
|
|
@@ -72543,6 +72660,7 @@ var require_jsx_dev_runtime = __commonJS((exports, module) => {
|
|
|
72543
72660
|
});
|
|
72544
72661
|
|
|
72545
72662
|
// src/ui/JsonTree.tsx
|
|
72663
|
+
import { spawn as spawn5 } from "child_process";
|
|
72546
72664
|
function getType(value) {
|
|
72547
72665
|
if (value === null)
|
|
72548
72666
|
return "null";
|
|
@@ -72648,6 +72766,32 @@ var import_react26, jsx_dev_runtime, JsonTree = ({ data, rootLabel, onNavigate,
|
|
|
72648
72766
|
}
|
|
72649
72767
|
return;
|
|
72650
72768
|
}
|
|
72769
|
+
if (input === "s") {
|
|
72770
|
+
const node = visibleNodes[selectedIndex];
|
|
72771
|
+
if (!node)
|
|
72772
|
+
return;
|
|
72773
|
+
const handler2 = getServeHandler(node.id);
|
|
72774
|
+
if (!handler2) {
|
|
72775
|
+
if (feedbackTimeout.current)
|
|
72776
|
+
clearTimeout(feedbackTimeout.current);
|
|
72777
|
+
setFeedbackMessage("⚠️ No preview available for this path");
|
|
72778
|
+
feedbackTimeout.current = setTimeout(() => setFeedbackMessage(null), 3000);
|
|
72779
|
+
return;
|
|
72780
|
+
}
|
|
72781
|
+
const onProgress = (message) => {
|
|
72782
|
+
if (feedbackTimeout.current)
|
|
72783
|
+
clearTimeout(feedbackTimeout.current);
|
|
72784
|
+
setFeedbackMessage(message);
|
|
72785
|
+
};
|
|
72786
|
+
const ctx = { key: node.key, value: node.value, path: node.id, onProgress };
|
|
72787
|
+
handler2.serve(ctx).then((result) => {
|
|
72788
|
+
if (feedbackTimeout.current)
|
|
72789
|
+
clearTimeout(feedbackTimeout.current);
|
|
72790
|
+
setFeedbackMessage(result.message);
|
|
72791
|
+
feedbackTimeout.current = setTimeout(() => setFeedbackMessage(null), 1e4);
|
|
72792
|
+
});
|
|
72793
|
+
return;
|
|
72794
|
+
}
|
|
72651
72795
|
if (input === "o") {
|
|
72652
72796
|
const node = visibleNodes[selectedIndex];
|
|
72653
72797
|
if (!node)
|
|
@@ -72682,7 +72826,7 @@ var import_react26, jsx_dev_runtime, JsonTree = ({ data, rootLabel, onNavigate,
|
|
|
72682
72826
|
if (projectId) {
|
|
72683
72827
|
const url2 = `https://stitch.withgoogle.com/projects/${projectId}`;
|
|
72684
72828
|
const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
72685
|
-
|
|
72829
|
+
spawn5(openCmd, [url2], { stdio: "ignore", detached: true }).unref();
|
|
72686
72830
|
if (feedbackTimeout.current)
|
|
72687
72831
|
clearTimeout(feedbackTimeout.current);
|
|
72688
72832
|
setFeedbackMessage(`\uD83D\uDD17 Opened project in browser`);
|
|
@@ -72837,7 +72981,7 @@ var import_react26, jsx_dev_runtime, JsonTree = ({ data, rootLabel, onNavigate,
|
|
|
72837
72981
|
children: [
|
|
72838
72982
|
"Selected Path: ",
|
|
72839
72983
|
visibleNodes[selectedIndex]?.id || "none",
|
|
72840
|
-
" |
|
|
72984
|
+
" | 'c' copy, 'cc' extended, 's' preview"
|
|
72841
72985
|
]
|
|
72842
72986
|
}, undefined, true, undefined, this),
|
|
72843
72987
|
feedbackMessage && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
@@ -72853,6 +72997,7 @@ var init_JsonTree = __esm(async () => {
|
|
|
72853
72997
|
await init_build2();
|
|
72854
72998
|
init_copy_behaviors();
|
|
72855
72999
|
init_navigation_behaviors();
|
|
73000
|
+
init_serve_behaviors();
|
|
72856
73001
|
jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
72857
73002
|
});
|
|
72858
73003
|
|
|
@@ -75538,10 +75683,10 @@ class McpConfigHandler {
|
|
|
75538
75683
|
if (input.client === "claude-code" || input.client === "gemini-cli" || input.client === "codex") {
|
|
75539
75684
|
return null;
|
|
75540
75685
|
}
|
|
75541
|
-
const env2 = {
|
|
75542
|
-
|
|
75543
|
-
|
|
75544
|
-
|
|
75686
|
+
const env2 = {};
|
|
75687
|
+
if (!input.apiKey) {
|
|
75688
|
+
env2.STITCH_PROJECT_ID = input.projectId;
|
|
75689
|
+
} else {
|
|
75545
75690
|
env2.STITCH_API_KEY = input.apiKey;
|
|
75546
75691
|
}
|
|
75547
75692
|
if (input.client === "vscode") {
|
|
@@ -75701,24 +75846,52 @@ ${theme.green("Setup Gemini CLI:")}
|
|
|
75701
75846
|
`;
|
|
75702
75847
|
case "codex": {
|
|
75703
75848
|
const isHttp = transport === "http";
|
|
75704
|
-
|
|
75705
|
-
|
|
75706
|
-
|
|
75707
|
-
|
|
75708
|
-
|
|
75709
|
-
|
|
75710
|
-
|
|
75711
|
-
|
|
75712
|
-
`
|
|
75713
|
-
|
|
75714
|
-
|
|
75715
|
-
|
|
75716
|
-
|
|
75717
|
-
|
|
75718
|
-
|
|
75719
|
-
|
|
75849
|
+
let configBlock;
|
|
75850
|
+
if (isHttp) {
|
|
75851
|
+
if (apiKey) {
|
|
75852
|
+
configBlock = [
|
|
75853
|
+
"[mcp_servers.stitch]",
|
|
75854
|
+
'url = "https://stitch.googleapis.com/mcp"',
|
|
75855
|
+
"",
|
|
75856
|
+
"[mcp_servers.stitch.env_http_headers]",
|
|
75857
|
+
`X-Goog-Api-Key = "${apiKey}"`
|
|
75858
|
+
].join(`
|
|
75859
|
+
`);
|
|
75860
|
+
} else {
|
|
75861
|
+
configBlock = [
|
|
75862
|
+
"[mcp_servers.stitch]",
|
|
75863
|
+
'url = "https://stitch.googleapis.com/mcp"',
|
|
75864
|
+
'bearer_token_env_var = "STITCH_ACCESS_TOKEN"',
|
|
75865
|
+
"",
|
|
75866
|
+
"[mcp_servers.stitch.env_http_headers]",
|
|
75867
|
+
'X-Goog-User-Project = "GOOGLE_CLOUD_PROJECT"'
|
|
75868
|
+
].join(`
|
|
75869
|
+
`);
|
|
75870
|
+
}
|
|
75871
|
+
} else {
|
|
75872
|
+
if (apiKey) {
|
|
75873
|
+
configBlock = [
|
|
75874
|
+
"[mcp_servers.stitch]",
|
|
75875
|
+
'command = "npx"',
|
|
75876
|
+
'args = ["@_davideast/stitch-mcp", "proxy"]',
|
|
75877
|
+
"",
|
|
75878
|
+
"[mcp_servers.stitch.env]",
|
|
75879
|
+
`STITCH_API_KEY = "${apiKey}"`
|
|
75880
|
+
].join(`
|
|
75720
75881
|
`);
|
|
75721
|
-
|
|
75882
|
+
} else {
|
|
75883
|
+
configBlock = [
|
|
75884
|
+
"[mcp_servers.stitch]",
|
|
75885
|
+
'command = "npx"',
|
|
75886
|
+
'args = ["@_davideast/stitch-mcp", "proxy"]',
|
|
75887
|
+
"",
|
|
75888
|
+
"[mcp_servers.stitch.env]",
|
|
75889
|
+
`STITCH_PROJECT_ID = "${projectId}"`
|
|
75890
|
+
].join(`
|
|
75891
|
+
`);
|
|
75892
|
+
}
|
|
75893
|
+
}
|
|
75894
|
+
const note = isHttp && !apiKey ? `${theme.yellow("Note:")} Direct mode requires a valid access token in ${theme.blue("STITCH_ACCESS_TOKEN")} and a project id in ${theme.blue("GOOGLE_CLOUD_PROJECT")}.
|
|
75722
75895
|
` : `${theme.yellow("Note:")} Proxy mode handles token refresh automatically.
|
|
75723
75896
|
`;
|
|
75724
75897
|
return `
|
|
@@ -77063,16 +77236,22 @@ ${theme.green("\uD83C\uDF89 Setup complete!")}
|
|
|
77063
77236
|
return;
|
|
77064
77237
|
}
|
|
77065
77238
|
if (transport === "stdio") {
|
|
77239
|
+
const env3 = {
|
|
77240
|
+
PATH: process.env.PATH || ""
|
|
77241
|
+
};
|
|
77242
|
+
if (apiKey) {
|
|
77243
|
+
env3.STITCH_API_KEY = apiKey;
|
|
77244
|
+
} else {
|
|
77245
|
+
env3.STITCH_PROJECT_ID = projectId;
|
|
77246
|
+
}
|
|
77066
77247
|
config.mcpServers.stitch = {
|
|
77067
77248
|
command: "npx",
|
|
77068
77249
|
args: ["@_davideast/stitch-mcp", "proxy"],
|
|
77069
|
-
env:
|
|
77070
|
-
STITCH_PROJECT_ID: projectId,
|
|
77071
|
-
PATH: process.env.PATH || ""
|
|
77072
|
-
}
|
|
77250
|
+
env: env3
|
|
77073
77251
|
};
|
|
77074
77252
|
fs10.writeFileSync(extensionPath, JSON.stringify(config, null, 4));
|
|
77075
|
-
|
|
77253
|
+
const successMsg = apiKey ? "Stitch extension configured for STDIO with API Key" : `Stitch extension configured for STDIO: Project ID set to ${theme.blue(projectId)}`;
|
|
77254
|
+
spinner.succeed(successMsg);
|
|
77076
77255
|
} else {
|
|
77077
77256
|
const existingHeaders = config.mcpServers.stitch.headers || {};
|
|
77078
77257
|
if (apiKey) {
|
package/dist/index.js
CHANGED
|
@@ -18885,10 +18885,10 @@ class McpConfigHandler {
|
|
|
18885
18885
|
if (input.client === "claude-code" || input.client === "gemini-cli" || input.client === "codex") {
|
|
18886
18886
|
return null;
|
|
18887
18887
|
}
|
|
18888
|
-
const env2 = {
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
18888
|
+
const env2 = {};
|
|
18889
|
+
if (!input.apiKey) {
|
|
18890
|
+
env2.STITCH_PROJECT_ID = input.projectId;
|
|
18891
|
+
} else {
|
|
18892
18892
|
env2.STITCH_API_KEY = input.apiKey;
|
|
18893
18893
|
}
|
|
18894
18894
|
if (input.client === "vscode") {
|
|
@@ -19048,24 +19048,52 @@ ${theme.green("Setup Gemini CLI:")}
|
|
|
19048
19048
|
`;
|
|
19049
19049
|
case "codex": {
|
|
19050
19050
|
const isHttp = transport === "http";
|
|
19051
|
-
|
|
19052
|
-
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19057
|
-
|
|
19058
|
-
|
|
19059
|
-
`
|
|
19060
|
-
|
|
19061
|
-
|
|
19062
|
-
|
|
19063
|
-
|
|
19064
|
-
|
|
19065
|
-
|
|
19066
|
-
|
|
19051
|
+
let configBlock;
|
|
19052
|
+
if (isHttp) {
|
|
19053
|
+
if (apiKey) {
|
|
19054
|
+
configBlock = [
|
|
19055
|
+
"[mcp_servers.stitch]",
|
|
19056
|
+
'url = "https://stitch.googleapis.com/mcp"',
|
|
19057
|
+
"",
|
|
19058
|
+
"[mcp_servers.stitch.env_http_headers]",
|
|
19059
|
+
`X-Goog-Api-Key = "${apiKey}"`
|
|
19060
|
+
].join(`
|
|
19061
|
+
`);
|
|
19062
|
+
} else {
|
|
19063
|
+
configBlock = [
|
|
19064
|
+
"[mcp_servers.stitch]",
|
|
19065
|
+
'url = "https://stitch.googleapis.com/mcp"',
|
|
19066
|
+
'bearer_token_env_var = "STITCH_ACCESS_TOKEN"',
|
|
19067
|
+
"",
|
|
19068
|
+
"[mcp_servers.stitch.env_http_headers]",
|
|
19069
|
+
'X-Goog-User-Project = "GOOGLE_CLOUD_PROJECT"'
|
|
19070
|
+
].join(`
|
|
19071
|
+
`);
|
|
19072
|
+
}
|
|
19073
|
+
} else {
|
|
19074
|
+
if (apiKey) {
|
|
19075
|
+
configBlock = [
|
|
19076
|
+
"[mcp_servers.stitch]",
|
|
19077
|
+
'command = "npx"',
|
|
19078
|
+
'args = ["@_davideast/stitch-mcp", "proxy"]',
|
|
19079
|
+
"",
|
|
19080
|
+
"[mcp_servers.stitch.env]",
|
|
19081
|
+
`STITCH_API_KEY = "${apiKey}"`
|
|
19082
|
+
].join(`
|
|
19067
19083
|
`);
|
|
19068
|
-
|
|
19084
|
+
} else {
|
|
19085
|
+
configBlock = [
|
|
19086
|
+
"[mcp_servers.stitch]",
|
|
19087
|
+
'command = "npx"',
|
|
19088
|
+
'args = ["@_davideast/stitch-mcp", "proxy"]',
|
|
19089
|
+
"",
|
|
19090
|
+
"[mcp_servers.stitch.env]",
|
|
19091
|
+
`STITCH_PROJECT_ID = "${projectId}"`
|
|
19092
|
+
].join(`
|
|
19093
|
+
`);
|
|
19094
|
+
}
|
|
19095
|
+
}
|
|
19096
|
+
const note = isHttp && !apiKey ? `${theme.yellow("Note:")} Direct mode requires a valid access token in ${theme.blue("STITCH_ACCESS_TOKEN")} and a project id in ${theme.blue("GOOGLE_CLOUD_PROJECT")}.
|
|
19069
19097
|
` : `${theme.yellow("Note:")} Proxy mode handles token refresh automatically.
|
|
19070
19098
|
`;
|
|
19071
19099
|
return `
|
|
@@ -20412,16 +20440,22 @@ ${theme.green("\uD83C\uDF89 Setup complete!")}
|
|
|
20412
20440
|
return;
|
|
20413
20441
|
}
|
|
20414
20442
|
if (transport === "stdio") {
|
|
20443
|
+
const env3 = {
|
|
20444
|
+
PATH: process.env.PATH || ""
|
|
20445
|
+
};
|
|
20446
|
+
if (apiKey) {
|
|
20447
|
+
env3.STITCH_API_KEY = apiKey;
|
|
20448
|
+
} else {
|
|
20449
|
+
env3.STITCH_PROJECT_ID = projectId;
|
|
20450
|
+
}
|
|
20415
20451
|
config.mcpServers.stitch = {
|
|
20416
20452
|
command: "npx",
|
|
20417
20453
|
args: ["@_davideast/stitch-mcp", "proxy"],
|
|
20418
|
-
env:
|
|
20419
|
-
STITCH_PROJECT_ID: projectId,
|
|
20420
|
-
PATH: process.env.PATH || ""
|
|
20421
|
-
}
|
|
20454
|
+
env: env3
|
|
20422
20455
|
};
|
|
20423
20456
|
fs10.writeFileSync(extensionPath, JSON.stringify(config, null, 4));
|
|
20424
|
-
|
|
20457
|
+
const successMsg = apiKey ? "Stitch extension configured for STDIO with API Key" : `Stitch extension configured for STDIO: Project ID set to ${theme.blue(projectId)}`;
|
|
20458
|
+
spinner.succeed(successMsg);
|
|
20425
20459
|
} else {
|
|
20426
20460
|
const existingHeaders = config.mcpServers.stitch.headers || {};
|
|
20427
20461
|
if (apiKey) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serve handlers - isolated behavior implementations.
|
|
3
|
+
*/
|
|
4
|
+
import type { ServeHandler } from './types.js';
|
|
5
|
+
import { serveHtmlInMemory } from './server.js';
|
|
6
|
+
export declare const deps: {
|
|
7
|
+
serveHtmlInMemory: typeof serveHtmlInMemory;
|
|
8
|
+
};
|
|
9
|
+
export declare const htmlCodeServeHandler: ServeHandler;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serve behaviors for JSON viewer.
|
|
3
|
+
*/
|
|
4
|
+
export type { ServeHandler, ServeContext, ServeResult, PathMatcher } from './types.js';
|
|
5
|
+
export { serveHtmlInMemory } from './server.js';
|
|
6
|
+
export { htmlCodeServeHandler } from './handlers.js';
|
|
7
|
+
export { registerServeHandler, getServeHandler, endsWith, contains } from './registry.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry for path-based serve handler selection.
|
|
3
|
+
*/
|
|
4
|
+
import type { ServeHandler, PathMatcher } from './types.js';
|
|
5
|
+
import { htmlCodeServeHandler } from './handlers.js';
|
|
6
|
+
export declare function registerServeHandler(matcher: PathMatcher, handler: ServeHandler): void;
|
|
7
|
+
export declare function getServeHandler(path: string): ServeHandler | null;
|
|
8
|
+
export declare function endsWith(suffix: string): PathMatcher;
|
|
9
|
+
export declare function contains(segment: string): PathMatcher;
|
|
10
|
+
export { htmlCodeServeHandler };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serve behavior types for the JSON viewer.
|
|
3
|
+
*/
|
|
4
|
+
export interface ServeContext {
|
|
5
|
+
key: string;
|
|
6
|
+
value: any;
|
|
7
|
+
path: string;
|
|
8
|
+
onProgress?: (message: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface ServeResult {
|
|
11
|
+
success: boolean;
|
|
12
|
+
message: string;
|
|
13
|
+
url?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ServeHandler {
|
|
16
|
+
serve(ctx: ServeContext): Promise<ServeResult>;
|
|
17
|
+
}
|
|
18
|
+
export type PathMatcher = (path: string) => boolean;
|
package/package.json
CHANGED