browxai 0.7.0 → 0.8.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/dist/cli/serve.js +38 -21
- package/package.json +1 -1
package/dist/cli/serve.js
CHANGED
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
// server, identical to stdio.
|
|
15
15
|
import { chmodSync, existsSync, unlinkSync } from "node:fs";
|
|
16
16
|
import { createServer as createNetServer } from "node:net";
|
|
17
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/
|
|
18
|
-
import {
|
|
17
|
+
import { Server as McpServer } from "@modelcontextprotocol/sdk/server/index.js";
|
|
18
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
19
|
+
import { createServer, NAME, VERSION } from "../server.js";
|
|
19
20
|
import { SocketTransport } from "../sdk/socket-transport.js";
|
|
20
21
|
import { log } from "../util/logging.js";
|
|
21
22
|
function parseFlagString(args, flag) {
|
|
@@ -54,29 +55,45 @@ export async function startServeForTests(opts) {
|
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
const browxai = await createServer({ attachCdp: opts.attachCdp, headless: opts.headless });
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
// the
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// would require duplicating server.ts's input schemas. Instead we expose
|
|
66
|
-
// a thin tool-call proxy: the connection's McpServer registers a single
|
|
67
|
-
// catch-all? No — the MCP SDK requires tools to be registered by name.
|
|
68
|
-
// The cleanest path is: register the same tool names that the in-process
|
|
69
|
-
// server already has, with `inputSchema: { additionalProperties: true }`
|
|
70
|
-
// (open schema — the underlying handler still validates). Each tool's
|
|
71
|
-
// handler delegates to `browxai.handlers[name]`.
|
|
58
|
+
// Each attached client connection gets its OWN low-level MCP Server that
|
|
59
|
+
// routes JSON-RPC straight to the SHARED `browxai.handlers` map (session-state
|
|
60
|
+
// isolation is the SessionRegistry's job, already true). We deliberately do
|
|
61
|
+
// NOT use the high-level `McpServer.registerTool` with per-tool schemas: that
|
|
62
|
+
// path validates/strips arguments against the declared schema, and an empty
|
|
63
|
+
// schema dropped every argument (the `navigate`-hangs-forever bug). The
|
|
64
|
+
// low-level CallTool handler forwards raw arguments, exactly like the
|
|
65
|
+
// in-process transport.
|
|
72
66
|
const liveConnections = new Set();
|
|
73
67
|
const netServer = createNetServer((socket) => {
|
|
74
68
|
void (async () => {
|
|
75
69
|
try {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
70
|
+
// Route JSON-RPC straight to the in-process handler map with the RAW
|
|
71
|
+
// arguments. The previous `McpServer.registerTool(name, { inputSchema:
|
|
72
|
+
// {} }, …)` path validated each call against an EMPTY object schema,
|
|
73
|
+
// which silently STRIPPED every argument — so e.g. `navigate` reached
|
|
74
|
+
// its handler with no `url` and hung the whole call (load wait that
|
|
75
|
+
// never resolves). The per-tool handler does its own validation, so the
|
|
76
|
+
// socket layer must pass args through untouched, exactly like the
|
|
77
|
+
// in-process transport (`src/sdk/transport-in-process.ts`).
|
|
78
|
+
const mcp = new McpServer({ name: NAME, version: VERSION }, { capabilities: { tools: {} } });
|
|
79
|
+
mcp.setRequestHandler(ListToolsRequestSchema, () => ({
|
|
80
|
+
tools: Object.keys(browxai.handlers).map((name) => ({
|
|
81
|
+
name,
|
|
82
|
+
description: `browxai/${name}`,
|
|
83
|
+
// Open schema — NOT `{}` (which strips args). The handler validates.
|
|
84
|
+
inputSchema: { type: "object", additionalProperties: true },
|
|
85
|
+
})),
|
|
86
|
+
}));
|
|
87
|
+
mcp.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
88
|
+
const handler = browxai.handlers[request.params.name];
|
|
89
|
+
if (!handler) {
|
|
90
|
+
return {
|
|
91
|
+
isError: true,
|
|
92
|
+
content: [{ type: "text", text: `browxai: unknown tool "${request.params.name}"` }],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return await handler(request.params.arguments ?? {});
|
|
96
|
+
});
|
|
80
97
|
const transport = new SocketTransport(socket);
|
|
81
98
|
await mcp.connect(transport);
|
|
82
99
|
const conn = {
|