@bli-cockpit/mcp 0.1.37 → 0.1.38

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
- **90 of 93 Tower verbs have an MCP twin.**
37
+ **91 of 94 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
@@ -131,6 +131,7 @@ three tables below.
131
131
  | `cockpit team members` | `team_members` | `GET /api/team/members` |
132
132
  | `cockpit team role` | `team_role` | `PATCH /api/team/members/[userId]/role` |
133
133
  | `cockpit usage people` | `usage_people` | `GET /api/usage/people` |
134
+ | `cockpit usage sessions` | `usage_sessions` | `GET /api/usage/sessions` |
134
135
  | `cockpit workbook` | `workbook_read` | `GET /api/cockpit/workbook` |
135
136
 
136
137
  ### Owed a twin
@@ -5,7 +5,7 @@ export function registerUsageTools(server, deps) {
5
5
  registrarFor(server)("usage_people", {
6
6
  title: "Read usage by person",
7
7
  description: "Per-person Claude Code and Codex token usage, list-price equivalent, and extraction coverage.",
8
- inputSchema: { minConfidence: z.enum(["high", "medium", "low"]).optional(), groupBy: z.enum(["repo", "task_type"]).optional(), since: z.string().optional().describe("<n>d (1 to 365), <n>h (1 to 8760), or an ISO timestamp. Default 30d; invalid values return invalid_usage_window."), until: z.string().optional(), include_automated: z.boolean().optional() },
8
+ inputSchema: { minConfidence: z.enum(["high", "medium", "low"]).optional(), groupBy: z.enum(["repo", "task_type", "topic"]).optional(), since: z.string().optional().describe("<n>d (1 to 365), <n>h (1 to 8760), or an ISO timestamp. Default 30d; invalid values return invalid_usage_window."), until: z.string().optional(), include_automated: z.boolean().optional() },
9
9
  }, async (args) => withSession(deps, async (session) => {
10
10
  const query = new URLSearchParams({ since: String(args.since ?? "30d") });
11
11
  if (args.until)
@@ -22,4 +22,20 @@ export function registerUsageTools(server, deps) {
22
22
  const coverage = response.body.coverage;
23
23
  return textResult(`${coverage?.sessions_extracted ?? 0} of ${coverage?.sessions_observed ?? 0} sessions extracted.${args.groupBy === "task_type" ? ` ${coverage?.sessions_labelled ?? 0} of ${coverage?.sessions_observed ?? 0} sessions labelled by topic.` : ""}`, response.body);
24
24
  }));
25
+ registrarFor(server)("usage_sessions", {
26
+ title: "Read subject sessions",
27
+ description: "List subject sessions with titles, tokens and work types; read digest windows on demand with session.",
28
+ inputSchema: { subject: z.string().optional(), repo: z.string().optional(), since: z.string().optional(), until: z.string().optional(), include_automated: z.boolean().optional(), session: z.string().optional(), fromWindow: z.number().int().positive().optional() },
29
+ }, async (args) => withSession(deps, async (session) => {
30
+ const query = new URLSearchParams();
31
+ for (const key of ["subject", "repo", "since", "until", "session", "fromWindow"])
32
+ if (args[key] !== undefined)
33
+ query.set(key, String(args[key]));
34
+ if (args.include_automated)
35
+ query.set("include_automated", "1");
36
+ const response = await callAgentDoor(session, deps.fetchImpl, "GET", `/api/usage/sessions?${query}`);
37
+ if (!response.ok)
38
+ return errorResult(doorFailureText("usage_sessions", response));
39
+ return textResult("Subject sessions and requested digest windows.", response.body);
40
+ }));
25
41
  }
@@ -212,6 +212,7 @@ export const MCP_TWINS = {
212
212
  "careers list": { tool: "careers_list", door: "GET /api/careers/applications" },
213
213
  "careers show": { tool: "careers_show", door: "GET /api/careers/applications/[id]" },
214
214
  "careers rescreen": { tool: "careers_rescreen", door: "POST /api/careers/applications/[id]/rescreen" },
215
+ "usage sessions": { tool: "usage_sessions", door: "GET /api/usage/sessions" },
215
216
  "usage people": { tool: "usage_people", door: "GET /api/usage/people" },
216
217
  "docs list": { tool: "docs_list", door: "GET /api/docs/documents" },
217
218
  "docs tree": { tool: "docs_tree", door: "GET /api/docs/tree" },
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@bli-cockpit/mcp",
3
- "version": "0.1.37",
3
+ "version": "0.1.38",
4
4
  "private": false,
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).",
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",
7
7
  "bin": {
8
8
  "bli-cockpit-mcp": "./dist/index.js"