Skip to content

Commit ff61335

Browse files
committed
chore: remove obsolete .browser-echo-mcp.json file, update pnpm-lock.yaml to use new package URLs, and adjust example app package.json files to reference updated browser-echo packages
1 parent 70c8792 commit ff61335

15 files changed

Lines changed: 319 additions & 59 deletions

File tree

.browser-echo-mcp.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

.cursor/mcp.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"mcpServers": {
33
"browser-echo": {
44
"command": "npx",
5-
"args": ["https://pkg.pr.new/instructa/browser-echo/@browser-echo/mcp@f6031a3"]
5+
"args": ["https://pkg.pr.new/instructa/browser-echo/@browser-echo/mcp@70c8792"]
66
}
77
}
88
}

example/next-app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"react-dom": "19.1.1"
1515
},
1616
"devDependencies": {
17-
"@browser-echo/mcp": "workspace:*",
18-
"@browser-echo/next": "workspace:*",
17+
"@browser-echo/mcp": "https://pkg.pr.new/instructa/browser-echo/@browser-echo/mcp@70c8792",
18+
"@browser-echo/next": "https://pkg.pr.new/instructa/browser-echo/@browser-echo/next@70c8792",
1919
"@eslint/eslintrc": "^3",
2020
"@tailwindcss/postcss": "^4.1.12",
2121
"@types/node": "^24.3.0",

example/nuxt-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
},
1717
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac",
1818
"devDependencies": {
19-
"@browser-echo/nuxt": "workspace:*"
19+
"@browser-echo/nuxt": "https://pkg.pr.new/instructa/browser-echo/@browser-echo/nuxt@70c8792"
2020
}
2121
}

example/react-vite-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"react-dom": "^19.1.1"
1515
},
1616
"devDependencies": {
17-
"@browser-echo/vite": "workspace:*",
17+
"@browser-echo/vite": "https://pkg.pr.new/instructa/browser-echo/@browser-echo/vite@70c8792",
1818
"@eslint/js": "^9.17.0",
1919
"@types/react": "^19.1.10",
2020
"@types/react-dom": "^19.1.7",

example/tanstack-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"zod": "^4.0.17"
1919
},
2020
"devDependencies": {
21-
"@browser-echo/vite": "workspace:*",
21+
"@browser-echo/vite": "https://pkg.pr.new/instructa/browser-echo/@browser-echo/vite@70c8792",
2222
"@types/node": "^24.3.0",
2323
"@types/react": "^19.1.10",
2424
"@types/react-dom": "^19.1.7",

example/vue-vite-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"vue": "^3.5.18"
1313
},
1414
"devDependencies": {
15-
"@browser-echo/vite": "workspace:*",
15+
"@browser-echo/vite": "https://pkg.pr.new/instructa/browser-echo/@browser-echo/vite@70c8792",
1616
"@vitejs/plugin-vue": "^6.0.1",
1717
"typescript": "~5.9.2",
1818
"vite": "^7.1.3",

example/vue-vite-app/vite.config.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ import browserEcho from '@browser-echo/vite'
66
export default defineConfig({
77
plugins: [vue(), browserEcho(
88
{
9-
stackMode: 'condensed',
10-
mcp: {
11-
suppressTerminal: true
12-
}
9+
stackMode: 'condensed'
1310
},
1411
)],
1512
})

packages/mcp/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,9 @@ publishLogEntry({
399399
- `BROWSER_ECHO_BUFFER_SIZE` — Max entries in memory (default: `1000`)
400400
- `BROWSER_ECHO_MCP_URL` — MCP server URL for framework forwarding (if set, frameworks bypass discovery)
401401
- `BROWSER_ECHO_INGEST_PORT` — Force a fixed ingest port in stdio mode (default: ephemeral)
402+
- `BROWSER_ECHO_ALLOW_TMP_DISCOVERY=1` — Opt-in to writing tmp discovery file; a token is generated and enforced via `x-be-token`
403+
- `BROWSER_ECHO_PROJECT_ROOT=/abs/path` — Explicit project root to embed in discovery metadata for correct scoping
404+
- `BROWSER_ECHO_ALLOW_PORT_SCAN=1` — Opt-in for the Vite plugin to use port scanning when discovery is unavailable
402405

403406
---
404407

packages/mcp/src/server.ts

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ export async function startHttpServer(
223223
await new Promise<void>((resolve) => nodeServer.listen(opts.port, opts.host, () => resolve()));
224224

225225
// Advertise discovery so providers can auto-detect this server locally
226-
await advertiseDiscovery(opts.host, opts.port, opts.logsRoute, { projectRoot: process.cwd(), scope: 'http' });
226+
await advertiseDiscovery(opts.host, opts.port, opts.logsRoute, { projectRoot: process.env.BROWSER_ECHO_PROJECT_ROOT || process.cwd(), scope: 'http' });
227227

228228
// eslint-disable-next-line no-console
229229
console.log(`MCP (Streamable HTTP) listening → http://${opts.host}:${opts.port}${opts.endpoint}`);
@@ -315,39 +315,60 @@ export async function startIngestOnlyServer(
315315
}
316316
}
317317

318-
// Only the primary (5179) should advertise to OS tmp to avoid discovery flapping
318+
// Advertise discovery for stdio transport. By default, only write project-local discovery.
319319
const requestedPort = opts.port;
320320
const isAggregator = requestedPort !== 0 && actualPort === requestedPort;
321-
await advertiseDiscovery(opts.host, actualPort, opts.logsRoute, { projectRoot: process.cwd(), scope: 'stdio', aggregator: isAggregator });
321+
await advertiseDiscovery(opts.host, actualPort, opts.logsRoute, { projectRoot: process.env.BROWSER_ECHO_PROJECT_ROOT || process.cwd(), scope: 'stdio', aggregator: isAggregator });
322322

323323
// eslint-disable-next-line no-console
324324
console.error(`Log ingest endpoint → http://${opts.host}:${actualPort}${opts.logsRoute}`);
325325
}
326326

327327
async function advertiseDiscovery(host: string, port: number, logsRoute: `/${string}`, meta?: { projectRoot?: string; token?: string; scope?: 'http' | 'stdio'; aggregator?: boolean }) {
328328
try {
329-
const { writeFileSync } = await import('node:fs');
329+
const { writeFileSync, chmodSync } = await import('node:fs');
330330
const { join } = await import('node:path');
331331
const { tmpdir } = await import('node:os');
332332

333333
const baseUrl = `http://${host}:${port}`;
334-
const payload = JSON.stringify({
334+
const allowTmp = process.env.BROWSER_ECHO_ALLOW_TMP_DISCOVERY === '1';
335+
const token = allowTmp ? (process.env.BROWSER_ECHO_DISCOVERY_TOKEN || randomUUID()) : undefined;
336+
if (allowTmp) {
337+
try { process.env.BROWSER_ECHO_DISCOVERY_TOKEN = token as string; } catch {}
338+
try { process.env.BROWSER_ECHO_REQUIRE_TOKEN = process.env.BROWSER_ECHO_REQUIRE_TOKEN || '1'; } catch {}
339+
}
340+
const payloadLocal = JSON.stringify({
341+
url: baseUrl,
342+
routeLogs: logsRoute,
343+
timestamp: Date.now(),
344+
pid: typeof process !== 'undefined' ? process.pid : undefined,
345+
projectRoot: meta?.projectRoot || process.cwd()
346+
});
347+
const payloadTmp = JSON.stringify({
335348
url: baseUrl,
336349
routeLogs: logsRoute,
337350
timestamp: Date.now(),
338351
pid: typeof process !== 'undefined' ? process.pid : undefined,
339352
projectRoot: meta?.projectRoot || process.cwd(),
340-
token: meta?.token || undefined
353+
token
341354
});
342355

343-
const files = meta?.scope === 'http'
344-
? [ join(tmpdir(), 'browser-echo-mcp.json') ]
345-
: meta?.aggregator
346-
? [ join(process.cwd(), '.browser-echo-mcp.json'), join(tmpdir(), 'browser-echo-mcp.json') ]
347-
: [ join(process.cwd(), '.browser-echo-mcp.json') ];
356+
let files: string[] = [];
357+
if (meta?.scope === 'http') {
358+
// HTTP transport: write project-local; mirror to tmp only when explicitly enabled
359+
files = [ join(process.cwd(), '.browser-echo-mcp.json') ];
360+
if (allowTmp) files.push(join(tmpdir(), 'browser-echo-mcp.json'));
361+
} else {
362+
// STDIO transport writes only to project-local by default; optionally mirror to tmp when explicitly enabled
363+
files = [ join(process.cwd(), '.browser-echo-mcp.json') ];
364+
if (allowTmp) files.push(join(tmpdir(), 'browser-echo-mcp.json'));
365+
}
348366

349367
for (const f of files) {
350-
try { writeFileSync(f, payload); } catch {}
368+
const isTmp = f === join(tmpdir(), 'browser-echo-mcp.json');
369+
try { writeFileSync(f, isTmp ? payloadTmp : payloadLocal); } catch {}
370+
// Restrict permissions when writing token-bearing tmp file
371+
if (isTmp) { try { chmodSync(f, 0o600); } catch {} }
351372
}
352373
} catch {
353374
// best-effort only

0 commit comments

Comments
 (0)