@bli-cockpit/mcp 0.1.103 → 0.1.104

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.
@@ -32,7 +32,7 @@ const KINDS = ["doc", "msg", "issue", "note", "mail", "cal", "memory"];
32
32
  const KIND_LABELS = {
33
33
  doc: "Document",
34
34
  msg: "Message",
35
- issue: "Issue",
35
+ issue: "Ticket",
36
36
  note: "Meeting note",
37
37
  mail: "Email",
38
38
  cal: "Calendar event",
@@ -51,11 +51,11 @@ export function registerSearchTool(server, deps) {
51
51
  const register = server.registerTool.bind(server);
52
52
  register("tower_search", {
53
53
  title: "Search everything in Tower",
54
- description: "One search over documents, messages, issues, meeting notes, the caller's own mail, their calendar and BLI Memory. Use it when you know WHAT you are looking for but not WHERE it lives. Every result names the corpus it came from and where to open it; a memory has no page, so its text is the whole record. Mail and calendar are the caller's OWN — their mailboxes, their calendars and the ones shared with the organisation — never the whole company's. A calendar hit is the stored event, so a recurring meeting comes back once as its series rather than once per occurrence. A corpus that could not answer is reported separately from one that found nothing — do not read a failure as silence.",
54
+ description: "One search over documents, messages, Tower tickets, meeting notes, the caller's own mail, their calendar and BLI Memory. Use it when you know WHAT you are looking for but not WHERE it lives. Every result names the corpus it came from and where to open it; a memory has no page, so its text is the whole record. Mail and calendar are the caller's OWN — their mailboxes, their calendars and the ones shared with the organisation — never the whole company's. A calendar hit is the stored event, so a recurring meeting comes back once as its series rather than once per occurrence. A corpus that could not answer is reported separately from one that found nothing — do not read a failure as silence.",
55
55
  inputSchema: {
56
56
  query: z.string().min(2).max(1000).describe("What to look for, in the words a person would type."),
57
57
  kinds: z
58
- .array(z.enum(KINDS))
58
+ .array(z.enum([...KINDS, "ticket"]))
59
59
  .optional()
60
60
  .describe("Narrow to these corpora. Omit to search every one."),
61
61
  limit: z.number().int().min(1).max(50).optional().describe("Results to return (default 20)."),
@@ -69,7 +69,7 @@ export function registerSearchTool(server, deps) {
69
69
  const query = String(args.query ?? "");
70
70
  const params = new URLSearchParams({ q: query });
71
71
  if (Array.isArray(args.kinds) && args.kinds.length > 0) {
72
- params.set("kinds", args.kinds.join(","));
72
+ params.set("kinds", args.kinds.map((kind) => (kind === "ticket" ? "issue" : kind)).join(","));
73
73
  }
74
74
  if (typeof args.limit === "number")
75
75
  params.set("limit", String(args.limit));
@@ -84,13 +84,13 @@ async function resolveParentId(deps, session, ref) {
84
84
  export function registerWorkTools(server, deps) {
85
85
  const register = registrarFor(server);
86
86
  register("work_list_issues", {
87
- title: "List Tower issues",
88
- description: "Issues you may see, most recently updated first: identifier, state, title, priority, assignee, project. "
87
+ title: "List Tower tickets",
88
+ description: "Tower tickets you may see, most recently updated first: identifier, state, title, priority, assignee, project. "
89
89
  + "Filter by state, assignee (\"me\", \"unassigned\", or a uuid) or project (name or uuid). "
90
- + `Default ${DEFAULT_LIST_LIMIT} issues; the answer says when more exist. `
91
- + "Never a description — call work_get_issue for one issue's full text.",
90
+ + `Default ${DEFAULT_LIST_LIMIT} tickets; the answer says when more exist. `
91
+ + "Never a description — call work_get_issue for one ticket's full text.",
92
92
  inputSchema: {
93
- state: z.enum(WORK_ISSUE_STATES).optional().describe("Only issues in this state."),
93
+ state: z.enum(WORK_ISSUE_STATES).optional().describe("Only tickets in this state."),
94
94
  assignee: z.string().min(1).max(100).optional().describe('"me", "unassigned", or a person\'s uuid.'),
95
95
  project: z.string().min(1).max(200).optional().describe("A project name or uuid."),
96
96
  limit: z.number().int().min(1).max(ISSUE_LIST_MAX).optional().describe(`At most this many issues. Default ${DEFAULT_LIST_LIMIT}.`),
@@ -144,8 +144,8 @@ export function registerWorkTools(server, deps) {
144
144
  });
145
145
  }));
146
146
  register("work_get_issue", {
147
- title: "Read a Tower issue",
148
- description: "One issue's title, state, priority, assignee (name and email, not just its id), description and every "
147
+ title: "Read a Tower ticket",
148
+ description: "One Tower ticket's title, state, priority, assignee (name and email, not just its id), description and every "
149
149
  + "comment on it. `ids` reads several in one call — still one request per issue plus its comments, "
150
150
  + "no bulk door exists yet. A single id answers `{ issue, comments }`; several answer "
151
151
  + "`{ issues: [{ ref, ok, issue, comments } | { ref, ok: false, error, detail }] }` so one bad id never "
@@ -189,8 +189,8 @@ export function registerWorkTools(server, deps) {
189
189
  });
190
190
  }));
191
191
  register("work_create_issue", {
192
- title: "File a Tower issue",
193
- description: "Files a new issue and returns the BLI-#### identifier it was given. Use this the way you would file a Linear ticket.",
192
+ title: "File a Tower ticket",
193
+ description: "Files a new Tower ticket and returns the BLI-#### identifier it was given. Use this the way you would file a Linear ticket.",
194
194
  inputSchema: {
195
195
  title: z.string().min(1).max(300).describe("The issue title."),
196
196
  description: z.string().max(200_000).optional().describe("The issue body, markdown."),
@@ -236,8 +236,8 @@ export function registerWorkTools(server, deps) {
236
236
  return textResult(`Filed ${issue?.identifier ?? ""} — ${issue?.title ?? ""} (${issue?.id ?? ""}).`, { issue: issue ? withSizeLabel(issue) : issue });
237
237
  }));
238
238
  register("work_update_issue", {
239
- title: "Update a Tower issue",
240
- description: "Changes an issue's title, description, priority, assignee or project. Only the fields you pass change. "
239
+ title: "Update a Tower ticket",
240
+ description: "Changes a Tower ticket's title, description, priority, assignee or project. Only the fields you pass change. "
241
241
  + "State does NOT move here — call work_move_issue, which records the move.",
242
242
  inputSchema: {
243
243
  id: ISSUE_REF,
@@ -285,8 +285,8 @@ export function registerWorkTools(server, deps) {
285
285
  return textResult(`Updated ${issue?.identifier ?? ref} — ${issue?.title ?? ""}.`, { issue: issue ? withSizeLabel(issue) : issue });
286
286
  }));
287
287
  register("work_move_issue", {
288
- title: "Move a Tower issue",
289
- description: "Moves an issue to a new state and records the move in its history. This is how an issue's state changes; "
288
+ title: "Move a Tower ticket",
289
+ description: "Moves a Tower ticket to a new state and records the move in its history. This is how a ticket's state changes; "
290
290
  + "there is no other door.",
291
291
  inputSchema: { id: ISSUE_REF, state: z.enum(WORK_ISSUE_STATES).describe("The state to move it to.") },
292
292
  }, async (args) => withSession(deps, async (session) => {
@@ -300,8 +300,8 @@ export function registerWorkTools(server, deps) {
300
300
  return textResult(`${issue?.identifier ?? ref} is now ${issue?.state ?? String(args.state)}.`, { issue });
301
301
  }));
302
302
  register("work_comment_issue", {
303
- title: "Comment on a Tower issue",
304
- description: "Posts a comment. Comments are append-only — nothing here edits or deletes one.",
303
+ title: "Comment on a Tower ticket",
304
+ description: "Posts a comment on a Tower ticket. Comments are append-only — nothing here edits or deletes one.",
305
305
  inputSchema: { id: ISSUE_REF, body_markdown: z.string().min(1).max(50_000).describe("The comment, markdown.") },
306
306
  }, async (args) => withSession(deps, async (session) => {
307
307
  const ref = String(args.id ?? "");
@@ -312,8 +312,8 @@ export function registerWorkTools(server, deps) {
312
312
  return textResult(`Commented on ${ref} (${comment?.id ?? "?"}).`, { comment });
313
313
  }));
314
314
  register("work_issue_history", {
315
- title: "Read a Tower issue's history",
316
- description: "Every recorded change to one issue — state moves, assignee changes — newest first, with who made it and "
315
+ title: "Read a Tower ticket's history",
316
+ description: "Every recorded change to one Tower ticket — state moves, assignee changes — newest first, with who made it and "
317
317
  + "when. History rows are never rewritten; a row imported without state names says so rather than showing "
318
318
  + "\"(none) -> (none)\".",
319
319
  inputSchema: {
@@ -336,7 +336,7 @@ export function registerWorkTools(server, deps) {
336
336
  }));
337
337
  register("work_list_projects", {
338
338
  title: "List Tower projects",
339
- description: "The projects issues are filed under. Use a project's name with work_list_issues or work_create_issue.",
339
+ description: "The projects Tower tickets are filed under. Use a project's name with work_list_issues or work_create_issue.",
340
340
  inputSchema: { include_archived: z.boolean().optional().describe("true: archived projects too.") },
341
341
  }, async (args) => withSession(deps, async (session) => {
342
342
  const response = await callAgentDoor(session, deps.fetchImpl, "GET", `/api/work/projects${args.include_archived ? "?include_archived=true" : ""}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/mcp",
3
- "version": "0.1.103",
3
+ "version": "0.1.104",
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",