@bli-cockpit/mcp 0.1.78 → 0.1.80
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 +4 -1
- package/dist/careers-tools.js +18 -1
- package/dist/rename-tools.d.ts +15 -0
- package/dist/rename-tools.js +52 -0
- package/dist/server.js +4 -0
- package/dist/tool-catalog.d.ts +2 -2
- package/dist/tool-catalog.js +3 -0
- package/dist/verb-census.js +5 -0
- package/package.json +7 -2
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
|
+
**119 of 124 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
|
|
@@ -131,6 +131,7 @@ three tables below.
|
|
|
131
131
|
| `cockpit careers decide` | `careers_decide` | `POST /api/careers/applications/[id]/decide` |
|
|
132
132
|
| `cockpit careers followup` | `careers_followup` | `POST /api/careers/applications/[id]/followup` |
|
|
133
133
|
| `cockpit careers grade` | `careers_grade` | `POST /api/careers/applications/[id]/grade` |
|
|
134
|
+
| `cockpit careers interview` | `careers_interview` | `POST /api/careers/applications/[id]/interview` |
|
|
134
135
|
| `cockpit careers send-takehome` | `careers_send_takehome` | `POST /api/careers/applications/[id]/invite` |
|
|
135
136
|
| `cockpit careers list` | `careers_list` | `GET /api/careers/applications` |
|
|
136
137
|
| `cockpit careers rescreen` | `careers_rescreen` | `POST /api/careers/applications/[id]/rescreen` |
|
|
@@ -208,6 +209,8 @@ three tables below.
|
|
|
208
209
|
| `cockpit ops recompile` | `ops_recompile` | `POST /api/ops/recompile` |
|
|
209
210
|
| `cockpit ops status` | `ops_status` | `GET /api/ops/status` |
|
|
210
211
|
| `cockpit project list` | `work_list_projects` | `GET /api/work/projects` |
|
|
212
|
+
| `cockpit rename list` | `rename_pending` | `GET /api/jarvis/rename-scope` |
|
|
213
|
+
| `cockpit rename resolve` | `rename_resolve` | `POST /api/jarvis/rename-scope` |
|
|
211
214
|
| `cockpit scout board` | `scout_board` | `GET /api/cockpit/scout` |
|
|
212
215
|
| `cockpit scout dismiss` | `scout_dismiss` | `POST /api/cockpit/scout (dismiss)` |
|
|
213
216
|
| `cockpit scout start` | `scout_start` | `POST /api/cockpit/scout (start)` |
|
package/dist/careers-tools.js
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { callAgentDoor } from './agent-door.js';
|
|
3
3
|
import { dataResult, doorFailureText, errorResult, registrarFor, withSession } from './tool-result.js';
|
|
4
4
|
/** Verbatim from `lib/careers/applications.ts` `PIPELINE_STAGES`. */
|
|
5
|
-
const PIPELINE_STAGES = ['screened', 'invited', 'submitted', 'graded', 'booking_sent', 'passed_on', 'archived'];
|
|
5
|
+
const PIPELINE_STAGES = ['screened', 'invited', 'submitted', 'graded', 'booking_sent', 'interview', 'passed_on', 'archived'];
|
|
6
6
|
const APPLICATION_ID = z.string().uuid().describe('An application id, as careers_list returns it.');
|
|
7
7
|
/**
|
|
8
8
|
* One list row without the screening's prose (BLI-10432). The door returns the
|
|
@@ -137,6 +137,23 @@ export function registerCareersTools(server, deps) {
|
|
|
137
137
|
const answer = await callAgentDoor(session, deps.fetchImpl, 'POST', `/api/careers/applications/${encodeURIComponent(String(args.id))}/followup`, body, 60_000);
|
|
138
138
|
return answer.ok ? dataResult(args.record_sent_at === undefined ? 'Follow-up sent' : 'Follow-up recorded', answer.body) : errorResult(doorFailureText('careers_followup', answer));
|
|
139
139
|
}));
|
|
140
|
+
// BLI-12198: an interview Edward booked himself. Same door as the drawer's
|
|
141
|
+
// Interview booked control: `at` books or reschedules, `clear` undoes it.
|
|
142
|
+
register('careers_interview', {
|
|
143
|
+
title: 'Book, reschedule or clear an interview',
|
|
144
|
+
description: 'Super-admin only. With `at`, records an interview Edward booked himself: the row moves to the interview stage (any stage but archived), its chip reads Interview plus the time, and booking again reschedules. With `clear: true`, returns the row to the stage it stood at before. Exactly one of at or clear.',
|
|
145
|
+
inputSchema: {
|
|
146
|
+
id: APPLICATION_ID,
|
|
147
|
+
at: z.string().min(1).max(40).optional().describe('ISO-8601 instant with an offset, e.g. 2026-10-05T10:00:00-07:00. Books or reschedules the interview.'),
|
|
148
|
+
clear: z.boolean().optional().describe('true: remove the interview and return the row to its earlier stage. Not with at.'),
|
|
149
|
+
},
|
|
150
|
+
}, async (args) => withSession(deps, async (session) => {
|
|
151
|
+
if ((args.at === undefined) === (args.clear !== true))
|
|
152
|
+
return errorResult('careers_interview needs exactly one of at or clear: true.');
|
|
153
|
+
const body = args.clear === true ? { clear: true } : { at: args.at };
|
|
154
|
+
const answer = await callAgentDoor(session, deps.fetchImpl, 'POST', `/api/careers/applications/${encodeURIComponent(String(args.id))}/interview`, body, 60_000);
|
|
155
|
+
return answer.ok ? dataResult(args.clear === true ? 'Interview cleared' : 'Interview saved', answer.body) : errorResult(doorFailureText('careers_interview', answer));
|
|
156
|
+
}));
|
|
140
157
|
register('careers_decide', {
|
|
141
158
|
title: 'Decide on an application',
|
|
142
159
|
description: 'Super-admin only. Records the call on one application: `passed_on`, `archived`, or `reopen` to put it back at `screened`.',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `rename_pending` / `rename_resolve` (BLI-12378): the MCP twins of
|
|
3
|
+
* `cockpit rename list|resolve`, over the same door the panel's two buttons
|
|
4
|
+
* call (`/api/jarvis/rename-scope`) with the same device token.
|
|
5
|
+
*
|
|
6
|
+
* A correction JARVIS cannot classify is fixed on one page and waits for a
|
|
7
|
+
* human's call. Whether it becomes a permanent rule is that call, never an
|
|
8
|
+
* agent's guess: an agent should pass `everywhere` only on a person's say-so,
|
|
9
|
+
* and the door still refuses to make a fact (a status, a date, a number) a
|
|
10
|
+
* rule whatever is asked.
|
|
11
|
+
*/
|
|
12
|
+
import { type ToolDeps } from "./tool-result.js";
|
|
13
|
+
export declare function registerRenameTools(server: {
|
|
14
|
+
registerTool: (...args: never[]) => unknown;
|
|
15
|
+
}, deps: ToolDeps): void;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `rename_pending` / `rename_resolve` (BLI-12378): the MCP twins of
|
|
3
|
+
* `cockpit rename list|resolve`, over the same door the panel's two buttons
|
|
4
|
+
* call (`/api/jarvis/rename-scope`) with the same device token.
|
|
5
|
+
*
|
|
6
|
+
* A correction JARVIS cannot classify is fixed on one page and waits for a
|
|
7
|
+
* human's call. Whether it becomes a permanent rule is that call, never an
|
|
8
|
+
* agent's guess: an agent should pass `everywhere` only on a person's say-so,
|
|
9
|
+
* and the door still refuses to make a fact (a status, a date, a number) a
|
|
10
|
+
* rule whatever is asked.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { callAgentDoor } from "./agent-door.js";
|
|
14
|
+
import { dataResult, doorFailureText, errorResult, registrarFor, withSession, } from "./tool-result.js";
|
|
15
|
+
export function registerRenameTools(server, deps) {
|
|
16
|
+
const register = registrarFor(server);
|
|
17
|
+
register("rename_pending", {
|
|
18
|
+
title: "List corrections waiting on a human",
|
|
19
|
+
description: "The caller's open rename choices: a misspelling JARVIS fixed on ONE page and is asking about (\"just this page, or everywhere from now on?\"), " +
|
|
20
|
+
"and spellings it applied everywhere on its own that can still be undone. Each row has an id, the wrong and right form, and kind `choose` or `undo`. " +
|
|
21
|
+
"Answer one with rename_resolve.",
|
|
22
|
+
inputSchema: {},
|
|
23
|
+
}, async () => withSession(deps, async (session) => {
|
|
24
|
+
const answer = await callAgentDoor(session, deps.fetchImpl, "GET", "/api/jarvis/rename-scope");
|
|
25
|
+
return answer.ok
|
|
26
|
+
? dataResult("Corrections waiting", answer.body)
|
|
27
|
+
: errorResult(doorFailureText("rename_pending", answer));
|
|
28
|
+
}));
|
|
29
|
+
register("rename_resolve", {
|
|
30
|
+
title: "Answer a correction: this page, everywhere, or undo",
|
|
31
|
+
description: "Answer one open rename choice from rename_pending. `page` keeps it a one-page fix; `everywhere` writes the permanent rule and fixes every other page " +
|
|
32
|
+
"(only on a person's explicit say-so: whether a correction becomes a rule is a human's call); `undo` takes back a rule JARVIS applied on its own " +
|
|
33
|
+
"(your own rules only, unless you are a super admin). A fact is never made a rule, whatever is asked.",
|
|
34
|
+
inputSchema: {
|
|
35
|
+
id: z.string().uuid().optional().describe("The id rename_pending returned."),
|
|
36
|
+
scope: z.enum(["page", "everywhere", "undo"]).describe("The human's choice."),
|
|
37
|
+
wrong_form: z.string().min(1).max(80).optional().describe("With right_form and scope undo only: remove an OLD rule of yours by its pair, instead of an id."),
|
|
38
|
+
right_form: z.string().min(1).max(80).optional().describe("See wrong_form."),
|
|
39
|
+
},
|
|
40
|
+
}, async (args) => withSession(deps, async (session) => {
|
|
41
|
+
const byPair = args.id === undefined && args.wrong_form !== undefined && args.right_form !== undefined;
|
|
42
|
+
if (args.id === undefined && !(byPair && args.scope === "undo")) {
|
|
43
|
+
return errorResult("rename_resolve needs an id from rename_pending, or wrong_form and right_form with scope undo.");
|
|
44
|
+
}
|
|
45
|
+
const answer = await callAgentDoor(session, deps.fetchImpl, "POST", "/api/jarvis/rename-scope", args.id !== undefined
|
|
46
|
+
? { pendingId: String(args.id), choice: String(args.scope) }
|
|
47
|
+
: { wrongForm: String(args.wrong_form), canonicalForm: String(args.right_form), choice: "undo" });
|
|
48
|
+
return answer.ok
|
|
49
|
+
? dataResult("Correction answered", answer.body)
|
|
50
|
+
: errorResult(doorFailureText("rename_resolve", answer));
|
|
51
|
+
}));
|
|
52
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -31,6 +31,7 @@ import { registerSettingsWriteTools } from "./settings-write-tools.js";
|
|
|
31
31
|
import { registerTeamWriteTools } from "./team-write-tools.js";
|
|
32
32
|
import { registerWorkTools } from "./work-tools.js";
|
|
33
33
|
import { registerCareersTools } from "./careers-tools.js";
|
|
34
|
+
import { registerRenameTools } from "./rename-tools.js";
|
|
34
35
|
import { registerUsageTools } from "./usage-tools.js";
|
|
35
36
|
import { registerSourcesTools } from "./sources-tools.js";
|
|
36
37
|
export const PACKAGE_NAME = "@bli-cockpit/mcp";
|
|
@@ -425,6 +426,9 @@ export function createServer(deps) {
|
|
|
425
426
|
// file and move a Tower issue the way it files and moves a Linear one.
|
|
426
427
|
registerWorkTools(server, { fetchImpl: deps.fetchImpl });
|
|
427
428
|
registerCareersTools(server, deps);
|
|
429
|
+
// BLI-12378: the twins of `cockpit rename list|resolve`, the human's call on
|
|
430
|
+
// whether a correction becomes a rule.
|
|
431
|
+
registerRenameTools(server, deps);
|
|
428
432
|
registerUsageTools(server, { fetchImpl: deps.fetchImpl });
|
|
429
433
|
// BLI-3708: the mailboxes a person attached. Reads, a send and a sync over
|
|
430
434
|
// the same /api/mail/** doors `cockpit mail` calls; `add-imap` deliberately
|
package/dist/tool-catalog.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* from `src/` under Node's type stripping, so it may import nothing.
|
|
11
11
|
*/
|
|
12
12
|
/** Tools that change nothing. The smoke calls every one. */
|
|
13
|
-
export declare const READ_TOOLS: readonly ["get_ticket_timeline", "get_active_tickets", "docs_list", "docs_tree", "docs_read", "docs_sync_status", "msg_channels", "msg_read", "msg_thread", "work_list_issues", "work_get_issue", "work_issue_history", "work_list_projects", "careers_list", "careers_show", "careers_resume_url", "careers_takehome_show", "careers_settings_show", "usage_people", "usage_sessions", "mail_accounts", "mail_inbox", "mail_read", "mail_search", "mail_attachment", "mail_sync_status", "cal_today", "cal_week", "cal_next", "cal_find", "cal_calendars", "cal_sync_status", "jarvis_ask", "jarvis_trace", "jarvis_check", "models_list", "models_card", "models_compare", "brief_read", "brief_history", "brief_status", "brief_missed", "notes_folders", "notes_list", "notes_show", "notes_shelf", "notes_shelves", "notes_place", "notes_accounts", "notes_sync_status", "notes_granola_status", "ops_status", "slack_coverage", "slack_read", "memory_profile", "memory_consolidation", "settings_show", "settings_list", "model_show", "team_members", "team_device_list", "scout_board", "workbook_read", "tower_search", "sources_check"];
|
|
13
|
+
export declare const READ_TOOLS: readonly ["get_ticket_timeline", "get_active_tickets", "docs_list", "docs_tree", "docs_read", "docs_sync_status", "msg_channels", "msg_read", "msg_thread", "work_list_issues", "work_get_issue", "work_issue_history", "work_list_projects", "careers_list", "careers_show", "careers_resume_url", "careers_takehome_show", "careers_settings_show", "rename_pending", "usage_people", "usage_sessions", "mail_accounts", "mail_inbox", "mail_read", "mail_search", "mail_attachment", "mail_sync_status", "cal_today", "cal_week", "cal_next", "cal_find", "cal_calendars", "cal_sync_status", "jarvis_ask", "jarvis_trace", "jarvis_check", "models_list", "models_card", "models_compare", "brief_read", "brief_history", "brief_status", "brief_missed", "notes_folders", "notes_list", "notes_show", "notes_shelf", "notes_shelves", "notes_place", "notes_accounts", "notes_sync_status", "notes_granola_status", "ops_status", "slack_coverage", "slack_read", "memory_profile", "memory_consolidation", "settings_show", "settings_list", "model_show", "team_members", "team_device_list", "scout_board", "workbook_read", "tower_search", "sources_check"];
|
|
14
14
|
/**
|
|
15
15
|
* Tools that write, but answer a dry run that writes nothing. The smoke calls
|
|
16
16
|
* each one ONLY with its dry-run flag set (`scripts/smoke.ts` says which).
|
|
@@ -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_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_followup", "careers_takehome_set", "careers_settings_set", "mail_send", "mail_sync", "mail_detach", "cal_create", "cal_share", "cal_sync", "cal_detach", "cal_delete", "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_followup", "careers_interview", "careers_takehome_set", "careers_settings_set", "rename_resolve", "mail_send", "mail_sync", "mail_detach", "cal_create", "cal_share", "cal_sync", "cal_detach", "cal_delete", "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
|
@@ -29,6 +29,7 @@ export const READ_TOOLS = [
|
|
|
29
29
|
"careers_resume_url",
|
|
30
30
|
"careers_takehome_show",
|
|
31
31
|
"careers_settings_show",
|
|
32
|
+
"rename_pending",
|
|
32
33
|
"usage_people",
|
|
33
34
|
"usage_sessions",
|
|
34
35
|
"mail_accounts",
|
|
@@ -106,8 +107,10 @@ export const WRITE_TOOLS = [
|
|
|
106
107
|
"careers_grade",
|
|
107
108
|
"careers_decide",
|
|
108
109
|
"careers_followup",
|
|
110
|
+
"careers_interview",
|
|
109
111
|
"careers_takehome_set",
|
|
110
112
|
"careers_settings_set",
|
|
113
|
+
"rename_resolve",
|
|
111
114
|
"mail_send",
|
|
112
115
|
"mail_sync",
|
|
113
116
|
"mail_detach",
|
package/dist/verb-census.js
CHANGED
|
@@ -220,6 +220,8 @@ export const MCP_TWINS = {
|
|
|
220
220
|
"careers invite": { tool: "careers_send_takehome", door: "POST /api/careers/applications/[id]/invite" },
|
|
221
221
|
// BLI-12183: the second-chance follow-up, sent now or recorded as sent elsewhere.
|
|
222
222
|
"careers followup": { tool: "careers_followup", door: "POST /api/careers/applications/[id]/followup" },
|
|
223
|
+
// BLI-12198: an interview Edward booked himself, booked, rescheduled or cleared.
|
|
224
|
+
"careers interview": { tool: "careers_interview", door: "POST /api/careers/applications/[id]/interview" },
|
|
223
225
|
"careers decide": { tool: "careers_decide", door: "POST /api/careers/applications/[id]/decide" },
|
|
224
226
|
"careers grade": { tool: "careers_grade", door: "POST /api/careers/applications/[id]/grade" },
|
|
225
227
|
// BLI-4462: the drawer's Open resume button, typed. Both twins call the door
|
|
@@ -229,6 +231,9 @@ export const MCP_TWINS = {
|
|
|
229
231
|
"careers takehome-set": { tool: "careers_takehome_set", door: "PUT /api/careers/takehomes/[role]" },
|
|
230
232
|
"careers settings-show": { tool: "careers_settings_show", door: "GET /api/careers/settings" },
|
|
231
233
|
"careers settings-set": { tool: "careers_settings_set", door: "PUT /api/careers/settings" },
|
|
234
|
+
// BLI-12378: the human's call on whether a correction becomes a rule.
|
|
235
|
+
"rename list": { tool: "rename_pending", door: "GET /api/jarvis/rename-scope" },
|
|
236
|
+
"rename resolve": { tool: "rename_resolve", door: "POST /api/jarvis/rename-scope" },
|
|
232
237
|
"usage sessions": { tool: "usage_sessions", door: "GET /api/usage/sessions" },
|
|
233
238
|
"usage people": { tool: "usage_people", door: "GET /api/usage/people" },
|
|
234
239
|
"docs list": { tool: "docs_list", door: "GET /api/docs/documents" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.80",
|
|
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",
|
|
@@ -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.
|
|
33
|
+
"@bli-cockpit/telemetry-core": "0.1.57",
|
|
34
34
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
35
35
|
"zod": "^4.3.6"
|
|
36
36
|
},
|
|
@@ -38,5 +38,10 @@
|
|
|
38
38
|
"@types/node": "^20",
|
|
39
39
|
"typescript": "^5",
|
|
40
40
|
"vitest": "^3.2.4"
|
|
41
|
+
},
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/BLI-INC/bli-cockpit.git",
|
|
45
|
+
"directory": "packages/bli-cockpit-mcp"
|
|
41
46
|
}
|
|
42
47
|
}
|