@sixtynine-digital/blitz-mcp 0.2.1 → 0.3.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.
- package/dist/{http-Dk8tMK0J.mjs → http-kEKXBhoW.mjs} +4 -3
- package/dist/http-kEKXBhoW.mjs.map +1 -0
- package/dist/index.mjs +2 -2
- package/dist/{server-pwmkXBAV.mjs → server-Y1bv_8dx.mjs} +175 -61
- package/dist/server-Y1bv_8dx.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/http-Dk8tMK0J.mjs.map +0 -1
- package/dist/server-pwmkXBAV.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as loadConfig, t as createServer$1 } from "./server-
|
|
2
|
+
import { n as loadConfig, t as createServer$1 } from "./server-Y1bv_8dx.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";
|
|
@@ -78,7 +78,8 @@ function startHttpServer() {
|
|
|
78
78
|
const config = loadConfig({
|
|
79
79
|
apiUrl,
|
|
80
80
|
apiKey,
|
|
81
|
-
workspaceSlug
|
|
81
|
+
workspaceSlug,
|
|
82
|
+
projectId: query.project_id || process.env.BLITZ_PROJECT_ID || void 0
|
|
82
83
|
});
|
|
83
84
|
const transport = new StreamableHTTPServerTransport({
|
|
84
85
|
sessionIdGenerator: () => randomUUID(),
|
|
@@ -137,4 +138,4 @@ function startHttpServer() {
|
|
|
137
138
|
|
|
138
139
|
//#endregion
|
|
139
140
|
export { startHttpServer };
|
|
140
|
-
//# sourceMappingURL=http-
|
|
141
|
+
//# sourceMappingURL=http-kEKXBhoW.mjs.map
|
|
@@ -0,0 +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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"}
|
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-
|
|
2
|
+
import { n as loadConfig, t as createServer } from "./server-Y1bv_8dx.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-
|
|
6
|
+
const { startHttpServer } = await import("./http-kEKXBhoW.mjs");
|
|
7
7
|
startHttpServer();
|
|
8
8
|
} else {
|
|
9
9
|
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
@@ -7,20 +7,28 @@ function loadConfig(overrides) {
|
|
|
7
7
|
const apiUrl = overrides?.apiUrl || process.env.BLITZ_API_URL;
|
|
8
8
|
const apiKey = overrides?.apiKey || process.env.BLITZ_API_KEY;
|
|
9
9
|
const workspaceSlug = overrides?.workspaceSlug || process.env.BLITZ_WORKSPACE_SLUG;
|
|
10
|
+
const projectId = overrides?.projectId || process.env.BLITZ_PROJECT_ID;
|
|
10
11
|
const missing = [];
|
|
11
12
|
if (!apiUrl) missing.push("BLITZ_API_URL");
|
|
12
13
|
if (!apiKey) missing.push("BLITZ_API_KEY");
|
|
13
14
|
if (!workspaceSlug) missing.push("BLITZ_WORKSPACE_SLUG");
|
|
14
15
|
if (missing.length > 0) throw new Error(`Missing required environment variables: ${missing.join(", ")}\n\nPlease set the following:
|
|
15
|
-
BLITZ_API_URL
|
|
16
|
-
BLITZ_API_KEY
|
|
17
|
-
BLITZ_WORKSPACE_SLUG - Workspace slug
|
|
16
|
+
BLITZ_API_URL - Blitz instance URL (e.g. http://localhost:8000)
|
|
17
|
+
BLITZ_API_KEY - API key (format: plane_api_<hex>)
|
|
18
|
+
BLITZ_WORKSPACE_SLUG - Workspace slug
|
|
19
|
+
BLITZ_PROJECT_ID - (Optional) Default project UUID`);
|
|
18
20
|
return {
|
|
19
21
|
apiUrl: apiUrl.replace(/\/+$/, ""),
|
|
20
22
|
apiKey,
|
|
21
|
-
workspaceSlug
|
|
23
|
+
workspaceSlug,
|
|
24
|
+
projectId: projectId || void 0
|
|
22
25
|
};
|
|
23
26
|
}
|
|
27
|
+
function resolveProjectId(projectId, config) {
|
|
28
|
+
const id = projectId || config.projectId;
|
|
29
|
+
if (!id) throw new Error("project_id is required. Either pass it as a parameter or set BLITZ_PROJECT_ID environment variable.");
|
|
30
|
+
return id;
|
|
31
|
+
}
|
|
24
32
|
|
|
25
33
|
//#endregion
|
|
26
34
|
//#region src/client.ts
|
|
@@ -70,9 +78,9 @@ var BlitzClient = class {
|
|
|
70
78
|
|
|
71
79
|
//#endregion
|
|
72
80
|
//#region src/tools/projects.ts
|
|
73
|
-
function registerProjectTools(server, client,
|
|
81
|
+
function registerProjectTools(server, client, config) {
|
|
74
82
|
server.tool("list-projects", "List all projects in the Blitz workspace. Returns project names, identifiers, and IDs.", {}, async () => {
|
|
75
|
-
const data = await client.get(`workspaces/${workspaceSlug}/projects/`);
|
|
83
|
+
const data = await client.get(`workspaces/${config.workspaceSlug}/projects/`);
|
|
76
84
|
return { content: [{
|
|
77
85
|
type: "text",
|
|
78
86
|
text: JSON.stringify(data, null, 2)
|
|
@@ -82,9 +90,10 @@ function registerProjectTools(server, client, workspaceSlug) {
|
|
|
82
90
|
|
|
83
91
|
//#endregion
|
|
84
92
|
//#region src/tools/states.ts
|
|
85
|
-
function registerStateTools(server, client,
|
|
86
|
-
server.tool("list-states", "List all workflow states for a project. Use this to find valid state IDs when creating or updating work items.", { project_id: z.string().uuid().describe("Project UUID") }, async ({ project_id }) => {
|
|
87
|
-
const
|
|
93
|
+
function registerStateTools(server, client, config) {
|
|
94
|
+
server.tool("list-states", "List all workflow states for a project. Use this to find valid state IDs when creating or updating work items.", { project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)") }, async ({ project_id }) => {
|
|
95
|
+
const pid = resolveProjectId(project_id, config);
|
|
96
|
+
const data = await client.get(`workspaces/${config.workspaceSlug}/projects/${pid}/states/`);
|
|
88
97
|
return { content: [{
|
|
89
98
|
type: "text",
|
|
90
99
|
text: JSON.stringify(data, null, 2)
|
|
@@ -94,21 +103,23 @@ function registerStateTools(server, client, workspaceSlug) {
|
|
|
94
103
|
|
|
95
104
|
//#endregion
|
|
96
105
|
//#region src/tools/labels.ts
|
|
97
|
-
function registerLabelTools(server, client,
|
|
98
|
-
server.tool("list-labels", "List all labels for a project. Use this to find valid label IDs when creating or updating work items.", { project_id: z.string().uuid().describe("Project UUID") }, async ({ project_id }) => {
|
|
99
|
-
const
|
|
106
|
+
function registerLabelTools(server, client, config) {
|
|
107
|
+
server.tool("list-labels", "List all labels for a project. Use this to find valid label IDs when creating or updating work items.", { project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)") }, async ({ project_id }) => {
|
|
108
|
+
const pid = resolveProjectId(project_id, config);
|
|
109
|
+
const data = await client.get(`workspaces/${config.workspaceSlug}/projects/${pid}/labels/`);
|
|
100
110
|
return { content: [{
|
|
101
111
|
type: "text",
|
|
102
112
|
text: JSON.stringify(data, null, 2)
|
|
103
113
|
}] };
|
|
104
114
|
});
|
|
105
115
|
server.tool("create-label", "Create a new label in a project.", {
|
|
106
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
116
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
107
117
|
name: z.string().min(1).max(255).describe("Label name"),
|
|
108
118
|
color: z.string().optional().describe("Hex color (e.g. #ff0000)"),
|
|
109
119
|
description: z.string().optional().describe("Label description")
|
|
110
120
|
}, async ({ project_id,...body }) => {
|
|
111
|
-
const
|
|
121
|
+
const pid = resolveProjectId(project_id, config);
|
|
122
|
+
const data = await client.post(`workspaces/${config.workspaceSlug}/projects/${pid}/labels/`, body);
|
|
112
123
|
return { content: [{
|
|
113
124
|
type: "text",
|
|
114
125
|
text: JSON.stringify(data, null, 2)
|
|
@@ -118,13 +129,14 @@ function registerLabelTools(server, client, workspaceSlug) {
|
|
|
118
129
|
|
|
119
130
|
//#endregion
|
|
120
131
|
//#region src/tools/search.ts
|
|
121
|
-
function registerSearchTools(server, client,
|
|
132
|
+
function registerSearchTools(server, client, config) {
|
|
122
133
|
server.tool("search-work-items", "Search for work items (tasks/issues) across the workspace by text query. Searches in title and identifier.", {
|
|
123
134
|
query: z.string().min(1).describe("Search text"),
|
|
124
|
-
project_id: z.string().uuid().optional().describe("Optional project UUID to scope the search")
|
|
135
|
+
project_id: z.string().uuid().optional().describe("Optional project UUID to scope the search (defaults to BLITZ_PROJECT_ID if set)")
|
|
125
136
|
}, async ({ query, project_id }) => {
|
|
126
|
-
|
|
127
|
-
|
|
137
|
+
const pid = project_id || config.projectId;
|
|
138
|
+
let path = `workspaces/${config.workspaceSlug}/work-items/search/?search=${encodeURIComponent(query)}`;
|
|
139
|
+
if (pid) path += `&project_id=${pid}`;
|
|
128
140
|
const data = await client.get(path);
|
|
129
141
|
return { content: [{
|
|
130
142
|
type: "text",
|
|
@@ -135,20 +147,112 @@ function registerSearchTools(server, client, workspaceSlug) {
|
|
|
135
147
|
|
|
136
148
|
//#endregion
|
|
137
149
|
//#region src/tools/work-items.ts
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
const STATE_GROUPS = [
|
|
151
|
+
"backlog",
|
|
152
|
+
"unstarted",
|
|
153
|
+
"started",
|
|
154
|
+
"completed",
|
|
155
|
+
"cancelled"
|
|
156
|
+
];
|
|
157
|
+
const SUMMARY_FIELDS = [
|
|
158
|
+
"id",
|
|
159
|
+
"sequence_id",
|
|
160
|
+
"name",
|
|
161
|
+
"state_id",
|
|
162
|
+
"priority",
|
|
163
|
+
"assignee_ids",
|
|
164
|
+
"label_ids",
|
|
165
|
+
"start_date",
|
|
166
|
+
"target_date",
|
|
167
|
+
"created_at",
|
|
168
|
+
"updated_at",
|
|
169
|
+
"completed_at"
|
|
170
|
+
];
|
|
171
|
+
const HEAVY_FIELDS = [
|
|
172
|
+
"description_html",
|
|
173
|
+
"description_binary",
|
|
174
|
+
"description_stripped",
|
|
175
|
+
"description",
|
|
176
|
+
"issue_reactions",
|
|
177
|
+
"issue_attachments",
|
|
178
|
+
"issue_link"
|
|
179
|
+
];
|
|
180
|
+
function buildListParams(opts) {
|
|
181
|
+
const params = new URLSearchParams();
|
|
182
|
+
if (opts.cursor) params.set("cursor", opts.cursor);
|
|
183
|
+
if (opts.per_page) params.set("per_page", String(opts.per_page));
|
|
184
|
+
if (opts.order_by) params.set("order_by", opts.order_by);
|
|
185
|
+
if (opts.state_group?.length) params.set("state_group", opts.state_group.join(","));
|
|
186
|
+
if (opts.state_id?.length) params.set("state", opts.state_id.join(","));
|
|
187
|
+
return params;
|
|
188
|
+
}
|
|
189
|
+
function stripHeavyFields(item) {
|
|
190
|
+
const result = { ...item };
|
|
191
|
+
for (const field of HEAVY_FIELDS) delete result[field];
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
function pickSummaryFields(item) {
|
|
195
|
+
const result = {};
|
|
196
|
+
for (const field of SUMMARY_FIELDS) if (field in item) result[field] = item[field];
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
function mapBodyForApi(body) {
|
|
200
|
+
const mapped = { ...body };
|
|
201
|
+
if ("state_id" in mapped) {
|
|
202
|
+
mapped.state = mapped.state_id;
|
|
203
|
+
delete mapped.state_id;
|
|
204
|
+
}
|
|
205
|
+
if ("parent_id" in mapped) {
|
|
206
|
+
mapped.parent = mapped.parent_id;
|
|
207
|
+
delete mapped.parent_id;
|
|
208
|
+
}
|
|
209
|
+
return mapped;
|
|
210
|
+
}
|
|
211
|
+
function registerWorkItemTools(server, client, config) {
|
|
212
|
+
const { workspaceSlug } = config;
|
|
213
|
+
server.tool("list-work-items", "List work items in a project with filtering, pagination and sorting. Returns all fields except heavy description content.", {
|
|
214
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
141
215
|
cursor: z.string().optional().describe("Pagination cursor from previous response"),
|
|
142
216
|
per_page: z.number().min(1).max(100).optional().describe("Items per page (default 20)"),
|
|
143
|
-
order_by: z.string().optional().describe("Sort field (e.g. -created_at, priority, state)")
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
217
|
+
order_by: z.string().optional().describe("Sort field (e.g. -created_at, priority, state)"),
|
|
218
|
+
state_group: z.array(z.enum(STATE_GROUPS)).optional().describe("Filter by state group: backlog, unstarted, started, completed, cancelled"),
|
|
219
|
+
state_id: z.array(z.string().uuid()).optional().describe("Filter by specific state UUIDs")
|
|
220
|
+
}, async ({ project_id, cursor, per_page, order_by, state_group, state_id }) => {
|
|
221
|
+
const pid = resolveProjectId(project_id, config);
|
|
222
|
+
const query = buildListParams({
|
|
223
|
+
cursor,
|
|
224
|
+
per_page,
|
|
225
|
+
order_by,
|
|
226
|
+
state_group,
|
|
227
|
+
state_id
|
|
228
|
+
}).toString();
|
|
229
|
+
const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : ""}`;
|
|
151
230
|
const data = await client.get(path);
|
|
231
|
+
if (data.results && Array.isArray(data.results)) data.results = data.results.map((item) => stripHeavyFields(item));
|
|
232
|
+
return { content: [{
|
|
233
|
+
type: "text",
|
|
234
|
+
text: JSON.stringify(data, null, 2)
|
|
235
|
+
}] };
|
|
236
|
+
});
|
|
237
|
+
server.tool("list-work-items-summary", "List work items with minimal fields only: name, state, priority, dates. Use this for overviews and large projects.", {
|
|
238
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
239
|
+
cursor: z.string().optional().describe("Pagination cursor from previous response"),
|
|
240
|
+
per_page: z.number().min(1).max(100).optional().describe("Items per page (default 20)"),
|
|
241
|
+
order_by: z.string().optional().describe("Sort field (e.g. -created_at, priority, state)"),
|
|
242
|
+
state_group: z.array(z.enum(STATE_GROUPS)).optional().describe("Filter by state group: backlog, unstarted, started, completed, cancelled"),
|
|
243
|
+
state_id: z.array(z.string().uuid()).optional().describe("Filter by specific state UUIDs")
|
|
244
|
+
}, async ({ project_id, cursor, per_page, order_by, state_group, state_id }) => {
|
|
245
|
+
const pid = resolveProjectId(project_id, config);
|
|
246
|
+
const query = buildListParams({
|
|
247
|
+
cursor,
|
|
248
|
+
per_page,
|
|
249
|
+
order_by,
|
|
250
|
+
state_group,
|
|
251
|
+
state_id
|
|
252
|
+
}).toString();
|
|
253
|
+
const path = `workspaces/${workspaceSlug}/projects/${pid}/work-items/${query ? `?${query}` : ""}`;
|
|
254
|
+
const data = await client.get(path);
|
|
255
|
+
if (data.results && Array.isArray(data.results)) data.results = data.results.map((item) => pickSummaryFields(item));
|
|
152
256
|
return { content: [{
|
|
153
257
|
type: "text",
|
|
154
258
|
text: JSON.stringify(data, null, 2)
|
|
@@ -162,17 +266,18 @@ function registerWorkItemTools(server, client, workspaceSlug) {
|
|
|
162
266
|
}] };
|
|
163
267
|
});
|
|
164
268
|
server.tool("get-work-item-by-id", "Get a work item by its project ID and work item UUID.", {
|
|
165
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
269
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
166
270
|
work_item_id: z.string().uuid().describe("Work item UUID")
|
|
167
271
|
}, async ({ project_id, work_item_id }) => {
|
|
168
|
-
const
|
|
272
|
+
const pid = resolveProjectId(project_id, config);
|
|
273
|
+
const data = await client.get(`workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`);
|
|
169
274
|
return { content: [{
|
|
170
275
|
type: "text",
|
|
171
276
|
text: JSON.stringify(data, null, 2)
|
|
172
277
|
}] };
|
|
173
278
|
});
|
|
174
279
|
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.", {
|
|
175
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
280
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
176
281
|
name: z.string().min(1).max(255).describe("Work item title"),
|
|
177
282
|
description_html: z.string().optional().describe("HTML description content"),
|
|
178
283
|
priority: z.enum([
|
|
@@ -188,15 +293,17 @@ function registerWorkItemTools(server, client, workspaceSlug) {
|
|
|
188
293
|
start_date: z.string().optional().describe("Start date (YYYY-MM-DD)"),
|
|
189
294
|
target_date: z.string().optional().describe("Target date (YYYY-MM-DD)"),
|
|
190
295
|
parent_id: z.string().uuid().optional().describe("Parent work item UUID for sub-issues")
|
|
191
|
-
}, async ({ project_id,...
|
|
192
|
-
const
|
|
296
|
+
}, async ({ project_id,...fields }) => {
|
|
297
|
+
const pid = resolveProjectId(project_id, config);
|
|
298
|
+
const body = mapBodyForApi(fields);
|
|
299
|
+
const data = await client.post(`workspaces/${workspaceSlug}/projects/${pid}/work-items/`, body);
|
|
193
300
|
return { content: [{
|
|
194
301
|
type: "text",
|
|
195
302
|
text: JSON.stringify(data, null, 2)
|
|
196
303
|
}] };
|
|
197
304
|
});
|
|
198
305
|
server.tool("update-work-item", "Update an existing work item. Only provide fields you want to change.", {
|
|
199
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
306
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
200
307
|
work_item_id: z.string().uuid().describe("Work item UUID"),
|
|
201
308
|
name: z.string().min(1).max(255).optional().describe("New title"),
|
|
202
309
|
description_html: z.string().optional().describe("New HTML description"),
|
|
@@ -207,23 +314,26 @@ function registerWorkItemTools(server, client, workspaceSlug) {
|
|
|
207
314
|
"low",
|
|
208
315
|
"none"
|
|
209
316
|
]).optional().describe("New priority level"),
|
|
210
|
-
state_id: z.string().uuid().optional().describe("New state UUID"),
|
|
317
|
+
state_id: z.string().uuid().optional().describe("New state UUID (use list-states to find valid IDs)"),
|
|
211
318
|
assignees: z.array(z.string().uuid()).optional().describe("New assignee UUIDs (replaces existing)"),
|
|
212
319
|
labels: z.array(z.string().uuid()).optional().describe("New label UUIDs (replaces existing)"),
|
|
213
320
|
start_date: z.string().nullable().optional().describe("Start date (YYYY-MM-DD) or null to clear"),
|
|
214
321
|
target_date: z.string().nullable().optional().describe("Target date (YYYY-MM-DD) or null to clear")
|
|
215
|
-
}, async ({ project_id, work_item_id,...
|
|
216
|
-
const
|
|
322
|
+
}, async ({ project_id, work_item_id,...fields }) => {
|
|
323
|
+
const pid = resolveProjectId(project_id, config);
|
|
324
|
+
const body = mapBodyForApi(fields);
|
|
325
|
+
const data = await client.patch(`workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`, body);
|
|
217
326
|
return { content: [{
|
|
218
327
|
type: "text",
|
|
219
328
|
text: JSON.stringify(data, null, 2)
|
|
220
329
|
}] };
|
|
221
330
|
});
|
|
222
331
|
server.tool("delete-work-item", "Delete a work item. This action cannot be undone.", {
|
|
223
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
332
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
224
333
|
work_item_id: z.string().uuid().describe("Work item UUID")
|
|
225
334
|
}, async ({ project_id, work_item_id }) => {
|
|
226
|
-
|
|
335
|
+
const pid = resolveProjectId(project_id, config);
|
|
336
|
+
await client.delete(`workspaces/${workspaceSlug}/projects/${pid}/work-items/${work_item_id}/`);
|
|
227
337
|
return { content: [{
|
|
228
338
|
type: "text",
|
|
229
339
|
text: "Work item deleted successfully."
|
|
@@ -233,33 +343,36 @@ function registerWorkItemTools(server, client, workspaceSlug) {
|
|
|
233
343
|
|
|
234
344
|
//#endregion
|
|
235
345
|
//#region src/tools/comments.ts
|
|
236
|
-
function registerCommentTools(server, client,
|
|
346
|
+
function registerCommentTools(server, client, config) {
|
|
237
347
|
server.tool("list-comments", "List all comments on a work item.", {
|
|
238
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
348
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
239
349
|
work_item_id: z.string().uuid().describe("Work item UUID")
|
|
240
350
|
}, async ({ project_id, work_item_id }) => {
|
|
241
|
-
const
|
|
351
|
+
const pid = resolveProjectId(project_id, config);
|
|
352
|
+
const data = await client.get(`workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/comments/`);
|
|
242
353
|
return { content: [{
|
|
243
354
|
type: "text",
|
|
244
355
|
text: JSON.stringify(data, null, 2)
|
|
245
356
|
}] };
|
|
246
357
|
});
|
|
247
358
|
server.tool("add-comment", "Add a comment to a work item.", {
|
|
248
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
359
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
249
360
|
work_item_id: z.string().uuid().describe("Work item UUID"),
|
|
250
361
|
comment_html: z.string().min(1).describe("Comment content in HTML format")
|
|
251
362
|
}, async ({ project_id, work_item_id, comment_html }) => {
|
|
252
|
-
const
|
|
363
|
+
const pid = resolveProjectId(project_id, config);
|
|
364
|
+
const data = await client.post(`workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/comments/`, { comment_html });
|
|
253
365
|
return { content: [{
|
|
254
366
|
type: "text",
|
|
255
367
|
text: JSON.stringify(data, null, 2)
|
|
256
368
|
}] };
|
|
257
369
|
});
|
|
258
370
|
server.tool("list-activities", "View the activity history (changelog) of a work item. Shows what changed, when, and by whom.", {
|
|
259
|
-
project_id: z.string().uuid().describe("Project UUID"),
|
|
371
|
+
project_id: z.string().uuid().optional().describe("Project UUID (optional if BLITZ_PROJECT_ID is set)"),
|
|
260
372
|
work_item_id: z.string().uuid().describe("Work item UUID")
|
|
261
373
|
}, async ({ project_id, work_item_id }) => {
|
|
262
|
-
const
|
|
374
|
+
const pid = resolveProjectId(project_id, config);
|
|
375
|
+
const data = await client.get(`workspaces/${config.workspaceSlug}/projects/${pid}/work-items/${work_item_id}/activities/`);
|
|
263
376
|
return { content: [{
|
|
264
377
|
type: "text",
|
|
265
378
|
text: JSON.stringify(data, null, 2)
|
|
@@ -269,18 +382,19 @@ function registerCommentTools(server, client, workspaceSlug) {
|
|
|
269
382
|
|
|
270
383
|
//#endregion
|
|
271
384
|
//#region src/tools/index.ts
|
|
272
|
-
function registerAllTools(server, client,
|
|
273
|
-
registerProjectTools(server, client,
|
|
274
|
-
registerStateTools(server, client,
|
|
275
|
-
registerLabelTools(server, client,
|
|
276
|
-
registerSearchTools(server, client,
|
|
277
|
-
registerWorkItemTools(server, client,
|
|
278
|
-
registerCommentTools(server, client,
|
|
385
|
+
function registerAllTools(server, client, config) {
|
|
386
|
+
registerProjectTools(server, client, config);
|
|
387
|
+
registerStateTools(server, client, config);
|
|
388
|
+
registerLabelTools(server, client, config);
|
|
389
|
+
registerSearchTools(server, client, config);
|
|
390
|
+
registerWorkItemTools(server, client, config);
|
|
391
|
+
registerCommentTools(server, client, config);
|
|
279
392
|
}
|
|
280
393
|
|
|
281
394
|
//#endregion
|
|
282
395
|
//#region src/resources/projects.ts
|
|
283
|
-
function registerProjectResources(server, client,
|
|
396
|
+
function registerProjectResources(server, client, config) {
|
|
397
|
+
const { workspaceSlug } = config;
|
|
284
398
|
server.registerResource("projects", "blitz://projects", {
|
|
285
399
|
description: "List of all projects in the Blitz workspace with their identifiers, names, and IDs.",
|
|
286
400
|
mimeType: "application/json"
|
|
@@ -318,8 +432,8 @@ function registerProjectResources(server, client, workspaceSlug) {
|
|
|
318
432
|
|
|
319
433
|
//#endregion
|
|
320
434
|
//#region src/resources/index.ts
|
|
321
|
-
function registerAllResources(server, client,
|
|
322
|
-
registerProjectResources(server, client,
|
|
435
|
+
function registerAllResources(server, client, config) {
|
|
436
|
+
registerProjectResources(server, client, config);
|
|
323
437
|
}
|
|
324
438
|
|
|
325
439
|
//#endregion
|
|
@@ -328,13 +442,13 @@ function createServer(config) {
|
|
|
328
442
|
const client = new BlitzClient(config);
|
|
329
443
|
const server = new McpServer({
|
|
330
444
|
name: "blitz-mcp",
|
|
331
|
-
version: "0.
|
|
445
|
+
version: "0.3.0"
|
|
332
446
|
});
|
|
333
|
-
registerAllTools(server, client, config
|
|
334
|
-
registerAllResources(server, client, config
|
|
447
|
+
registerAllTools(server, client, config);
|
|
448
|
+
registerAllResources(server, client, config);
|
|
335
449
|
return server;
|
|
336
450
|
}
|
|
337
451
|
|
|
338
452
|
//#endregion
|
|
339
453
|
export { loadConfig as n, createServer as t };
|
|
340
|
-
//# sourceMappingURL=server-
|
|
454
|
+
//# sourceMappingURL=server-Y1bv_8dx.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"http-Dk8tMK0J.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 config = loadConfig({\n apiUrl,\n apiKey,\n workspaceSlug,\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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-pwmkXBAV.mjs","names":["missing: string[]","headers: Record<string, string>"],"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}\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\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 }\n\n return {\n apiUrl: apiUrl!.replace(/\\/+$/, \"\"),\n apiKey: apiKey!,\n workspaceSlug: workspaceSlug!,\n };\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\";\n\nexport function registerProjectTools(server: McpServer, client: BlitzClient, workspaceSlug: string) {\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/${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\";\n\nexport function registerStateTools(server: McpServer, client: BlitzClient, workspaceSlug: string) {\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().describe(\"Project UUID\"),\n },\n async ({ project_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/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\";\n\nexport function registerLabelTools(server: McpServer, client: BlitzClient, workspaceSlug: string) {\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().describe(\"Project UUID\"),\n },\n async ({ project_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/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().describe(\"Project UUID\"),\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 data = await client.post(\n `workspaces/${workspaceSlug}/projects/${project_id}/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\";\n\nexport function registerSearchTools(server: McpServer, client: BlitzClient, workspaceSlug: string) {\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\"),\n },\n async ({ query, project_id }) => {\n let path = `workspaces/${workspaceSlug}/work-items/search/?search=${encodeURIComponent(query)}`;\n if (project_id) {\n path += `&project_id=${project_id}`;\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\";\n\nexport function registerWorkItemTools(server: McpServer, client: BlitzClient, workspaceSlug: string) {\n server.tool(\n \"list-work-items\",\n \"List work items (tasks/issues) in a project with pagination and sorting.\",\n {\n project_id: z.string().uuid().describe(\"Project UUID\"),\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 },\n async ({ project_id, cursor, per_page, order_by }) => {\n const params = new URLSearchParams();\n if (cursor) params.set(\"cursor\", cursor);\n if (per_page) params.set(\"per_page\", String(per_page));\n if (order_by) params.set(\"order_by\", order_by);\n\n const query = params.toString();\n const path = `workspaces/${workspaceSlug}/projects/${project_id}/work-items/${query ? `?${query}` : \"\"}`;\n const data = await client.get(path);\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().describe(\"Project UUID\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/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().describe(\"Project UUID\"),\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, ...body }) => {\n const data = await client.post(\n `workspaces/${workspaceSlug}/projects/${project_id}/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().describe(\"Project UUID\"),\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\"),\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, ...body }) => {\n const data = await client.patch(\n `workspaces/${workspaceSlug}/projects/${project_id}/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().describe(\"Project UUID\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n await client.delete(\n `workspaces/${workspaceSlug}/projects/${project_id}/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\";\n\nexport function registerCommentTools(server: McpServer, client: BlitzClient, workspaceSlug: string) {\n server.tool(\n \"list-comments\",\n \"List all comments on a work item.\",\n {\n project_id: z.string().uuid().describe(\"Project UUID\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/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().describe(\"Project UUID\"),\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 data = await client.post(\n `workspaces/${workspaceSlug}/projects/${project_id}/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().describe(\"Project UUID\"),\n work_item_id: z.string().uuid().describe(\"Work item UUID\"),\n },\n async ({ project_id, work_item_id }) => {\n const data = await client.get(\n `workspaces/${workspaceSlug}/projects/${project_id}/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 { 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, workspaceSlug: string) {\n registerProjectTools(server, client, workspaceSlug);\n registerStateTools(server, client, workspaceSlug);\n registerLabelTools(server, client, workspaceSlug);\n registerSearchTools(server, client, workspaceSlug);\n registerWorkItemTools(server, client, workspaceSlug);\n registerCommentTools(server, client, workspaceSlug);\n}\n","import { McpServer, ResourceTemplate } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { BlitzClient } from \"../client.js\";\n\nexport function registerProjectResources(server: McpServer, client: BlitzClient, workspaceSlug: string) {\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 { registerProjectResources } from \"./projects.js\";\n\nexport function registerAllResources(server: McpServer, client: BlitzClient, workspaceSlug: string) {\n registerProjectResources(server, client, workspaceSlug);\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.1.1\",\n });\n\n registerAllTools(server, client, config.workspaceSlug);\n registerAllResources(server, client, config.workspaceSlug);\n\n return server;\n}\n"],"mappings":"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"}
|