backlog-mcp 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,22 +50,11 @@ npm install && npm run build
50
50
  npm start
51
51
  ```
52
52
 
53
- Claude Desktop config:
54
-
55
- ```json
56
- {
57
- "mcpServers": {
58
- "backlog": {
59
- "command": "node",
60
- "args": ["/path/to/backlog-mcp/dist/server.js"]
61
- }
62
- }
63
- }
64
- ```
65
-
66
53
  ## Storage
67
54
 
68
- Single file: `data/backlog.json` (atomic writes via temp + rename)
55
+ - Active tasks: `data/backlog.json`
56
+ - Completed/cancelled tasks: `data/archive.json` (auto-archived)
57
+ - Atomic writes via temp + rename
69
58
 
70
59
  ## License
71
60
 
package/package.json CHANGED
@@ -1,7 +1,22 @@
1
1
  {
2
2
  "name": "backlog-mcp",
3
- "version": "0.1.0",
4
- "description": "Minimal, boring, correct core for persistent backlog state",
3
+ "version": "0.1.2",
4
+ "description": "Minimal task backlog MCP server for Claude and AI agents",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "claude",
9
+ "anthropic",
10
+ "ai",
11
+ "llm",
12
+ "backlog",
13
+ "task-management",
14
+ "claude-code"
15
+ ],
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/gkoreli/backlog-mcp.git"
19
+ },
5
20
  "type": "module",
6
21
  "main": "dist/index.js",
7
22
  "types": "dist/index.d.ts",
@@ -1,32 +0,0 @@
1
- import type { Task, Status, Blocked, Dod, Evidence, ValidationError } from './schema.js';
2
- export declare const TERMINAL_STATUSES: readonly Status[];
3
- export interface TransitionToBlocked {
4
- to: 'blocked';
5
- blocked: Blocked;
6
- }
7
- export interface TransitionToVerifying {
8
- to: 'verifying';
9
- dod: Dod;
10
- evidence: Evidence;
11
- }
12
- export interface TransitionToDone {
13
- to: 'done';
14
- }
15
- export interface TransitionToInProgress {
16
- to: 'in_progress';
17
- }
18
- export interface TransitionToCancelled {
19
- to: 'cancelled';
20
- }
21
- export type TransitionInput = TransitionToBlocked | TransitionToVerifying | TransitionToDone | TransitionToInProgress | TransitionToCancelled;
22
- export type TransitionResult = {
23
- ok: true;
24
- task: Task;
25
- } | {
26
- ok: false;
27
- errors: ValidationError[];
28
- };
29
- export declare function canTransition(from: Status, to: Status): boolean;
30
- export declare function getAllowedTransitions(from: Status): readonly Status[];
31
- export declare function isTerminal(status: Status): boolean;
32
- export declare function transition(task: Task, input: TransitionInput): TransitionResult;
@@ -1,174 +0,0 @@
1
- // ============================================================================
2
- // Constants
3
- // ============================================================================
4
- export const TERMINAL_STATUSES = ['done', 'cancelled'];
5
- /**
6
- * State machine transitions:
7
- *
8
- * open ──────► in_progress ──────► verifying ──────► done
9
- * │ │ │
10
- * │ │ ├─► in_progress (rejected)
11
- * │ │ │
12
- * │ │ └─► cancelled
13
- * │ │
14
- * │ ├────────────────► blocked
15
- * │ │ │
16
- * │ │ ├─► in_progress
17
- * │ │ │
18
- * │ │ └─► cancelled
19
- * │ │
20
- * │ └────────────────► cancelled
21
- * │
22
- * └────────────────────────────────► cancelled
23
- */
24
- const ALLOWED_TRANSITIONS = {
25
- open: ['in_progress', 'cancelled'],
26
- in_progress: ['blocked', 'verifying', 'cancelled'],
27
- blocked: ['in_progress', 'cancelled'],
28
- verifying: ['done', 'in_progress', 'cancelled'],
29
- done: [],
30
- cancelled: [],
31
- };
32
- // ============================================================================
33
- // Helpers
34
- // ============================================================================
35
- function isNonEmptyString(value) {
36
- return typeof value === 'string' && value.trim().length > 0;
37
- }
38
- function isNonEmptyStringArray(value) {
39
- return Array.isArray(value) && value.length > 0 && value.every(isNonEmptyString);
40
- }
41
- // ============================================================================
42
- // Query Functions
43
- // ============================================================================
44
- export function canTransition(from, to) {
45
- return ALLOWED_TRANSITIONS[from].includes(to);
46
- }
47
- export function getAllowedTransitions(from) {
48
- return ALLOWED_TRANSITIONS[from];
49
- }
50
- export function isTerminal(status) {
51
- return TERMINAL_STATUSES.includes(status);
52
- }
53
- // ============================================================================
54
- // Transition Validators
55
- // ============================================================================
56
- function validateBlockedInput(input, errors) {
57
- if (!input.blocked || typeof input.blocked !== 'object') {
58
- errors.push({ field: 'blocked', message: 'required for transition to blocked' });
59
- return;
60
- }
61
- if (!isNonEmptyString(input.blocked.reason)) {
62
- errors.push({ field: 'blocked.reason', message: 'must be a non-empty string' });
63
- }
64
- if (input.blocked.dependency !== undefined && typeof input.blocked.dependency !== 'string') {
65
- errors.push({ field: 'blocked.dependency', message: 'must be a string if present' });
66
- }
67
- }
68
- function validateVerifyingInput(input, errors) {
69
- // Validate dod
70
- if (!input.dod || typeof input.dod !== 'object') {
71
- errors.push({ field: 'dod', message: 'required for transition to verifying' });
72
- }
73
- else if (!isNonEmptyStringArray(input.dod.checklist)) {
74
- errors.push({ field: 'dod.checklist', message: 'must be a non-empty array of non-empty strings' });
75
- }
76
- // Validate evidence
77
- if (!input.evidence || typeof input.evidence !== 'object') {
78
- errors.push({ field: 'evidence', message: 'required for transition to verifying' });
79
- return;
80
- }
81
- if (!isNonEmptyStringArray(input.evidence.artifacts)) {
82
- errors.push({ field: 'evidence.artifacts', message: 'must have at least 1 non-empty artifact' });
83
- }
84
- if (input.evidence.commands !== undefined) {
85
- if (!Array.isArray(input.evidence.commands)) {
86
- errors.push({ field: 'evidence.commands', message: 'must be an array if present' });
87
- }
88
- else if (!input.evidence.commands.every((c) => typeof c === 'string')) {
89
- errors.push({ field: 'evidence.commands', message: 'all items must be strings' });
90
- }
91
- }
92
- if (input.evidence.notes !== undefined && typeof input.evidence.notes !== 'string') {
93
- errors.push({ field: 'evidence.notes', message: 'must be a string if present' });
94
- }
95
- }
96
- function validateDoneTransition(task, errors) {
97
- // Structural verification: task must already have dod and evidence from verifying state
98
- if (!task.dod || !Array.isArray(task.dod.checklist) || task.dod.checklist.length === 0) {
99
- errors.push({ field: 'dod.checklist', message: 'must be non-empty to complete verification' });
100
- }
101
- if (!task.evidence || !Array.isArray(task.evidence.artifacts) || task.evidence.artifacts.length === 0) {
102
- errors.push({ field: 'evidence.artifacts', message: 'must have at least 1 artifact to complete verification' });
103
- }
104
- }
105
- // ============================================================================
106
- // Transition Function
107
- // ============================================================================
108
- export function transition(task, input) {
109
- const errors = [];
110
- const from = task.status;
111
- const to = input.to;
112
- // Check if transition is allowed by state machine
113
- if (!canTransition(from, to)) {
114
- const allowed = getAllowedTransitions(from);
115
- const allowedStr = allowed.length > 0 ? allowed.join(', ') : 'none (terminal state)';
116
- errors.push({
117
- field: 'status',
118
- message: `cannot transition from '${from}' to '${to}'. Allowed: ${allowedStr}`,
119
- });
120
- return { ok: false, errors };
121
- }
122
- // Validate transition-specific requirements
123
- switch (input.to) {
124
- case 'blocked':
125
- validateBlockedInput(input, errors);
126
- break;
127
- case 'verifying':
128
- validateVerifyingInput(input, errors);
129
- break;
130
- case 'done':
131
- validateDoneTransition(task, errors);
132
- break;
133
- }
134
- if (errors.length > 0) {
135
- return { ok: false, errors };
136
- }
137
- // Build the updated task
138
- const now = new Date().toISOString();
139
- const updatedTask = {
140
- ...task,
141
- status: to,
142
- updated_at: now,
143
- };
144
- // Apply transition-specific changes
145
- switch (input.to) {
146
- case 'blocked':
147
- updatedTask.blocked = input.blocked;
148
- break;
149
- case 'verifying':
150
- updatedTask.dod = input.dod;
151
- updatedTask.evidence = input.evidence;
152
- updatedTask.blocked = null;
153
- break;
154
- case 'done':
155
- // No changes needed - dod and evidence already set from verifying
156
- updatedTask.blocked = null;
157
- break;
158
- case 'in_progress':
159
- if (from === 'blocked') {
160
- // Clear blocked field when unblocking
161
- updatedTask.blocked = null;
162
- }
163
- else if (from === 'verifying') {
164
- // Rejection: clear evidence, keep dod for retry
165
- updatedTask.evidence = undefined;
166
- }
167
- break;
168
- case 'cancelled':
169
- updatedTask.blocked = null;
170
- break;
171
- }
172
- return { ok: true, task: updatedTask };
173
- }
174
- //# sourceMappingURL=transitions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transitions.js","sourceRoot":"","sources":["../src/transitions.ts"],"names":[],"mappings":"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"}