@oimdb/mcp 1.0.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/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # @oimdb/mcp
2
+
3
+ Connects AI assistants to a live OIMDB store running in the browser. Provides MCP tools for Claude Code and an optional CDP inspector for any AI that can run a shell command.
4
+
5
+ ## For AI Assistants
6
+
7
+ If you are an AI assistant and this package is present in the project, you can get live OIMDB state from the running browser tab.
8
+
9
+ **Check if MCP is already configured** — look for `mcpServers.oimdb` in `.claude/settings.json` or `~/.claude/settings.json`. If it is, the tools `oimdb_inspect`, `oimdb_dump`, `oimdb_collection`, and `oimdb_computed` are available. Call `oimdb_inspect` now to see the current state.
10
+
11
+ **If MCP is not configured yet**, add this to the project's MCP config:
12
+
13
+ - Claude Code: `.claude/settings.json`
14
+ - Cursor: `.cursor/mcp.json`
15
+
16
+ ```json
17
+ {
18
+ "mcpServers": {
19
+ "oimdb": {
20
+ "command": "npx",
21
+ "args": ["-y", "@oimdb/mcp"]
22
+ }
23
+ }
24
+ }
25
+ ```
26
+
27
+ Then ask the user to:
28
+ 1. Reload Claude Code so the MCP server starts
29
+ 2. Make sure `debug.ts` calls `registry.connect()` and the app is running in the browser
30
+
31
+ **If the user just wants a one-shot snapshot** without MCP setup, run this via Bash (requires Chrome launched with `--remote-debugging-port=9222`):
32
+
33
+ ```bash
34
+ npx @oimdb/mcp cdp
35
+ ```
36
+
37
+ ## Human Setup
38
+
39
+ ### Standalone DevTools UI (for humans)
40
+
41
+ ```bash
42
+ npx @oimdb/mcp devtools
43
+ ```
44
+
45
+ Opens `http://localhost:7433` automatically. Shows live collections and computeds from the running browser tab. No Chrome extension needed.
46
+
47
+ ```bash
48
+ OIMDB_WS_PORT=7433 OIMDB_UI_PORT=7434 npx @oimdb/mcp devtools # custom ports
49
+ npx @oimdb/mcp devtools --no-open # don't open browser
50
+ ```
51
+
52
+ ### 1. Add MCP config (for AI tools)
53
+
54
+ Claude Code — `.claude/settings.json`:
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "oimdb": {
60
+ "command": "npx",
61
+ "args": ["-y", "@oimdb/mcp"]
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ Cursor — `.cursor/mcp.json`:
68
+
69
+ ```json
70
+ {
71
+ "mcpServers": {
72
+ "oimdb": {
73
+ "command": "npx",
74
+ "args": ["-y", "@oimdb/mcp"]
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ ### 2. Connect the browser
81
+
82
+ ```ts
83
+ // src/debug.ts
84
+ import './store/users.debug';
85
+ import './store/tasks.debug';
86
+ import { registry } from '@oimdb/devtools';
87
+
88
+ if (typeof window !== 'undefined') {
89
+ (window as Record<string, unknown>).__OIMDB_DEV__ = registry;
90
+ registry.connect(); // connects to ws://localhost:7432
91
+ }
92
+ ```
93
+
94
+ ### 3. Use from Claude
95
+
96
+ ```
97
+ Call oimdb_inspect to see what's in the store.
98
+ ```
99
+
100
+ ## Available MCP Tools
101
+
102
+ | Tool | Description |
103
+ |---|---|
104
+ | `oimdb_inspect` | Full structured state — all collections, computeds, dep graph |
105
+ | `oimdb_dump` | Human-readable text summary (same as `registry.dump()`) |
106
+ | `oimdb_collection` | Details of one collection by name |
107
+ | `oimdb_computed` | Status + deps of one computed by name |
108
+
109
+ ## CDP Inspector (no browser-side code needed)
110
+
111
+ Launch Chrome with `--remote-debugging-port=9222`, then:
112
+
113
+ ```bash
114
+ npx @oimdb/mcp cdp
115
+ npx @oimdb/mcp cdp | jq .collections
116
+ OIMDB_CDP_URL=http://localhost:9222 npx @oimdb/mcp cdp
117
+ ```
118
+
119
+ ## Port
120
+
121
+ The MCP bridge WebSocket runs on port `7432` by default. Change it:
122
+
123
+ ```bash
124
+ OIMDB_WS_PORT=7433 npx @oimdb/mcp
125
+ ```
126
+
127
+ Update `registry.connect()` accordingly:
128
+
129
+ ```ts
130
+ registry.connect('ws://localhost:7433');
131
+ ```
package/bin/cdp.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * One-shot CDP inspector: connects to Chrome, evaluates __OIMDB_DEV__.inspect(),
4
+ * prints JSON to stdout. Pipe to jq or paste into an AI prompt.
5
+ *
6
+ * Requirements:
7
+ * Launch Chrome with: --remote-debugging-port=9222
8
+ * (or set CDP_URL env var to point to a different address)
9
+ *
10
+ * Usage:
11
+ * npx @oimdb/mcp cdp
12
+ * OIMDB_CDP_URL=http://localhost:9222 npx @oimdb/mcp cdp
13
+ * npx @oimdb/mcp cdp | jq .collections
14
+ */
15
+
16
+ const cdpBase = process.env.OIMDB_CDP_URL || 'http://localhost:9222';
17
+
18
+ async function run() {
19
+ // 1. List open tabs
20
+ let tabs;
21
+ try {
22
+ const res = await fetch(`${cdpBase}/json/list`);
23
+ tabs = await res.json();
24
+ } catch {
25
+ process.stderr.write(
26
+ `[OIMDB CDP] Cannot reach Chrome at ${cdpBase}\n` +
27
+ `Launch Chrome with: --remote-debugging-port=9222\n`
28
+ );
29
+ process.exit(1);
30
+ }
31
+
32
+ // Find first tab that has a debugger URL
33
+ const tab = tabs.find((t) => t.webSocketDebuggerUrl);
34
+ if (!tab) {
35
+ process.stderr.write('[OIMDB CDP] No debuggable tabs found.\n');
36
+ process.exit(1);
37
+ }
38
+
39
+ process.stderr.write(`[OIMDB CDP] Connected to: ${tab.title} (${tab.url})\n`);
40
+
41
+ // 2. Open CDP WebSocket
42
+ const { WebSocket } = await import('ws');
43
+ const ws = new WebSocket(tab.webSocketDebuggerUrl);
44
+
45
+ await new Promise((resolve, reject) => {
46
+ const timeout = setTimeout(() => {
47
+ ws.close();
48
+ reject(new Error('CDP timeout (5s)'));
49
+ }, 5000);
50
+
51
+ ws.once('open', () => {
52
+ ws.send(JSON.stringify({
53
+ id: 1,
54
+ method: 'Runtime.evaluate',
55
+ params: {
56
+ expression: [
57
+ '(function(){',
58
+ ' if(!window.__OIMDB_DEV__) return null;',
59
+ ' return JSON.parse(JSON.stringify(window.__OIMDB_DEV__.inspect()));',
60
+ '})()',
61
+ ].join(''),
62
+ returnByValue: true,
63
+ awaitPromise: false,
64
+ },
65
+ }));
66
+ });
67
+
68
+ ws.on('message', (raw) => {
69
+ const msg = JSON.parse(raw.toString());
70
+ if (msg.id !== 1) return;
71
+ clearTimeout(timeout);
72
+ ws.close();
73
+
74
+ const val = msg.result?.result?.value;
75
+ if (val === null || val === undefined) {
76
+ process.stderr.write(
77
+ '[OIMDB CDP] __OIMDB_DEV__ not found on this page.\n' +
78
+ 'Make sure debug.ts sets: window.__OIMDB_DEV__ = registry\n'
79
+ );
80
+ process.exit(1);
81
+ }
82
+ process.stdout.write(JSON.stringify(val, null, 2) + '\n');
83
+ resolve(undefined);
84
+ });
85
+
86
+ ws.once('error', (err) => {
87
+ clearTimeout(timeout);
88
+ reject(err);
89
+ });
90
+ });
91
+ }
92
+
93
+ run().catch((err) => {
94
+ process.stderr.write('[OIMDB CDP] Error: ' + err.message + '\n');
95
+ process.exit(1);
96
+ });
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ const path = require('path');
3
+ const { OIMDevUIServer } = require('../dist/index.cjs');
4
+
5
+ const wsPort = process.env.OIMDB_WS_PORT ? Number(process.env.OIMDB_WS_PORT) : 7432;
6
+ const uiPort = process.env.OIMDB_UI_PORT ? Number(process.env.OIMDB_UI_PORT) : 7433;
7
+ const noOpen = process.argv.includes('--no-open');
8
+ const uiDir = path.join(__dirname, '../ui');
9
+
10
+ const server = new OIMDevUIServer({ wsPort, uiPort, uiDir, open: !noOpen });
11
+ server.start();
package/bin/server.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ const { OIMDevMcpServer } = require('../dist/index.cjs');
3
+
4
+ const wsPort = process.env.OIMDB_WS_PORT ? Number(process.env.OIMDB_WS_PORT) : 7432;
5
+ const server = new OIMDevMcpServer({ wsPort });
6
+ server.start().catch((err) => {
7
+ process.stderr.write('[OIMDB MCP] Fatal: ' + err.message + '\n');
8
+ process.exit(1);
9
+ });
package/dist/index.cjs ADDED
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ OIMDevMcpServer: () => OIMDevMcpServer,
24
+ OIMDevUIServer: () => OIMDevUIServer,
25
+ createOIMDevMcpServer: () => createOIMDevMcpServer,
26
+ createOIMDevUIServer: () => createOIMDevUIServer
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/core/OIMDevMcpServer.ts
31
+ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
32
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
33
+ var import_ws = require("ws");
34
+ var import_zod = require("zod");
35
+ var OIMDevMcpServer = class {
36
+ constructor(options = {}) {
37
+ this.wss = null;
38
+ this.latestBrowser = null;
39
+ this.pending = /* @__PURE__ */ new Map();
40
+ this.wsPort = options.wsPort ?? 7432;
41
+ this.mcpServer = new import_mcp.McpServer({ name: "oimdb", version: "1.0.0" });
42
+ this.registerTools();
43
+ }
44
+ registerTools() {
45
+ const server = this.mcpServer;
46
+ const nameSchema = { name: import_zod.z.string().describe("Registered name") };
47
+ server.registerTool("oimdb_inspect", {
48
+ description: "Get full state of all registered OIMDB collections and computeds from the connected browser tab. Returns structured JSON with entity counts, field names, index keys, relations, and computed statuses."
49
+ }, async () => {
50
+ const data = await this.queryBrowser("inspect");
51
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
52
+ });
53
+ server.registerTool("oimdb_dump", {
54
+ description: "Get a human-readable text summary of OIMDB state. Same output as registry.dump() in the browser."
55
+ }, async () => {
56
+ const text = await this.queryBrowser("dump");
57
+ return { content: [{ type: "text", text }] };
58
+ });
59
+ server.registerTool("oimdb_collection", {
60
+ description: "Get details of a specific registered collection: entity count, field names, index keys, and relations.",
61
+ inputSchema: nameSchema
62
+ }, async ({ name }) => {
63
+ const data = await this.queryBrowser("inspect");
64
+ const info = data.collections[name];
65
+ if (!info) {
66
+ const available = Object.keys(data.collections).join(", ") || "(none registered)";
67
+ return { content: [{ type: "text", text: `Collection '${name}' not found. Registered: ${available}` }] };
68
+ }
69
+ return { content: [{ type: "text", text: JSON.stringify(info, null, 2) }] };
70
+ });
71
+ server.registerTool("oimdb_computed", {
72
+ description: "Get status and resolved dependency names of a specific registered computed value. Shows fresh/stale/pending status, current value, and which registered sources it depends on.",
73
+ inputSchema: nameSchema
74
+ }, async ({ name }) => {
75
+ const data = await this.queryBrowser("inspect");
76
+ const info = data.computeds[name];
77
+ if (!info) {
78
+ const available = Object.keys(data.computeds).join(", ") || "(none registered)";
79
+ return { content: [{ type: "text", text: `Computed '${name}' not found. Registered: ${available}` }] };
80
+ }
81
+ return { content: [{ type: "text", text: JSON.stringify(info, null, 2) }] };
82
+ });
83
+ }
84
+ async queryBrowser(action) {
85
+ if (!this.latestBrowser) {
86
+ throw new Error(
87
+ `No browser tab connected to the OIMDB MCP bridge.
88
+
89
+ Add to your debug entry point:
90
+ import { registry } from '@oimdb/devtools';
91
+ registry.connect(); // connects to ws://localhost:${this.wsPort}
92
+
93
+ Then reload the page.`
94
+ );
95
+ }
96
+ return new Promise((resolve, reject) => {
97
+ const id = Math.random().toString(36).slice(2);
98
+ const timer = setTimeout(() => {
99
+ this.pending.delete(id);
100
+ reject(new Error("Browser response timeout (5s). Is the page active?"));
101
+ }, 5e3);
102
+ this.pending.set(id, { resolve, reject, timer });
103
+ this.latestBrowser.ws.send(JSON.stringify({ type: "request", id, action }));
104
+ });
105
+ }
106
+ setupWebSocketServer() {
107
+ this.wss = new import_ws.WebSocketServer({ port: this.wsPort });
108
+ this.wss.on("error", (err) => {
109
+ if (err.code === "EADDRINUSE") {
110
+ process.stderr.write(
111
+ `[OIMDB MCP] Port ${this.wsPort} is already in use.
112
+ Set a different port: OIMDB_WS_PORT=7433 npx @oimdb/mcp
113
+ `
114
+ );
115
+ process.exit(1);
116
+ }
117
+ process.stderr.write(`[OIMDB MCP] WebSocket server error: ${err.message}
118
+ `);
119
+ process.exit(1);
120
+ });
121
+ this.wss.on("connection", (ws) => {
122
+ ws.on("message", (raw) => {
123
+ const msg = JSON.parse(raw.toString());
124
+ if (msg.type === "hello") {
125
+ this.latestBrowser = { ws, url: msg.url, title: msg.title };
126
+ process.stderr.write(`[OIMDB MCP] Browser connected: ${msg.title} (${msg.url})
127
+ `);
128
+ return;
129
+ }
130
+ if (msg.type === "response") {
131
+ const pending = this.pending.get(msg.id);
132
+ if (!pending) return;
133
+ this.pending.delete(msg.id);
134
+ clearTimeout(pending.timer);
135
+ if (msg.error) {
136
+ pending.reject(new Error(msg.error));
137
+ } else {
138
+ pending.resolve(msg.data);
139
+ }
140
+ }
141
+ });
142
+ ws.on("close", () => {
143
+ if (this.latestBrowser?.ws === ws) {
144
+ this.latestBrowser = null;
145
+ process.stderr.write("[OIMDB MCP] Browser disconnected\n");
146
+ }
147
+ });
148
+ });
149
+ process.stderr.write(`[OIMDB MCP] Bridge ready on ws://localhost:${this.wsPort}
150
+ `);
151
+ }
152
+ async start() {
153
+ this.setupWebSocketServer();
154
+ const transport = new import_stdio.StdioServerTransport();
155
+ await this.mcpServer.connect(transport);
156
+ }
157
+ };
158
+
159
+ // src/core/OIMDevUIServer.ts
160
+ var import_http = require("http");
161
+ var import_fs = require("fs");
162
+ var import_path = require("path");
163
+ var import_child_process = require("child_process");
164
+ var import_ws2 = require("ws");
165
+ var MIME = {
166
+ ".html": "text/html; charset=utf-8",
167
+ ".js": "text/javascript; charset=utf-8",
168
+ ".css": "text/css; charset=utf-8"
169
+ };
170
+ var OIMDevUIServer = class {
171
+ constructor(options) {
172
+ this.wss = null;
173
+ this.latestBrowser = null;
174
+ this.pending = /* @__PURE__ */ new Map();
175
+ this.wsPort = options.wsPort ?? 7432;
176
+ this.uiPort = options.uiPort ?? 7433;
177
+ this.uiDir = options.uiDir;
178
+ this.shouldOpen = options.open ?? true;
179
+ }
180
+ async queryBrowser(action) {
181
+ if (!this.latestBrowser) return null;
182
+ return new Promise((resolve, reject) => {
183
+ const id = Math.random().toString(36).slice(2);
184
+ const timer = setTimeout(() => {
185
+ this.pending.delete(id);
186
+ reject(new Error("timeout"));
187
+ }, 5e3);
188
+ this.pending.set(id, { resolve, reject, timer });
189
+ this.latestBrowser.ws.send(JSON.stringify({ type: "request", id, action }));
190
+ });
191
+ }
192
+ setupBridge() {
193
+ this.wss = new import_ws2.WebSocketServer({ port: this.wsPort });
194
+ this.wss.on("error", (err) => {
195
+ if (err.code === "EADDRINUSE") {
196
+ process.stderr.write(
197
+ `[OIMDB DevTools] Port ${this.wsPort} is already in use.
198
+ Set a different port: OIMDB_WS_PORT=7433 npx @oimdb/mcp devtools
199
+ `
200
+ );
201
+ process.exit(1);
202
+ }
203
+ process.stderr.write(`[OIMDB DevTools] Bridge error: ${err.message}
204
+ `);
205
+ process.exit(1);
206
+ });
207
+ this.wss.on("connection", (ws) => {
208
+ ws.on("message", (raw) => {
209
+ const msg = JSON.parse(raw.toString());
210
+ if (msg.type === "hello") {
211
+ this.latestBrowser = { ws, url: msg.url, title: msg.title };
212
+ process.stderr.write(`[OIMDB DevTools] Browser connected: ${msg.title} (${msg.url})
213
+ `);
214
+ return;
215
+ }
216
+ if (msg.type === "response") {
217
+ const req = this.pending.get(msg.id);
218
+ if (!req) return;
219
+ this.pending.delete(msg.id);
220
+ clearTimeout(req.timer);
221
+ if (msg.error) req.reject(new Error(msg.error));
222
+ else req.resolve(msg.data);
223
+ }
224
+ });
225
+ ws.on("close", () => {
226
+ if (this.latestBrowser?.ws === ws) {
227
+ this.latestBrowser = null;
228
+ process.stderr.write("[OIMDB DevTools] Browser disconnected\n");
229
+ }
230
+ });
231
+ });
232
+ process.stderr.write(`[OIMDB DevTools] Bridge on ws://localhost:${this.wsPort}
233
+ `);
234
+ }
235
+ setupHTTP() {
236
+ const server = (0, import_http.createServer)((req, res) => {
237
+ const url = req.url ?? "/";
238
+ res.setHeader("Access-Control-Allow-Origin", "*");
239
+ if (url === "/api/inspect") {
240
+ this.queryBrowser("inspect").then((data) => {
241
+ res.writeHead(200, { "Content-Type": "application/json" });
242
+ res.end(JSON.stringify({
243
+ connected: !!this.latestBrowser,
244
+ tab: this.latestBrowser ? { url: this.latestBrowser.url, title: this.latestBrowser.title } : null,
245
+ data
246
+ }));
247
+ }).catch(() => {
248
+ res.writeHead(200, { "Content-Type": "application/json" });
249
+ res.end(JSON.stringify({ connected: false, tab: null, data: null }));
250
+ });
251
+ return;
252
+ }
253
+ const filePath = (0, import_path.join)(this.uiDir, url === "/" ? "index.html" : url);
254
+ try {
255
+ const content = (0, import_fs.readFileSync)(filePath);
256
+ res.writeHead(200, { "Content-Type": MIME[(0, import_path.extname)(filePath)] ?? "text/plain" });
257
+ res.end(content);
258
+ } catch {
259
+ res.writeHead(404);
260
+ res.end("Not found");
261
+ }
262
+ });
263
+ server.on("error", (err) => {
264
+ if (err.code === "EADDRINUSE") {
265
+ process.stderr.write(
266
+ `[OIMDB DevTools] UI port ${this.uiPort} is already in use.
267
+ Set a different port: OIMDB_UI_PORT=7434 npx @oimdb/mcp devtools
268
+ `
269
+ );
270
+ process.exit(1);
271
+ }
272
+ });
273
+ server.listen(this.uiPort, () => {
274
+ const uiUrl = `http://localhost:${this.uiPort}`;
275
+ process.stderr.write(`[OIMDB DevTools] UI ready \u2192 ${uiUrl}
276
+ `);
277
+ if (this.shouldOpen) this.openURL(uiUrl);
278
+ });
279
+ }
280
+ openURL(url) {
281
+ const cmd = process.platform === "win32" ? `start "" "${url}"` : process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`;
282
+ (0, import_child_process.exec)(cmd, (err) => {
283
+ if (err) process.stderr.write(`[OIMDB DevTools] Could not open browser: ${err.message}
284
+ `);
285
+ });
286
+ }
287
+ start() {
288
+ this.setupBridge();
289
+ this.setupHTTP();
290
+ process.stderr.write(
291
+ `[OIMDB DevTools] Add to debug.ts: registry.connect();
292
+ `
293
+ );
294
+ }
295
+ };
296
+
297
+ // src/index.ts
298
+ function createOIMDevMcpServer(options) {
299
+ return new OIMDevMcpServer(options);
300
+ }
301
+ function createOIMDevUIServer(options) {
302
+ return new OIMDevUIServer(options);
303
+ }
304
+ // Annotate the CommonJS export names for ESM import in node:
305
+ 0 && (module.exports = {
306
+ OIMDevMcpServer,
307
+ OIMDevUIServer,
308
+ createOIMDevMcpServer,
309
+ createOIMDevUIServer
310
+ });
@@ -0,0 +1,44 @@
1
+ type TOIMDevMcpOptions = {
2
+ /** Port for the WebSocket bridge that browser tabs connect to. Default: 7432 */
3
+ wsPort?: number;
4
+ };
5
+
6
+ declare class OIMDevMcpServer {
7
+ private readonly mcpServer;
8
+ private readonly wsPort;
9
+ private wss;
10
+ private latestBrowser;
11
+ private readonly pending;
12
+ constructor(options?: TOIMDevMcpOptions);
13
+ private registerTools;
14
+ private queryBrowser;
15
+ private setupWebSocketServer;
16
+ start(): Promise<void>;
17
+ }
18
+
19
+ type TOIMDevUIServerOptions = {
20
+ wsPort?: number;
21
+ uiPort?: number;
22
+ uiDir: string;
23
+ open?: boolean;
24
+ };
25
+ declare class OIMDevUIServer {
26
+ private readonly wsPort;
27
+ private readonly uiPort;
28
+ private readonly uiDir;
29
+ private readonly shouldOpen;
30
+ private wss;
31
+ private latestBrowser;
32
+ private readonly pending;
33
+ constructor(options: TOIMDevUIServerOptions);
34
+ private queryBrowser;
35
+ private setupBridge;
36
+ private setupHTTP;
37
+ private openURL;
38
+ start(): void;
39
+ }
40
+
41
+ declare function createOIMDevMcpServer(options?: TOIMDevMcpOptions): OIMDevMcpServer;
42
+ declare function createOIMDevUIServer(options: TOIMDevUIServerOptions): OIMDevUIServer;
43
+
44
+ export { OIMDevMcpServer, OIMDevUIServer, type TOIMDevMcpOptions, type TOIMDevUIServerOptions, createOIMDevMcpServer, createOIMDevUIServer };
@@ -0,0 +1,44 @@
1
+ type TOIMDevMcpOptions = {
2
+ /** Port for the WebSocket bridge that browser tabs connect to. Default: 7432 */
3
+ wsPort?: number;
4
+ };
5
+
6
+ declare class OIMDevMcpServer {
7
+ private readonly mcpServer;
8
+ private readonly wsPort;
9
+ private wss;
10
+ private latestBrowser;
11
+ private readonly pending;
12
+ constructor(options?: TOIMDevMcpOptions);
13
+ private registerTools;
14
+ private queryBrowser;
15
+ private setupWebSocketServer;
16
+ start(): Promise<void>;
17
+ }
18
+
19
+ type TOIMDevUIServerOptions = {
20
+ wsPort?: number;
21
+ uiPort?: number;
22
+ uiDir: string;
23
+ open?: boolean;
24
+ };
25
+ declare class OIMDevUIServer {
26
+ private readonly wsPort;
27
+ private readonly uiPort;
28
+ private readonly uiDir;
29
+ private readonly shouldOpen;
30
+ private wss;
31
+ private latestBrowser;
32
+ private readonly pending;
33
+ constructor(options: TOIMDevUIServerOptions);
34
+ private queryBrowser;
35
+ private setupBridge;
36
+ private setupHTTP;
37
+ private openURL;
38
+ start(): void;
39
+ }
40
+
41
+ declare function createOIMDevMcpServer(options?: TOIMDevMcpOptions): OIMDevMcpServer;
42
+ declare function createOIMDevUIServer(options: TOIMDevUIServerOptions): OIMDevUIServer;
43
+
44
+ export { OIMDevMcpServer, OIMDevUIServer, type TOIMDevMcpOptions, type TOIMDevUIServerOptions, createOIMDevMcpServer, createOIMDevUIServer };