Skip to content

Commit b4be2d5

Browse files
committed
chore: enhance package.json and build configurations to integrate @browser-echo/mcp across Next, Nuxt, and Vite packages
1 parent bd1e490 commit b4be2d5

12 files changed

Lines changed: 402 additions & 18 deletions

File tree

.cursor/mcp.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"mcpServers": {
3+
"browser-echo": {
4+
"url": "http://localhost:5173/__mcp"
5+
}
6+
}
7+
}

packages/mcp/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,10 @@
2525
"devDependencies": {
2626
"typescript": "^5.5.4",
2727
"unbuild": "^2.0.0"
28+
},
29+
"scripts": {
30+
"build": "unbuild",
31+
"dev": "unbuild -w",
32+
"clean": "rimraf dist || true"
2833
}
2934
}

packages/next/build.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ export default defineBuildConfig({
1313
emitCJS: false,
1414
esbuild: { jsx: 'automatic', jsxImportSource: 'react' }
1515
},
16-
externals: ['next', 'react', 'react-dom', 'next/script', 'react/jsx-runtime', '@browser-echo/core']
16+
externals: ['next', 'react', 'react-dom', 'next/script', 'react/jsx-runtime', '@browser-echo/core', '@browser-echo/mcp']
1717
});

packages/next/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
"react-dom": ">=18.0.0"
4242
},
4343
"dependencies": {
44-
"@browser-echo/core": "workspace:*"
44+
"@browser-echo/core": "workspace:*",
45+
"@browser-echo/mcp": "workspace:*"
4546
},
4647
"scripts": {
4748
"build": "unbuild",

packages/nuxt/build.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ export default defineBuildConfig({
88
declaration: true,
99
clean: true,
1010
rollup: { emitCJS: false },
11-
externals: ['@nuxt/kit', '@nuxt/schema', 'h3', '@browser-echo/core']
11+
externals: ['@nuxt/kit', '@nuxt/schema', 'h3', '@browser-echo/core', '@browser-echo/mcp']
1212
});

packages/nuxt/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"@nuxt/kit": ">=3.11.0"
2626
},
2727
"dependencies": {
28-
"@browser-echo/core": "workspace:*"
28+
"@browser-echo/core": "workspace:*",
29+
"@browser-echo/mcp": "workspace:*"
2930
},
3031
"scripts": {
3132
"build": "unbuild",

packages/nuxt/test/handler.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ vi.mock('h3', async () => {
1212
import handler from '../src/runtime/server/handler';
1313

1414
it('prints forwarded logs and returns 204', async () => {
15+
// Disable MCP during test so console printing occurs
16+
process.env.BROWSER_ECHO_MCP = '0';
1517
const w = vi.spyOn(console, 'warn').mockImplementation(() => {});
1618
const e = {} as any;
1719
const res = await handler(e);

packages/vite/build.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ export default defineBuildConfig({
77
rollup: {
88
emitCJS: false,
99
},
10-
externals: ['vite', 'ansis', '@browser-echo/core']
10+
externals: ['vite', 'ansis', '@browser-echo/core', '@browser-echo/mcp']
1111
});

packages/vite/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
},
2727
"dependencies": {
2828
"ansis": "^3.2.0",
29-
"@browser-echo/core": "workspace:*"
29+
"@browser-echo/core": "workspace:*",
30+
"@browser-echo/mcp": "workspace:*"
3031
},
3132
"scripts": {
3233
"build": "unbuild",

packages/vite/src/index.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Avoid exporting Vite types to prevent cross-version type mismatches in consumers
22
import ansis from 'ansis';
33
import type { BrowserLogLevel } from '@browser-echo/core';
4+
import type { IncomingMessage, ServerResponse } from 'node:http';
45
import { mkdirSync, appendFileSync } from 'node:fs';
56
import { dirname, join as joinPath } from 'node:path';
67
import { startMcpServer, handleMcpHttpRequest, publishLogEntry, isMcpEnabled as _mcpEnvEnabled } from '@browser-echo/mcp';
@@ -44,7 +45,7 @@ const DEFAULTS: ResolvedOptions = {
4445
mcpRoute: '/__mcp'
4546
};
4647

47-
export default function browserEcho
48+
export default function browserEcho(opts: BrowserLogsToTerminalOptions = {}): import('vite').Plugin {
4849
const options: ResolvedOptions = {
4950
...DEFAULTS,
5051
...opts,
@@ -74,21 +75,22 @@ export default function browserEcho
7475
configureServer(server) {
7576
if (!options.enabled) return;
7677
try { startMcpServer(); } catch {}
77-
server.middlewares.use(options.mcpRoute, (req, res, next) => {
78-
// Allow only MCP methods; otherwise fall-through
79-
const m = req.method || 'GET';
80-
if (m !== 'GET' && m !== 'POST' && m !== 'DELETE') return next();
78+
server.middlewares.use(options.mcpRoute, (req: IncomingMessage, res: ServerResponse, _next: () => void) => {
79+
const m = (req.method || 'GET').toUpperCase();
8180
(async () => {
8281
try {
8382
let body: Buffer | undefined;
84-
if (m === 'POST') {
83+
if (m === 'POST' || m === 'PUT' || m === 'PATCH') {
8584
body = await collectBody(req);
8685
}
8786
await handleMcpHttpRequest(req as any, res as any, body);
8887
} catch (err: any) {
8988
server.config.logger.error(`${options.tag} MCP error: ${err?.message || err}`);
90-
res.statusCode = 500;
91-
res.end('mcp error');
89+
if (!res.headersSent) {
90+
res.statusCode = 500;
91+
try { res.setHeader('content-type', 'application/json'); } catch {}
92+
}
93+
res.end(JSON.stringify({ jsonrpc: '2.0', error: { code: -32603, message: 'Internal server error' }, id: null }));
9294
}
9395
})();
9496
});
@@ -102,7 +104,7 @@ function attachMiddleware(server: any, options: ResolvedOptions) {
102104
const logFilePath = joinPath(options.fileLog.dir, `dev-${sessionStamp}.log`);
103105
if (options.fileLog.enabled) { try { mkdirSync(dirname(logFilePath), { recursive: true }); } catch {} }
104106

105-
server.middlewares.use(options.route, (req, res, next) => {
107+
server.middlewares.use(options.route, (req: IncomingMessage, res: ServerResponse, next: () => void) => {
106108
if (req.method !== 'POST') return next();
107109
collectBody(req).then((raw) => {
108110
let payload: ClientPayload | null = null;

0 commit comments

Comments
 (0)