saga-mcp 1.0.1

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.
Files changed (44) hide show
  1. package/README.md +184 -0
  2. package/dist/db.d.ts +3 -0
  3. package/dist/db.js +25 -0
  4. package/dist/db.js.map +1 -0
  5. package/dist/helpers/activity-logger.d.ts +3 -0
  6. package/dist/helpers/activity-logger.js +15 -0
  7. package/dist/helpers/activity-logger.js.map +1 -0
  8. package/dist/helpers/sql-builder.d.ts +5 -0
  9. package/dist/helpers/sql-builder.js +24 -0
  10. package/dist/helpers/sql-builder.js.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.js +79 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/schema.d.ts +1 -0
  15. package/dist/schema.js +125 -0
  16. package/dist/schema.js.map +1 -0
  17. package/dist/tools/activity.d.ts +4 -0
  18. package/dist/tools/activity.js +125 -0
  19. package/dist/tools/activity.js.map +1 -0
  20. package/dist/tools/dashboard.d.ts +4 -0
  21. package/dist/tools/dashboard.js +145 -0
  22. package/dist/tools/dashboard.js.map +1 -0
  23. package/dist/tools/epics.d.ts +4 -0
  24. package/dist/tools/epics.js +124 -0
  25. package/dist/tools/epics.js.map +1 -0
  26. package/dist/tools/notes.d.ts +4 -0
  27. package/dist/tools/notes.js +169 -0
  28. package/dist/tools/notes.js.map +1 -0
  29. package/dist/tools/projects.d.ts +4 -0
  30. package/dist/tools/projects.js +112 -0
  31. package/dist/tools/projects.js.map +1 -0
  32. package/dist/tools/search.d.ts +4 -0
  33. package/dist/tools/search.js +61 -0
  34. package/dist/tools/search.js.map +1 -0
  35. package/dist/tools/subtasks.d.ts +4 -0
  36. package/dist/tools/subtasks.js +122 -0
  37. package/dist/tools/subtasks.js.map +1 -0
  38. package/dist/tools/tasks.d.ts +4 -0
  39. package/dist/tools/tasks.js +190 -0
  40. package/dist/tools/tasks.js.map +1 -0
  41. package/dist/types.d.ts +78 -0
  42. package/dist/types.js +2 -0
  43. package/dist/types.js.map +1 -0
  44. package/package.json +51 -0
package/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # saga-mcp
2
+
3
+ A Jira-like project tracker MCP server for AI agents. SQLite-backed, per-project scoped, with full hierarchy and activity logging — so LLMs never lose track.
4
+
5
+ **No more scattered markdown files.** saga-mcp gives your AI assistant a structured database to track projects, epics, tasks, subtasks, notes, and decisions across sessions.
6
+
7
+ ## Features
8
+
9
+ - **Full hierarchy**: Projects > Epics > Tasks > Subtasks
10
+ - **SQLite**: Self-contained `.tracker.db` file per project — zero setup, no external database
11
+ - **Activity log**: Every mutation is automatically tracked with old/new values
12
+ - **Dashboard**: One tool call gives full project overview (stats, blocked tasks, recent changes)
13
+ - **Notes system**: Decisions, context, meeting notes, blockers — all searchable
14
+ - **Batch operations**: Create multiple subtasks or update multiple tasks in one call
15
+ - **22 focused tools**: Reduced from typical 38+ by combining related operations
16
+
17
+ ## Quick Start
18
+
19
+ ### With Claude Code
20
+
21
+ Add to your project's `.mcp.json`:
22
+
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "saga": {
27
+ "command": "npx",
28
+ "args": ["-y", "saga-mcp"],
29
+ "env": {
30
+ "DB_PATH": "/absolute/path/to/your/project/.tracker.db"
31
+ }
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ ### With Claude Desktop
38
+
39
+ Add to your Claude Desktop config (`claude_desktop_config.json`):
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "saga": {
45
+ "command": "npx",
46
+ "args": ["-y", "saga-mcp"],
47
+ "env": {
48
+ "DB_PATH": "/absolute/path/to/your/project/.tracker.db"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### Manual install
56
+
57
+ ```bash
58
+ npm install -g saga-mcp
59
+ DB_PATH=./my-project/.tracker.db saga-mcp
60
+ ```
61
+
62
+ ## Tools
63
+
64
+ ### Getting Started
65
+
66
+ | Tool | Description |
67
+ |------|-------------|
68
+ | `tracker_init` | Initialize tracker and create first project |
69
+ | `tracker_dashboard` | Full project overview — **call this first when resuming work** |
70
+
71
+ ### Projects
72
+
73
+ | Tool | Description |
74
+ |------|-------------|
75
+ | `project_create` | Create a new project |
76
+ | `project_list` | List projects with completion stats |
77
+ | `project_update` | Update project (archive to soft-delete) |
78
+
79
+ ### Epics
80
+
81
+ | Tool | Description |
82
+ |------|-------------|
83
+ | `epic_create` | Create an epic within a project |
84
+ | `epic_list` | List epics with task counts |
85
+ | `epic_update` | Update an epic |
86
+
87
+ ### Tasks
88
+
89
+ | Tool | Description |
90
+ |------|-------------|
91
+ | `task_create` | Create a task within an epic |
92
+ | `task_list` | List/filter tasks (by epic, status, priority, assignee, tag) |
93
+ | `task_get` | Get task with subtasks and related notes |
94
+ | `task_update` | Update task (status changes auto-logged) |
95
+ | `task_batch_update` | Update multiple tasks at once |
96
+
97
+ ### Subtasks
98
+
99
+ | Tool | Description |
100
+ |------|-------------|
101
+ | `subtask_create` | Create subtask(s) — supports batch |
102
+ | `subtask_update` | Update subtask title/status |
103
+ | `subtask_delete` | Delete subtask(s) — supports batch |
104
+
105
+ ### Notes
106
+
107
+ | Tool | Description |
108
+ |------|-------------|
109
+ | `note_save` | Create or update a note (upsert) |
110
+ | `note_list` | List notes with filters |
111
+ | `note_search` | Full-text search across notes |
112
+ | `note_delete` | Delete a note |
113
+
114
+ ### Intelligence
115
+
116
+ | Tool | Description |
117
+ |------|-------------|
118
+ | `tracker_search` | Cross-entity search (projects, epics, tasks, notes) |
119
+ | `activity_log` | View change history with filters |
120
+
121
+ ## How It Works
122
+
123
+ saga-mcp stores everything in a single SQLite file (`.tracker.db`) per project. The database is auto-created on first use with all tables and indexes — no migration step needed.
124
+
125
+ ### Hierarchy
126
+
127
+ ```
128
+ Project
129
+ └── Epic (feature/workstream)
130
+ └── Task (unit of work)
131
+ └── Subtask (checklist item)
132
+ ```
133
+
134
+ ### Note Types
135
+
136
+ Notes replace scattered markdown files. Each note has a type:
137
+
138
+ | Type | Use case |
139
+ |------|----------|
140
+ | `general` | Free-form notes |
141
+ | `decision` | Architecture/design decisions |
142
+ | `context` | Conversation context for future sessions |
143
+ | `meeting` | Meeting notes |
144
+ | `technical` | Technical details, specs |
145
+ | `blocker` | Blockers and issues |
146
+ | `progress` | Progress updates |
147
+ | `release` | Release notes |
148
+
149
+ ### Activity Log
150
+
151
+ Every create, update, and delete is automatically recorded:
152
+
153
+ ```json
154
+ {
155
+ "summary": "Task 'Fix CORS issue' status: blocked -> done",
156
+ "action": "status_changed",
157
+ "entity_type": "task",
158
+ "entity_id": 15,
159
+ "field_name": "status",
160
+ "old_value": "blocked",
161
+ "new_value": "done",
162
+ "created_at": "2026-02-21T18:30:00"
163
+ }
164
+ ```
165
+
166
+ ## Environment Variables
167
+
168
+ | Variable | Required | Description |
169
+ |----------|----------|-------------|
170
+ | `DB_PATH` | Yes | Absolute path to the `.tracker.db` file |
171
+
172
+ ## Development
173
+
174
+ ```bash
175
+ git clone https://github.com/spranab/saga-mcp.git
176
+ cd saga-mcp
177
+ npm install
178
+ npm run build
179
+ DB_PATH=./test.db npm start
180
+ ```
181
+
182
+ ## License
183
+
184
+ MIT
package/dist/db.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import Database from 'better-sqlite3';
2
+ export declare function getDb(): Database.Database;
3
+ export declare function closeDb(): void;
package/dist/db.js ADDED
@@ -0,0 +1,25 @@
1
+ import Database from 'better-sqlite3';
2
+ import { SCHEMA_SQL } from './schema.js';
3
+ let db = null;
4
+ export function getDb() {
5
+ if (db)
6
+ return db;
7
+ const dbPath = process.env.DB_PATH;
8
+ if (!dbPath) {
9
+ throw new Error('DB_PATH environment variable is required. Set it to the path of your .tracker.db file, e.g., DB_PATH=/path/to/project/.tracker.db');
10
+ }
11
+ db = new Database(dbPath);
12
+ db.pragma('journal_mode = WAL');
13
+ db.pragma('foreign_keys = ON');
14
+ db.pragma('busy_timeout = 5000');
15
+ db.pragma('synchronous = NORMAL');
16
+ db.exec(SCHEMA_SQL);
17
+ return db;
18
+ }
19
+ export function closeDb() {
20
+ if (db) {
21
+ db.close();
22
+ db = null;
23
+ }
24
+ }
25
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,IAAI,EAAE,GAA6B,IAAI,CAAC;AAExC,MAAM,UAAU,KAAK;IACnB,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,mIAAmI,CACpI,CAAC;IACJ,CAAC;IAED,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE1B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC/B,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IACjC,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAElC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEpB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,EAAE,GAAG,IAAI,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type Database from 'better-sqlite3';
2
+ export declare function logActivity(db: Database.Database, entityType: string, entityId: number, action: string, fieldName: string | null, oldValue: string | null, newValue: string | null, summary: string): void;
3
+ export declare function logEntityUpdate(db: Database.Database, entityType: string, entityId: number, entityName: string, oldRow: Record<string, unknown>, newRow: Record<string, unknown>, trackedFields: string[]): void;
@@ -0,0 +1,15 @@
1
+ export function logActivity(db, entityType, entityId, action, fieldName, oldValue, newValue, summary) {
2
+ db.prepare(`INSERT INTO activity_log (entity_type, entity_id, action, field_name, old_value, new_value, summary)
3
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(entityType, entityId, action, fieldName, oldValue, newValue, summary);
4
+ }
5
+ export function logEntityUpdate(db, entityType, entityId, entityName, oldRow, newRow, trackedFields) {
6
+ for (const field of trackedFields) {
7
+ const oldVal = String(oldRow[field] ?? '');
8
+ const newVal = String(newRow[field] ?? '');
9
+ if (oldVal !== newVal) {
10
+ const action = field === 'status' ? 'status_changed' : 'updated';
11
+ logActivity(db, entityType, entityId, action, field, oldVal, newVal, `${entityType} '${entityName}' ${field}: ${oldVal} -> ${newVal}`);
12
+ }
13
+ }
14
+ }
15
+ //# sourceMappingURL=activity-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-logger.js","sourceRoot":"","sources":["../../src/helpers/activity-logger.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CACzB,EAAqB,EACrB,UAAkB,EAClB,QAAgB,EAChB,MAAc,EACd,SAAwB,EACxB,QAAuB,EACvB,QAAuB,EACvB,OAAe;IAEf,EAAE,CAAC,OAAO,CACR;kCAC8B,CAC/B,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,EAAqB,EACrB,UAAkB,EAClB,QAAgB,EAChB,UAAkB,EAClB,MAA+B,EAC/B,MAA+B,EAC/B,aAAuB;IAEvB,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;YACjE,WAAW,CACT,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EACvD,GAAG,UAAU,KAAK,UAAU,KAAK,KAAK,KAAK,MAAM,OAAO,MAAM,EAAE,CACjE,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function buildUpdate(table: string, id: number, fields: Record<string, unknown>, allowedColumns: string[]): {
2
+ sql: string;
3
+ params: unknown[];
4
+ } | null;
5
+ export declare function addTagFilter(whereClauses: string[], params: unknown[], tag: string, table: string): void;
@@ -0,0 +1,24 @@
1
+ const JSON_COLUMNS = new Set(['tags', 'metadata']);
2
+ export function buildUpdate(table, id, fields, allowedColumns) {
3
+ const updates = [];
4
+ const params = [];
5
+ for (const col of allowedColumns) {
6
+ if (fields[col] !== undefined) {
7
+ updates.push(`${col} = ?`);
8
+ params.push(JSON_COLUMNS.has(col) ? JSON.stringify(fields[col]) : fields[col]);
9
+ }
10
+ }
11
+ if (updates.length === 0)
12
+ return null;
13
+ updates.push("updated_at = datetime('now')");
14
+ params.push(id);
15
+ return {
16
+ sql: `UPDATE ${table} SET ${updates.join(', ')} WHERE id = ? RETURNING *`,
17
+ params,
18
+ };
19
+ }
20
+ export function addTagFilter(whereClauses, params, tag, table) {
21
+ whereClauses.push(`EXISTS (SELECT 1 FROM json_each(${table}.tags) WHERE json_each.value = ?)`);
22
+ params.push(tag);
23
+ }
24
+ //# sourceMappingURL=sql-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-builder.js","sourceRoot":"","sources":["../../src/helpers/sql-builder.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAEnD,MAAM,UAAU,WAAW,CACzB,KAAa,EACb,EAAU,EACV,MAA+B,EAC/B,cAAwB;IAExB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAc,EAAE,CAAC;IAE7B,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC7C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEhB,OAAO;QACL,GAAG,EAAE,UAAU,KAAK,QAAQ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,2BAA2B;QACzE,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,YAAsB,EACtB,MAAiB,EACjB,GAAW,EACX,KAAa;IAEb,YAAY,CAAC,IAAI,CACf,mCAAmC,KAAK,mCAAmC,CAC5E,CAAC;IACF,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { definitions as projectDefs, handlers as projectHandlers } from './tools/projects.js';
6
+ import { definitions as epicDefs, handlers as epicHandlers } from './tools/epics.js';
7
+ import { definitions as taskDefs, handlers as taskHandlers } from './tools/tasks.js';
8
+ import { definitions as subtaskDefs, handlers as subtaskHandlers } from './tools/subtasks.js';
9
+ import { definitions as noteDefs, handlers as noteHandlers } from './tools/notes.js';
10
+ import { definitions as dashboardDefs, handlers as dashboardHandlers } from './tools/dashboard.js';
11
+ import { definitions as searchDefs, handlers as searchHandlers } from './tools/search.js';
12
+ import { definitions as activityDefs, handlers as activityHandlers } from './tools/activity.js';
13
+ import { closeDb } from './db.js';
14
+ const ALL_TOOLS = [
15
+ ...projectDefs,
16
+ ...epicDefs,
17
+ ...taskDefs,
18
+ ...subtaskDefs,
19
+ ...noteDefs,
20
+ ...dashboardDefs,
21
+ ...searchDefs,
22
+ ...activityDefs,
23
+ ];
24
+ const ALL_HANDLERS = {
25
+ ...projectHandlers,
26
+ ...epicHandlers,
27
+ ...taskHandlers,
28
+ ...subtaskHandlers,
29
+ ...noteHandlers,
30
+ ...dashboardHandlers,
31
+ ...searchHandlers,
32
+ ...activityHandlers,
33
+ };
34
+ const server = new Server({ name: 'tracker', version: '1.0.0' }, { capabilities: { tools: {} } });
35
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
36
+ return { tools: ALL_TOOLS };
37
+ });
38
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
39
+ try {
40
+ const { name, arguments: args } = request.params;
41
+ const handler = ALL_HANDLERS[name];
42
+ if (!handler) {
43
+ throw new Error(`Unknown tool: ${name}`);
44
+ }
45
+ const result = handler(args ?? {});
46
+ return {
47
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
48
+ };
49
+ }
50
+ catch (error) {
51
+ return {
52
+ content: [
53
+ {
54
+ type: 'text',
55
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
56
+ },
57
+ ],
58
+ isError: true,
59
+ };
60
+ }
61
+ });
62
+ async function main() {
63
+ const transport = new StdioServerTransport();
64
+ await server.connect(transport);
65
+ console.error('Tracker MCP Server running on stdio');
66
+ }
67
+ process.on('SIGINT', () => {
68
+ closeDb();
69
+ process.exit(0);
70
+ });
71
+ process.on('SIGTERM', () => {
72
+ closeDb();
73
+ process.exit(0);
74
+ });
75
+ main().catch((error) => {
76
+ console.error('Fatal error:', error);
77
+ process.exit(1);
78
+ });
79
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const SCHEMA_SQL = "\n-- Core hierarchy: projects > epics > tasks > subtasks\n\nCREATE TABLE IF NOT EXISTS projects (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT NOT NULL,\n description TEXT,\n status TEXT NOT NULL DEFAULT 'active'\n CHECK (status IN ('active', 'on_hold', 'completed', 'archived')),\n tags TEXT NOT NULL DEFAULT '[]',\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE TABLE IF NOT EXISTS epics (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n description TEXT,\n status TEXT NOT NULL DEFAULT 'planned'\n CHECK (status IN ('planned', 'in_progress', 'completed', 'cancelled')),\n priority TEXT NOT NULL DEFAULT 'medium'\n CHECK (priority IN ('low', 'medium', 'high', 'critical')),\n sort_order INTEGER NOT NULL DEFAULT 0,\n tags TEXT NOT NULL DEFAULT '[]',\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE TABLE IF NOT EXISTS tasks (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n epic_id INTEGER NOT NULL REFERENCES epics(id) ON DELETE CASCADE,\n title TEXT NOT NULL,\n description TEXT,\n status TEXT NOT NULL DEFAULT 'todo'\n CHECK (status IN ('todo', 'in_progress', 'review', 'done', 'blocked')),\n priority TEXT NOT NULL DEFAULT 'medium'\n CHECK (priority IN ('low', 'medium', 'high', 'critical')),\n sort_order INTEGER NOT NULL DEFAULT 0,\n assigned_to TEXT,\n estimated_hours REAL,\n actual_hours REAL,\n due_date TEXT,\n tags TEXT NOT NULL DEFAULT '[]',\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE TABLE IF NOT EXISTS subtasks (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n title TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'todo'\n CHECK (status IN ('todo', 'in_progress', 'done')),\n sort_order INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Unified notes (replaces summaries + status_updates + context)\n\nCREATE TABLE IF NOT EXISTS notes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n title TEXT NOT NULL,\n content TEXT NOT NULL,\n note_type TEXT NOT NULL DEFAULT 'general'\n CHECK (note_type IN (\n 'general', 'decision', 'context', 'meeting',\n 'technical', 'blocker', 'progress', 'release'\n )),\n related_entity_type TEXT CHECK (related_entity_type IN ('project', 'epic', 'task') OR related_entity_type IS NULL),\n related_entity_id INTEGER,\n tags TEXT NOT NULL DEFAULT '[]',\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Automatic activity log\n\nCREATE TABLE IF NOT EXISTS activity_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n entity_type TEXT NOT NULL,\n entity_id INTEGER NOT NULL,\n action TEXT NOT NULL,\n field_name TEXT,\n old_value TEXT,\n new_value TEXT,\n summary TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes\n\nCREATE INDEX IF NOT EXISTS idx_epics_project_id ON epics(project_id);\nCREATE INDEX IF NOT EXISTS idx_tasks_epic_id ON tasks(epic_id);\nCREATE INDEX IF NOT EXISTS idx_subtasks_task_id ON subtasks(task_id);\n\nCREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);\nCREATE INDEX IF NOT EXISTS idx_epics_status ON epics(status);\nCREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);\nCREATE INDEX IF NOT EXISTS idx_subtasks_status ON subtasks(status);\n\nCREATE INDEX IF NOT EXISTS idx_epics_priority ON epics(priority);\nCREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);\n\nCREATE INDEX IF NOT EXISTS idx_epics_sort ON epics(project_id, sort_order);\nCREATE INDEX IF NOT EXISTS idx_tasks_sort ON tasks(epic_id, sort_order);\nCREATE INDEX IF NOT EXISTS idx_subtasks_sort ON subtasks(task_id, sort_order);\n\nCREATE INDEX IF NOT EXISTS idx_notes_type ON notes(note_type);\nCREATE INDEX IF NOT EXISTS idx_notes_entity ON notes(related_entity_type, related_entity_id);\nCREATE INDEX IF NOT EXISTS idx_notes_created ON notes(created_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_activity_entity ON activity_log(entity_type, entity_id);\nCREATE INDEX IF NOT EXISTS idx_activity_created ON activity_log(created_at DESC);\nCREATE INDEX IF NOT EXISTS idx_activity_action ON activity_log(action);\n\nCREATE INDEX IF NOT EXISTS idx_tasks_assigned ON tasks(assigned_to);\nCREATE INDEX IF NOT EXISTS idx_tasks_due ON tasks(due_date);\n";
package/dist/schema.js ADDED
@@ -0,0 +1,125 @@
1
+ export const SCHEMA_SQL = `
2
+ -- Core hierarchy: projects > epics > tasks > subtasks
3
+
4
+ CREATE TABLE IF NOT EXISTS projects (
5
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
6
+ name TEXT NOT NULL,
7
+ description TEXT,
8
+ status TEXT NOT NULL DEFAULT 'active'
9
+ CHECK (status IN ('active', 'on_hold', 'completed', 'archived')),
10
+ tags TEXT NOT NULL DEFAULT '[]',
11
+ metadata TEXT NOT NULL DEFAULT '{}',
12
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
13
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
14
+ );
15
+
16
+ CREATE TABLE IF NOT EXISTS epics (
17
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
18
+ project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19
+ name TEXT NOT NULL,
20
+ description TEXT,
21
+ status TEXT NOT NULL DEFAULT 'planned'
22
+ CHECK (status IN ('planned', 'in_progress', 'completed', 'cancelled')),
23
+ priority TEXT NOT NULL DEFAULT 'medium'
24
+ CHECK (priority IN ('low', 'medium', 'high', 'critical')),
25
+ sort_order INTEGER NOT NULL DEFAULT 0,
26
+ tags TEXT NOT NULL DEFAULT '[]',
27
+ metadata TEXT NOT NULL DEFAULT '{}',
28
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
29
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
30
+ );
31
+
32
+ CREATE TABLE IF NOT EXISTS tasks (
33
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
34
+ epic_id INTEGER NOT NULL REFERENCES epics(id) ON DELETE CASCADE,
35
+ title TEXT NOT NULL,
36
+ description TEXT,
37
+ status TEXT NOT NULL DEFAULT 'todo'
38
+ CHECK (status IN ('todo', 'in_progress', 'review', 'done', 'blocked')),
39
+ priority TEXT NOT NULL DEFAULT 'medium'
40
+ CHECK (priority IN ('low', 'medium', 'high', 'critical')),
41
+ sort_order INTEGER NOT NULL DEFAULT 0,
42
+ assigned_to TEXT,
43
+ estimated_hours REAL,
44
+ actual_hours REAL,
45
+ due_date TEXT,
46
+ tags TEXT NOT NULL DEFAULT '[]',
47
+ metadata TEXT NOT NULL DEFAULT '{}',
48
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
49
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
50
+ );
51
+
52
+ CREATE TABLE IF NOT EXISTS subtasks (
53
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
54
+ task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
55
+ title TEXT NOT NULL,
56
+ status TEXT NOT NULL DEFAULT 'todo'
57
+ CHECK (status IN ('todo', 'in_progress', 'done')),
58
+ sort_order INTEGER NOT NULL DEFAULT 0,
59
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
60
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
61
+ );
62
+
63
+ -- Unified notes (replaces summaries + status_updates + context)
64
+
65
+ CREATE TABLE IF NOT EXISTS notes (
66
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ title TEXT NOT NULL,
68
+ content TEXT NOT NULL,
69
+ note_type TEXT NOT NULL DEFAULT 'general'
70
+ CHECK (note_type IN (
71
+ 'general', 'decision', 'context', 'meeting',
72
+ 'technical', 'blocker', 'progress', 'release'
73
+ )),
74
+ related_entity_type TEXT CHECK (related_entity_type IN ('project', 'epic', 'task') OR related_entity_type IS NULL),
75
+ related_entity_id INTEGER,
76
+ tags TEXT NOT NULL DEFAULT '[]',
77
+ metadata TEXT NOT NULL DEFAULT '{}',
78
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
79
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
80
+ );
81
+
82
+ -- Automatic activity log
83
+
84
+ CREATE TABLE IF NOT EXISTS activity_log (
85
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
86
+ entity_type TEXT NOT NULL,
87
+ entity_id INTEGER NOT NULL,
88
+ action TEXT NOT NULL,
89
+ field_name TEXT,
90
+ old_value TEXT,
91
+ new_value TEXT,
92
+ summary TEXT,
93
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
94
+ );
95
+
96
+ -- Indexes
97
+
98
+ CREATE INDEX IF NOT EXISTS idx_epics_project_id ON epics(project_id);
99
+ CREATE INDEX IF NOT EXISTS idx_tasks_epic_id ON tasks(epic_id);
100
+ CREATE INDEX IF NOT EXISTS idx_subtasks_task_id ON subtasks(task_id);
101
+
102
+ CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);
103
+ CREATE INDEX IF NOT EXISTS idx_epics_status ON epics(status);
104
+ CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
105
+ CREATE INDEX IF NOT EXISTS idx_subtasks_status ON subtasks(status);
106
+
107
+ CREATE INDEX IF NOT EXISTS idx_epics_priority ON epics(priority);
108
+ CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
109
+
110
+ CREATE INDEX IF NOT EXISTS idx_epics_sort ON epics(project_id, sort_order);
111
+ CREATE INDEX IF NOT EXISTS idx_tasks_sort ON tasks(epic_id, sort_order);
112
+ CREATE INDEX IF NOT EXISTS idx_subtasks_sort ON subtasks(task_id, sort_order);
113
+
114
+ CREATE INDEX IF NOT EXISTS idx_notes_type ON notes(note_type);
115
+ CREATE INDEX IF NOT EXISTS idx_notes_entity ON notes(related_entity_type, related_entity_id);
116
+ CREATE INDEX IF NOT EXISTS idx_notes_created ON notes(created_at DESC);
117
+
118
+ CREATE INDEX IF NOT EXISTS idx_activity_entity ON activity_log(entity_type, entity_id);
119
+ CREATE INDEX IF NOT EXISTS idx_activity_created ON activity_log(created_at DESC);
120
+ CREATE INDEX IF NOT EXISTS idx_activity_action ON activity_log(action);
121
+
122
+ CREATE INDEX IF NOT EXISTS idx_tasks_assigned ON tasks(assigned_to);
123
+ CREATE INDEX IF NOT EXISTS idx_tasks_due ON tasks(due_date);
124
+ `;
125
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2HzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import type { ToolHandler } from '../types.js';
3
+ export declare const definitions: Tool[];
4
+ export declare const handlers: Record<string, ToolHandler>;
@@ -0,0 +1,125 @@
1
+ import { getDb } from '../db.js';
2
+ import { logActivity } from '../helpers/activity-logger.js';
3
+ export const definitions = [
4
+ {
5
+ name: 'activity_log',
6
+ description: 'View the activity log showing what changed and when. Useful for understanding recent progress or reviewing what happened since the last session.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ entity_type: {
11
+ type: 'string',
12
+ enum: ['project', 'epic', 'task', 'subtask', 'note'],
13
+ description: 'Filter by entity type',
14
+ },
15
+ entity_id: { type: 'integer', description: 'Filter by specific entity' },
16
+ action: {
17
+ type: 'string',
18
+ enum: ['created', 'updated', 'deleted', 'status_changed'],
19
+ description: 'Filter by action type',
20
+ },
21
+ since: { type: 'string', description: 'ISO 8601 datetime - show only activity after this time' },
22
+ limit: { type: 'integer', default: 50 },
23
+ },
24
+ },
25
+ },
26
+ {
27
+ name: 'task_batch_update',
28
+ description: 'Update multiple tasks at once. Useful for changing status of several tasks (e.g., mark 3 tasks as done) or reassigning tasks.',
29
+ inputSchema: {
30
+ type: 'object',
31
+ properties: {
32
+ ids: {
33
+ type: 'array',
34
+ items: { type: 'integer' },
35
+ description: 'Task IDs to update',
36
+ },
37
+ status: { type: 'string', enum: ['todo', 'in_progress', 'review', 'done', 'blocked'] },
38
+ priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
39
+ assigned_to: { type: 'string' },
40
+ },
41
+ required: ['ids'],
42
+ },
43
+ },
44
+ ];
45
+ function handleActivityLog(args) {
46
+ const db = getDb();
47
+ const entityType = args.entity_type;
48
+ const entityId = args.entity_id;
49
+ const action = args.action;
50
+ const since = args.since;
51
+ const limit = args.limit ?? 50;
52
+ const whereClauses = [];
53
+ const params = [];
54
+ if (entityType) {
55
+ whereClauses.push('entity_type = ?');
56
+ params.push(entityType);
57
+ }
58
+ if (entityId !== undefined) {
59
+ whereClauses.push('entity_id = ?');
60
+ params.push(entityId);
61
+ }
62
+ if (action) {
63
+ whereClauses.push('action = ?');
64
+ params.push(action);
65
+ }
66
+ if (since) {
67
+ whereClauses.push('created_at > ?');
68
+ params.push(since);
69
+ }
70
+ const whereStr = whereClauses.length > 0 ? `WHERE ${whereClauses.join(' AND ')}` : '';
71
+ const sql = `SELECT * FROM activity_log ${whereStr} ORDER BY created_at DESC LIMIT ?`;
72
+ params.push(limit);
73
+ return db.prepare(sql).all(...params);
74
+ }
75
+ function handleTaskBatchUpdate(args) {
76
+ const db = getDb();
77
+ const ids = args.ids;
78
+ const status = args.status;
79
+ const priority = args.priority;
80
+ const assignedTo = args.assigned_to;
81
+ if (!status && !priority && assignedTo === undefined) {
82
+ throw new Error('Provide at least one field to update: status, priority, or assigned_to');
83
+ }
84
+ const getStmt = db.prepare('SELECT * FROM tasks WHERE id = ?');
85
+ const results = db.transaction(() => {
86
+ return ids.map((id) => {
87
+ const oldRow = getStmt.get(id);
88
+ if (!oldRow)
89
+ throw new Error(`Task ${id} not found`);
90
+ const updates = [];
91
+ const params = [];
92
+ if (status) {
93
+ updates.push('status = ?');
94
+ params.push(status);
95
+ }
96
+ if (priority) {
97
+ updates.push('priority = ?');
98
+ params.push(priority);
99
+ }
100
+ if (assignedTo !== undefined) {
101
+ updates.push('assigned_to = ?');
102
+ params.push(assignedTo);
103
+ }
104
+ updates.push("updated_at = datetime('now')");
105
+ params.push(id);
106
+ const newRow = db
107
+ .prepare(`UPDATE tasks SET ${updates.join(', ')} WHERE id = ? RETURNING *`)
108
+ .get(...params);
109
+ // Log status changes
110
+ if (status && oldRow.status !== status) {
111
+ logActivity(db, 'task', id, 'status_changed', 'status', oldRow.status, status, `Task '${newRow.title}' status: ${oldRow.status} -> ${status}`);
112
+ }
113
+ if (priority && oldRow.priority !== priority) {
114
+ logActivity(db, 'task', id, 'updated', 'priority', oldRow.priority, priority, `Task '${newRow.title}' priority: ${oldRow.priority} -> ${priority}`);
115
+ }
116
+ return newRow;
117
+ });
118
+ })();
119
+ return { updated: results.length, tasks: results };
120
+ }
121
+ export const handlers = {
122
+ activity_log: handleActivityLog,
123
+ task_batch_update: handleTaskBatchUpdate,
124
+ };
125
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../../src/tools/activity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import type { ToolHandler } from '../types.js';
3
+ export declare const definitions: Tool[];
4
+ export declare const handlers: Record<string, ToolHandler>;