@bli-cockpit/mcp 0.1.106 → 0.1.108
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/setup-tools.js +1 -1
- package/dist/speed-tools.js +45 -1
- package/dist/tool-catalog.d.ts +1 -1
- package/dist/tool-catalog.js +1 -0
- package/dist/verb-census.js +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ about what an agent can reach.
|
|
|
109
109
|
|
|
110
110
|
<!-- BEGIN GENERATED verb census — `npm run mcp:readme` -->
|
|
111
111
|
|
|
112
|
-
**
|
|
112
|
+
**138 of 143 Tower verbs have an MCP twin.**
|
|
113
113
|
Each tool goes through the SAME door its CLI verb calls, with the same
|
|
114
114
|
collector device token — never a second route and never a service-role
|
|
115
115
|
reader. `src/verb-census.test.ts` fails when a verb is in none of the
|
|
@@ -245,6 +245,7 @@ three tables below.
|
|
|
245
245
|
| `cockpit slack coverage` | `slack_coverage` | `GET /api/ops/slack/coverage` |
|
|
246
246
|
| `cockpit slack read` | `slack_read` | `POST /api/ops/slack/read` |
|
|
247
247
|
| `cockpit speed` | `speed_read` | `GET /api/* (every rail page's data door, see speed-tools.ts)` |
|
|
248
|
+
| `cockpit speed --seen` | `speed_seen` | `GET /api/speed/seen` |
|
|
248
249
|
| `cockpit team device doctor` | `team_device_doctor` | `POST /api/ambient/devices/[deviceId]/doctor` |
|
|
249
250
|
| `cockpit team device list` | `team_device_list` | `GET /api/team/devices` |
|
|
250
251
|
| `cockpit team device revoke` | `team_device_revoke` | `POST /api/ambient/devices/[deviceId]/revoke` |
|
package/dist/setup-tools.js
CHANGED
|
@@ -5,7 +5,7 @@ export function registerSetupTools(server, deps) {
|
|
|
5
5
|
registrarFor(server)("setup_read", {
|
|
6
6
|
title: "Compare agent setups and outcomes",
|
|
7
7
|
description: "Read machine setup names and windowed (default 30-day) merged PR volume, tokens per merged PR and session yield. Compare exact emails. Differences are observations, not evidence that a setting causes better results. Missing or stale setup and incomplete token coverage are labeled. Members see their own outcomes; team comparisons require super_admin.",
|
|
8
|
-
inputSchema: { since: z.string().max(40).optional().describe("7d, 30d, or an ISO date before now."), person: z.string().max(200).optional().describe("Only this person, by exact email address."), compare: z.string().max(401).optional().describe("Two exact email
|
|
8
|
+
inputSchema: { since: z.string().max(40).optional().describe("7d, 30d, or an ISO date before now."), person: z.string().max(200).optional().describe("Only this person, by exact first name, display name or email address."), compare: z.string().max(401).optional().describe("Two people, by exact first name, display name or email address, separated by a comma (for example edward,ian). An ambiguous name is refused with its candidates.") },
|
|
9
9
|
}, async (args) => withSession(deps, async (session) => {
|
|
10
10
|
const query = new URLSearchParams();
|
|
11
11
|
if (args.since)
|
package/dist/speed-tools.js
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
* nothing is cached on this side, so the number is Tower's, not ours.
|
|
13
13
|
*/
|
|
14
14
|
import { z } from "zod";
|
|
15
|
-
import {
|
|
15
|
+
import { callAgentDoor } from "./agent-door.js";
|
|
16
|
+
import { dataResult, doorFailureText, errorResult, registrarFor, withSession } from "./tool-result.js";
|
|
16
17
|
export function speedPages(memoryContainer) {
|
|
17
18
|
return [
|
|
18
19
|
{ name: "today", label: "Today (JARVIS home)", path: "/api/jarvis/brief" },
|
|
@@ -156,7 +157,50 @@ async function timeOneRead(fetchImpl, session, page) {
|
|
|
156
157
|
clearTimeout(timer);
|
|
157
158
|
}
|
|
158
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* `speed_seen` (BLI-13054) — the MCP twin of `cockpit speed --seen`: what real
|
|
162
|
+
* visits experienced, per page, from the page-view beacons the browser sends.
|
|
163
|
+
* One GET on `/api/speed/seen`; the door counts in the database on the caller's
|
|
164
|
+
* own row policies, so this side only relays and words the answer.
|
|
165
|
+
*/
|
|
166
|
+
const SEEN_WINDOW = /^\d{1,4}[mhd]$/;
|
|
159
167
|
export function registerSpeedTools(server, deps) {
|
|
168
|
+
registrarFor(server)("speed_seen", {
|
|
169
|
+
title: "What real visits saw on each Tower page",
|
|
170
|
+
description: "Per Tower page, from real page views: visit count, p50 and p95 milliseconds until real content first showed "
|
|
171
|
+
+ "(the last-known screen or the fresh one), the share painted from the last-known screen (snapshot), and median "
|
|
172
|
+
+ "HTML and script transfer where the browser reported them. Slowest first. A person sees their own visits; "
|
|
173
|
+
+ "`everyone` needs super_admin and is refused for anyone else. Window `since` is <n>m, <n>h or <n>d (default 24h, "
|
|
174
|
+
+ "at most 30d). Read only. Twin of `cockpit speed --seen`.",
|
|
175
|
+
inputSchema: {
|
|
176
|
+
since: z.string().max(10).optional().describe("Window such as 90m, 24h or 7d (default 24h, at most 30d)."),
|
|
177
|
+
everyone: z.boolean().optional().describe("Every person's visits (super_admin only)."),
|
|
178
|
+
pages: z.array(z.enum(SPEED_PAGE_NAMES)).max(14).optional()
|
|
179
|
+
.describe("Only these pages. Omit for every page."),
|
|
180
|
+
},
|
|
181
|
+
}, async (args) => withSession(deps, async (session) => {
|
|
182
|
+
const since = typeof args.since === "string" ? args.since.trim().toLowerCase() : "24h";
|
|
183
|
+
if (!SEEN_WINDOW.test(since))
|
|
184
|
+
return errorResult("speed_seen: `since` takes <n>m, <n>h or <n>d, for example 24h.");
|
|
185
|
+
const everyone = args.everyone === true;
|
|
186
|
+
const query = new URLSearchParams({ since });
|
|
187
|
+
if (everyone)
|
|
188
|
+
query.set("everyone", "1");
|
|
189
|
+
const response = await callAgentDoor(session, deps.fetchImpl, "GET", `/api/speed/seen?${query}`);
|
|
190
|
+
if (!response.ok)
|
|
191
|
+
return errorResult(doorFailureText("speed_seen", response));
|
|
192
|
+
const asked = Array.isArray(args.pages) ? args.pages : [];
|
|
193
|
+
const body = response.body;
|
|
194
|
+
const pages = (body.pages ?? [])
|
|
195
|
+
.filter((page) => asked.length === 0 || asked.includes(page.page))
|
|
196
|
+
.sort((a, b) => b.p50_ms - a.p50_ms || a.page.localeCompare(b.page));
|
|
197
|
+
const lines = pages.map((page, index) => `${index + 1}. ${page.page} ${page.visits} visit${page.visits === 1 ? "" : "s"} p50 ${Math.round(page.p50_ms)} ms `
|
|
198
|
+
+ `p95 ${Math.round(page.p95_ms)} ms snapshot ${Math.round(page.snapshot_share * 100)}%`);
|
|
199
|
+
const who = everyone ? "everyone's visits" : "your visits";
|
|
200
|
+
return dataResult(pages.length === 0
|
|
201
|
+
? `No page views recorded in the last ${since} (${who}).`
|
|
202
|
+
: `Real page views over the last ${since} (${who}), slowest first:\n${lines.join("\n")}`, { ok: true, since, everyone, pages });
|
|
203
|
+
}));
|
|
160
204
|
registrarFor(server)("speed_read", {
|
|
161
205
|
title: "Time every Tower page's data door",
|
|
162
206
|
description: "How long each Tower rail page's data door takes, measured from where this server runs with this machine's "
|
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", "rename_pending", "github_pr", "setup_read", "speed_read", "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", "glossary_list", "notes_show", "notes_shelf", "notes_shelves", "notes_place", "notes_accounts", "notes_recordings", "notes_recording", "notes_sync_status", "notes_granola_status", "ops_status", "slack_coverage", "slack_read", "memory_rules", "memory_profile", "memory_consolidation", "settings_show", "settings_list", "model_show", "team_members", "team_device_list", "scout_board", "workbook_read", "tower_search", "sources_check", "logs_digest", "brain_status"];
|
|
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", "github_pr", "setup_read", "speed_read", "speed_seen", "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", "glossary_list", "notes_show", "notes_shelf", "notes_shelves", "notes_place", "notes_accounts", "notes_recordings", "notes_recording", "notes_sync_status", "notes_granola_status", "ops_status", "slack_coverage", "slack_read", "memory_rules", "memory_profile", "memory_consolidation", "settings_show", "settings_list", "model_show", "team_members", "team_device_list", "scout_board", "workbook_read", "tower_search", "sources_check", "logs_digest", "brain_status"];
|
|
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).
|
package/dist/tool-catalog.js
CHANGED
package/dist/verb-census.js
CHANGED
|
@@ -244,6 +244,8 @@ export const MCP_TWINS = {
|
|
|
244
244
|
"setup": { tool: "setup_read", door: "GET /api/setup" },
|
|
245
245
|
// BLI-13033: times the data door of every rail page; the twin runs the same GETs.
|
|
246
246
|
"speed": { tool: "speed_read", door: "GET /api/* (every rail page's data door, see speed-tools.ts)" },
|
|
247
|
+
// BLI-13054: a mode flag, entered by hand like `jarvis --trace`.
|
|
248
|
+
"speed --seen": { tool: "speed_seen", door: "GET /api/speed/seen" },
|
|
247
249
|
"usage people": { tool: "usage_people", door: "GET /api/usage/people" },
|
|
248
250
|
"glossary list": { tool: "glossary_list", door: "GET /api/glossary" },
|
|
249
251
|
"glossary add": { tool: "glossary_add", door: "POST /api/glossary" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.108",
|
|
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",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"readme": "npm run build && node scripts/write-readme-census.mjs"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@bli-cockpit/telemetry-core": "0.1.
|
|
40
|
+
"@bli-cockpit/telemetry-core": "0.1.68",
|
|
41
41
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
42
42
|
"zod": "^4.3.6"
|
|
43
43
|
},
|