@sixtynine-digital/blitz-mcp 0.3.0 → 0.4.0

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as loadConfig, t as createServer$1 } from "./server-Y1bv_8dx.mjs";
2
+ import { n as loadConfig, t as createServer$1 } from "./server-BIEP9XVB.mjs";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { createServer } from "node:http";
5
5
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -138,4 +138,4 @@ function startHttpServer() {
138
138
 
139
139
  //#endregion
140
140
  export { startHttpServer };
141
- //# sourceMappingURL=http-kEKXBhoW.mjs.map
141
+ //# sourceMappingURL=http-DqMYQFKB.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"http-kEKXBhoW.mjs","names":["params: Record<string, string>","createHttpServer","body","createServer"],"sources":["../src/http.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createServer as createHttpServer } from \"node:http\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { isInitializeRequest } from \"@modelcontextprotocol/sdk/types.js\";\nimport { loadConfig } from \"./config.js\";\nimport { createServer } from \"./server.js\";\n\ninterface SessionEntry {\n transport: StreamableHTTPServerTransport;\n server: ReturnType<typeof createServer>;\n}\n\nconst sessions = new Map<string, SessionEntry>();\n\nfunction parseBody(req: import(\"node:http\").IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = \"\";\n req.on(\"data\", (chunk: Buffer) => (data += chunk.toString()));\n req.on(\"end\", () => {\n try {\n resolve(JSON.parse(data));\n } catch {\n reject(new Error(\"Invalid JSON\"));\n }\n });\n req.on(\"error\", reject);\n });\n}\n\nfunction jsonResponse(\n res: import(\"node:http\").ServerResponse,\n status: number,\n body: unknown\n) {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n\nfunction parseQueryParams(url: string): Record<string, string> {\n const idx = url.indexOf(\"?\");\n if (idx === -1) return {};\n const params: Record<string, string> = {};\n const search = url.slice(idx + 1);\n for (const pair of search.split(\"&\")) {\n const [key, val] = pair.split(\"=\");\n if (key) params[decodeURIComponent(key)] = decodeURIComponent(val || \"\");\n }\n return params;\n}\n\nexport function startHttpServer() {\n const port = parseInt(process.env.BLITZ_MCP_PORT || \"3100\", 10);\n const apiUrl = process.env.BLITZ_API_URL;\n\n if (!apiUrl) {\n throw new Error(\"BLITZ_API_URL environment variable is required\");\n }\n\n const httpServer = createHttpServer(async (req, res) => {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, DELETE, OPTIONS\");\n res.setHeader(\n \"Access-Control-Allow-Headers\",\n \"Content-Type, mcp-session-id\"\n );\n res.setHeader(\"Access-Control-Expose-Headers\", \"mcp-session-id\");\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204);\n res.end();\n return;\n }\n\n const urlPath = (req.url || \"\").split(\"?\")[0];\n\n if (urlPath !== \"/mcp\") {\n jsonResponse(res, 404, { error: \"Not found\" });\n return;\n }\n\n if (req.method === \"POST\") {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n\n if (sessionId && sessions.has(sessionId)) {\n const entry = sessions.get(sessionId)!;\n const body = await parseBody(req);\n await entry.transport.handleRequest(req, res, body);\n return;\n }\n\n const body = (await parseBody(req)) as Record<string, unknown>;\n\n if (!sessionId && isInitializeRequest(body)) {\n // Read per-user credentials from query params\n const query = parseQueryParams(req.url || \"\");\n const apiKey = query.api_key || process.env.BLITZ_API_KEY;\n const workspaceSlug = query.workspace || process.env.BLITZ_WORKSPACE_SLUG;\n\n if (!apiKey) {\n jsonResponse(res, 401, {\n error: \"API key required. Add ?api_key=plane_api_XXX to the URL\",\n });\n return;\n }\n\n if (!workspaceSlug) {\n jsonResponse(res, 400, {\n error:\n \"Workspace slug required. Add ?workspace=YOUR_SLUG to the URL\",\n });\n return;\n }\n\n const projectId = query.project_id || process.env.BLITZ_PROJECT_ID;\n\n const config = loadConfig({\n apiUrl,\n apiKey,\n workspaceSlug,\n projectId: projectId || undefined,\n });\n\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (id) => {\n sessions.set(id, { transport, server });\n },\n });\n\n transport.onclose = () => {\n if (transport.sessionId) {\n sessions.delete(transport.sessionId);\n }\n };\n\n const server = createServer(config);\n await server.connect(transport);\n await transport.handleRequest(req, res, body);\n return;\n }\n\n jsonResponse(res, 400, {\n jsonrpc: \"2.0\",\n error: { code: -32000, message: \"Invalid session\" },\n id: null,\n });\n return;\n }\n\n if (req.method === \"GET\") {\n const sessionId = req.headers[\"mcp-session-id\"] as string;\n if (sessionId && sessions.has(sessionId)) {\n const entry = sessions.get(sessionId)!;\n await entry.transport.handleRequest(req, res);\n } else {\n jsonResponse(res, 400, { error: \"Invalid session\" });\n }\n return;\n }\n\n if (req.method === \"DELETE\") {\n const sessionId = req.headers[\"mcp-session-id\"] as string;\n if (sessionId && sessions.has(sessionId)) {\n const entry = sessions.get(sessionId)!;\n await entry.transport.handleRequest(req, res);\n } else {\n jsonResponse(res, 400, { error: \"Invalid session\" });\n }\n return;\n }\n\n jsonResponse(res, 405, { error: \"Method not allowed\" });\n });\n\n httpServer.listen(port, \"0.0.0.0\", () => {\n console.log(`Blitz MCP HTTP server running on port ${port}`);\n console.log(`Endpoint: http://0.0.0.0:${port}/mcp`);\n });\n\n process.on(\"SIGINT\", () => {\n httpServer.close();\n process.exit(0);\n });\n\n process.on(\"SIGTERM\", () => {\n httpServer.close();\n process.exit(0);\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"http-DqMYQFKB.mjs","names":["params: Record<string, string>","createHttpServer","body","createServer"],"sources":["../src/http.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createServer as createHttpServer } from \"node:http\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { isInitializeRequest } from \"@modelcontextprotocol/sdk/types.js\";\nimport { loadConfig } from \"./config.js\";\nimport { createServer } from \"./server.js\";\n\ninterface SessionEntry {\n transport: StreamableHTTPServerTransport;\n server: ReturnType<typeof createServer>;\n}\n\nconst sessions = new Map<string, SessionEntry>();\n\nfunction parseBody(req: import(\"node:http\").IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = \"\";\n req.on(\"data\", (chunk: Buffer) => (data += chunk.toString()));\n req.on(\"end\", () => {\n try {\n resolve(JSON.parse(data));\n } catch {\n reject(new Error(\"Invalid JSON\"));\n }\n });\n req.on(\"error\", reject);\n });\n}\n\nfunction jsonResponse(\n res: import(\"node:http\").ServerResponse,\n status: number,\n body: unknown\n) {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n\nfunction parseQueryParams(url: string): Record<string, string> {\n const idx = url.indexOf(\"?\");\n if (idx === -1) return {};\n const params: Record<string, string> = {};\n const search = url.slice(idx + 1);\n for (const pair of search.split(\"&\")) {\n const [key, val] = pair.split(\"=\");\n if (key) params[decodeURIComponent(key)] = decodeURIComponent(val || \"\");\n }\n return params;\n}\n\nexport function startHttpServer() {\n const port = parseInt(process.env.BLITZ_MCP_PORT || \"3100\", 10);\n const apiUrl = process.env.BLITZ_API_URL;\n\n if (!apiUrl) {\n throw new Error(\"BLITZ_API_URL environment variable is required\");\n }\n\n const httpServer = createHttpServer(async (req, res) => {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, DELETE, OPTIONS\");\n res.setHeader(\n \"Access-Control-Allow-Headers\",\n \"Content-Type, mcp-session-id\"\n );\n res.setHeader(\"Access-Control-Expose-Headers\", \"mcp-session-id\");\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204);\n res.end();\n return;\n }\n\n const urlPath = (req.url || \"\").split(\"?\")[0];\n\n if (urlPath !== \"/mcp\") {\n jsonResponse(res, 404, { error: \"Not found\" });\n return;\n }\n\n if (req.method === \"POST\") {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n\n if (sessionId && sessions.has(sessionId)) {\n const entry = sessions.get(sessionId)!;\n const body = await parseBody(req);\n await entry.transport.handleRequest(req, res, body);\n return;\n }\n\n const body = (await parseBody(req)) as Record<string, unknown>;\n\n if (!sessionId && isInitializeRequest(body)) {\n // Read per-user credentials from query params\n const query = parseQueryParams(req.url || \"\");\n const apiKey = query.api_key || process.env.BLITZ_API_KEY;\n const workspaceSlug = query.workspace || process.env.BLITZ_WORKSPACE_SLUG;\n\n if (!apiKey) {\n jsonResponse(res, 401, {\n error: \"API key required. Add ?api_key=plane_api_XXX to the URL\",\n });\n return;\n }\n\n if (!workspaceSlug) {\n jsonResponse(res, 400, {\n error:\n \"Workspace slug required. Add ?workspace=YOUR_SLUG to the URL\",\n });\n return;\n }\n\n const projectId = query.project_id || process.env.BLITZ_PROJECT_ID;\n\n const config = loadConfig({\n apiUrl,\n apiKey,\n workspaceSlug,\n projectId: projectId || undefined,\n });\n\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (id) => {\n sessions.set(id, { transport, server });\n },\n });\n\n transport.onclose = () => {\n if (transport.sessionId) {\n sessions.delete(transport.sessionId);\n }\n };\n\n const server = createServer(config);\n await server.connect(transport);\n await transport.handleRequest(req, res, body);\n return;\n }\n\n jsonResponse(res, 400, {\n jsonrpc: \"2.0\",\n error: { code: -32000, message: \"Invalid session\" },\n id: null,\n });\n return;\n }\n\n if (req.method === \"GET\") {\n const sessionId = req.headers[\"mcp-session-id\"] as string;\n if (sessionId && sessions.has(sessionId)) {\n const entry = sessions.get(sessionId)!;\n await entry.transport.handleRequest(req, res);\n } else {\n jsonResponse(res, 400, { error: \"Invalid session\" });\n }\n return;\n }\n\n if (req.method === \"DELETE\") {\n const sessionId = req.headers[\"mcp-session-id\"] as string;\n if (sessionId && sessions.has(sessionId)) {\n const entry = sessions.get(sessionId)!;\n await entry.transport.handleRequest(req, res);\n } else {\n jsonResponse(res, 400, { error: \"Invalid session\" });\n }\n return;\n }\n\n jsonResponse(res, 405, { error: \"Method not allowed\" });\n });\n\n httpServer.listen(port, \"0.0.0.0\", () => {\n console.log(`Blitz MCP HTTP server running on port ${port}`);\n console.log(`Endpoint: http://0.0.0.0:${port}/mcp`);\n });\n\n process.on(\"SIGINT\", () => {\n httpServer.close();\n process.exit(0);\n });\n\n process.on(\"SIGTERM\", () => {\n httpServer.close();\n process.exit(0);\n });\n}\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { n as loadConfig, t as createServer } from "./server-Y1bv_8dx.mjs";
2
+ import { n as loadConfig, t as createServer } from "./server-BIEP9XVB.mjs";
3
3
 
4
4
  //#region src/index.ts
5
5
  if ((process.env.BLITZ_MCP_MODE || "stdio") === "http") {
6
- const { startHttpServer } = await import("./http-kEKXBhoW.mjs");
6
+ const { startHttpServer } = await import("./http-DqMYQFKB.mjs");
7
7
  startHttpServer();
8
8
  } else {
9
9
  const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
@@ -145,6 +145,84 @@ function registerSearchTools(server, client, config) {
145
145
  });
146
146
  }
147
147
 
148
+ //#endregion
149
+ //#region src/tools/members.ts
150
+ var MemberCache = class {
151
+ cache = /* @__PURE__ */ new Map();
152
+ ttlMs;
153
+ constructor(ttlMs = 300 * 1e3) {
154
+ this.ttlMs = ttlMs;
155
+ }
156
+ get(key) {
157
+ const entry = this.cache.get(key);
158
+ if (!entry || Date.now() - entry.fetchedAt > this.ttlMs) {
159
+ if (entry) this.cache.delete(key);
160
+ return null;
161
+ }
162
+ return entry.members;
163
+ }
164
+ set(key, members) {
165
+ this.cache.set(key, {
166
+ members,
167
+ fetchedAt: Date.now()
168
+ });
169
+ }
170
+ };
171
+ const cache = new MemberCache();
172
+ async function fetchProjectMembers(client, workspaceSlug, projectId) {
173
+ const key = `project:${projectId}`;
174
+ const cached = cache.get(key);
175
+ if (cached) return cached;
176
+ const data = await client.get(`workspaces/${workspaceSlug}/projects/${projectId}/members/`);
177
+ cache.set(key, data);
178
+ return data;
179
+ }
180
+ async function fetchWorkspaceMembers(client, workspaceSlug) {
181
+ const key = `workspace:${workspaceSlug}`;
182
+ const cached = cache.get(key);
183
+ if (cached) return cached;
184
+ const data = await client.get(`workspaces/${workspaceSlug}/members/`);
185
+ cache.set(key, data);
186
+ return data;
187
+ }
188
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
189
+ async function resolveAssignees(values, client, workspaceSlug, projectId) {
190
+ if (values.every((v) => UUID_RE.test(v))) return values;
191
+ const members = await fetchProjectMembers(client, workspaceSlug, projectId);
192
+ return values.map((value) => {
193
+ if (UUID_RE.test(value)) return value;
194
+ const lower = value.toLowerCase();
195
+ const match = members.find((m) => m.display_name.toLowerCase() === lower || `${m.first_name} ${m.last_name}`.toLowerCase().trim() === lower || m.email.toLowerCase() === lower);
196
+ if (!match) throw new Error(`Could not resolve assignee "${value}". Use list-members to see available members.`);
197
+ return match.id;
198
+ });
199
+ }
200
+ function enrichAssigneeNames(item, members) {
201
+ const assigneeIds = item.assignees;
202
+ if (!Array.isArray(assigneeIds) || assigneeIds.length === 0) return item;
203
+ const memberMap = new Map(members.map((m) => [m.id, m.display_name]));
204
+ const assignees = assigneeIds.map((id) => ({
205
+ id,
206
+ display_name: memberMap.get(id) ?? "Unknown"
207
+ }));
208
+ return {
209
+ ...item,
210
+ assignees
211
+ };
212
+ }
213
+ function registerMemberTools(server, client, config) {
214
+ const { workspaceSlug } = config;
215
+ server.tool("list-members", "List members of a project or workspace. Use this to find user IDs and display names for assigning work items. You can also assign work items by display name directly.", { project_id: z.string().uuid().optional().describe("Project UUID - lists project members. Omit to list workspace members (requires admin).") }, async ({ project_id }) => {
216
+ let members;
217
+ if (project_id || config.projectId) members = await fetchProjectMembers(client, workspaceSlug, project_id || config.projectId);
218
+ else members = await fetchWorkspaceMembers(client, workspaceSlug);
219
+ return { content: [{
220
+ type: "text",
221
+ text: JSON.stringify(members, null, 2)
222
+ }] };
223
+ });
224
+ }
225
+
148
226
  //#endregion
149
227
  //#region src/tools/work-items.ts
150
228
  const STATE_GROUPS = [
@@ -158,10 +236,10 @@ const SUMMARY_FIELDS = [
158
236
  "id",
159
237
  "sequence_id",
160
238
  "name",
161
- "state_id",
239
+ "state",
162
240
  "priority",
163
- "assignee_ids",
164
- "label_ids",
241
+ "assignees",
242
+ "labels",
165
243
  "start_date",
166
244
  "target_date",
167
245
  "created_at",
@@ -228,7 +306,10 @@ function registerWorkItemTools(server, client, config) {
228
306
  }).toString();
229
307
  const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : ""}`;
230
308
  const data = await client.get(path);
231
- if (data.results && Array.isArray(data.results)) data.results = data.results.map((item) => stripHeavyFields(item));
309
+ if (data.results && Array.isArray(data.results)) {
310
+ const members = await fetchProjectMembers(client, workspaceSlug, pid);
311
+ data.results = data.results.map((item) => enrichAssigneeNames(stripHeavyFields(item), members));
312
+ }
232
313
  return { content: [{
233
314
  type: "text",
234
315
  text: JSON.stringify(data, null, 2)
@@ -252,7 +333,10 @@ function registerWorkItemTools(server, client, config) {
252
333
  }).toString();
253
334
  const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : ""}`;
254
335
  const data = await client.get(path);
255
- if (data.results && Array.isArray(data.results)) data.results = data.results.map((item) => pickSummaryFields(item));
336
+ if (data.results && Array.isArray(data.results)) {
337
+ const members = await fetchProjectMembers(client, workspaceSlug, pid);
338
+ data.results = data.results.map((item) => enrichAssigneeNames(pickSummaryFields(item), members));
339
+ }
256
340
  return { content: [{
257
341
  type: "text",
258
342
  text: JSON.stringify(data, null, 2)
@@ -260,6 +344,14 @@ function registerWorkItemTools(server, client, config) {
260
344
  });
261
345
  server.tool("get-work-item", "Get a work item by its human-readable identifier (e.g. BLZ-42). Returns full details.", { identifier: z.string().min(1).describe("Work item identifier (e.g. PROJ-123)") }, async ({ identifier }) => {
262
346
  const data = await client.get(`workspaces/${workspaceSlug}/work-items/${identifier}/`);
347
+ const projectId = data.project_id ?? data.project;
348
+ if (projectId && Array.isArray(data.assignees)) try {
349
+ const members = await fetchProjectMembers(client, workspaceSlug, projectId);
350
+ return { content: [{
351
+ type: "text",
352
+ text: JSON.stringify(enrichAssigneeNames(data, members), null, 2)
353
+ }] };
354
+ } catch {}
263
355
  return { content: [{
264
356
  type: "text",
265
357
  text: JSON.stringify(data, null, 2)
@@ -271,9 +363,10 @@ function registerWorkItemTools(server, client, config) {
271
363
  }, async ({ project_id, work_item_id }) => {
272
364
  const pid = resolveProjectId(project_id, config);
273
365
  const data = await client.get(`workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`);
366
+ const members = await fetchProjectMembers(client, workspaceSlug, pid);
274
367
  return { content: [{
275
368
  type: "text",
276
- text: JSON.stringify(data, null, 2)
369
+ text: JSON.stringify(enrichAssigneeNames(data, members), null, 2)
277
370
  }] };
278
371
  });
279
372
  server.tool("create-work-item", "Create a new work item (task/issue) in a project. Use list-projects to find project IDs, list-states for state IDs, and list-labels for label IDs.", {
@@ -288,14 +381,16 @@ function registerWorkItemTools(server, client, config) {
288
381
  "none"
289
382
  ]).optional().describe("Priority level"),
290
383
  state_id: z.string().uuid().optional().describe("State UUID (use list-states to find valid IDs)"),
291
- assignees: z.array(z.string().uuid()).optional().describe("Array of user UUIDs to assign"),
384
+ assignees: z.array(z.string()).optional().describe("Array of user UUIDs or display names to assign. Use list-members to find valid names."),
292
385
  labels: z.array(z.string().uuid()).optional().describe("Array of label UUIDs"),
293
386
  start_date: z.string().optional().describe("Start date (YYYY-MM-DD)"),
294
387
  target_date: z.string().optional().describe("Target date (YYYY-MM-DD)"),
295
388
  parent_id: z.string().uuid().optional().describe("Parent work item UUID for sub-issues")
296
389
  }, async ({ project_id,...fields }) => {
297
390
  const pid = resolveProjectId(project_id, config);
298
- const body = mapBodyForApi(fields);
391
+ const resolvedFields = { ...fields };
392
+ if (fields.assignees?.length) resolvedFields.assignees = await resolveAssignees(fields.assignees, client, workspaceSlug, pid);
393
+ const body = mapBodyForApi(resolvedFields);
299
394
  const data = await client.post(`workspaces/${workspaceSlug}/projects/${pid}/work-items/`, body);
300
395
  return { content: [{
301
396
  type: "text",
@@ -315,13 +410,15 @@ function registerWorkItemTools(server, client, config) {
315
410
  "none"
316
411
  ]).optional().describe("New priority level"),
317
412
  state_id: z.string().uuid().optional().describe("New state UUID (use list-states to find valid IDs)"),
318
- assignees: z.array(z.string().uuid()).optional().describe("New assignee UUIDs (replaces existing)"),
413
+ assignees: z.array(z.string()).optional().describe("New assignee UUIDs or display names (replaces existing). Use list-members to find valid names."),
319
414
  labels: z.array(z.string().uuid()).optional().describe("New label UUIDs (replaces existing)"),
320
415
  start_date: z.string().nullable().optional().describe("Start date (YYYY-MM-DD) or null to clear"),
321
416
  target_date: z.string().nullable().optional().describe("Target date (YYYY-MM-DD) or null to clear")
322
417
  }, async ({ project_id, work_item_id,...fields }) => {
323
418
  const pid = resolveProjectId(project_id, config);
324
- const body = mapBodyForApi(fields);
419
+ const resolvedFields = { ...fields };
420
+ if (fields.assignees?.length) resolvedFields.assignees = await resolveAssignees(fields.assignees, client, workspaceSlug, pid);
421
+ const body = mapBodyForApi(resolvedFields);
325
422
  const data = await client.patch(`workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`, body);
326
423
  return { content: [{
327
424
  type: "text",
@@ -389,6 +486,7 @@ function registerAllTools(server, client, config) {
389
486
  registerSearchTools(server, client, config);
390
487
  registerWorkItemTools(server, client, config);
391
488
  registerCommentTools(server, client, config);
489
+ registerMemberTools(server, client, config);
392
490
  }
393
491
 
394
492
  //#endregion
@@ -451,4 +549,4 @@ function createServer(config) {
451
549
 
452
550
  //#endregion
453
551
  export { loadConfig as n, createServer as t };
454
- //# sourceMappingURL=server-Y1bv_8dx.mjs.map
552
+ //# sourceMappingURL=server-BIEP9XVB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-BIEP9XVB.mjs","names":["missing: string[]","headers: Record<string, string>","members: Member[]","result: Record<string, unknown>"],"sources":["../src/config.ts","../src/client.ts","../src/tools/projects.ts","../src/tools/states.ts","../src/tools/labels.ts","../src/tools/search.ts","../src/tools/members.ts","../src/tools/work-items.ts","../src/tools/comments.ts","../src/tools/index.ts","../src/resources/projects.ts","../src/resources/index.ts","../src/server.ts"],"sourcesContent":["export interface BlitzConfig {\n apiUrl: string;\n apiKey: string;\n workspaceSlug: string;\n projectId?: string;\n}\n\nexport function loadConfig(overrides?: Partial<BlitzConfig>): BlitzConfig {\n const apiUrl = overrides?.apiUrl || process.env.BLITZ_API_URL;\n const apiKey = overrides?.apiKey || process.env.BLITZ_API_KEY;\n const workspaceSlug = overrides?.workspaceSlug || process.env.BLITZ_WORKSPACE_SLUG;\n const projectId = overrides?.projectId || process.env.BLITZ_PROJECT_ID;\n\n const missing: string[] = [];\n if (!apiUrl) missing.push(\"BLITZ_API_URL\");\n if (!apiKey) missing.push(\"BLITZ_API_KEY\");\n if (!workspaceSlug) missing.push(\"BLITZ_WORKSPACE_SLUG\");\n\n if (missing.length > 0) {\n throw new Error(\n `Missing required environment variables: ${missing.join(\", \")}\\n\\n` +\n \"Please set the following:\\n\" +\n \" BLITZ_API_URL - Blitz instance URL (e.g. http://localhost:8000)\\n\" +\n \" BLITZ_API_KEY - API key (format: plane_api_<hex>)\\n\" +\n \" BLITZ_WORKSPACE_SLUG - Workspace slug\\n\" +\n \" BLITZ_PROJECT_ID - (Optional) Default project UUID\"\n );\n }\n\n return {\n apiUrl: apiUrl!.replace(/\\/+$/, \"\"),\n apiKey: apiKey!,\n workspaceSlug: workspaceSlug!,\n projectId: projectId || undefined,\n };\n}\n\nexport function resolveProjectId(projectId: string | undefined, config: BlitzConfig): string {\n const id = projectId || config.projectId;\n if (!id) {\n throw new Error(\n \"project_id is required. Either pass it as a parameter or set BLITZ_PROJECT_ID environment variable.\"\n );\n }\n return id;\n}\n","import type { BlitzConfig } from \"./config.js\";\n\nexport class BlitzClient {\n private baseUrl: string;\n private apiKey: string;\n\n constructor(config: BlitzConfig) {\n this.baseUrl = `${config.apiUrl}/api/v1`;\n this.apiKey = config.apiKey;\n }\n\n private async request<T = unknown>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}/${path.replace(/^\\/+/, \"\")}`;\n\n const headers: Record<string, string> = {\n \"X-Api-Key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n throw new Error(\n `Rate limit exceeded. ${retryAfter ? `Retry after ${retryAfter} seconds.` : \"Please wait before retrying.\"}`\n );\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const data = await response.json();\n\n if (!response.ok) {\n const message =\n typeof data === \"object\" && data !== null\n ? JSON.stringify(data, null, 2)\n : String(data);\n throw new Error(`API error (${response.status}): ${message}`);\n }\n\n return data as T;\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"POST\", path, body);\n }\n\n async patch<T = unknown>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PATCH\", path, body);\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>(\"DELETE\", path);\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\n\nexport function registerProjectTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-projects\",\n \"List all projects in the Blitz workspace. Returns project names, identifiers, and IDs.\",\n {},\n async () => {\n const data = await client.get(`workspaces/${config.workspaceSlug}/projects/`);\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\n\nexport function registerStateTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-states\",\n \"List all workflow states for a project. Use this to find valid state IDs when creating or updating work items.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n },\n async ({ project_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/states/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\n\nexport function registerLabelTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-labels\",\n \"List all labels for a project. Use this to find valid label IDs when creating or updating work items.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n },\n async ({ project_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/labels/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"create-label\",\n \"Create a new label in a project.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n name: z.string().min(1).max(255).describe(\"Label name\"),\n color: z.string().optional().describe(\"Hex color (e.g. #ff0000)\"),\n description: z.string().optional().describe(\"Label description\"),\n },\n async ({ project_id, ...body }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.post(\n `workspaces/${config.workspaceSlug}/projects/${pid}/labels/`,\n body\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\n\nexport function registerSearchTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"search-work-items\",\n \"Search for work items (tasks/issues) across the workspace by text query. Searches in title and identifier.\",\n {\n query: z.string().min(1).describe(\"Search text\"),\n project_id: z.string().uuid().optional().describe(\"Optional project UUID to scope the search (defaults to BLITZ_PROJECT_ID if set)\"),\n },\n async ({ query, project_id }) => {\n const pid = project_id || config.projectId;\n let path = `workspaces/${config.workspaceSlug}/work-items/search/?search=${encodeURIComponent(query)}`;\n if (pid) {\n path += `&project_id=${pid}`;\n }\n const data = await client.get(path);\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\n\nexport interface Member {\n id: string;\n first_name: string;\n last_name: string;\n email: string;\n display_name: string;\n avatar: string;\n avatar_url: string;\n}\n\n// ---- Cache ----\n\nclass MemberCache {\n private cache = new Map<string, { members: Member[]; fetchedAt: number }>();\n private ttlMs: number;\n\n constructor(ttlMs = 5 * 60 * 1000) {\n this.ttlMs = ttlMs;\n }\n\n get(key: string): Member[] | null {\n const entry = this.cache.get(key);\n if (!entry || Date.now() - entry.fetchedAt > this.ttlMs) {\n if (entry) this.cache.delete(key);\n return null;\n }\n return entry.members;\n }\n\n set(key: string, members: Member[]): void {\n this.cache.set(key, { members, fetchedAt: Date.now() });\n }\n}\n\nconst cache = new MemberCache();\n\n// ---- Fetch helpers ----\n\nexport async function fetchProjectMembers(\n client: BlitzClient,\n workspaceSlug: string,\n projectId: string,\n): Promise<Member[]> {\n const key = `project:${projectId}`;\n const cached = cache.get(key);\n if (cached) return cached;\n\n const data = await client.get<Member[]>(\n `workspaces/${workspaceSlug}/projects/${projectId}/members/`\n );\n cache.set(key, data);\n return data;\n}\n\nasync function fetchWorkspaceMembers(\n client: BlitzClient,\n workspaceSlug: string,\n): Promise<Member[]> {\n const key = `workspace:${workspaceSlug}`;\n const cached = cache.get(key);\n if (cached) return cached;\n\n const data = await client.get<Member[]>(\n `workspaces/${workspaceSlug}/members/`\n );\n cache.set(key, data);\n return data;\n}\n\n// ---- Name resolution ----\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport async function resolveAssignees(\n values: string[],\n client: BlitzClient,\n workspaceSlug: string,\n projectId: string,\n): Promise<string[]> {\n if (values.every(v => UUID_RE.test(v))) return values;\n\n const members = await fetchProjectMembers(client, workspaceSlug, projectId);\n\n return values.map(value => {\n if (UUID_RE.test(value)) return value;\n\n const lower = value.toLowerCase();\n const match = members.find(m =>\n m.display_name.toLowerCase() === lower ||\n `${m.first_name} ${m.last_name}`.toLowerCase().trim() === lower ||\n m.email.toLowerCase() === lower\n );\n if (!match) {\n throw new Error(\n `Could not resolve assignee \"${value}\". Use list-members to see available members.`\n );\n }\n return match.id;\n });\n}\n\n// ---- Enrichment helper ----\n\nexport function enrichAssigneeNames(\n item: Record<string, unknown>,\n members: Member[],\n): Record<string, unknown> {\n const assigneeIds = item.assignees;\n if (!Array.isArray(assigneeIds) || assigneeIds.length === 0) return item;\n\n const memberMap = new Map(members.map(m => [m.id, m.display_name]));\n const assignees = assigneeIds.map(id => ({\n id,\n display_name: memberMap.get(id as string) ?? \"Unknown\",\n }));\n\n return { ...item, assignees };\n}\n\n// ---- Tool registration ----\n\nexport function registerMemberTools(\n server: McpServer,\n client: BlitzClient,\n config: BlitzConfig,\n) {\n const { workspaceSlug } = config;\n\n server.tool(\n \"list-members\",\n \"List members of a project or workspace. Use this to find user IDs and display names for assigning work items. You can also assign work items by display name directly.\",\n {\n project_id: z.string().uuid().optional().describe(\n \"Project UUID - lists project members. Omit to list workspace members (requires admin).\"\n ),\n },\n async ({ project_id }) => {\n let members: Member[];\n if (project_id || config.projectId) {\n const pid = project_id || config.projectId!;\n members = await fetchProjectMembers(client, workspaceSlug, pid);\n } else {\n members = await fetchWorkspaceMembers(client, workspaceSlug);\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(members, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\nimport { fetchProjectMembers, enrichAssigneeNames, resolveAssignees } from \"./members.js\";\n\nconst STATE_GROUPS = [\"backlog\", \"unstarted\", \"started\", \"completed\", \"cancelled\"] as const;\n\nconst SUMMARY_FIELDS = [\n \"id\", \"sequence_id\", \"name\", \"state\", \"priority\",\n \"assignees\", \"labels\", \"start_date\", \"target_date\",\n \"created_at\", \"updated_at\", \"completed_at\",\n] as const;\n\nconst HEAVY_FIELDS = [\n \"description_html\", \"description_binary\", \"description_stripped\",\n \"description\", \"issue_reactions\", \"issue_attachments\", \"issue_link\",\n];\n\nfunction buildListParams(opts: {\n cursor?: string;\n per_page?: number;\n order_by?: string;\n state_group?: string[];\n state_id?: string[];\n}): URLSearchParams {\n const params = new URLSearchParams();\n if (opts.cursor) params.set(\"cursor\", opts.cursor);\n if (opts.per_page) params.set(\"per_page\", String(opts.per_page));\n if (opts.order_by) params.set(\"order_by\", opts.order_by);\n if (opts.state_group?.length) params.set(\"state_group\", opts.state_group.join(\",\"));\n if (opts.state_id?.length) params.set(\"state\", opts.state_id.join(\",\"));\n return params;\n}\n\nfunction stripHeavyFields(item: Record<string, unknown>): Record<string, unknown> {\n const result = { ...item };\n for (const field of HEAVY_FIELDS) {\n delete result[field];\n }\n return result;\n}\n\nfunction pickSummaryFields(item: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const field of SUMMARY_FIELDS) {\n if (field in item) result[field] = item[field];\n }\n return result;\n}\n\nfunction mapBodyForApi(body: Record<string, unknown>): Record<string, unknown> {\n const mapped = { ...body };\n // API serializer expects \"state\" not \"state_id\"\n if (\"state_id\" in mapped) {\n mapped.state = mapped.state_id;\n delete mapped.state_id;\n }\n // API serializer expects \"parent\" not \"parent_id\"\n if (\"parent_id\" in mapped) {\n mapped.parent = mapped.parent_id;\n delete mapped.parent_id;\n }\n return mapped;\n}\n\nexport function registerWorkItemTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n const { workspaceSlug } = config;\n\n server.tool(\n \"list-work-items\",\n \"List work items in a project with filtering, pagination and sorting. Returns all fields except heavy description content.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n cursor: z.string().optional().describe(\"Pagination cursor from previous response\"),\n per_page: z.number().min(1).max(100).optional().describe(\"Items per page (default 20)\"),\n order_by: z.string().optional().describe(\"Sort field (e.g. -created_at, priority, state)\"),\n state_group: z.array(z.enum(STATE_GROUPS)).optional().describe(\"Filter by state group: backlog, unstarted, started, completed, cancelled\"),\n state_id: z.array(z.string().uuid()).optional().describe(\"Filter by specific state UUIDs\"),\n },\n async ({ project_id, cursor, per_page, order_by, state_group, state_id }) => {\n const pid = resolveProjectId(project_id, config);\n const params = buildListParams({ cursor, per_page, order_by, state_group, state_id });\n const query = params.toString();\n const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : \"\"}`;\n const data = await client.get<Record<string, unknown>>(path);\n\n if (data.results && Array.isArray(data.results)) {\n const members = await fetchProjectMembers(client, workspaceSlug, pid);\n data.results = data.results.map((item: Record<string, unknown>) =>\n enrichAssigneeNames(stripHeavyFields(item), members)\n );\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"list-work-items-summary\",\n \"List work items with minimal fields only: name, state, priority, dates. Use this for overviews and large projects.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n cursor: z.string().optional().describe(\"Pagination cursor from previous response\"),\n per_page: z.number().min(1).max(100).optional().describe(\"Items per page (default 20)\"),\n order_by: z.string().optional().describe(\"Sort field (e.g. -created_at, priority, state)\"),\n state_group: z.array(z.enum(STATE_GROUPS)).optional().describe(\"Filter by state group: backlog, unstarted, started, completed, cancelled\"),\n state_id: z.array(z.string().uuid()).optional().describe(\"Filter by specific state UUIDs\"),\n },\n async ({ project_id, cursor, per_page, order_by, state_group, state_id }) => {\n const pid = resolveProjectId(project_id, config);\n const params = buildListParams({ cursor, per_page, order_by, state_group, state_id });\n const query = params.toString();\n const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : \"\"}`;\n const data = await client.get<Record<string, unknown>>(path);\n\n if (data.results && Array.isArray(data.results)) {\n const members = await fetchProjectMembers(client, workspaceSlug, pid);\n data.results = data.results.map((item: Record<string, unknown>) =>\n enrichAssigneeNames(pickSummaryFields(item), members)\n );\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"get-work-item\",\n \"Get a work item by its human-readable identifier (e.g. BLZ-42). Returns full details.\",\n {\n identifier: z.string().min(1).describe(\"Work item identifier (e.g. PROJ-123)\"),\n },\n async ({ identifier }) => {\n const data = await client.get<Record<string, unknown>>(\n `workspaces/${workspaceSlug}/work-items/${identifier}/`\n );\n const projectId = (data.project_id ?? data.project) as string | undefined;\n if (projectId && Array.isArray(data.assignees)) {\n try {\n const members = await fetchProjectMembers(client, workspaceSlug, projectId);\n return {\n content: [{ type: \"text\", text: JSON.stringify(enrichAssigneeNames(data, members), null, 2) }],\n };\n } catch {\n // If member fetch fails, return unenriched\n }\n }\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"get-work-item-by-id\",\n \"Get a work item by its project ID and work item UUID.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get<Record<string, unknown>>(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`\n );\n const members = await fetchProjectMembers(client, workspaceSlug, pid);\n return {\n content: [{ type: \"text\", text: JSON.stringify(enrichAssigneeNames(data, members), null, 2) }],\n };\n }\n );\n\n server.tool(\n \"create-work-item\",\n \"Create a new work item (task/issue) in a project. Use list-projects to find project IDs, list-states for state IDs, and list-labels for label IDs.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n name: z.string().min(1).max(255).describe(\"Work item title\"),\n description_html: z.string().optional().describe(\"HTML description content\"),\n priority: z\n .enum([\"urgent\", \"high\", \"medium\", \"low\", \"none\"])\n .optional()\n .describe(\"Priority level\"),\n state_id: z.string().uuid().optional().describe(\"State UUID (use list-states to find valid IDs)\"),\n assignees: z\n .array(z.string())\n .optional()\n .describe(\"Array of user UUIDs or display names to assign. Use list-members to find valid names.\"),\n labels: z\n .array(z.string().uuid())\n .optional()\n .describe(\"Array of label UUIDs\"),\n start_date: z.string().optional().describe(\"Start date (YYYY-MM-DD)\"),\n target_date: z.string().optional().describe(\"Target date (YYYY-MM-DD)\"),\n parent_id: z.string().uuid().optional().describe(\"Parent work item UUID for sub-issues\"),\n },\n async ({ project_id, ...fields }) => {\n const pid = resolveProjectId(project_id, config);\n const resolvedFields = { ...fields } as Record<string, unknown>;\n if (fields.assignees?.length) {\n resolvedFields.assignees = await resolveAssignees(\n fields.assignees, client, workspaceSlug, pid\n );\n }\n const body = mapBodyForApi(resolvedFields);\n const data = await client.post(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/`,\n body\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"update-work-item\",\n \"Update an existing work item. Only provide fields you want to change.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n name: z.string().min(1).max(255).optional().describe(\"New title\"),\n description_html: z.string().optional().describe(\"New HTML description\"),\n priority: z\n .enum([\"urgent\", \"high\", \"medium\", \"low\", \"none\"])\n .optional()\n .describe(\"New priority level\"),\n state_id: z.string().uuid().optional().describe(\"New state UUID (use list-states to find valid IDs)\"),\n assignees: z\n .array(z.string())\n .optional()\n .describe(\"New assignee UUIDs or display names (replaces existing). Use list-members to find valid names.\"),\n labels: z\n .array(z.string().uuid())\n .optional()\n .describe(\"New label UUIDs (replaces existing)\"),\n start_date: z.string().nullable().optional().describe(\"Start date (YYYY-MM-DD) or null to clear\"),\n target_date: z.string().nullable().optional().describe(\"Target date (YYYY-MM-DD) or null to clear\"),\n },\n async ({ project_id, work_item_id, ...fields }) => {\n const pid = resolveProjectId(project_id, config);\n const resolvedFields = { ...fields } as Record<string, unknown>;\n if (fields.assignees?.length) {\n resolvedFields.assignees = await resolveAssignees(\n fields.assignees, client, workspaceSlug, pid\n );\n }\n const body = mapBodyForApi(resolvedFields);\n const data = await client.patch(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`,\n body\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"delete-work-item\",\n \"Delete a work item. This action cannot be undone.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n await client.delete(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`\n );\n return {\n content: [{ type: \"text\", text: \"Work item deleted successfully.\" }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\n\nexport function registerCommentTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-comments\",\n \"List all comments on a work item.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/comments/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"add-comment\",\n \"Add a comment to a work item.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n comment_html: z.string().min(1).describe(\"Comment content in HTML format\"),\n },\n async ({ project_id, work_item_id, comment_html }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.post(\n `workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/comments/`,\n { comment_html }\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"list-activities\",\n \"View the activity history (changelog) of a work item. Shows what changed, when, and by whom.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/activities/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { registerProjectTools } from \"./projects.js\";\nimport { registerStateTools } from \"./states.js\";\nimport { registerLabelTools } from \"./labels.js\";\nimport { registerSearchTools } from \"./search.js\";\nimport { registerWorkItemTools } from \"./work-items.js\";\nimport { registerCommentTools } from \"./comments.js\";\nimport { registerMemberTools } from \"./members.js\";\n\nexport function registerAllTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n registerProjectTools(server, client, config);\n registerStateTools(server, client, config);\n registerLabelTools(server, client, config);\n registerSearchTools(server, client, config);\n registerWorkItemTools(server, client, config);\n registerCommentTools(server, client, config);\n registerMemberTools(server, client, config);\n}\n","import { McpServer, ResourceTemplate } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\n\nexport function registerProjectResources(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n const { workspaceSlug } = config;\n\n server.registerResource(\n \"projects\",\n \"blitz://projects\",\n {\n description: \"List of all projects in the Blitz workspace with their identifiers, names, and IDs.\",\n mimeType: \"application/json\",\n },\n async (uri) => {\n const data = await client.get(`workspaces/${workspaceSlug}/projects/`);\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n );\n\n server.registerResource(\n \"project-states\",\n new ResourceTemplate(\"blitz://projects/{project_id}/states\", { list: undefined }),\n {\n description: \"Workflow states for a specific project.\",\n mimeType: \"application/json\",\n },\n async (uri, { project_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/states/`\n );\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n );\n\n server.registerResource(\n \"project-labels\",\n new ResourceTemplate(\"blitz://projects/{project_id}/labels\", { list: undefined }),\n {\n description: \"Labels for a specific project.\",\n mimeType: \"application/json\",\n },\n async (uri, { project_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/labels/`\n );\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { registerProjectResources } from \"./projects.js\";\n\nexport function registerAllResources(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n registerProjectResources(server, client, config);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { BlitzClient } from \"./client.js\";\nimport { registerAllTools } from \"./tools/index.js\";\nimport { registerAllResources } from \"./resources/index.js\";\nimport type { BlitzConfig } from \"./config.js\";\n\nexport function createServer(config: BlitzConfig) {\n const client = new BlitzClient(config);\n\n const server = new McpServer({\n name: \"blitz-mcp\",\n version: \"0.3.0\",\n });\n\n registerAllTools(server, client, config);\n registerAllResources(server, client, config);\n\n return server;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sixtynine-digital/blitz-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "license": "AGPL-3.0",
5
5
  "description": "MCP server for Blitz project management",
6
6
  "private": false,
@@ -1 +0,0 @@
1
- {"version":3,"file":"server-Y1bv_8dx.mjs","names":["missing: string[]","headers: Record<string, string>","result: Record<string, unknown>"],"sources":["../src/config.ts","../src/client.ts","../src/tools/projects.ts","../src/tools/states.ts","../src/tools/labels.ts","../src/tools/search.ts","../src/tools/work-items.ts","../src/tools/comments.ts","../src/tools/index.ts","../src/resources/projects.ts","../src/resources/index.ts","../src/server.ts"],"sourcesContent":["export interface BlitzConfig {\n apiUrl: string;\n apiKey: string;\n workspaceSlug: string;\n projectId?: string;\n}\n\nexport function loadConfig(overrides?: Partial<BlitzConfig>): BlitzConfig {\n const apiUrl = overrides?.apiUrl || process.env.BLITZ_API_URL;\n const apiKey = overrides?.apiKey || process.env.BLITZ_API_KEY;\n const workspaceSlug = overrides?.workspaceSlug || process.env.BLITZ_WORKSPACE_SLUG;\n const projectId = overrides?.projectId || process.env.BLITZ_PROJECT_ID;\n\n const missing: string[] = [];\n if (!apiUrl) missing.push(\"BLITZ_API_URL\");\n if (!apiKey) missing.push(\"BLITZ_API_KEY\");\n if (!workspaceSlug) missing.push(\"BLITZ_WORKSPACE_SLUG\");\n\n if (missing.length > 0) {\n throw new Error(\n `Missing required environment variables: ${missing.join(\", \")}\\n\\n` +\n \"Please set the following:\\n\" +\n \" BLITZ_API_URL - Blitz instance URL (e.g. http://localhost:8000)\\n\" +\n \" BLITZ_API_KEY - API key (format: plane_api_<hex>)\\n\" +\n \" BLITZ_WORKSPACE_SLUG - Workspace slug\\n\" +\n \" BLITZ_PROJECT_ID - (Optional) Default project UUID\"\n );\n }\n\n return {\n apiUrl: apiUrl!.replace(/\\/+$/, \"\"),\n apiKey: apiKey!,\n workspaceSlug: workspaceSlug!,\n projectId: projectId || undefined,\n };\n}\n\nexport function resolveProjectId(projectId: string | undefined, config: BlitzConfig): string {\n const id = projectId || config.projectId;\n if (!id) {\n throw new Error(\n \"project_id is required. Either pass it as a parameter or set BLITZ_PROJECT_ID environment variable.\"\n );\n }\n return id;\n}\n","import type { BlitzConfig } from \"./config.js\";\n\nexport class BlitzClient {\n private baseUrl: string;\n private apiKey: string;\n\n constructor(config: BlitzConfig) {\n this.baseUrl = `${config.apiUrl}/api/v1`;\n this.apiKey = config.apiKey;\n }\n\n private async request<T = unknown>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}/${path.replace(/^\\/+/, \"\")}`;\n\n const headers: Record<string, string> = {\n \"X-Api-Key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n throw new Error(\n `Rate limit exceeded. ${retryAfter ? `Retry after ${retryAfter} seconds.` : \"Please wait before retrying.\"}`\n );\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const data = await response.json();\n\n if (!response.ok) {\n const message =\n typeof data === \"object\" && data !== null\n ? JSON.stringify(data, null, 2)\n : String(data);\n throw new Error(`API error (${response.status}): ${message}`);\n }\n\n return data as T;\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"POST\", path, body);\n }\n\n async patch<T = unknown>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PATCH\", path, body);\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>(\"DELETE\", path);\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\n\nexport function registerProjectTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-projects\",\n \"List all projects in the Blitz workspace. Returns project names, identifiers, and IDs.\",\n {},\n async () => {\n const data = await client.get(`workspaces/${config.workspaceSlug}/projects/`);\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\n\nexport function registerStateTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-states\",\n \"List all workflow states for a project. Use this to find valid state IDs when creating or updating work items.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n },\n async ({ project_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/states/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\n\nexport function registerLabelTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-labels\",\n \"List all labels for a project. Use this to find valid label IDs when creating or updating work items.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n },\n async ({ project_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/labels/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"create-label\",\n \"Create a new label in a project.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n name: z.string().min(1).max(255).describe(\"Label name\"),\n color: z.string().optional().describe(\"Hex color (e.g. #ff0000)\"),\n description: z.string().optional().describe(\"Label description\"),\n },\n async ({ project_id, ...body }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.post(\n `workspaces/${config.workspaceSlug}/projects/${pid}/labels/`,\n body\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\n\nexport function registerSearchTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"search-work-items\",\n \"Search for work items (tasks/issues) across the workspace by text query. Searches in title and identifier.\",\n {\n query: z.string().min(1).describe(\"Search text\"),\n project_id: z.string().uuid().optional().describe(\"Optional project UUID to scope the search (defaults to BLITZ_PROJECT_ID if set)\"),\n },\n async ({ query, project_id }) => {\n const pid = project_id || config.projectId;\n let path = `workspaces/${config.workspaceSlug}/work-items/search/?search=${encodeURIComponent(query)}`;\n if (pid) {\n path += `&project_id=${pid}`;\n }\n const data = await client.get(path);\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\n\nconst STATE_GROUPS = [\"backlog\", \"unstarted\", \"started\", \"completed\", \"cancelled\"] as const;\n\nconst SUMMARY_FIELDS = [\n \"id\", \"sequence_id\", \"name\", \"state_id\", \"priority\",\n \"assignee_ids\", \"label_ids\", \"start_date\", \"target_date\",\n \"created_at\", \"updated_at\", \"completed_at\",\n] as const;\n\nconst HEAVY_FIELDS = [\n \"description_html\", \"description_binary\", \"description_stripped\",\n \"description\", \"issue_reactions\", \"issue_attachments\", \"issue_link\",\n];\n\nfunction buildListParams(opts: {\n cursor?: string;\n per_page?: number;\n order_by?: string;\n state_group?: string[];\n state_id?: string[];\n}): URLSearchParams {\n const params = new URLSearchParams();\n if (opts.cursor) params.set(\"cursor\", opts.cursor);\n if (opts.per_page) params.set(\"per_page\", String(opts.per_page));\n if (opts.order_by) params.set(\"order_by\", opts.order_by);\n if (opts.state_group?.length) params.set(\"state_group\", opts.state_group.join(\",\"));\n if (opts.state_id?.length) params.set(\"state\", opts.state_id.join(\",\"));\n return params;\n}\n\nfunction stripHeavyFields(item: Record<string, unknown>): Record<string, unknown> {\n const result = { ...item };\n for (const field of HEAVY_FIELDS) {\n delete result[field];\n }\n return result;\n}\n\nfunction pickSummaryFields(item: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const field of SUMMARY_FIELDS) {\n if (field in item) result[field] = item[field];\n }\n return result;\n}\n\nfunction mapBodyForApi(body: Record<string, unknown>): Record<string, unknown> {\n const mapped = { ...body };\n // API serializer expects \"state\" not \"state_id\"\n if (\"state_id\" in mapped) {\n mapped.state = mapped.state_id;\n delete mapped.state_id;\n }\n // API serializer expects \"parent\" not \"parent_id\"\n if (\"parent_id\" in mapped) {\n mapped.parent = mapped.parent_id;\n delete mapped.parent_id;\n }\n return mapped;\n}\n\nexport function registerWorkItemTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n const { workspaceSlug } = config;\n\n server.tool(\n \"list-work-items\",\n \"List work items in a project with filtering, pagination and sorting. Returns all fields except heavy description content.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n cursor: z.string().optional().describe(\"Pagination cursor from previous response\"),\n per_page: z.number().min(1).max(100).optional().describe(\"Items per page (default 20)\"),\n order_by: z.string().optional().describe(\"Sort field (e.g. -created_at, priority, state)\"),\n state_group: z.array(z.enum(STATE_GROUPS)).optional().describe(\"Filter by state group: backlog, unstarted, started, completed, cancelled\"),\n state_id: z.array(z.string().uuid()).optional().describe(\"Filter by specific state UUIDs\"),\n },\n async ({ project_id, cursor, per_page, order_by, state_group, state_id }) => {\n const pid = resolveProjectId(project_id, config);\n const params = buildListParams({ cursor, per_page, order_by, state_group, state_id });\n const query = params.toString();\n const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : \"\"}`;\n const data = await client.get<Record<string, unknown>>(path);\n\n if (data.results && Array.isArray(data.results)) {\n data.results = data.results.map((item: Record<string, unknown>) => stripHeavyFields(item));\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"list-work-items-summary\",\n \"List work items with minimal fields only: name, state, priority, dates. Use this for overviews and large projects.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n cursor: z.string().optional().describe(\"Pagination cursor from previous response\"),\n per_page: z.number().min(1).max(100).optional().describe(\"Items per page (default 20)\"),\n order_by: z.string().optional().describe(\"Sort field (e.g. -created_at, priority, state)\"),\n state_group: z.array(z.enum(STATE_GROUPS)).optional().describe(\"Filter by state group: backlog, unstarted, started, completed, cancelled\"),\n state_id: z.array(z.string().uuid()).optional().describe(\"Filter by specific state UUIDs\"),\n },\n async ({ project_id, cursor, per_page, order_by, state_group, state_id }) => {\n const pid = resolveProjectId(project_id, config);\n const params = buildListParams({ cursor, per_page, order_by, state_group, state_id });\n const query = params.toString();\n const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : \"\"}`;\n const data = await client.get<Record<string, unknown>>(path);\n\n if (data.results && Array.isArray(data.results)) {\n data.results = data.results.map((item: Record<string, unknown>) => pickSummaryFields(item));\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"get-work-item\",\n \"Get a work item by its human-readable identifier (e.g. BLZ-42). Returns full details.\",\n {\n identifier: z.string().min(1).describe(\"Work item identifier (e.g. PROJ-123)\"),\n },\n async ({ identifier }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/work-items/${identifier}/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"get-work-item-by-id\",\n \"Get a work item by its project ID and work item UUID.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"create-work-item\",\n \"Create a new work item (task/issue) in a project. Use list-projects to find project IDs, list-states for state IDs, and list-labels for label IDs.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n name: z.string().min(1).max(255).describe(\"Work item title\"),\n description_html: z.string().optional().describe(\"HTML description content\"),\n priority: z\n .enum([\"urgent\", \"high\", \"medium\", \"low\", \"none\"])\n .optional()\n .describe(\"Priority level\"),\n state_id: z.string().uuid().optional().describe(\"State UUID (use list-states to find valid IDs)\"),\n assignees: z\n .array(z.string().uuid())\n .optional()\n .describe(\"Array of user UUIDs to assign\"),\n labels: z\n .array(z.string().uuid())\n .optional()\n .describe(\"Array of label UUIDs\"),\n start_date: z.string().optional().describe(\"Start date (YYYY-MM-DD)\"),\n target_date: z.string().optional().describe(\"Target date (YYYY-MM-DD)\"),\n parent_id: z.string().uuid().optional().describe(\"Parent work item UUID for sub-issues\"),\n },\n async ({ project_id, ...fields }) => {\n const pid = resolveProjectId(project_id, config);\n const body = mapBodyForApi(fields as Record<string, unknown>);\n const data = await client.post(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/`,\n body\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"update-work-item\",\n \"Update an existing work item. Only provide fields you want to change.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n name: z.string().min(1).max(255).optional().describe(\"New title\"),\n description_html: z.string().optional().describe(\"New HTML description\"),\n priority: z\n .enum([\"urgent\", \"high\", \"medium\", \"low\", \"none\"])\n .optional()\n .describe(\"New priority level\"),\n state_id: z.string().uuid().optional().describe(\"New state UUID (use list-states to find valid IDs)\"),\n assignees: z\n .array(z.string().uuid())\n .optional()\n .describe(\"New assignee UUIDs (replaces existing)\"),\n labels: z\n .array(z.string().uuid())\n .optional()\n .describe(\"New label UUIDs (replaces existing)\"),\n start_date: z.string().nullable().optional().describe(\"Start date (YYYY-MM-DD) or null to clear\"),\n target_date: z.string().nullable().optional().describe(\"Target date (YYYY-MM-DD) or null to clear\"),\n },\n async ({ project_id, work_item_id, ...fields }) => {\n const pid = resolveProjectId(project_id, config);\n const body = mapBodyForApi(fields as Record<string, unknown>);\n const data = await client.patch(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`,\n body\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"delete-work-item\",\n \"Delete a work item. This action cannot be undone.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n await client.delete(\n `workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`\n );\n return {\n content: [{ type: \"text\", text: \"Work item deleted successfully.\" }],\n };\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { resolveProjectId } from \"../config.js\";\n\nexport function registerCommentTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n server.tool(\n \"list-comments\",\n \"List all comments on a work item.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/comments/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"add-comment\",\n \"Add a comment to a work item.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n comment_html: z.string().min(1).describe(\"Comment content in HTML format\"),\n },\n async ({ project_id, work_item_id, comment_html }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.post(\n `workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/comments/`,\n { comment_html }\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n\n server.tool(\n \"list-activities\",\n \"View the activity history (changelog) of a work item. Shows what changed, when, and by whom.\",\n {\n project_id: z.string().uuid().optional().describe(\"Project UUID (optional if BLITZ_PROJECT_ID is set)\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const pid = resolveProjectId(project_id, config);\n const data = await client.get(\n `workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/activities/`\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { registerProjectTools } from \"./projects.js\";\nimport { registerStateTools } from \"./states.js\";\nimport { registerLabelTools } from \"./labels.js\";\nimport { registerSearchTools } from \"./search.js\";\nimport { registerWorkItemTools } from \"./work-items.js\";\nimport { registerCommentTools } from \"./comments.js\";\n\nexport function registerAllTools(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n registerProjectTools(server, client, config);\n registerStateTools(server, client, config);\n registerLabelTools(server, client, config);\n registerSearchTools(server, client, config);\n registerWorkItemTools(server, client, config);\n registerCommentTools(server, client, config);\n}\n","import { McpServer, ResourceTemplate } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\n\nexport function registerProjectResources(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n const { workspaceSlug } = config;\n\n server.registerResource(\n \"projects\",\n \"blitz://projects\",\n {\n description: \"List of all projects in the Blitz workspace with their identifiers, names, and IDs.\",\n mimeType: \"application/json\",\n },\n async (uri) => {\n const data = await client.get(`workspaces/${workspaceSlug}/projects/`);\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n );\n\n server.registerResource(\n \"project-states\",\n new ResourceTemplate(\"blitz://projects/{project_id}/states\", { list: undefined }),\n {\n description: \"Workflow states for a specific project.\",\n mimeType: \"application/json\",\n },\n async (uri, { project_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/states/`\n );\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n );\n\n server.registerResource(\n \"project-labels\",\n new ResourceTemplate(\"blitz://projects/{project_id}/labels\", { list: undefined }),\n {\n description: \"Labels for a specific project.\",\n mimeType: \"application/json\",\n },\n async (uri, { project_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/labels/`\n );\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\nimport type { BlitzConfig } from \"../config.js\";\nimport { registerProjectResources } from \"./projects.js\";\n\nexport function registerAllResources(server: McpServer, client: BlitzClient, config: BlitzConfig) {\n registerProjectResources(server, client, config);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { BlitzClient } from \"./client.js\";\nimport { registerAllTools } from \"./tools/index.js\";\nimport { registerAllResources } from \"./resources/index.js\";\nimport type { BlitzConfig } from \"./config.js\";\n\nexport function createServer(config: BlitzConfig) {\n const client = new BlitzClient(config);\n\n const server = new McpServer({\n name: \"blitz-mcp\",\n version: \"0.3.0\",\n });\n\n registerAllTools(server, client, config);\n registerAllResources(server, client, config);\n\n return server;\n}\n"],"mappings":"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"}