@bli-cockpit/mcp 0.1.57 → 0.1.58
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 +2 -1
- package/dist/memory-requeue-tools.d.ts +23 -0
- package/dist/memory-requeue-tools.js +107 -0
- package/dist/server.js +4 -0
- package/dist/verb-census.js +4 -0
- package/package.json +1 -1
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
|
-
**
|
|
37
|
+
**107 of 112 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
|
|
@@ -95,6 +95,7 @@ three tables below.
|
|
|
95
95
|
| `cockpit memory forget` | `forget_memory` (`bli-memory`) | `POST /api/memory/forget` |
|
|
96
96
|
| `cockpit memory log` | `memory_experience` | `POST /api/memory/experience` |
|
|
97
97
|
| `cockpit memory profile` | `memory_profile` | `GET /api/memory/profile` |
|
|
98
|
+
| `cockpit memory requeue` | `memory_requeue` | `POST /api/memory/requeue` |
|
|
98
99
|
| `cockpit memory save` | `save_memory` (`bli-memory`) | `POST /api/memory/save` |
|
|
99
100
|
| `cockpit memory search` | `search_memory` (`bli-memory`) | `POST /api/memory/search` |
|
|
100
101
|
| `cockpit memory update` | `update_memory` (`bli-memory`) | `POST /api/memory/update` |
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `memory_requeue` (BLI-4539) — put a window of finished extractions back in
|
|
3
|
+
* the queue, over the same `POST /api/memory/requeue` door
|
|
4
|
+
* `cockpit memory requeue` calls.
|
|
5
|
+
*
|
|
6
|
+
* It exists because the alternative was a one-off script. Between 04:16Z and
|
|
7
|
+
* 11:36Z on 2026-09-21 every insert into the memory store that carried aliases
|
|
8
|
+
* was refused, 122 extraction receipts closed as if nothing were wrong, and
|
|
9
|
+
* recovering them meant somebody hand-writing SQL against production.
|
|
10
|
+
*
|
|
11
|
+
* It lives on `bli-tower` rather than on `bli-memory` for the same reason
|
|
12
|
+
* `memory_profile` does: that server's four tools are the vendor-compatible
|
|
13
|
+
* set the Claude Code plugin expects, and this is ours.
|
|
14
|
+
*
|
|
15
|
+
* **`dryRun` defaults to TRUE, here as at the door.** An apply re-runs one
|
|
16
|
+
* model call per receipt, so an agent that means to count must never be able
|
|
17
|
+
* to spend by omission. The door's super_admin gate is the real boundary; this
|
|
18
|
+
* default is the one that stops an honest mistake.
|
|
19
|
+
*/
|
|
20
|
+
import { type ToolDeps } from "./tool-result.js";
|
|
21
|
+
export declare function registerMemoryRequeueTools(server: {
|
|
22
|
+
registerTool: (...args: never[]) => unknown;
|
|
23
|
+
}, deps: ToolDeps): void;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `memory_requeue` (BLI-4539) — put a window of finished extractions back in
|
|
3
|
+
* the queue, over the same `POST /api/memory/requeue` door
|
|
4
|
+
* `cockpit memory requeue` calls.
|
|
5
|
+
*
|
|
6
|
+
* It exists because the alternative was a one-off script. Between 04:16Z and
|
|
7
|
+
* 11:36Z on 2026-09-21 every insert into the memory store that carried aliases
|
|
8
|
+
* was refused, 122 extraction receipts closed as if nothing were wrong, and
|
|
9
|
+
* recovering them meant somebody hand-writing SQL against production.
|
|
10
|
+
*
|
|
11
|
+
* It lives on `bli-tower` rather than on `bli-memory` for the same reason
|
|
12
|
+
* `memory_profile` does: that server's four tools are the vendor-compatible
|
|
13
|
+
* set the Claude Code plugin expects, and this is ours.
|
|
14
|
+
*
|
|
15
|
+
* **`dryRun` defaults to TRUE, here as at the door.** An apply re-runs one
|
|
16
|
+
* model call per receipt, so an agent that means to count must never be able
|
|
17
|
+
* to spend by omission. The door's super_admin gate is the real boundary; this
|
|
18
|
+
* default is the one that stops an honest mistake.
|
|
19
|
+
*/
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import { callAgentDoor } from "./agent-door.js";
|
|
22
|
+
import { doorFailureText, errorResult, registrarFor, textResult, withSession, } from "./tool-result.js";
|
|
23
|
+
/** `hook:104, harvest:18` — counts and labels only, never a receipt's content. */
|
|
24
|
+
function split(counts) {
|
|
25
|
+
if (!counts)
|
|
26
|
+
return "none";
|
|
27
|
+
const entries = Object.entries(counts).sort((left, right) => right[1] - left[1] || (left[0] < right[0] ? -1 : 1));
|
|
28
|
+
return entries.length === 0 ? "none" : entries.map(([label, count]) => `${label}:${count}`).join(", ");
|
|
29
|
+
}
|
|
30
|
+
export function registerMemoryRequeueTools(server, deps) {
|
|
31
|
+
registrarFor(server)("memory_requeue", {
|
|
32
|
+
title: "Requeue a window of memory extractions",
|
|
33
|
+
description: "Put finished `memory_extract_jobs` receipts back to `queued` after the store refused their writes — "
|
|
34
|
+
+ "the recovery for a `store_failed` window once its cause is fixed. Nothing is ever deleted: the previous "
|
|
35
|
+
+ "outcome is kept on the row under `result.requeued_from`. Super admins only. `dryRun` defaults to TRUE "
|
|
36
|
+
+ "and an apply re-runs one model call per receipt, so count first. A window is required; there is no "
|
|
37
|
+
+ "requeue-everything.",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
since: z
|
|
40
|
+
.string()
|
|
41
|
+
.min(1)
|
|
42
|
+
.describe("ISO instant; receipts that FINISHED at or after it, e.g. 2026-09-21T04:10:00Z."),
|
|
43
|
+
until: z
|
|
44
|
+
.string()
|
|
45
|
+
.min(1)
|
|
46
|
+
.optional()
|
|
47
|
+
.describe("ISO instant; receipts that finished at or before it."),
|
|
48
|
+
source: z
|
|
49
|
+
.enum(["hook", "harvest"])
|
|
50
|
+
.optional()
|
|
51
|
+
.describe("One arm only. Absent means both."),
|
|
52
|
+
reason: z
|
|
53
|
+
.string()
|
|
54
|
+
.min(1)
|
|
55
|
+
.max(80)
|
|
56
|
+
.optional()
|
|
57
|
+
.describe("A short label, written onto the row as `requeued:<label>`. Never a sentence."),
|
|
58
|
+
dryRun: z
|
|
59
|
+
.boolean()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Count and write nothing. Defaults to true; pass false to apply."),
|
|
62
|
+
},
|
|
63
|
+
}, async (args) => withSession(deps, async (session) => {
|
|
64
|
+
const dryRun = args.dryRun === undefined ? true : Boolean(args.dryRun);
|
|
65
|
+
const response = await callAgentDoor(session, deps.fetchImpl, "POST", "/api/memory/requeue", {
|
|
66
|
+
since: String(args.since),
|
|
67
|
+
...(args.until === undefined ? {} : { until: String(args.until) }),
|
|
68
|
+
...(args.source === undefined ? {} : { source: String(args.source) }),
|
|
69
|
+
...(args.reason === undefined ? {} : { reason: String(args.reason) }),
|
|
70
|
+
dryRun,
|
|
71
|
+
});
|
|
72
|
+
if (!response.ok)
|
|
73
|
+
return errorResult(doorFailureText("memory_requeue", response));
|
|
74
|
+
const body = response.body;
|
|
75
|
+
const matched = body.matched ?? 0;
|
|
76
|
+
if (matched === 0) {
|
|
77
|
+
// Named, not blank: "nothing matched" and "the store is down" are
|
|
78
|
+
// different facts, and the second one took the branch above.
|
|
79
|
+
return textResult(`No finished extraction receipt is in that window. Nothing to requeue; the receipts table answered.`, { ok: true, dryRun: body.dryRun ?? dryRun, matched: 0, requeued: 0 });
|
|
80
|
+
}
|
|
81
|
+
const head = body.dryRun
|
|
82
|
+
? `${matched} receipt(s) would be requeued`
|
|
83
|
+
: `${body.requeued ?? 0} of ${matched} receipt(s) requeued`;
|
|
84
|
+
return textResult([
|
|
85
|
+
`${head} (${split(body.bySource)}).`,
|
|
86
|
+
`By reason: ${split(body.byReason)}.`,
|
|
87
|
+
body.coverage === "capped"
|
|
88
|
+
? "The page ceiling stopped this run before the window ended; run it again for the rest."
|
|
89
|
+
: "",
|
|
90
|
+
body.dryRun
|
|
91
|
+
? "Nothing was written. Call again with dryRun: false to apply."
|
|
92
|
+
: "The previous result is kept on each row under result.requeued_from.",
|
|
93
|
+
]
|
|
94
|
+
.filter((line) => line.length > 0)
|
|
95
|
+
.join("\n"), {
|
|
96
|
+
ok: true,
|
|
97
|
+
dryRun: body.dryRun ?? dryRun,
|
|
98
|
+
matched,
|
|
99
|
+
scanned: body.scanned ?? 0,
|
|
100
|
+
requeued: body.requeued ?? 0,
|
|
101
|
+
refused: body.refused ?? 0,
|
|
102
|
+
coverage: body.coverage ?? "unknown",
|
|
103
|
+
bySource: body.bySource ?? {},
|
|
104
|
+
byReason: body.byReason ?? {},
|
|
105
|
+
});
|
|
106
|
+
}));
|
|
107
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -18,6 +18,7 @@ import { registerNotesWriteTools } from "./notes-write-tools.js";
|
|
|
18
18
|
import { registerMemoryConsolidationTools } from "./memory-consolidation-tools.js";
|
|
19
19
|
import { registerMemoryExperienceTools } from "./memory-experience-tools.js";
|
|
20
20
|
import { registerMemoryProfileTools } from "./memory-profile-tools.js";
|
|
21
|
+
import { registerMemoryRequeueTools } from "./memory-requeue-tools.js";
|
|
21
22
|
import { registerModelsTools } from "./models-tools.js";
|
|
22
23
|
import { registerOpsTools } from "./ops-tools.js";
|
|
23
24
|
import { registerPagesTools } from "./pages-tools.js";
|
|
@@ -430,6 +431,9 @@ export function createServer(deps) {
|
|
|
430
431
|
// BLI-4534: the nightly consolidation receipts, twin of `cockpit memory
|
|
431
432
|
// consolidation`. Read-only, and the pass it reports on never deletes.
|
|
432
433
|
registerMemoryConsolidationTools(server, { fetchImpl: deps.fetchImpl });
|
|
434
|
+
// BLI-4539: putting a window of refused extractions back, the twin of
|
|
435
|
+
// `cockpit memory requeue`. Dry run by default, super_admin at the door.
|
|
436
|
+
registerMemoryRequeueTools(server, { fetchImpl: deps.fetchImpl });
|
|
433
437
|
registerSettingsTools(server, { fetchImpl: deps.fetchImpl });
|
|
434
438
|
registerPagesTools(server, { fetchImpl: deps.fetchImpl });
|
|
435
439
|
// BLI-3756 batch 2: the WRITES. Same doors, same device token, same refusal
|
package/dist/verb-census.js
CHANGED
|
@@ -308,6 +308,10 @@ export const MCP_TWINS = {
|
|
|
308
308
|
// `bli-tower` rather than `bli-memory`, because it is a read of a JOB s
|
|
309
309
|
// counts and not a read or write of the store itself.
|
|
310
310
|
"memory consolidation": { tool: "memory_consolidation", door: "GET /api/memory/consolidation" },
|
|
311
|
+
// BLI-4539: the recovery verb, after a window of extractions whose writes
|
|
312
|
+
// the store refused. Also on `bli-tower`, for the same reason
|
|
313
|
+
// `memory profile` is: it is ours, not the vendor's four.
|
|
314
|
+
"memory requeue": { tool: "memory_requeue", door: "POST /api/memory/requeue" },
|
|
311
315
|
"ops status": { tool: "ops_status", door: "GET /api/ops/status" },
|
|
312
316
|
"ops recompile": { tool: "ops_recompile", door: "POST /api/ops/recompile" },
|
|
313
317
|
"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.
|
|
3
|
+
"version": "0.1.58",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "bli-tower: 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",
|