@bli-cockpit/mcp 0.1.27 → 0.1.29

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
@@ -34,7 +34,7 @@ about what an agent can reach.
34
34
 
35
35
  <!-- BEGIN GENERATED verb census — `npm run mcp:readme` -->
36
36
 
37
- **77 of 80 Tower verbs have an MCP twin.**
37
+ **81 of 84 Tower verbs have an MCP twin.**
38
38
  Each tool goes through the SAME door its CLI verb calls, with the same
39
39
  collector device token — never a second route and never a service-role
40
40
  reader. `src/verb-census.test.ts` fails when a verb is in none of the
@@ -78,7 +78,11 @@ three tables below.
78
78
  | `cockpit mail search` | `mail_search` | `GET /api/mail/search` |
79
79
  | `cockpit mail send` | `mail_send` | `POST /api/mail/send` |
80
80
  | `cockpit mail sync` | `mail_sync` | `POST /api/mail/accounts/[id]/sync` |
81
+ | `cockpit memory forget` | `forget_memory` (`bli-memory`) | `POST /api/memory/forget` |
81
82
  | `cockpit memory log` | `memory_experience` | `POST /api/memory/experience` |
83
+ | `cockpit memory save` | `save_memory` (`bli-memory`) | `POST /api/memory/save` |
84
+ | `cockpit memory search` | `search_memory` (`bli-memory`) | `POST /api/memory/search` |
85
+ | `cockpit memory update` | `update_memory` (`bli-memory`) | `POST /api/memory/update` |
82
86
  | `cockpit model set` | `model_set` | `POST /api/settings/jarvis-model` |
83
87
  | `cockpit model show` | `model_show` | `GET /api/settings/jarvis-model` |
84
88
  | `cockpit models compare` | `models_compare` | `GET /api/models/cards?compare=` |
@@ -26,7 +26,10 @@ export function renderCensusMarkdown() {
26
26
  .filter((verb) => MCP_TWINS[verb])
27
27
  .map((verb) => {
28
28
  const twin = MCP_TWINS[verb];
29
- return `| ${spell(verb)} | \`${twin.tool}\` | \`${twin.door}\` |`;
29
+ // BLI-4047: two MCP servers ship. A tool cell that did not say which one
30
+ // registers it would send a reader to `bli-tower` for `search_memory`.
31
+ const server = twin.server && twin.server !== "bli-tower" ? ` (\`${twin.server}\`)` : "";
32
+ return `| ${spell(verb)} | \`${twin.tool}\`${server} | \`${twin.door}\` |`;
30
33
  });
31
34
  const owedRows = verbs
32
35
  .filter((verb) => AWAITING_TWIN[verb])
@@ -39,11 +39,31 @@ export interface TowerVerb {
39
39
  export declare function towerNouns(): string[];
40
40
  /** Every Tower verb a person may type today. */
41
41
  export declare function towerVerbs(): TowerVerb[];
42
+ /**
43
+ * The tools the SECOND MCP server registers (BLI-4047).
44
+ *
45
+ * BLI Memory ships its own server, `bli-memory`
46
+ * (`packages/cockpit-memory-mcp`), because its hooks and its session handling
47
+ * are its own; the four memory tools live there and not on `bli-tower`. This
48
+ * package declares no dependency on it, so — exactly like the collector scan
49
+ * above — the names are read out of its source. A text scan is the weaker
50
+ * check, and it is still strictly better than a census that calls four verbs
51
+ * twinned against tools nothing verifies exist.
52
+ */
53
+ export declare const MEMORY_MCP_SERVER_FILE: string;
54
+ export declare function memoryMcpToolNames(): string[];
42
55
  export interface McpTwin {
43
56
  /** The MCP tool name. Must actually be registered — the suite checks. */
44
57
  tool: string;
45
58
  /** The API door it goes through: the SAME one the CLI verb calls. */
46
59
  door: string;
60
+ /**
61
+ * Which MCP server registers it. Absent means `bli-tower`, this package.
62
+ * BLI-4047: `bli-memory` is the second server we ship, and a twin naming a
63
+ * tool on it while the suite only ever read `bli-tower`'s registry would be
64
+ * a claim nothing checks.
65
+ */
66
+ server?: "bli-tower" | "bli-memory";
47
67
  }
48
68
  /** A CLI verb and the MCP tool that does the same thing, over the same door. */
49
69
  export declare const MCP_TWINS: Record<string, McpTwin>;
@@ -138,7 +138,10 @@ function resolveShapeAlias(variant, unionSource) {
138
138
  export function towerVerbs() {
139
139
  const nouns = new Set(towerNouns());
140
140
  const aliases = actionAliases();
141
- const verbs = [{ noun: "memory", action: "log", spelling: "memory log" }];
141
+ const verbs = [
142
+ { noun: "memory", action: "log", spelling: "memory log" },
143
+ ...memoryStoreVerbs(aliases),
144
+ ];
142
145
  const seenNouns = new Set();
143
146
  for (const variant of commandVariants()) {
144
147
  const kind = /kind:\s*"([a-z-]+)"/.exec(variant)?.[1];
@@ -169,6 +172,41 @@ export function towerVerbs() {
169
172
  }
170
173
  return verbs.sort((a, b) => a.spelling.localeCompare(b.spelling));
171
174
  }
175
+ /**
176
+ * `cockpit memory search|save|update|forget` (BLI-4047).
177
+ *
178
+ * `memory` is a COLLECTOR noun — `parseMemoryArgs` lives in
179
+ * `local-args-collector-status.ts` and is not re-exported from
180
+ * `local-args-tower.ts`, because `install` and `status` act on THIS MACHINE.
181
+ * Four of its verbs act on Tower, so the mechanical noun scan cannot see them
182
+ * and this reads them off `MemoryStoreAction` instead. Deliberately NOT a
183
+ * hardcoded list of four: a fifth store verb still has to face the census and
184
+ * name its MCP twin.
185
+ */
186
+ function memoryStoreVerbs(aliases) {
187
+ const actions = aliases.get("MemoryStoreAction") ?? [];
188
+ if (actions.length === 0) {
189
+ throw new Error("MemoryStoreAction not found in the collector's local-args-tower-* files — "
190
+ + "`cockpit memory`'s Tower verbs would drop out of the census silently.");
191
+ }
192
+ return actions.map((action) => ({ noun: "memory", action, spelling: `memory ${action}` }));
193
+ }
194
+ /**
195
+ * The tools the SECOND MCP server registers (BLI-4047).
196
+ *
197
+ * BLI Memory ships its own server, `bli-memory`
198
+ * (`packages/cockpit-memory-mcp`), because its hooks and its session handling
199
+ * are its own; the four memory tools live there and not on `bli-tower`. This
200
+ * package declares no dependency on it, so — exactly like the collector scan
201
+ * above — the names are read out of its source. A text scan is the weaker
202
+ * check, and it is still strictly better than a census that calls four verbs
203
+ * twinned against tools nothing verifies exist.
204
+ */
205
+ export const MEMORY_MCP_SERVER_FILE = resolve(HERE, "../../cockpit-memory-mcp/src/server.ts");
206
+ export function memoryMcpToolNames() {
207
+ const source = readFileSync(MEMORY_MCP_SERVER_FILE, "utf8");
208
+ return [...source.matchAll(/registerTool\(\s*"([a-z_]+)"/g)].map((match) => match[1]);
209
+ }
172
210
  /** A CLI verb and the MCP tool that does the same thing, over the same door. */
173
211
  export const MCP_TWINS = {
174
212
  "docs list": { tool: "docs_list", door: "GET /api/docs/documents" },
@@ -222,6 +260,12 @@ export const MCP_TWINS = {
222
260
  "notes unshare": { tool: "notes_unshare", door: "POST /api/notes/share (share=false)" },
223
261
  "notes move": { tool: "notes_move", door: "POST /api/notes/move" },
224
262
  "memory log": { tool: "memory_experience", door: "POST /api/memory/experience" },
263
+ // BLI-4047: the memory STORE at a terminal. The twins live on the second
264
+ // server, `bli-memory`, over the same four doors these CLI verbs call.
265
+ "memory search": { tool: "search_memory", door: "POST /api/memory/search", server: "bli-memory" },
266
+ "memory save": { tool: "save_memory", door: "POST /api/memory/save", server: "bli-memory" },
267
+ "memory update": { tool: "update_memory", door: "POST /api/memory/update", server: "bli-memory" },
268
+ "memory forget": { tool: "forget_memory", door: "POST /api/memory/forget", server: "bli-memory" },
225
269
  "ops status": { tool: "ops_status", door: "GET /api/ops/status" },
226
270
  "ops recompile": { tool: "ops_recompile", door: "POST /api/ops/recompile" },
227
271
  "slack coverage": { tool: "slack_coverage", door: "GET /api/ops/slack/coverage" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/mcp",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "private": false,
5
5
  "description": "bli-tower \u2014 an MCP server over BLI Cockpit's agent doors: JARVIS (jarvis_*), documents (docs_*), channels (msg_*), issues (work_*), the daily page (brief_*), meeting notes (notes_*), the ops board (ops_status/slack_*), settings/team/model, Scout and the workbook, plus the legacy event-stream tools (emit_event, get_ticket_timeline, get_active_tickets).",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "readme": "npm run build && node scripts/write-readme-census.mjs"
31
31
  },
32
32
  "dependencies": {
33
- "@bli-cockpit/telemetry-core": "0.1.41",
33
+ "@bli-cockpit/telemetry-core": "0.1.42",
34
34
  "@modelcontextprotocol/sdk": "^1.29.0",
35
35
  "zod": "^4.3.6"
36
36
  },