Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 0 additions & 172 deletions mcp/app.mjs

This file was deleted.

16 changes: 16 additions & 0 deletions mcp/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ const html = `<!doctype html>
</html>
`;

// The CLI transports (stdio, local HTTP) consume the same server definition
// as the deployed route. Bundled here because they run as plain node — no
// TS, no path aliases — and a stale bundle should say so rather than drift.
const core = await build({
entryPoints: [join(root, 'src', 'lib', 'mcp', 'server.ts')],
bundle: true,
platform: 'node',
format: 'esm',
write: false,
tsconfig: join(root, 'tsconfig.json'),
alias: { 'server-only': join(root, 'test', 'stubs', 'server-only.ts') },
external: ['@modelcontextprotocol/sdk*', '@ai-sdk/*', '@openrouter/*', '@supabase/*', 'ai', 'zod', 'react', 'node:*'],
logLevel: 'error',
});
writeFileSync(join(outDir, 'server-core.mjs'), core.outputFiles[0].text);

const out = join(outDir, 'widget-shell.html');
writeFileSync(out, html);

Expand Down
32 changes: 32 additions & 0 deletions mcp/core.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Loads the bundled server definition for the CLI transports.
*
* `src/lib/mcp/server.ts` is the one source of the tool surface; this file
* only adapts it to plain-node life: the bundle from `pnpm mcp:build`, the
* shell read from disk, and the API origin from env.
*/
import { existsSync, readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';

const root = dirname(fileURLToPath(import.meta.url));
const API_ORIGIN = process.env.WIDGET_API_ORIGIN ?? 'http://localhost:3100';

const corePath = join(root, 'dist', 'server-core.mjs');
const shellPath = join(root, 'dist', 'widget-shell.html');

for (const [path, what] of [[corePath, 'server bundle'], [shellPath, 'widget shell']]) {
if (!existsSync(path)) {
console.error(`[mcp] ${what} missing at ${path} — run: pnpm mcp:build`);
process.exit(1);
}
}

const { buildMcpServer } = await import(pathToFileURL(corePath).href);

export function createServer() {
return buildMcpServer({
origin: API_ORIGIN,
loadShell: async () => readFileSync(shellPath, 'utf8'),
});
}
2 changes: 1 addition & 1 deletion mcp/server-http.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { createServer as createHttpServer } from 'node:http';

import { createServer } from './app.mjs';
import { createServer } from './core.mjs';

const PORT = Number(process.env.MCP_HTTP_PORT ?? 3300);

Expand Down
2 changes: 1 addition & 1 deletion mcp/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
*/
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

import { createServer } from './app.mjs';
import { createServer } from './core.mjs';

await createServer().connect(new StdioServerTransport());
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"predev": "node mcp/build.mjs",
"prebuild": "node mcp/build.mjs",
"conformance": "node scripts/a2ui-conformance.mjs",
"conformance:update": "node scripts/a2ui-conformance.mjs --update"
"conformance:update": "node scripts/a2ui-conformance.mjs --update",
"mcp:inspect": "npx --yes @modelcontextprotocol/inspector@latest"
},
"dependencies": {
"@ag-ui/core": "^0.0.58",
Expand Down
Loading
Loading