@bli-cockpit/mcp 0.1.66 → 0.1.68
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/cal-tools.js +10 -0
- package/dist/docs-delete-tool.d.ts +7 -0
- package/dist/docs-delete-tool.js +58 -0
- package/dist/docs-msg-tools.js +13 -0
- package/dist/docs-read-tool.d.ts +14 -0
- package/dist/docs-read-tool.js +5 -2
- package/dist/tool-catalog.d.ts +1 -1
- package/dist/tool-catalog.js +1 -0
- package/dist/verb-census.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ about what an agent can reach.
|
|
|
103
103
|
|
|
104
104
|
<!-- BEGIN GENERATED verb census — `npm run mcp:readme` -->
|
|
105
105
|
|
|
106
|
-
**
|
|
106
|
+
**110 of 115 Tower verbs have an MCP twin.**
|
|
107
107
|
Each tool goes through the SAME door its CLI verb calls, with the same
|
|
108
108
|
collector device token — never a second route and never a service-role
|
|
109
109
|
reader. `src/verb-census.test.ts` fails when a verb is in none of the
|
|
@@ -139,6 +139,7 @@ three tables below.
|
|
|
139
139
|
| `cockpit careers takehome show` | `careers_takehome_show` | `GET /api/careers/takehomes/[role]` |
|
|
140
140
|
| `cockpit correct` | `brief_correct` | `POST /api/jarvis/corrections` |
|
|
141
141
|
| `cockpit docs create` | `docs_create` | `POST /api/docs/documents` |
|
|
142
|
+
| `cockpit docs delete` | `docs_delete` | `DELETE /api/docs/documents/[id]` |
|
|
142
143
|
| `cockpit docs link` | `docs_link` | `PUT /api/docs/documents/[id]/notion-link` |
|
|
143
144
|
| `cockpit docs list` | `docs_list` | `GET /api/docs/documents` |
|
|
144
145
|
| `cockpit docs read` | `docs_read` | `GET /api/docs/documents/[id]` |
|
package/dist/cal-tools.js
CHANGED
|
@@ -204,6 +204,7 @@ export function registerCalTools(server, deps) {
|
|
|
204
204
|
return errorResult(doorFailureText("cal_create", response));
|
|
205
205
|
const event = response.body.event;
|
|
206
206
|
return textResult(`Created "${event?.title ?? String(args.title)}" at ${event?.starts_at ?? String(args.starts_at)}.`
|
|
207
|
+
+ towerIdLine(event)
|
|
207
208
|
+ (event?.html_link ? `\n${event.html_link}` : "")
|
|
208
209
|
+ (args.meet === true
|
|
209
210
|
? event?.meet_link
|
|
@@ -274,3 +275,12 @@ export function registerCalTools(server, deps) {
|
|
|
274
275
|
return textResult(`Detached ${String(args.calendar_id)}. Its stored events went with it; the calendar itself is untouched at Google.`, response.body);
|
|
275
276
|
}));
|
|
276
277
|
}
|
|
278
|
+
/** BLI-10560: the new event's Tower id, or why there is none yet. */
|
|
279
|
+
function towerIdLine(event) {
|
|
280
|
+
if (event?.event_id)
|
|
281
|
+
return `\nTower event: ${event.event_id}`;
|
|
282
|
+
if (event?.local_store === "failed" || event?.local_store === "unreadable") {
|
|
283
|
+
return "\nGoogle has the event; Tower has not stored it yet (the next calendar sync will), so there is no Tower id to open yet.";
|
|
284
|
+
}
|
|
285
|
+
return "";
|
|
286
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type DocsMsgDeps } from "./docs-msg-helpers.js";
|
|
2
|
+
import { type ToolResult } from "./tool-result.js";
|
|
3
|
+
export interface DocsDeleteArgs {
|
|
4
|
+
id?: unknown;
|
|
5
|
+
ids?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare function runDocsDeleteTool(deps: DocsMsgDeps, args: DocsDeleteArgs): Promise<ToolResult>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `docs_delete` (BLI‑10555) — the MCP twin of `cockpit docs delete`, the same
|
|
3
|
+
* `DELETE /api/docs/documents/[id]` door the browser's own delete calls.
|
|
4
|
+
*
|
|
5
|
+
* Soft delete only: the door sets `deleted_at` and never issues a real SQL
|
|
6
|
+
* `DELETE`, so it is recoverable (only a super_admin clearing `deleted_at`
|
|
7
|
+
* brings it back — there is no self-service undo) and never cascades: a
|
|
8
|
+
* deleted document's children keep their own `parent_id` and stay exactly
|
|
9
|
+
* where they were.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors `docs-read-tool.ts`'s multi-ref shape: `resolveDocumentIds` runs
|
|
12
|
+
* ONE shared list read for every non-uuid ref, then one `DELETE` per
|
|
13
|
+
* document — one bad ref never loses the rest of the batch.
|
|
14
|
+
*/
|
|
15
|
+
import { callAgentDoor } from "./agent-door.js";
|
|
16
|
+
import { resolveDocumentId } from "./docs-msg-helpers.js";
|
|
17
|
+
import { resolveDocumentIds } from "./docs-read-tool.js";
|
|
18
|
+
import { doorFailureText, errorResult, textResult, withSession } from "./tool-result.js";
|
|
19
|
+
async function deleteOneDocument(deps, session, ref, id) {
|
|
20
|
+
if (!id)
|
|
21
|
+
return { ref, ok: false, text: `No document matches "${ref}" — check docs_list for the id or slug.` };
|
|
22
|
+
const response = await callAgentDoor(session, deps.fetchImpl, "DELETE", `/api/docs/documents/${encodeURIComponent(id)}`);
|
|
23
|
+
if (!response.ok)
|
|
24
|
+
return { ref, ok: false, text: doorFailureText("docs_delete", response) };
|
|
25
|
+
return { ref, ok: true, id };
|
|
26
|
+
}
|
|
27
|
+
export async function runDocsDeleteTool(deps, args) {
|
|
28
|
+
return withSession(deps, async (session) => {
|
|
29
|
+
const refs = Array.isArray(args.ids) && args.ids.length > 0 ? args.ids.map(String) : [String(args.id ?? "")];
|
|
30
|
+
if (refs.length === 1 && refs[0] === "")
|
|
31
|
+
return errorResult("docs_delete needs id or ids.");
|
|
32
|
+
const resolved = refs.length === 1
|
|
33
|
+
? await (async () => {
|
|
34
|
+
const one = await resolveDocumentId(deps, session, refs[0]);
|
|
35
|
+
if (one.status === "list_failed")
|
|
36
|
+
return { status: "list_failed", text: one.text };
|
|
37
|
+
const ids = new Map();
|
|
38
|
+
if (one.status === "ok")
|
|
39
|
+
ids.set(refs[0], one.id);
|
|
40
|
+
return { status: "ok", ids };
|
|
41
|
+
})()
|
|
42
|
+
: await resolveDocumentIds(deps, session, refs);
|
|
43
|
+
if (resolved.status === "list_failed")
|
|
44
|
+
return errorResult(resolved.text);
|
|
45
|
+
const results = await Promise.all(refs.map((ref) => deleteOneDocument(deps, session, ref, resolved.ids.get(ref))));
|
|
46
|
+
const failed = results.filter((result) => !result.ok);
|
|
47
|
+
if (refs.length === 1) {
|
|
48
|
+
const [result] = results;
|
|
49
|
+
if (!result?.ok)
|
|
50
|
+
return errorResult(result?.text ?? "docs_delete could not delete that document.");
|
|
51
|
+
return textResult(`Deleted ${result.id}. Recoverable by a super_admin; its children stay in place.`, { document_id: result.id });
|
|
52
|
+
}
|
|
53
|
+
const lines = results.map((result) => (result.ok ? `Deleted ${result.ref} (${result.id}).` : `${result.ref}: ${result.text}`)).join("\n");
|
|
54
|
+
return textResult(`${results.length - failed.length}/${results.length} document(s) deleted. Recoverable by a super_admin; children stay in place.\n${lines}`, {
|
|
55
|
+
documents: results.map((result) => result.ok ? { ref: result.ref, ok: true, document_id: result.id } : { ref: result.ref, ok: false, error: result.text }),
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
package/dist/docs-msg-tools.js
CHANGED
|
@@ -13,6 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
import { callAgentDoor } from "./agent-door.js";
|
|
14
14
|
import { DEFAULT_LIST_LIMIT, doorFailureText, errorResult, moreNote, registrarFor, textResult, withSession, } from "./tool-result.js";
|
|
15
15
|
import { DOCS_LIST_MAX, slimTree, renderDocTree, countTree, docListRow, docListLine, resolveDocumentId, resolveChannelId, messageLine, docsListPath } from "./docs-msg-helpers.js";
|
|
16
|
+
import { runDocsDeleteTool } from "./docs-delete-tool.js";
|
|
16
17
|
import { runDocsReadTool } from "./docs-read-tool.js";
|
|
17
18
|
export { docsListPath } from "./docs-msg-helpers.js";
|
|
18
19
|
export function registerDocsMsgTools(server, deps) {
|
|
@@ -133,6 +134,18 @@ export function registerDocsMsgTools(server, deps) {
|
|
|
133
134
|
const document = response.body.document;
|
|
134
135
|
return textResult(`Updated "${document?.title ?? ""}" (${document?.id ?? resolved.id}).`, { document });
|
|
135
136
|
}));
|
|
137
|
+
register("docs_delete", {
|
|
138
|
+
title: "Delete a Tower document",
|
|
139
|
+
description: "Soft-deletes one or more documents (id or slug — docs_list returns both), or several with ids. Sets "
|
|
140
|
+
+ "deleted_at; never a real SQL delete. Recoverable — only a super_admin clearing deleted_at brings it back, "
|
|
141
|
+
+ "there is no self-service undo. Deleting a parent does NOT delete its children; they keep their own "
|
|
142
|
+
+ "parent_id and stay exactly where they were. One shared list resolves every ref, then one delete each — "
|
|
143
|
+
+ "one bad ref never loses the rest.",
|
|
144
|
+
inputSchema: {
|
|
145
|
+
id: z.string().min(1).max(200).optional().describe("A document id, or its slug. Omit when passing ids."),
|
|
146
|
+
ids: z.array(z.string().min(1).max(200)).min(1).max(50).optional().describe("Several documents in one call."),
|
|
147
|
+
},
|
|
148
|
+
}, async (args) => runDocsDeleteTool(deps, args));
|
|
136
149
|
register("msg_channels", {
|
|
137
150
|
title: "List Tower channels",
|
|
138
151
|
description: "Every channel you are a member of: id, name (a direct message has none and lists its participants instead), "
|
package/dist/docs-read-tool.d.ts
CHANGED
|
@@ -11,6 +11,20 @@ export declare function sliceDocRange(body: string, offset: number | undefined,
|
|
|
11
11
|
truncated: boolean;
|
|
12
12
|
totalChars: number;
|
|
13
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* One shared list read for every non-uuid ref, never one per ref. Exported
|
|
16
|
+
* for `docs-delete-tool.ts` (BLI‑10555), which resolves a batch the same way.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveDocumentIds(deps: DocsMsgDeps, session: {
|
|
19
|
+
dashboardUrl: string;
|
|
20
|
+
deviceToken: string;
|
|
21
|
+
}, refs: string[]): Promise<{
|
|
22
|
+
status: "ok";
|
|
23
|
+
ids: Map<string, string>;
|
|
24
|
+
} | {
|
|
25
|
+
status: "list_failed";
|
|
26
|
+
text: string;
|
|
27
|
+
}>;
|
|
14
28
|
export interface DocsReadArgs {
|
|
15
29
|
id?: unknown;
|
|
16
30
|
ids?: unknown;
|
package/dist/docs-read-tool.js
CHANGED
|
@@ -70,8 +70,11 @@ function narrowBody(document, section, offset, limit, applyCharRange) {
|
|
|
70
70
|
return { ok: true };
|
|
71
71
|
}
|
|
72
72
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
|
|
73
|
-
/**
|
|
74
|
-
|
|
73
|
+
/**
|
|
74
|
+
* One shared list read for every non-uuid ref, never one per ref. Exported
|
|
75
|
+
* for `docs-delete-tool.ts` (BLI‑10555), which resolves a batch the same way.
|
|
76
|
+
*/
|
|
77
|
+
export async function resolveDocumentIds(deps, session, refs) {
|
|
75
78
|
const ids = new Map();
|
|
76
79
|
const needsList = refs.filter((ref) => !UUID_PATTERN.test(ref));
|
|
77
80
|
for (const ref of refs)
|
package/dist/tool-catalog.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare const DRY_RUN_TOOLS: readonly ["ops_recompile", "memory_requeue"]
|
|
|
21
21
|
* candidates, share calendars. Never called by the smoke; covered by the unit
|
|
22
22
|
* suites (`write-tools.test.ts` and each family's own).
|
|
23
23
|
*/
|
|
24
|
-
export declare const WRITE_TOOLS: readonly ["emit_event", "docs_create", "docs_update", "docs_link", "msg_create_channel", "msg_dm", "msg_send", "work_create_issue", "work_update_issue", "work_move_issue", "work_comment_issue", "careers_rescreen", "careers_send_takehome", "careers_invite", "careers_grade", "careers_decide", "careers_takehome_set", "careers_settings_set", "mail_send", "mail_sync", "mail_detach", "cal_create", "cal_share", "cal_sync", "cal_detach", "jarvis_dispatch", "notes_mkdir", "notes_rmdir", "notes_rename", "notes_upload", "notes_paste", "notes_share", "notes_unshare", "notes_move", "notes_sync", "notes_detach", "memory_experience", "scout_start", "scout_dismiss", "scout_undo", "brief_rewrite", "brief_correct", "brief_done", "brief_undone", "settings_set", "settings_delete", "model_set", "team_invite", "team_role", "team_device_revoke"];
|
|
24
|
+
export declare const WRITE_TOOLS: readonly ["emit_event", "docs_create", "docs_update", "docs_delete", "docs_link", "msg_create_channel", "msg_dm", "msg_send", "work_create_issue", "work_update_issue", "work_move_issue", "work_comment_issue", "careers_rescreen", "careers_send_takehome", "careers_invite", "careers_grade", "careers_decide", "careers_takehome_set", "careers_settings_set", "mail_send", "mail_sync", "mail_detach", "cal_create", "cal_share", "cal_sync", "cal_detach", "jarvis_dispatch", "notes_mkdir", "notes_rmdir", "notes_rename", "notes_upload", "notes_paste", "notes_share", "notes_unshare", "notes_move", "notes_sync", "notes_detach", "memory_experience", "scout_start", "scout_dismiss", "scout_undo", "brief_rewrite", "brief_correct", "brief_done", "brief_undone", "settings_set", "settings_delete", "model_set", "team_invite", "team_role", "team_device_revoke"];
|
|
25
25
|
/** Reads that spend a model turn. The smoke's `--no-model` leaves these out. */
|
|
26
26
|
export declare const MODEL_SPENDING_TOOLS: readonly ["jarvis_ask", "jarvis_check"];
|
|
27
27
|
/**
|
package/dist/tool-catalog.js
CHANGED
package/dist/verb-census.js
CHANGED
|
@@ -234,6 +234,7 @@ export const MCP_TWINS = {
|
|
|
234
234
|
"docs read": { tool: "docs_read", door: "GET /api/docs/documents/[id]" },
|
|
235
235
|
"docs create": { tool: "docs_create", door: "POST /api/docs/documents" },
|
|
236
236
|
"docs update": { tool: "docs_update", door: "PATCH /api/docs/documents/[id]" },
|
|
237
|
+
"docs delete": { tool: "docs_delete", door: "DELETE /api/docs/documents/[id]" },
|
|
237
238
|
"docs link": { tool: "docs_link", door: "PUT /api/docs/documents/[id]/notion-link" },
|
|
238
239
|
"docs sync-status": { tool: "docs_sync_status", door: "GET /api/docs/notion-sync" },
|
|
239
240
|
"msg channels": { tool: "msg_channels", door: "GET /api/msg/channels" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.68",
|
|
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",
|