@oimdb/mcp 2.0.0 → 3.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 CHANGED
@@ -1,19 +1,19 @@
1
1
  # @oimdb/mcp
2
2
 
3
- Connects AI assistants to a live OIMDB store running in the browser. It provides MCP tools for Claude Code, plus an optional CDP inspector for any AI that can run a shell command.
3
+ The MCP server for OIMDB. It gives an AI assistant the tools `oimdb_inspect`, `oimdb_dump`,
4
+ `oimdb_collection` and `oimdb_computed` over a live browser tab or an in-process model. It is built on
5
+ `@oimdb/cli`, which answers the same four questions from a shell: an assistant that can run a command
6
+ can use `npx @oimdb/cli inspect` instead.
4
7
 
5
8
  📖 **[Full documentation](https://oimdb.org/)**
6
9
 
7
10
  ## For AI Assistants
8
11
 
9
- 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.
12
+ **Check whether MCP is already configured.** Look for `mcpServers.oimdb` in `.claude/settings.json` or
13
+ `~/.claude/settings.json`. If it is there, call `oimdb_inspect` now to see the current state.
10
14
 
11
- **Check whether MCP is already configured.** Look for `mcpServers.oimdb` in `.claude/settings.json` or `~/.claude/settings.json`. If it is there, the tools `oimdb_inspect`, `oimdb_dump`, `oimdb_collection` and `oimdb_computed` are available. Call `oimdb_inspect` now to see the current state.
12
-
13
- **If MCP is not configured yet**, add this to the project's MCP config:
14
-
15
- - Claude Code: `.claude/settings.json`
16
- - Cursor: `.cursor/mcp.json`
15
+ **If MCP is not configured yet**, add this to the project's MCP config (Claude Code: `.claude/settings.json`,
16
+ Cursor: `.cursor/mcp.json`):
17
17
 
18
18
  ```json
19
19
  {
@@ -26,64 +26,8 @@ If you are an AI assistant and this package is present in the project, you can g
26
26
  }
27
27
  ```
28
28
 
29
- Then ask the user to:
30
- 1. Reload Claude Code so the MCP server starts
31
- 2. Make sure `debug.ts` calls `oimDevRegistry.connect()` and the app is running in the browser
32
-
33
- **If the user just wants a one-shot snapshot** without MCP setup, run this via Bash (requires Chrome launched with `--remote-debugging-port=9222`):
34
-
35
- ```bash
36
- npx @oimdb/mcp cdp
37
- ```
38
-
39
- ## Human Setup
40
-
41
- ### Standalone DevTools UI (for humans)
42
-
43
- ```bash
44
- npx @oimdb/mcp devtools
45
- ```
46
-
47
- Opens `http://localhost:7433` automatically and shows live collections and computeds from the running browser tab. No Chrome extension is needed.
48
-
49
- ```bash
50
- OIMDB_WS_PORT=7433 OIMDB_UI_PORT=7434 npx @oimdb/mcp devtools # custom ports
51
- npx @oimdb/mcp devtools --no-open # don't open browser
52
- ```
53
-
54
- ### 1. Add MCP config (for AI tools)
55
-
56
- Claude Code — `.claude/settings.json`:
57
-
58
- ```json
59
- {
60
- "mcpServers": {
61
- "oimdb": {
62
- "command": "npx",
63
- "args": ["-y", "@oimdb/mcp"]
64
- }
65
- }
66
- }
67
- ```
68
-
69
- Cursor — `.cursor/mcp.json`:
70
-
71
- ```json
72
- {
73
- "mcpServers": {
74
- "oimdb": {
75
- "command": "npx",
76
- "args": ["-y", "@oimdb/mcp"]
77
- }
78
- }
79
- }
80
- ```
81
-
82
- ### 2. Connect the browser
83
-
84
- The app calls `oimInitDevtools()` once at startup, before it builds its first
85
- service, where it builds the database (see the `@oimdb/devtools` README, Setup).
86
- The debug entry point then only connects:
29
+ Then ask the user to reload the assistant so the server starts, and to make sure the page connects to the
30
+ bridge:
87
31
 
88
32
  ```ts
89
33
  // src/debug.ts
@@ -97,72 +41,23 @@ if (typeof window !== 'undefined') {
97
41
  }
98
42
  ```
99
43
 
100
- ### 3. Use from Claude
101
-
102
- ```
103
- Call oimdb_inspect to see what's in the store.
104
- ```
105
-
106
44
  ## Available MCP Tools
107
45
 
108
46
  | Tool | Description |
109
47
  |---|---|
110
48
  | `oimdb_inspect` | Full structured state — collections with their index keys and relations, computeds, flush history, errors |
111
- | `oimdb_dump` | Human-readable text summary — what `oimDevRegistry.dumpString()` returns (`oimDevRegistry.dump()` is the sibling that console-logs it) |
49
+ | `oimdb_dump` | Human-readable text summary — what `oimDevRegistry.dumpString()` returns |
112
50
  | `oimdb_collection` | Details of one collection by name |
113
51
  | `oimdb_computed` | Current value of one registered computed, by name |
114
52
 
115
53
  ## Offline / static mode (no browser)
116
54
 
117
- By default the tools read a **live browser tab**. You can instead point the
118
- server at an **in-process model** so it answers offline. This suits "what's the
119
- data model?" questions when you don't want to run the app.
120
-
121
- **CLI: a model module.** Set `OIMDB_MODEL_MODULE` to a module that builds the
122
- model in Node and exports an `oimDevRegistry` (or a default export, or a zero-arg
123
- factory that returns one). It calls `oimInitDevtools()` before it builds the first
124
- service, as every app using `@oimdb/devtools` does:
125
-
126
- ```ts
127
- // oimdb-model.js (built JS, or run the server under a TS loader)
128
- import {
129
- OIMDB, createOIMBucketService, createOIMEntityService, type TOIMEntitySlot,
130
- } from '@oimdb/core';
131
- import { OIMDevRegistry, oimInitDevtools } from '@oimdb/devtools';
132
-
133
- oimInitDevtools();
134
-
135
- type TUser = { id: string; name: string; role: string };
136
-
137
- const db = new OIMDB();
138
- const usersService = createOIMEntityService<TUser>(db, { keyOf: (user) => user.id });
139
- const users = usersService.createStoreSlot(db);
140
- // A bucket's slots are the caller's — a write to a user moves the value and
141
- // files nothing, so whoever writes the user also calls
142
- // `usersByRoleService.slotContentService.writeBucketMemberSlots(bucketSlot, entitySlots)`.
143
- const usersByRoleService = createOIMBucketService<TOIMEntitySlot<TUser>>(db);
144
- const usersByRole = usersByRoleService.createStoreSlot(db);
145
-
146
- export const oimDevRegistry = new OIMDevRegistry();
147
- // The bucket collection and its store slot — you constructed them, so you hand them over.
148
- oimDevRegistry.collection('users', usersService, users, {
149
- indexes: { byRole: { bucketCollectionService: usersByRoleService, bucketStoreSlot: usersByRole } },
150
- });
151
- ```
152
-
153
- The server asks a registry for only two methods, `inspect()` and `dumpString()`,
154
- declared here as `IOIMDevRegistry`, so this package depends on no `@oimdb`
155
- package at all. `OIMDevRegistry` from `@oimdb/devtools` satisfies it as it
156
- stands, and so does anything else that answers those two.
157
-
158
55
  ```bash
159
56
  OIMDB_MODEL_MODULE=./oimdb-model.js npx @oimdb/mcp
160
57
  ```
161
58
 
162
- No WebSocket port is opened in this mode, and no browser is required.
163
-
164
- **Embedded: inject a registry.** When you run the server from your own Node
165
- process, pass the registry directly:
59
+ The module is the one `@oimdb/cli` reads with `--model`; see its README. No WebSocket port is opened in this
60
+ mode. From your own Node process, pass the registry directly:
166
61
 
167
62
  ```ts
168
63
  import { createOIMDevMcpServer } from '@oimdb/mcp';
@@ -171,106 +66,7 @@ import { oimDevRegistry } from '@oimdb/devtools';
171
66
  await createOIMDevMcpServer({ registry: oimDevRegistry }).start();
172
67
  ```
173
68
 
174
- > **Fields offline:** structure (collections, indexes, relations) is available
175
- > as soon as the model is constructed. Entity **field names** appear only when
176
- > the model holds at least one sample entity (TypeScript types are erased at
177
- > runtime) — seed a representative row in the model module if you want them.
178
-
179
- ## CDP Inspector (no browser-side code needed)
180
-
181
- Launch Chrome with `--remote-debugging-port=9222`, then:
182
-
183
- ```bash
184
- npx @oimdb/mcp cdp
185
- npx @oimdb/mcp cdp | jq .collections
186
- OIMDB_CDP_URL=http://localhost:9222 npx @oimdb/mcp cdp
187
- ```
188
-
189
- ## Ports, host and origins
190
-
191
- Everything here is configured through **environment variables**. The only CLI
192
- flag in the package is `devtools --no-open`.
193
-
194
- | Variable | Default | What it sets |
195
- |---|---|---|
196
- | `OIMDB_WS_PORT` | `7432` | The bridge WebSocket port |
197
- | `OIMDB_UI_PORT` | `7433` | The `devtools` UI HTTP port |
198
- | `OIMDB_HOST` | `127.0.0.1` | The interface both servers bind to |
199
- | `OIMDB_ALLOWED_ORIGINS` | *(empty)* | Extra page origins allowed onto the bridge, comma-separated |
200
- | `OIMDB_MODEL_MODULE` | — | Offline model module (see above) |
201
- | `OIMDB_CDP_URL` | `http://localhost:9222` | The CDP endpoint the `cdp` subcommand reads |
202
-
203
- The same two settings are `host` and `allowedOrigins` on `TOIMDevMcpOptions` and
204
- `TOIMDevUIServerOptions` when you construct a server yourself.
205
-
206
- **It binds to loopback by default, on purpose.** This port hands out the
207
- application's entire data model, and a `WebSocketServer` built with no host
208
- binds every interface, which would put the model on the café Wi-Fi.
209
- Set `OIMDB_HOST=0.0.0.0` when the browser really runs
210
- somewhere else (a container, a VM, a phone), and accept that everyone who can
211
- route there can talk to it. Both servers print the bound host at startup.
212
-
213
- **Origins are checked, and `'*'` is never allowed.** A request with no `Origin` header is
214
- allowed (that is a non-browser client). A loopback origin is allowed
215
- (`localhost`, `127.0.0.1`, `::1`, `[::1]`, `*.localhost`). Anything else is
216
- allowed only if you listed it exactly in `OIMDB_ALLOWED_ORIGINS`. The literal
217
- string `null` is always rejected, because a sandboxed iframe on any site in the world
218
- sends exactly that. Only an allow-listed origin gets
219
- `Access-Control-Allow-Origin` echoed back.
220
-
221
- While bound to a loopback host, the UI server also rejects a request whose
222
- `Host` header is not a loopback authority, with **421 Misdirected request**.
223
- This is the DNS-rebinding guard, and it is switched off when you bind elsewhere.
224
-
225
- Change the bridge port and update `oimDevRegistry.connect()` accordingly:
226
-
227
- ```bash
228
- OIMDB_WS_PORT=7433 npx @oimdb/mcp
229
- ```
230
-
231
- ```ts
232
- import { oimDevRegistry } from '@oimdb/devtools';
233
-
234
- oimDevRegistry.connect('ws://localhost:7433');
235
- ```
236
-
237
- ## Running a server from your own process
238
-
239
- ```ts
240
- import { createOIMDevMcpServer, createOIMDevUIServer } from '@oimdb/mcp';
241
- ```
242
-
243
- - **`createOIMDevMcpServer(options?)`** → `OIMDevMcpServer`. Options: `wsPort?`
244
- (7432), `registry?`, `modelModulePath?`, `host?` (`127.0.0.1`),
245
- `allowedOrigins?` (`[]`).
246
- - **`createOIMDevUIServer(options)`** → `OIMDevUIServer`. Options: `wsPort?`
247
- (7432), `uiPort?` (7433), **`uiDir` — required, no default**, `open?` (true),
248
- `host?` (`127.0.0.1`), `allowedOrigins?` (`[]`).
249
-
250
- Both classes are exported too, along with `TOIMDevMcpOptions`,
251
- `TOIMDevUIServerOptions` and `IOIMDevRegistry`.
252
-
253
- Know these three behaviours before you wire this into anything:
254
-
255
- - **The newest browser tab takes the bridge**, and the previous socket is closed
256
- with "Replaced by a newer OIMDB DevTools tab". Only the socket that currently
257
- holds the bridge may answer a request; anything else is ignored.
258
- - **A query times out after 5 seconds**, reported as "Browser response timeout
259
- (5s). Is the page active?".
260
- - **A malformed frame drops that client** with close code 1007, and `EADDRINUSE`
261
- exits the process with a message naming the env var to change.
262
-
263
- The `devtools` UI serves `/`, `/index.html`, `/app.js`, `/app.css`, plus
264
- `/api/inspect`, which answers `{ connected, tab, data }`:
265
-
266
- ```bash
267
- curl http://127.0.0.1:7433/api/inspect
268
- ```
269
-
270
- ## Subcommands
271
-
272
- ```bash
273
- npx @oimdb/mcp # the MCP server; `mcp` and `serve` are accepted aliases
274
- npx @oimdb/mcp devtools # the standalone UI
275
- npx @oimdb/mcp cdp # one-shot snapshot over the Chrome DevTools Protocol
276
- ```
69
+ `createOIMDevMcpServer(options?)` takes `wsPort?` (7432), `registry?`, `modelModulePath?`, `host?`
70
+ (`127.0.0.1`) and `allowedOrigins?` (`[]`). The bridge, ports, host and origin rules are `@oimdb/cli`'s and are
71
+ described in its README; `OIMDB_WS_PORT`, `OIMDB_HOST`, `OIMDB_ALLOWED_ORIGINS` and `OIMDB_MODEL_MODULE` set them
72
+ here too.
package/bin/oimdb-mcp.cjs CHANGED
@@ -10,26 +10,14 @@ process.on('uncaughtException', err => {
10
10
  process.on('unhandledRejection', reason => {
11
11
  process.stderr.write(`[OIMDB] Unhandled rejection (continuing): ${String(reason)}\n`);
12
12
  });
13
- /**
14
- * Single entry point for @oimdb/mcp. Dispatches on the first argument so all of
15
- * these work via npx (one bin → npx can always resolve it):
16
- *
17
- * npx @oimdb/mcp # MCP server (default; for AI tools)
18
- * npx @oimdb/mcp devtools # standalone DevTools UI (for humans)
19
- * npx @oimdb/mcp cdp # one-shot CDP snapshot to stdout
20
- */
21
13
  const sub = process.argv[2];
22
14
 
23
- if (sub === 'devtools') {
24
- require('./devtools.cjs')();
25
- } else if (sub === 'cdp') {
26
- require('./cdp.cjs')();
27
- } else if (sub === undefined || sub === 'mcp' || sub === 'serve') {
15
+ if (sub === undefined || sub === 'mcp' || sub === 'serve') {
28
16
  require('./server.cjs')();
29
17
  } else {
30
18
  process.stderr.write(
31
19
  `[OIMDB] Unknown command: ${sub}\n` +
32
- 'Usage: oimdb-mcp [devtools|cdp] (no argument = MCP server)\n'
20
+ 'Usage: oimdb-mcp (the MCP server). The DevTools UI and the CDP snapshot are in @oimdb/cli: oimdb serve, oimdb inspect --cdp.\n'
33
21
  );
34
22
  process.exit(1);
35
23
  }