backlog-mcp 0.18.0 → 0.20.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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ import { request } from 'node:http';
3
+ import { spawn } from 'node:child_process';
4
+ import { readFileSync } from 'node:fs';
5
+ import { join, dirname } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
8
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8'));
11
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
12
+ async function isServerRunning(port) {
13
+ return new Promise((resolve) => {
14
+ const req = request({ host: 'localhost', port, path: '/version', method: 'GET' }, (res) => {
15
+ resolve(res.statusCode === 200);
16
+ });
17
+ req.on('error', () => resolve(false));
18
+ req.end();
19
+ });
20
+ }
21
+ async function getServerVersion(port) {
22
+ return new Promise((resolve) => {
23
+ const req = request({ host: 'localhost', port, path: '/version', method: 'GET' }, (res) => {
24
+ if (res.statusCode !== 200) {
25
+ resolve(null);
26
+ return;
27
+ }
28
+ let data = '';
29
+ res.on('data', chunk => data += chunk);
30
+ res.on('end', () => resolve(data.trim()));
31
+ });
32
+ req.on('error', () => resolve(null));
33
+ req.end();
34
+ });
35
+ }
36
+ async function spawnServer(port) {
37
+ const serverPath = join(__dirname, '..', 'http-server.js');
38
+ const child = spawn(process.execPath, [serverPath], {
39
+ detached: true,
40
+ stdio: 'ignore',
41
+ env: { ...process.env, BACKLOG_VIEWER_PORT: String(port) }
42
+ });
43
+ child.unref();
44
+ }
45
+ async function shutdownServer(port) {
46
+ return new Promise((resolve) => {
47
+ const req = request({ host: 'localhost', port, path: '/shutdown', method: 'POST' }, () => {
48
+ resolve();
49
+ });
50
+ req.on('error', () => resolve());
51
+ req.end();
52
+ });
53
+ }
54
+ async function waitForServer(port, timeout) {
55
+ const start = Date.now();
56
+ let delay = 100;
57
+ while (Date.now() - start < timeout) {
58
+ if (await isServerRunning(port))
59
+ return;
60
+ await sleep(delay);
61
+ delay = Math.min(delay * 1.5, 1000);
62
+ }
63
+ throw new Error(`Server failed to start within ${timeout}ms`);
64
+ }
65
+ async function ensureServer(port) {
66
+ const running = await isServerRunning(port);
67
+ if (!running) {
68
+ await spawnServer(port);
69
+ await waitForServer(port, 10000);
70
+ return;
71
+ }
72
+ const serverVersion = await getServerVersion(port);
73
+ if (serverVersion !== pkg.version) {
74
+ await shutdownServer(port);
75
+ await sleep(1000);
76
+ await spawnServer(port);
77
+ await waitForServer(port, 10000);
78
+ }
79
+ }
80
+ async function runBridge(port) {
81
+ await ensureServer(port);
82
+ const transport = new SSEClientTransport(new URL(`http://localhost:${port}/mcp`));
83
+ const client = new Client({ name: 'backlog-mcp-bridge', version: pkg.version });
84
+ await client.connect(transport);
85
+ process.stdin.setEncoding('utf-8');
86
+ let buffer = '';
87
+ process.stdin.on('data', async (chunk) => {
88
+ buffer += chunk;
89
+ const lines = buffer.split('\n');
90
+ buffer = lines.pop() || '';
91
+ for (const line of lines) {
92
+ if (!line.trim())
93
+ continue;
94
+ try {
95
+ const message = JSON.parse(line);
96
+ // Handle notifications (messages without id) - don't send response
97
+ if (!message.id) {
98
+ // Notifications are fire-and-forget, skip for now
99
+ // TODO: Forward notifications to server when SDK supports it
100
+ continue;
101
+ }
102
+ // Route to appropriate client method based on JSON-RPC method
103
+ let result;
104
+ if (message.method === 'initialize') {
105
+ // MCP initialization - client is already initialized via connect()
106
+ // Return server capabilities
107
+ result = {
108
+ protocolVersion: '2024-11-05',
109
+ capabilities: {
110
+ tools: {},
111
+ resources: {},
112
+ prompts: {}
113
+ },
114
+ serverInfo: {
115
+ name: 'backlog-mcp',
116
+ version: pkg.version
117
+ }
118
+ };
119
+ }
120
+ else if (message.method === 'ping') {
121
+ result = {}; // Ping just returns empty object
122
+ }
123
+ else if (message.method === 'tools/list') {
124
+ result = await client.listTools(message.params);
125
+ }
126
+ else if (message.method === 'tools/call') {
127
+ result = await client.callTool(message.params);
128
+ }
129
+ else if (message.method === 'resources/list') {
130
+ result = await client.listResources(message.params);
131
+ }
132
+ else if (message.method === 'resources/read') {
133
+ result = await client.readResource(message.params);
134
+ }
135
+ else if (message.method === 'prompts/list') {
136
+ result = await client.listPrompts(message.params);
137
+ }
138
+ else if (message.method === 'prompts/get') {
139
+ result = await client.getPrompt(message.params);
140
+ }
141
+ else {
142
+ // Unknown method - return error
143
+ const errorResponse = {
144
+ jsonrpc: '2.0',
145
+ id: message.id,
146
+ error: { code: -32601, message: `Method not found: ${message.method}` }
147
+ };
148
+ process.stdout.write(JSON.stringify(errorResponse) + '\n');
149
+ continue;
150
+ }
151
+ const response = { jsonrpc: '2.0', id: message.id, result };
152
+ process.stdout.write(JSON.stringify(response) + '\n');
153
+ }
154
+ catch (error) {
155
+ const errorResponse = {
156
+ jsonrpc: '2.0',
157
+ error: { code: -32603, message: error.message || 'Internal error' },
158
+ id: null
159
+ };
160
+ process.stdout.write(JSON.stringify(errorResponse) + '\n');
161
+ }
162
+ }
163
+ });
164
+ }
165
+ const port = parseInt(process.env.BACKLOG_VIEWER_PORT || '3030');
166
+ runBridge(port).catch((error) => {
167
+ console.error('Bridge error:', error);
168
+ process.exit(1);
169
+ });
170
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/cli/bridge.ts"],"names":[],"mappings":"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"}
package/dist/cli.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ try {
3
+ await import('dotenv/config');
4
+ }
5
+ catch { }
6
+ const args = process.argv.slice(2);
7
+ const command = args[0];
8
+ if (command === 'serve') {
9
+ // HTTP server mode
10
+ const { startHttpServer } = await import('./http-server.js');
11
+ const port = parseInt(process.env.BACKLOG_VIEWER_PORT || '3030');
12
+ await startHttpServer(port);
13
+ }
14
+ else if (command === '--help' || command === '-h') {
15
+ console.log(`
16
+ backlog-mcp - Task management MCP server
17
+
18
+ Usage:
19
+ backlog-mcp Run as stdio MCP server (auto-bridges to HTTP server)
20
+ backlog-mcp serve Run as HTTP MCP server with viewer
21
+ backlog-mcp --help Show this help
22
+
23
+ Environment variables:
24
+ BACKLOG_DATA_DIR Data directory path (default: ./data)
25
+ BACKLOG_VIEWER_PORT HTTP server port (default: 3030)
26
+
27
+ How it works:
28
+ - Default mode auto-spawns HTTP server and bridges stdio to it
29
+ - HTTP server persists across sessions (shared by multiple clients)
30
+ - Automatic version upgrades on server restart
31
+ `);
32
+ process.exit(0);
33
+ }
34
+ else {
35
+ // Default: bridge mode (auto-spawn HTTP server)
36
+ await import('./cli/bridge.js');
37
+ }
38
+ export {};
39
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,IAAI,CAAC;IAAC,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;AAAC,CAAC;AAAC,MAAM,CAAC,CAAA,CAAC;AAE/C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAExB,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;IACxB,mBAAmB;IACnB,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,MAAM,CAAC,CAAC;IACjE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;KAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;GAgBX,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;KAAM,CAAC;IACN,gDAAgD;IAChD,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function startHttpServer(port?: number): Promise<void>;
@@ -0,0 +1,380 @@
1
+ #!/usr/bin/env node
2
+ try {
3
+ await import('dotenv/config');
4
+ }
5
+ catch { }
6
+ import { createServer, IncomingMessage, ServerResponse } from 'node:http';
7
+ import { readFileSync, existsSync } from 'node:fs';
8
+ import { join, dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
12
+ import { z } from 'zod';
13
+ import { nextTaskId } from './schema.js';
14
+ import { createTask, STATUSES, TASK_TYPES } from './schema.js';
15
+ import { storage } from './backlog.js';
16
+ import { writeResource } from './resources/index.js';
17
+ import { readMcpResource } from './resource-reader.js';
18
+ import { resolveMcpUri, filePathToMcpUri } from './uri-resolver.js';
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
21
+ // Session management
22
+ const sessions = new Map();
23
+ function createMcpServer() {
24
+ const server = new McpServer({
25
+ name: 'backlog-mcp',
26
+ version: pkg.version,
27
+ });
28
+ // Register tools
29
+ server.registerTool('backlog_list', {
30
+ description: 'List tasks from backlog. Returns most recently updated items first. Default: shows only active work (open/in_progress/blocked), limited to 20 items. Use counts=true to check if more items exist beyond the limit.',
31
+ inputSchema: z.object({
32
+ status: z.array(z.enum(STATUSES)).optional().describe('Filter by status. Options: open, in_progress, blocked, done, cancelled. Default: [open, in_progress, blocked]. Pass ["done"] to see completed work.'),
33
+ type: z.enum(TASK_TYPES).optional().describe('Filter by type. Options: task, epic. Default: returns both. Use type="epic" to list only epics.'),
34
+ epic_id: z.string().optional().describe('Filter tasks belonging to a specific epic. Example: epic_id="EPIC-0001"'),
35
+ counts: z.boolean().optional().describe('Include global counts { total_tasks, total_epics, by_status } alongside results. Use this to detect if more items exist beyond the limit. Default: false'),
36
+ limit: z.number().optional().describe('Max items to return. Default: 20. Increase if you need to see more items (e.g., limit=100 to list all epics).'),
37
+ }),
38
+ }, async ({ status, type, epic_id, counts, limit }) => {
39
+ const tasks = storage.list({ status, type, epic_id, limit });
40
+ const list = tasks.map((t) => ({ id: t.id, title: t.title, status: t.status, type: t.type ?? 'task', epic_id: t.epic_id }));
41
+ const result = { tasks: list };
42
+ if (counts)
43
+ result.counts = storage.counts();
44
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
45
+ });
46
+ server.registerTool('backlog_get', {
47
+ description: 'Get full task details by ID. Works for any task regardless of status.',
48
+ inputSchema: z.object({
49
+ id: z.union([z.string(), z.array(z.string())]).describe('Task ID like TASK-0001, or array for batch fetch'),
50
+ }),
51
+ }, async ({ id }) => {
52
+ const taskIds = Array.isArray(id) ? id : [id];
53
+ if (taskIds.length === 0) {
54
+ return { content: [{ type: 'text', text: 'Required: id' }], isError: true };
55
+ }
56
+ const results = taskIds.map((tid) => storage.getMarkdown(tid) || `Not found: ${tid}`);
57
+ return { content: [{ type: 'text', text: results.join('\n\n---\n\n') }] };
58
+ });
59
+ server.registerTool('backlog_create', {
60
+ description: 'Create a new task in the backlog.',
61
+ inputSchema: z.object({
62
+ title: z.string().describe('Task title'),
63
+ description: z.string().optional().describe('Task description in markdown'),
64
+ type: z.enum(TASK_TYPES).optional().describe('Type: task (default) or epic'),
65
+ epic_id: z.string().optional().describe('Parent epic ID to link this task to'),
66
+ references: z.array(z.object({ url: z.string(), title: z.string().optional() })).optional().describe('Reference links with optional titles'),
67
+ }),
68
+ }, async ({ title, description, type, epic_id, references }) => {
69
+ const id = nextTaskId(storage.getMaxId(type), type);
70
+ const task = createTask({ id, title, description, type, epic_id, references });
71
+ storage.add(task);
72
+ return { content: [{ type: 'text', text: `Created ${task.id}` }] };
73
+ });
74
+ server.registerTool('backlog_update', {
75
+ description: 'Update an existing task.',
76
+ inputSchema: z.object({
77
+ id: z.string().describe('Task ID to update'),
78
+ title: z.string().optional().describe('New title'),
79
+ description: z.string().optional().describe('New description'),
80
+ status: z.enum(STATUSES).optional().describe('New status'),
81
+ epic_id: z.union([z.string(), z.null()]).optional().describe('Parent epic ID (null to unlink)'),
82
+ blocked_reason: z.array(z.string()).optional().describe('Reason if status is blocked'),
83
+ evidence: z.array(z.string()).optional().describe('Proof of completion when marking done - links to PRs, docs, or notes'),
84
+ references: z.array(z.object({ url: z.string(), title: z.string().optional() })).optional().describe('Reference links with optional titles'),
85
+ }),
86
+ }, async ({ id, ...updates }) => {
87
+ const task = storage.get(id);
88
+ if (!task)
89
+ return { content: [{ type: 'text', text: `Task ${id} not found` }], isError: true };
90
+ Object.assign(task, updates, { updated_at: new Date().toISOString() });
91
+ storage.save(task);
92
+ return { content: [{ type: 'text', text: `Updated ${id}` }] };
93
+ });
94
+ server.registerTool('backlog_delete', {
95
+ description: 'Permanently delete a task from the backlog.',
96
+ inputSchema: z.object({
97
+ id: z.string().describe('Task ID to delete'),
98
+ }),
99
+ }, async ({ id }) => {
100
+ storage.delete(id);
101
+ return { content: [{ type: 'text', text: `Task ${id} deleted` }] };
102
+ });
103
+ // Register resources
104
+ server.registerResource('Task File', 'mcp://backlog/tasks/{taskId}/file', { mimeType: 'text/markdown', description: 'Task markdown file' }, async (uri) => {
105
+ const { content, mimeType } = readMcpResource(uri.toString());
106
+ return { contents: [{ uri: uri.toString(), mimeType, text: content }] };
107
+ });
108
+ server.registerResource('Task-Attached Resource', 'mcp://backlog/resources/{taskId}/{filename}', { description: 'Task-attached resources (ADRs, design docs, etc.)' }, async (uri) => {
109
+ const { content, mimeType } = readMcpResource(uri.toString());
110
+ return { contents: [{ uri: uri.toString(), mimeType, text: content }] };
111
+ });
112
+ server.registerResource('Repository Resource', 'mcp://backlog/resources/{path}', { description: 'Repository files (ADRs, source code, etc.)' }, async (uri) => {
113
+ const { content, mimeType } = readMcpResource(uri.toString());
114
+ return { contents: [{ uri: uri.toString(), mimeType, text: content }] };
115
+ });
116
+ return server;
117
+ }
118
+ export async function startHttpServer(port = 3030) {
119
+ const dataDir = process.env.BACKLOG_DATA_DIR ?? 'data';
120
+ storage.init(dataDir);
121
+ const httpServer = createServer(async (req, res) => {
122
+ res.setHeader('Access-Control-Allow-Origin', '*');
123
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
124
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
125
+ if (req.method === 'OPTIONS') {
126
+ res.writeHead(204);
127
+ res.end();
128
+ return;
129
+ }
130
+ // Version endpoint
131
+ if (req.url === '/version' && req.method === 'GET') {
132
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
133
+ res.end(pkg.version);
134
+ return;
135
+ }
136
+ // Shutdown endpoint
137
+ if (req.url === '/shutdown' && req.method === 'POST') {
138
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
139
+ res.end('Shutting down...');
140
+ httpServer.close(() => {
141
+ setTimeout(() => process.exit(0), 500);
142
+ });
143
+ return;
144
+ }
145
+ // MCP SSE endpoint
146
+ if (req.url === '/mcp' && req.method === 'GET') {
147
+ const transport = new SSEServerTransport('/mcp/message', res);
148
+ const mcpServer = createMcpServer();
149
+ sessions.set(transport.sessionId, transport);
150
+ transport.onclose = () => {
151
+ sessions.delete(transport.sessionId);
152
+ };
153
+ // Note: connect() calls transport.start() automatically
154
+ await mcpServer.connect(transport);
155
+ return;
156
+ }
157
+ // MCP message endpoint (POST)
158
+ if (req.url?.startsWith('/mcp/message') && req.method === 'POST') {
159
+ const sessionId = new URL(req.url, `http://${req.headers.host}`).searchParams.get('sessionId');
160
+ if (!sessionId) {
161
+ res.writeHead(400, { 'Content-Type': 'text/plain' });
162
+ res.end('Missing sessionId');
163
+ return;
164
+ }
165
+ const transport = sessions.get(sessionId);
166
+ if (!transport) {
167
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
168
+ res.end('Session not found');
169
+ return;
170
+ }
171
+ const MAX_BODY_SIZE = 10 * 1024 * 1024; // 10MB
172
+ let body = '';
173
+ let size = 0;
174
+ req.on('data', chunk => {
175
+ size += chunk.length;
176
+ if (size > MAX_BODY_SIZE) {
177
+ req.destroy();
178
+ res.writeHead(413, { 'Content-Type': 'text/plain' });
179
+ res.end('Payload too large');
180
+ return;
181
+ }
182
+ body += chunk;
183
+ });
184
+ req.on('end', async () => {
185
+ try {
186
+ const message = JSON.parse(body);
187
+ await transport.handlePostMessage(req, res, message);
188
+ }
189
+ catch (error) {
190
+ res.writeHead(400, { 'Content-Type': 'text/plain' });
191
+ res.end('Invalid JSON');
192
+ }
193
+ });
194
+ return;
195
+ }
196
+ // Viewer endpoints
197
+ if (req.url === '/' || req.url === '/index.html' || req.url?.startsWith('/?')) {
198
+ const htmlPath = join(__dirname, '..', 'viewer', 'index.html');
199
+ res.writeHead(200, { 'Content-Type': 'text/html' });
200
+ res.end(readFileSync(htmlPath));
201
+ return;
202
+ }
203
+ // Static files - pattern-based serving for viewer assets
204
+ // Safe extensions: js, css, svg, png, ico (does NOT serve .ts, .json, .md)
205
+ const projectRoot = join(__dirname, '..');
206
+ if (req.url?.match(/\.(js|css|svg|png|ico)$/)) {
207
+ const urlPath = req.url.split('?')[0] || '';
208
+ let filePath = join(projectRoot, 'dist', 'viewer', urlPath);
209
+ if (!existsSync(filePath)) {
210
+ filePath = join(projectRoot, 'viewer', urlPath);
211
+ }
212
+ if (existsSync(filePath)) {
213
+ const ext = urlPath.split('.').pop() || 'txt';
214
+ const contentTypeMap = {
215
+ js: 'application/javascript',
216
+ css: 'text/css',
217
+ svg: 'image/svg+xml',
218
+ png: 'image/png',
219
+ ico: 'image/x-icon',
220
+ };
221
+ res.writeHead(200, { 'Content-Type': contentTypeMap[ext] || 'text/plain' });
222
+ res.end(readFileSync(filePath));
223
+ return;
224
+ }
225
+ }
226
+ // Task API
227
+ if (req.url?.startsWith('/tasks')) {
228
+ const url = new URL(req.url, `http://${req.headers.host}`);
229
+ const pathParts = url.pathname.split('/').filter(Boolean);
230
+ if (pathParts.length === 1) {
231
+ const filter = url.searchParams.get('filter') || 'active';
232
+ const limit = parseInt(url.searchParams.get('limit') || '100');
233
+ const status = filter === 'active' ? ['open', 'in_progress', 'blocked'] :
234
+ filter === 'done' ? ['done'] :
235
+ filter === 'all' ? undefined : undefined;
236
+ const tasks = storage.list({ status: status, limit });
237
+ res.writeHead(200, { 'Content-Type': 'application/json' });
238
+ res.end(JSON.stringify(tasks));
239
+ return;
240
+ }
241
+ if (pathParts.length === 2 && pathParts[1]) {
242
+ const taskId = pathParts[1];
243
+ const task = storage.get(taskId);
244
+ if (task) {
245
+ res.writeHead(200, { 'Content-Type': 'application/json' });
246
+ res.end(JSON.stringify(task));
247
+ }
248
+ else {
249
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
250
+ res.end('Task not found');
251
+ }
252
+ return;
253
+ }
254
+ }
255
+ // GET /open/:id - open file in default editor
256
+ const openMatch = req.url?.match(/^\/open\/([^/]+)$/);
257
+ if (openMatch && openMatch[1]) {
258
+ const taskId = openMatch[1];
259
+ const filePath = storage.getFilePath(taskId);
260
+ if (!filePath) {
261
+ res.writeHead(404);
262
+ res.end('Task not found');
263
+ return;
264
+ }
265
+ const { exec } = await import('node:child_process');
266
+ exec(`open "${filePath}"`);
267
+ res.writeHead(200);
268
+ res.end('Opening...');
269
+ return;
270
+ }
271
+ // GET /resource?path=... - read file content for in-browser viewing
272
+ if (req.url?.startsWith('/resource?')) {
273
+ const url = new URL(req.url, `http://${req.headers.host}`);
274
+ const filePath = url.searchParams.get('path');
275
+ if (!filePath) {
276
+ res.writeHead(400, { 'Content-Type': 'application/json' });
277
+ res.end(JSON.stringify({ error: 'Missing path parameter' }));
278
+ return;
279
+ }
280
+ if (!existsSync(filePath)) {
281
+ res.writeHead(404, { 'Content-Type': 'application/json' });
282
+ res.end(JSON.stringify({ error: 'File not found', path: filePath }));
283
+ return;
284
+ }
285
+ try {
286
+ const content = readFileSync(filePath, 'utf-8');
287
+ const ext = filePath.split('.').pop()?.toLowerCase() || 'txt';
288
+ const mimeMap = {
289
+ md: 'text/markdown',
290
+ ts: 'text/typescript',
291
+ js: 'text/javascript',
292
+ json: 'application/json',
293
+ txt: 'text/plain',
294
+ };
295
+ let frontmatter = {};
296
+ let bodyContent = content;
297
+ // Parse frontmatter for markdown files
298
+ if (ext === 'md') {
299
+ const matter = await import('gray-matter');
300
+ const parsed = matter.default(content);
301
+ frontmatter = parsed.data;
302
+ bodyContent = parsed.content;
303
+ }
304
+ res.writeHead(200, { 'Content-Type': 'application/json' });
305
+ res.end(JSON.stringify({
306
+ content: bodyContent,
307
+ frontmatter,
308
+ type: mimeMap[ext] || 'text/plain',
309
+ path: filePath,
310
+ fileUri: `file://${filePath}`,
311
+ mcpUri: filePathToMcpUri(filePath),
312
+ ext
313
+ }));
314
+ }
315
+ catch (error) {
316
+ res.writeHead(500, { 'Content-Type': 'application/json' });
317
+ res.end(JSON.stringify({ error: 'Failed to read file', message: error.message }));
318
+ }
319
+ return;
320
+ }
321
+ // GET /mcp/resource?uri=mcp://backlog/... - MCP resource proxy
322
+ if (req.url?.startsWith('/mcp/resource?')) {
323
+ const url = new URL(req.url, `http://${req.headers.host}`);
324
+ const uri = url.searchParams.get('uri');
325
+ if (!uri || !uri.startsWith('mcp://backlog/')) {
326
+ res.writeHead(400, { 'Content-Type': 'application/json' });
327
+ res.end(JSON.stringify({ error: 'Invalid MCP URI' }));
328
+ return;
329
+ }
330
+ try {
331
+ const { content, frontmatter, mimeType } = readMcpResource(uri);
332
+ const filePath = resolveMcpUri(uri);
333
+ const ext = filePath.split('.').pop()?.toLowerCase() || 'txt';
334
+ res.writeHead(200, { 'Content-Type': 'application/json' });
335
+ res.end(JSON.stringify({
336
+ content,
337
+ frontmatter: frontmatter || {},
338
+ type: mimeType,
339
+ path: filePath,
340
+ fileUri: `file://${filePath}`,
341
+ mcpUri: uri,
342
+ ext
343
+ }));
344
+ }
345
+ catch (error) {
346
+ res.writeHead(404, { 'Content-Type': 'application/json' });
347
+ res.end(JSON.stringify({
348
+ error: 'Resource not found',
349
+ uri,
350
+ message: error.message
351
+ }));
352
+ }
353
+ return;
354
+ }
355
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
356
+ res.end('Not found');
357
+ });
358
+ httpServer.listen(port, () => {
359
+ console.error(`Backlog MCP HTTP server running on http://localhost:${port}`);
360
+ console.error(`- Viewer: http://localhost:${port}/`);
361
+ console.error(`- MCP endpoint: http://localhost:${port}/mcp`);
362
+ console.error(`- Version: ${pkg.version}`);
363
+ });
364
+ // Graceful shutdown on SIGTERM/SIGINT
365
+ const shutdown = () => {
366
+ console.error('Shutting down gracefully...');
367
+ httpServer.close(() => {
368
+ console.error('Server closed');
369
+ process.exit(0);
370
+ });
371
+ };
372
+ process.on('SIGTERM', shutdown);
373
+ process.on('SIGINT', shutdown);
374
+ }
375
+ // CLI entry point
376
+ if (import.meta.url === `file://${process.argv[1]}`) {
377
+ const port = parseInt(process.env.BACKLOG_VIEWER_PORT || '3030');
378
+ startHttpServer(port);
379
+ }
380
+ //# sourceMappingURL=http-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { isValidTaskId, parseTaskId, formatTaskId, nextTaskId, STATUSES, type Status, type Task, type CreateTaskInput, createTask, } from './schema.js';
2
2
  export { storage } from './backlog.js';
3
- export { startViewer } from './viewer.js';
3
+ export { startHttpServer } from './http-server.js';
package/dist/index.js CHANGED
@@ -2,6 +2,6 @@
2
2
  export { isValidTaskId, parseTaskId, formatTaskId, nextTaskId, STATUSES, createTask, } from './schema.js';
3
3
  // Storage
4
4
  export { storage } from './backlog.js';
5
- // Viewer
6
- export { startViewer } from './viewer.js';
5
+ // HTTP Server
6
+ export { startHttpServer } from './http-server.js';
7
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,EACV,QAAQ,EAIR,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,EACV,QAAQ,EAIR,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,cAAc;AACd,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -28,6 +28,19 @@ export function resolveMcpUri(uri) {
28
28
  return join(dataDir, 'tasks', `${match[1]}.md`);
29
29
  }
30
30
  }
31
+ // Special case: resources/{TASK-XXXX} or resources/{EPIC-XXXX} -> task-attached resources
32
+ if (path.startsWith('resources/')) {
33
+ const match = path.match(/^resources\/(TASK-\d+|EPIC-\d+)\//);
34
+ if (match) {
35
+ // Task-attached resource: dataDir/resources/{taskId}/{file}
36
+ return join(dataDir, path);
37
+ }
38
+ else {
39
+ // Repository resource: repoRoot/{path after resources/}
40
+ const repoPath = path.substring('resources/'.length);
41
+ return join(getRepoRoot(), repoPath);
42
+ }
43
+ }
31
44
  // Everything else: direct mapping to dataDir/{path}
32
45
  return join(dataDir, path);
33
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"uri-resolver.js","sourceRoot":"","sources":["../src/uri-resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"uri-resolver.js","sourceRoot":"","sources":["../src/uri-resolver.ts"],"names":[],"mappings":"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"}
@@ -2576,10 +2576,11 @@ var TaskList = class extends HTMLElement {
2576
2576
  return;
2577
2577
  }
2578
2578
  const epics = tasks.filter((t) => (t.type ?? "task") === "epic");
2579
+ const rootEpics = epics.filter((e) => !e.epic_id);
2579
2580
  const childTasks = tasks.filter((t) => t.epic_id && epics.some((e) => e.id === t.epic_id));
2580
2581
  const orphanTasks = tasks.filter((t) => (t.type ?? "task") === "task" && !childTasks.includes(t));
2581
2582
  const grouped = [];
2582
- for (const epic of epics) {
2583
+ for (const epic of rootEpics) {
2583
2584
  const children = childTasks.filter((t) => t.epic_id === epic.id);
2584
2585
  const isCollapsed = this.collapsedEpics.has(epic.id);
2585
2586
  grouped.push({ ...epic, childCount: children.length });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backlog-mcp",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "Minimal task backlog MCP server for Claude and AI agents",
5
5
  "keywords": [
6
6
  "mcp",
@@ -21,7 +21,7 @@
21
21
  "main": "dist/index.js",
22
22
  "types": "dist/index.d.ts",
23
23
  "bin": {
24
- "backlog-mcp": "./dist/server.js"
24
+ "backlog-mcp": "./dist/cli.js"
25
25
  },
26
26
  "exports": {
27
27
  ".": {
@@ -41,11 +41,11 @@
41
41
  "scripts": {
42
42
  "build": "tsc && esbuild viewer/main.ts --bundle --format=esm --outdir=dist/viewer --loader:.svg=text",
43
43
  "clean": "rm -rf dist",
44
- "start": "node dist/server.js",
45
- "inspect": "pnpm build && npx @modelcontextprotocol/inspector dist/server.js",
44
+ "start": "node dist/cli.js",
45
+ "inspect": "pnpm build && npx @modelcontextprotocol/inspector dist/cli.js",
46
46
  "test": "vitest run",
47
47
  "test:watch": "vitest",
48
- "dev": "pnpm build && concurrently \"tsx watch src/server.ts\" \"esbuild viewer/main.ts --bundle --format=esm --outdir=dist/viewer --watch --loader:.svg=text\"",
48
+ "dev": "pnpm build && concurrently \"tsx watch src/http-server.ts\" \"esbuild viewer/main.ts --bundle --format=esm --outdir=dist/viewer --watch --loader:.svg=text\"",
49
49
  "test:integration": "pnpm build && kiro-cli chat --agent mcp-resource-validator --trust-all-tools --no-interactive 'Execute the complete validation test plan'",
50
50
  "test:integration:resources": "pnpm build && kiro-cli chat --agent mcp-resource-validator --trust-all-tools --no-interactive 'Skip steps 1-7. Only test task-attached resources (step 8): First create a test task, then create ADR, modify it, create multiple resources, link to task, verify lifecycle management.'"
51
51
  },
package/dist/server.js DELETED
@@ -1,190 +0,0 @@
1
- #!/usr/bin/env node
2
- try {
3
- await import('dotenv/config');
4
- }
5
- catch { }
6
- import { readFileSync } from 'node:fs';
7
- import { dirname, join } from 'node:path';
8
- import { fileURLToPath } from 'node:url';
9
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
- import { z } from 'zod';
12
- import { nextTaskId } from './schema.js';
13
- import { createTask, STATUSES, TASK_TYPES } from './schema.js';
14
- import { storage } from './backlog.js';
15
- import { startViewer } from './viewer.js';
16
- import { writeResource } from './resources/index.js';
17
- import { readMcpResource } from './resource-reader.js';
18
- import { resolveMcpUri } from './uri-resolver.js';
19
- // Read version from package.json
20
- const __dirname = dirname(fileURLToPath(import.meta.url));
21
- const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
22
- // Init storage
23
- const dataDir = process.env.BACKLOG_DATA_DIR ?? 'data';
24
- storage.init(dataDir);
25
- const server = new McpServer({
26
- name: 'backlog-mcp',
27
- version: pkg.version,
28
- });
29
- // ============================================================================
30
- // Tools
31
- // ============================================================================
32
- server.registerTool('backlog_list', {
33
- description: 'List tasks from backlog. Returns most recently updated items first. Default: shows only active work (open/in_progress/blocked), limited to 20 items. Use counts=true to check if more items exist beyond the limit.',
34
- inputSchema: z.object({
35
- status: z.array(z.enum(STATUSES)).optional().describe('Filter by status. Options: open, in_progress, blocked, done, cancelled. Default: [open, in_progress, blocked]. Pass ["done"] to see completed work.'),
36
- type: z.enum(TASK_TYPES).optional().describe('Filter by type. Options: task, epic. Default: returns both. Use type="epic" to list only epics.'),
37
- epic_id: z.string().optional().describe('Filter tasks belonging to a specific epic. Example: epic_id="EPIC-0001"'),
38
- counts: z.boolean().optional().describe('Include global counts { total_tasks, total_epics, by_status } alongside results. Use this to detect if more items exist beyond the limit. Default: false'),
39
- limit: z.number().optional().describe('Max items to return. Default: 20. Increase if you need to see more items (e.g., limit=100 to list all epics).'),
40
- }),
41
- }, async ({ status, type, epic_id, counts, limit }) => {
42
- const tasks = storage.list({ status, type, epic_id, limit });
43
- const list = tasks.map((t) => ({ id: t.id, title: t.title, status: t.status, type: t.type ?? 'task', epic_id: t.epic_id }));
44
- const result = { tasks: list };
45
- if (counts) {
46
- result.counts = storage.counts();
47
- }
48
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
49
- });
50
- server.registerTool('backlog_get', {
51
- description: 'Get full task details by ID. Works for any task regardless of status.',
52
- inputSchema: z.object({
53
- id: z.union([z.string(), z.array(z.string())]).describe('Task ID like TASK-0001, or array for batch fetch'),
54
- }),
55
- }, async ({ id }) => {
56
- const taskIds = Array.isArray(id) ? id : [id];
57
- if (taskIds.length === 0) {
58
- return { content: [{ type: 'text', text: 'Required: id' }], isError: true };
59
- }
60
- const results = taskIds.map((tid) => storage.getMarkdown(tid) || `Not found: ${tid}`);
61
- return { content: [{ type: 'text', text: results.join('\n\n---\n\n') }] };
62
- });
63
- server.registerTool('backlog_create', {
64
- description: 'Create a new task in the backlog.',
65
- inputSchema: z.object({
66
- title: z.string().describe('Task title'),
67
- description: z.string().optional().describe('Task description in markdown'),
68
- type: z.enum(TASK_TYPES).optional().describe('Type: task (default) or epic'),
69
- epic_id: z.string().optional().describe('Parent epic ID to link this task to'),
70
- references: z.array(z.object({ url: z.string(), title: z.string().optional() })).optional().describe('Reference links with optional titles'),
71
- }),
72
- }, async ({ title, description, type, epic_id, references }) => {
73
- const id = nextTaskId(storage.getMaxId(type), type);
74
- const task = createTask({ id, title, description, type, epic_id, references });
75
- storage.add(task);
76
- return { content: [{ type: 'text', text: `Created ${task.id}` }] };
77
- });
78
- server.registerTool('backlog_update', {
79
- description: 'Update an existing task.',
80
- inputSchema: z.object({
81
- id: z.string().describe('Task ID to update'),
82
- title: z.string().optional().describe('New title'),
83
- description: z.string().optional().describe('New description'),
84
- status: z.enum(STATUSES).optional().describe('New status'),
85
- epic_id: z.string().nullable().optional().describe('Parent epic ID (null to unlink)'),
86
- references: z.array(z.object({ url: z.string(), title: z.string().optional() })).optional().describe('Reference links with optional titles'),
87
- blocked_reason: z.array(z.string()).optional().describe('Reason if status is blocked'),
88
- evidence: z.array(z.string()).optional().describe('Proof of completion when marking done - links to PRs, docs, or notes'),
89
- }),
90
- }, async ({ id, title, description, status, epic_id, references, blocked_reason, evidence }) => {
91
- const task = storage.get(id);
92
- if (!task) {
93
- return { content: [{ type: 'text', text: `Not found: ${id}` }], isError: true };
94
- }
95
- const updates = {};
96
- if (title !== undefined)
97
- updates.title = title;
98
- if (description !== undefined)
99
- updates.description = description;
100
- if (status !== undefined)
101
- updates.status = status;
102
- if (epic_id !== undefined)
103
- updates.epic_id = epic_id ?? undefined;
104
- if (references !== undefined)
105
- updates.references = references;
106
- if (blocked_reason !== undefined)
107
- updates.blocked_reason = blocked_reason;
108
- if (evidence !== undefined)
109
- updates.evidence = evidence;
110
- const updated = { ...task, ...updates, updated_at: new Date().toISOString() };
111
- storage.save(updated);
112
- return { content: [{ type: 'text', text: `Updated ${id}` }] };
113
- });
114
- server.registerTool('backlog_delete', {
115
- description: 'Permanently delete a task from the backlog.',
116
- inputSchema: z.object({
117
- id: z.string().describe('Task ID to delete'),
118
- }),
119
- }, async ({ id }) => {
120
- const deleted = storage.delete(id);
121
- if (!deleted) {
122
- return { content: [{ type: 'text', text: `Not found: ${id}` }], isError: true };
123
- }
124
- return { content: [{ type: 'text', text: `Deleted ${id}` }] };
125
- });
126
- server.registerTool('write_resource', {
127
- description: 'Write to MCP resources using fs_write-style operations. Similar to @builtin/fs_write but for mcp:// URIs.',
128
- inputSchema: z.object({
129
- uri: z.string().describe('Resource URI (e.g., mcp://backlog/tasks/TASK-0039/description)'),
130
- command: z.enum(['strReplace', 'insert']).describe('Operation: strReplace or insert'),
131
- oldStr: z.string().optional().describe('For strReplace: string to find'),
132
- newStr: z.string().optional().describe('For strReplace: replacement string'),
133
- content: z.string().optional().describe('For insert: content to add'),
134
- insertLine: z.number().optional().describe('For insert: line number (0-based). Omit to append.'),
135
- }),
136
- }, async ({ uri, command, oldStr, newStr, content, insertLine }) => {
137
- try {
138
- let operation;
139
- if (command === 'strReplace') {
140
- operation = { type: 'str_replace', old_str: oldStr, new_str: newStr };
141
- }
142
- else if (insertLine !== undefined) {
143
- operation = { type: 'insert', line: insertLine, content: content || newStr || '' };
144
- }
145
- else {
146
- operation = { type: 'append', content: content || newStr || '' };
147
- }
148
- const result = writeResource({ uri, operation }, (taskId) => storage.getFilePath(taskId), (uri) => resolveMcpUri(uri));
149
- if (!result.success) {
150
- return {
151
- content: [{ type: 'text', text: `${result.message}\n${result.error || ''}` }],
152
- isError: true
153
- };
154
- }
155
- return { content: [{ type: 'text', text: result.message }] };
156
- }
157
- catch (error) {
158
- return {
159
- content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
160
- isError: true
161
- };
162
- }
163
- });
164
- // ============================================================================
165
- // Resources
166
- // ============================================================================
167
- // Register resource templates for dynamic task resources
168
- server.registerResource('Task File', 'mcp://backlog/tasks/{taskId}/file', { mimeType: 'text/markdown', description: 'Task markdown file' }, async (uri) => {
169
- const { content, mimeType } = readMcpResource(uri.toString());
170
- return { contents: [{ uri: uri.toString(), mimeType, text: content }] };
171
- });
172
- server.registerResource('Task-Attached Resource', 'mcp://backlog/resources/{taskId}/{filename}', { description: 'Task-attached resources (ADRs, design docs, etc.)' }, async (uri) => {
173
- const { content, mimeType } = readMcpResource(uri.toString());
174
- return { contents: [{ uri: uri.toString(), mimeType, text: content }] };
175
- });
176
- server.registerResource('Repository Resource', 'mcp://backlog/resources/{path}', { description: 'Repository files (ADRs, source code, etc.)' }, async (uri) => {
177
- const { content, mimeType } = readMcpResource(uri.toString());
178
- return { contents: [{ uri: uri.toString(), mimeType, text: content }] };
179
- });
180
- // ============================================================================
181
- // Main
182
- // ============================================================================
183
- async function main() {
184
- const viewerPort = parseInt(process.env.BACKLOG_VIEWER_PORT || '3030');
185
- startViewer(viewerPort);
186
- const transport = new StdioServerTransport();
187
- await server.connect(transport);
188
- }
189
- main().catch(console.error);
190
- //# sourceMappingURL=server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/viewer.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function startViewer(port?: number): Promise<void>;
package/dist/viewer.js DELETED
@@ -1,205 +0,0 @@
1
- import { createServer } from 'node:http';
2
- import { readFileSync, existsSync } from 'node:fs';
3
- import { join, dirname } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { createConnection } from 'node:net';
6
- import { storage } from './backlog.js';
7
- import { resolveMcpUri, filePathToMcpUri } from './uri-resolver.js';
8
- import { readMcpResource } from './resource-reader.js';
9
- const __dirname = dirname(fileURLToPath(import.meta.url));
10
- function isPortInUse(port) {
11
- return new Promise((resolve) => {
12
- const client = createConnection({ port }, () => {
13
- client.end();
14
- resolve(true);
15
- });
16
- client.on('error', () => resolve(false));
17
- });
18
- }
19
- export async function startViewer(port = 3030) {
20
- if (await isPortInUse(port)) {
21
- console.error(`Backlog viewer already running on port ${port}`);
22
- return;
23
- }
24
- const server = createServer(async (req, res) => {
25
- // CORS
26
- res.setHeader('Access-Control-Allow-Origin', '*');
27
- // Serve index.html for root
28
- if (req.url === '/' || req.url === '/index.html' || req.url?.startsWith('/?')) {
29
- const htmlPath = join(__dirname, '..', 'viewer', 'index.html');
30
- res.writeHead(200, { 'Content-Type': 'text/html' });
31
- res.end(readFileSync(htmlPath));
32
- return;
33
- }
34
- // Serve static files
35
- const projectRoot = join(__dirname, '..');
36
- if (req.url?.match(/\.(js|css|svg|png|ico)$/)) {
37
- const urlPath = req.url.split('?')[0] || '';
38
- let filePath = join(projectRoot, 'dist', 'viewer', urlPath);
39
- if (!existsSync(filePath)) {
40
- filePath = join(projectRoot, 'viewer', urlPath);
41
- }
42
- if (existsSync(filePath)) {
43
- const ext = urlPath.split('.').pop() || 'txt';
44
- const contentType = {
45
- js: 'application/javascript',
46
- css: 'text/css',
47
- svg: 'image/svg+xml',
48
- png: 'image/png',
49
- ico: 'image/x-icon',
50
- };
51
- res.writeHead(200, { 'Content-Type': contentType[ext || 'txt'] || 'text/plain' });
52
- res.end(readFileSync(filePath));
53
- }
54
- else {
55
- res.writeHead(404, { 'Content-Type': 'text/plain' });
56
- res.end('File not found');
57
- }
58
- return;
59
- }
60
- // GET /tasks
61
- if (req.url === '/tasks' || req.url?.startsWith('/tasks?')) {
62
- const url = new URL(req.url || '/tasks', `http://localhost:${port}`);
63
- const filter = url.searchParams.get('filter') || 'active';
64
- const limit = parseInt(url.searchParams.get('limit') || '100');
65
- const statusMap = {
66
- active: ['open', 'in_progress', 'blocked'],
67
- completed: ['done', 'cancelled'],
68
- open: ['open'],
69
- in_progress: ['in_progress'],
70
- blocked: ['blocked'],
71
- done: ['done'],
72
- cancelled: ['cancelled'],
73
- };
74
- const statusFilter = filter === 'all' ? { limit } : { status: statusMap[filter], limit };
75
- const tasks = storage.list(statusFilter);
76
- res.writeHead(200, { 'Content-Type': 'application/json' });
77
- res.end(JSON.stringify(tasks));
78
- return;
79
- }
80
- // GET /tasks/:id
81
- const taskMatch = req.url?.match(/^\/tasks\/([^/]+)$/);
82
- if (taskMatch && taskMatch[1]) {
83
- const taskId = taskMatch[1];
84
- const task = storage.get(taskId);
85
- if (!task) {
86
- res.writeHead(404, { 'Content-Type': 'application/json' });
87
- res.end(JSON.stringify({ error: 'Task not found' }));
88
- return;
89
- }
90
- const filePath = storage.getFilePath(taskId);
91
- const raw = storage.getMarkdown(taskId);
92
- const epic = task.epic_id ? storage.get(task.epic_id) : null;
93
- const epicTitle = epic?.title;
94
- res.writeHead(200, { 'Content-Type': 'application/json' });
95
- res.end(JSON.stringify({ ...task, filePath, raw, epicTitle }));
96
- return;
97
- }
98
- // GET /open/:id - open file in default editor
99
- const openMatch = req.url?.match(/^\/open\/([^/]+)$/);
100
- if (openMatch && openMatch[1]) {
101
- const taskId = openMatch[1];
102
- const filePath = storage.getFilePath(taskId);
103
- if (!filePath) {
104
- res.writeHead(404);
105
- res.end('Task not found');
106
- return;
107
- }
108
- const { exec } = await import('node:child_process');
109
- exec(`open "${filePath}"`);
110
- res.writeHead(200);
111
- res.end('Opening...');
112
- return;
113
- }
114
- // GET /resource?path=... - read file content for in-browser viewing
115
- if (req.url?.startsWith('/resource?')) {
116
- const url = new URL(req.url, `http://localhost:${port}`);
117
- const filePath = url.searchParams.get('path');
118
- if (!filePath) {
119
- res.writeHead(400, { 'Content-Type': 'application/json' });
120
- res.end(JSON.stringify({ error: 'Missing path parameter' }));
121
- return;
122
- }
123
- if (!existsSync(filePath)) {
124
- res.writeHead(404, { 'Content-Type': 'application/json' });
125
- res.end(JSON.stringify({ error: 'File not found', path: filePath }));
126
- return;
127
- }
128
- try {
129
- const content = readFileSync(filePath, 'utf-8');
130
- const ext = filePath.split('.').pop()?.toLowerCase() || 'txt';
131
- const mimeMap = {
132
- md: 'text/markdown',
133
- ts: 'text/typescript',
134
- js: 'text/javascript',
135
- json: 'application/json',
136
- txt: 'text/plain',
137
- };
138
- let frontmatter = {};
139
- let bodyContent = content;
140
- // Parse frontmatter for markdown files
141
- if (ext === 'md') {
142
- const matter = await import('gray-matter');
143
- const parsed = matter.default(content);
144
- frontmatter = parsed.data;
145
- bodyContent = parsed.content;
146
- }
147
- res.writeHead(200, { 'Content-Type': 'application/json' });
148
- res.end(JSON.stringify({
149
- content: bodyContent,
150
- frontmatter,
151
- type: mimeMap[ext] || 'text/plain',
152
- path: filePath,
153
- fileUri: `file://${filePath}`,
154
- mcpUri: filePathToMcpUri(filePath),
155
- ext
156
- }));
157
- }
158
- catch (error) {
159
- res.writeHead(500, { 'Content-Type': 'application/json' });
160
- res.end(JSON.stringify({ error: 'Failed to read file', message: error.message }));
161
- }
162
- return;
163
- }
164
- // GET /mcp/resource?uri=mcp://backlog/... - MCP resource proxy
165
- if (req.url?.startsWith('/mcp/resource?')) {
166
- const url = new URL(req.url, `http://localhost:${port}`);
167
- const uri = url.searchParams.get('uri');
168
- if (!uri || !uri.startsWith('mcp://backlog/')) {
169
- res.writeHead(400, { 'Content-Type': 'application/json' });
170
- res.end(JSON.stringify({ error: 'Invalid MCP URI' }));
171
- return;
172
- }
173
- try {
174
- const { content, frontmatter, mimeType } = readMcpResource(uri);
175
- const filePath = resolveMcpUri(uri);
176
- const ext = filePath.split('.').pop()?.toLowerCase() || 'txt';
177
- res.writeHead(200, { 'Content-Type': 'application/json' });
178
- res.end(JSON.stringify({
179
- content,
180
- frontmatter: frontmatter || {},
181
- type: mimeType,
182
- path: filePath,
183
- fileUri: `file://${filePath}`,
184
- mcpUri: uri,
185
- ext
186
- }));
187
- }
188
- catch (error) {
189
- res.writeHead(404, { 'Content-Type': 'application/json' });
190
- res.end(JSON.stringify({
191
- error: 'Resource not found',
192
- uri,
193
- message: error.message
194
- }));
195
- }
196
- return;
197
- }
198
- res.writeHead(404);
199
- res.end('Not found');
200
- });
201
- server.listen(port, () => {
202
- console.error(`Backlog viewer: http://localhost:${port}`);
203
- });
204
- }
205
- //# sourceMappingURL=viewer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"viewer.js","sourceRoot":"","sources":["../src/viewer.ts"],"names":[],"mappings":"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"}
File without changes