@dalmasonto/taskflow-mcp 1.0.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/README.md +184 -0
- package/dist/db.d.ts +5 -0
- package/dist/db.js +109 -0
- package/dist/helpers.d.ts +21 -0
- package/dist/helpers.js +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +54 -0
- package/dist/sse.d.ts +7 -0
- package/dist/sse.js +282 -0
- package/dist/tools/activity.d.ts +28 -0
- package/dist/tools/activity.js +56 -0
- package/dist/tools/agent.d.ts +14 -0
- package/dist/tools/agent.js +85 -0
- package/dist/tools/analytics.d.ts +21 -0
- package/dist/tools/analytics.js +108 -0
- package/dist/tools/notifications.d.ts +31 -0
- package/dist/tools/notifications.js +59 -0
- package/dist/tools/projects.d.ts +55 -0
- package/dist/tools/projects.js +112 -0
- package/dist/tools/settings.d.ts +19 -0
- package/dist/tools/settings.js +52 -0
- package/dist/tools/tasks.d.ts +103 -0
- package/dist/tools/tasks.js +351 -0
- package/dist/tools/timer.d.ts +37 -0
- package/dist/tools/timer.js +131 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.js +24 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# TaskFlow MCP Server
|
|
2
|
+
|
|
3
|
+
A local-first task and time tracking system exposed as [MCP](https://modelcontextprotocol.io) tools. Any MCP-compatible AI agent can manage projects, tasks, timers, analytics, and notifications through this server.
|
|
4
|
+
|
|
5
|
+
## Quickstart
|
|
6
|
+
|
|
7
|
+
### 1. Install and build
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd mcp-server
|
|
11
|
+
npm install
|
|
12
|
+
npm run build
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 2. Configure your MCP client
|
|
16
|
+
|
|
17
|
+
Add a `.mcp.json` file to your project root (or wherever your MCP client reads config):
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"taskflow": {
|
|
23
|
+
"command": "node",
|
|
24
|
+
"args": ["/absolute/path/to/mcp-server/dist/index.js"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Replace the path with the absolute path to your built `dist/index.js`.
|
|
31
|
+
|
|
32
|
+
### 3. Auto-allow permissions (Claude Code)
|
|
33
|
+
|
|
34
|
+
By default, Claude Code will prompt you to approve each MCP tool call. To allow all TaskFlow tools without prompts, add this to `.claude/settings.local.json`:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"permissions": {
|
|
39
|
+
"allow": [
|
|
40
|
+
"mcp__taskflow__*"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"enableAllProjectMcpServers": true
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The `mcp__taskflow__*` wildcard matches every tool exposed by this server.
|
|
48
|
+
|
|
49
|
+
For other MCP clients (Cursor, Windsurf, etc.), check their docs for permission/auto-approve configuration.
|
|
50
|
+
|
|
51
|
+
## Agent Integration Guide
|
|
52
|
+
|
|
53
|
+
### How agents discover TaskFlow
|
|
54
|
+
|
|
55
|
+
TaskFlow uses two layers to guide agent behavior:
|
|
56
|
+
|
|
57
|
+
**Layer 1: Tool descriptions (passive discovery)**
|
|
58
|
+
Every tool has a description that hints at when and why to use it. MCP clients surface these descriptions when the agent connects, so the agent learns the workflow organically. For example, `start_timer` says "Call this before beginning work on any task to track focused time."
|
|
59
|
+
|
|
60
|
+
**Layer 2: `get_agent_instructions` tool (active onboarding)**
|
|
61
|
+
This is the key tool. Its description says **"Call this at the start of every conversation."** When called, it returns:
|
|
62
|
+
|
|
63
|
+
- A role description for the agent
|
|
64
|
+
- A startup checklist (list projects, check in-progress tasks, check notifications)
|
|
65
|
+
- Behavioral rules (when to start/stop timers, how to handle blockers, etc.)
|
|
66
|
+
- Live context (current project count, in-progress tasks, blocked tasks, unread notifications)
|
|
67
|
+
- The full task status workflow with valid transitions
|
|
68
|
+
|
|
69
|
+
Any well-behaved agent will call this tool when it sees the description, without needing explicit user instructions.
|
|
70
|
+
|
|
71
|
+
### Making it automatic (recommended)
|
|
72
|
+
|
|
73
|
+
For the most reliable experience, add one line to your project's `CLAUDE.md` (or equivalent agent config):
|
|
74
|
+
|
|
75
|
+
```markdown
|
|
76
|
+
## MCP Integration
|
|
77
|
+
At the start of each conversation, call the `get_agent_instructions` tool from the taskflow MCP server to understand your task management workflow.
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This guarantees the agent calls the instruction tool on every conversation start. Without this, the agent will still likely discover the tool via its description, but the CLAUDE.md line makes it deterministic.
|
|
81
|
+
|
|
82
|
+
### Example conversation flow
|
|
83
|
+
|
|
84
|
+
Here's what a conversation looks like when the agent is properly connected:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Agent connects → sees get_agent_instructions in tool list → calls it
|
|
88
|
+
↓
|
|
89
|
+
Gets instructions + live context (3 projects, 2 tasks in progress, 1 blocked)
|
|
90
|
+
↓
|
|
91
|
+
Calls list_tasks(status="in_progress") → sees "Build dashboard page" is active
|
|
92
|
+
↓
|
|
93
|
+
User: "Let's work on the dashboard"
|
|
94
|
+
↓
|
|
95
|
+
Agent: calls get_task(id=5) → reads description for implementation details
|
|
96
|
+
Agent: calls start_timer(task_id=5) → time tracking begins
|
|
97
|
+
↓
|
|
98
|
+
Agent implements the feature, referencing task description for acceptance criteria
|
|
99
|
+
↓
|
|
100
|
+
Agent: calls stop_timer(task_id=5, final_status="done")
|
|
101
|
+
Agent: checks if any blocked tasks depended on task 5
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Strategies for proactive agent behavior
|
|
105
|
+
|
|
106
|
+
The `get_agent_instructions` tool tells agents to:
|
|
107
|
+
|
|
108
|
+
1. **Check tasks before coding** — before starting work, search for a matching task and start its timer
|
|
109
|
+
2. **Track time automatically** — start_timer when beginning work, pause_timer on context switches, stop_timer when done
|
|
110
|
+
3. **Surface blockers** — if stuck, update the task to "blocked" with context in the description
|
|
111
|
+
4. **Suggest next work** — when the user asks "what should I work on?", surface high-priority unblocked tasks
|
|
112
|
+
5. **Stay in sync** — create tasks for new work items to keep the tracker up to date
|
|
113
|
+
6. **Read descriptions** — task descriptions contain implementation details and acceptance criteria
|
|
114
|
+
|
|
115
|
+
## Available Tools
|
|
116
|
+
|
|
117
|
+
### Agent
|
|
118
|
+
| Tool | Description |
|
|
119
|
+
|------|-------------|
|
|
120
|
+
| `get_agent_instructions` | Returns onboarding instructions and live context for AI agents. **Call first.** |
|
|
121
|
+
|
|
122
|
+
### Tasks
|
|
123
|
+
| Tool | Description |
|
|
124
|
+
|------|-------------|
|
|
125
|
+
| `create_task` | Create a task with dependencies, tags, links, and time estimates |
|
|
126
|
+
| `list_tasks` | List tasks with filters (status, project, priority, tag) |
|
|
127
|
+
| `get_task` | Get a task by ID with time tracking info |
|
|
128
|
+
| `update_task` | Update task fields |
|
|
129
|
+
| `update_task_status` | Change status with transition validation |
|
|
130
|
+
| `delete_task` | Delete a task by ID |
|
|
131
|
+
| `bulk_create_tasks` | Create multiple tasks in a single transaction |
|
|
132
|
+
| `search_tasks` | Full-text search by title or description |
|
|
133
|
+
|
|
134
|
+
### Projects
|
|
135
|
+
| Tool | Description |
|
|
136
|
+
|------|-------------|
|
|
137
|
+
| `create_project` | Create a project (active_project or project_idea) |
|
|
138
|
+
| `list_projects` | List all projects with task counts |
|
|
139
|
+
| `get_project` | Get a project with all its tasks |
|
|
140
|
+
| `update_project` | Update project fields |
|
|
141
|
+
| `delete_project` | Delete a project (tasks are unlinked, not deleted) |
|
|
142
|
+
|
|
143
|
+
### Timer
|
|
144
|
+
| Tool | Description |
|
|
145
|
+
|------|-------------|
|
|
146
|
+
| `start_timer` | Start a timer session (task transitions to in_progress) |
|
|
147
|
+
| `pause_timer` | Pause the active session (task transitions to paused) |
|
|
148
|
+
| `stop_timer` | Stop timer with final status (done/partial_done/blocked) |
|
|
149
|
+
| `list_sessions` | List sessions with optional date range filter |
|
|
150
|
+
|
|
151
|
+
### Analytics
|
|
152
|
+
| Tool | Description |
|
|
153
|
+
|------|-------------|
|
|
154
|
+
| `get_analytics` | Summary: focused time, completion rates, status distribution, time per project |
|
|
155
|
+
| `get_timeline` | Focused time grouped by day or week |
|
|
156
|
+
|
|
157
|
+
### Activity
|
|
158
|
+
| Tool | Description |
|
|
159
|
+
|------|-------------|
|
|
160
|
+
| `get_activity_log` | Recent activity: completions, timer events, status changes |
|
|
161
|
+
| `clear_activity_log` | Delete all activity log entries |
|
|
162
|
+
|
|
163
|
+
### Notifications
|
|
164
|
+
| Tool | Description |
|
|
165
|
+
|------|-------------|
|
|
166
|
+
| `list_notifications` | List notifications (filter by unread) |
|
|
167
|
+
| `mark_notification_read` | Mark a single notification as read |
|
|
168
|
+
| `mark_all_notifications_read` | Mark all as read |
|
|
169
|
+
| `clear_notifications` | Delete all notifications |
|
|
170
|
+
|
|
171
|
+
### Settings
|
|
172
|
+
| Tool | Description |
|
|
173
|
+
|------|-------------|
|
|
174
|
+
| `get_setting` | Get a setting by key (returns default if not set) |
|
|
175
|
+
| `update_setting` | Update or create a setting |
|
|
176
|
+
|
|
177
|
+
## Configuration
|
|
178
|
+
|
|
179
|
+
| Setting | Default | Description |
|
|
180
|
+
|---------|---------|-------------|
|
|
181
|
+
| `TASKFLOW_SSE_PORT` | `3456` | Port for the SSE broadcast server |
|
|
182
|
+
| Database location | `~/.taskflow/taskflow.db` | SQLite database with WAL mode |
|
|
183
|
+
|
|
184
|
+
The SSE server at `http://localhost:3456/events` broadcasts real-time changes to connected UI clients. The `/sync` endpoint returns a full data dump for initial sync.
|
package/dist/db.d.ts
ADDED
package/dist/db.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { mkdirSync } from 'fs';
|
|
3
|
+
import { dirname, resolve } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
const DEFAULT_DB_PATH = '~/.taskflow/taskflow.db';
|
|
6
|
+
let db = null;
|
|
7
|
+
// Expands ~/path to $HOME/path. Only handles ~/ prefix, not ~user/ paths.
|
|
8
|
+
export function resolvePath(p) {
|
|
9
|
+
if (p.startsWith('~/') || p === '~') {
|
|
10
|
+
return resolve(homedir(), p.slice(2));
|
|
11
|
+
}
|
|
12
|
+
return resolve(p);
|
|
13
|
+
}
|
|
14
|
+
export function getDb() {
|
|
15
|
+
if (db)
|
|
16
|
+
return db;
|
|
17
|
+
return initDb(process.env.TASKFLOW_DB_PATH || DEFAULT_DB_PATH);
|
|
18
|
+
}
|
|
19
|
+
// For testing: initialize with a specific path (use ':memory:' for tests)
|
|
20
|
+
export function initDb(path) {
|
|
21
|
+
if (db) {
|
|
22
|
+
db.close();
|
|
23
|
+
db = null;
|
|
24
|
+
}
|
|
25
|
+
const dbPath = path === ':memory:' ? ':memory:' : resolvePath(path);
|
|
26
|
+
if (path !== ':memory:')
|
|
27
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
28
|
+
db = new Database(dbPath);
|
|
29
|
+
db.pragma('journal_mode = WAL');
|
|
30
|
+
db.pragma('foreign_keys = ON');
|
|
31
|
+
db.pragma('busy_timeout = 5000');
|
|
32
|
+
initSchema(db);
|
|
33
|
+
return db;
|
|
34
|
+
}
|
|
35
|
+
function initSchema(db) {
|
|
36
|
+
db.exec(`
|
|
37
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
38
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
39
|
+
name TEXT NOT NULL,
|
|
40
|
+
color TEXT NOT NULL DEFAULT '#de8eff',
|
|
41
|
+
type TEXT NOT NULL DEFAULT 'active_project',
|
|
42
|
+
description TEXT,
|
|
43
|
+
created_at TEXT NOT NULL,
|
|
44
|
+
updated_at TEXT NOT NULL
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
48
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
49
|
+
title TEXT NOT NULL,
|
|
50
|
+
description TEXT,
|
|
51
|
+
status TEXT NOT NULL DEFAULT 'not_started',
|
|
52
|
+
priority TEXT NOT NULL DEFAULT 'medium',
|
|
53
|
+
project_id INTEGER REFERENCES projects(id) ON DELETE SET NULL,
|
|
54
|
+
dependencies TEXT NOT NULL DEFAULT '[]',
|
|
55
|
+
links TEXT NOT NULL DEFAULT '[]',
|
|
56
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
57
|
+
due_date TEXT,
|
|
58
|
+
estimated_time INTEGER,
|
|
59
|
+
created_at TEXT NOT NULL,
|
|
60
|
+
updated_at TEXT NOT NULL
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
64
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
65
|
+
task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
66
|
+
start TEXT NOT NULL,
|
|
67
|
+
end TEXT
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
CREATE TABLE IF NOT EXISTS activity_logs (
|
|
71
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
72
|
+
action TEXT NOT NULL,
|
|
73
|
+
title TEXT NOT NULL,
|
|
74
|
+
detail TEXT,
|
|
75
|
+
entity_type TEXT,
|
|
76
|
+
entity_id INTEGER,
|
|
77
|
+
created_at TEXT NOT NULL
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
CREATE TABLE IF NOT EXISTS notifications (
|
|
81
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
82
|
+
title TEXT NOT NULL,
|
|
83
|
+
message TEXT NOT NULL,
|
|
84
|
+
type TEXT NOT NULL DEFAULT 'info',
|
|
85
|
+
read INTEGER NOT NULL DEFAULT 0,
|
|
86
|
+
created_at TEXT NOT NULL
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE TABLE IF NOT EXISTS settings (
|
|
90
|
+
key TEXT PRIMARY KEY,
|
|
91
|
+
value TEXT NOT NULL
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
95
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_project_id ON tasks(project_id);
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
|
|
97
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_task_id ON sessions(task_id);
|
|
98
|
+
CREATE INDEX IF NOT EXISTS idx_activity_logs_created_at ON activity_logs(created_at);
|
|
99
|
+
CREATE INDEX IF NOT EXISTS idx_activity_logs_action ON activity_logs(action);
|
|
100
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_read ON notifications(read);
|
|
101
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_created_at ON notifications(created_at);
|
|
102
|
+
`);
|
|
103
|
+
}
|
|
104
|
+
export function closeDb() {
|
|
105
|
+
if (db) {
|
|
106
|
+
db.close();
|
|
107
|
+
db = null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ActivityAction, ErrorCode } from './types.js';
|
|
2
|
+
export declare function logActivity(action: ActivityAction, title: string, options?: {
|
|
3
|
+
detail?: string;
|
|
4
|
+
entityType?: string;
|
|
5
|
+
entityId?: number;
|
|
6
|
+
}): void;
|
|
7
|
+
export declare function errorResponse(error: string, code: ErrorCode): {
|
|
8
|
+
isError: true;
|
|
9
|
+
content: {
|
|
10
|
+
type: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
}[];
|
|
13
|
+
};
|
|
14
|
+
export declare function successResponse(data: unknown): {
|
|
15
|
+
content: {
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
}[];
|
|
19
|
+
};
|
|
20
|
+
export declare function now(): string;
|
|
21
|
+
export declare function broadcastChange(entity: string, action: string, payload: unknown): void;
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getDb } from './db.js';
|
|
2
|
+
import { broadcast } from './sse.js';
|
|
3
|
+
export function logActivity(action, title, options) {
|
|
4
|
+
const db = getDb();
|
|
5
|
+
const ts = new Date().toISOString();
|
|
6
|
+
const result = db.prepare(`INSERT INTO activity_logs (action, title, detail, entity_type, entity_id, created_at)
|
|
7
|
+
VALUES (?, ?, ?, ?, ?, ?)`).run(action, title, options?.detail ?? null, options?.entityType ?? null, options?.entityId ?? null, ts);
|
|
8
|
+
const entry = db.prepare('SELECT * FROM activity_logs WHERE id = ?').get(result.lastInsertRowid);
|
|
9
|
+
broadcast('activity_logged', { entity: 'activity', action: 'activity_logged', payload: entry });
|
|
10
|
+
}
|
|
11
|
+
export function errorResponse(error, code) {
|
|
12
|
+
return {
|
|
13
|
+
isError: true,
|
|
14
|
+
content: [{ type: 'text', text: JSON.stringify({ error, code }) }],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function successResponse(data) {
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function now() {
|
|
23
|
+
return new Date().toISOString();
|
|
24
|
+
}
|
|
25
|
+
export function broadcastChange(entity, action, payload) {
|
|
26
|
+
broadcast(action, { entity, action, payload });
|
|
27
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { startSSEServer } from './sse.js';
|
|
3
|
+
import { getDb } from './db.js';
|
|
4
|
+
import { broadcast } from './sse.js';
|
|
5
|
+
const httpOnly = process.argv.includes('--http-only');
|
|
6
|
+
// Close any orphaned sessions left from a previous crash
|
|
7
|
+
// If the server died while sessions were active, they'll have no `end` timestamp
|
|
8
|
+
function cleanupOrphanedSessions() {
|
|
9
|
+
const db = getDb();
|
|
10
|
+
const now = new Date().toISOString();
|
|
11
|
+
const orphaned = db.prepare('SELECT * FROM sessions WHERE end IS NULL').all();
|
|
12
|
+
if (orphaned.length === 0)
|
|
13
|
+
return;
|
|
14
|
+
db.prepare('UPDATE sessions SET end = ? WHERE end IS NULL').run(now);
|
|
15
|
+
// Set orphaned in_progress tasks back to paused
|
|
16
|
+
const taskIds = [...new Set(orphaned.map(s => s.task_id))];
|
|
17
|
+
for (const taskId of taskIds) {
|
|
18
|
+
const task = db.prepare('SELECT status FROM tasks WHERE id = ?').get(taskId);
|
|
19
|
+
if (task?.status === 'in_progress') {
|
|
20
|
+
db.prepare("UPDATE tasks SET status = 'paused', updated_at = ? WHERE id = ?").run(now, taskId);
|
|
21
|
+
broadcast('task_updated', { entity: 'task', action: 'task_status_changed', payload: db.prepare('SELECT * FROM tasks WHERE id = ?').get(taskId) });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
cleanupOrphanedSessions();
|
|
26
|
+
// Always start the HTTP/SSE server
|
|
27
|
+
startSSEServer();
|
|
28
|
+
// Only start MCP stdio transport when not in http-only mode
|
|
29
|
+
if (!httpOnly) {
|
|
30
|
+
const { McpServer } = await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
31
|
+
const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
|
|
32
|
+
const { registerTaskTools } = await import('./tools/tasks.js');
|
|
33
|
+
const { registerProjectTools } = await import('./tools/projects.js');
|
|
34
|
+
const { registerTimerTools } = await import('./tools/timer.js');
|
|
35
|
+
const { registerAnalyticsTools } = await import('./tools/analytics.js');
|
|
36
|
+
const { registerActivityTools } = await import('./tools/activity.js');
|
|
37
|
+
const { registerNotificationTools } = await import('./tools/notifications.js');
|
|
38
|
+
const { registerSettingsTools } = await import('./tools/settings.js');
|
|
39
|
+
const { registerAgentTools } = await import('./tools/agent.js');
|
|
40
|
+
const server = new McpServer({
|
|
41
|
+
name: 'taskflow',
|
|
42
|
+
version: '1.0.0',
|
|
43
|
+
});
|
|
44
|
+
registerAgentTools(server);
|
|
45
|
+
registerTaskTools(server);
|
|
46
|
+
registerProjectTools(server);
|
|
47
|
+
registerTimerTools(server);
|
|
48
|
+
registerAnalyticsTools(server);
|
|
49
|
+
registerActivityTools(server);
|
|
50
|
+
registerNotificationTools(server);
|
|
51
|
+
registerSettingsTools(server);
|
|
52
|
+
const transport = new StdioServerTransport();
|
|
53
|
+
await server.connect(transport);
|
|
54
|
+
}
|
package/dist/sse.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function startSSEServer(): void;
|
|
2
|
+
export declare function markSSEActive(): void;
|
|
3
|
+
/**
|
|
4
|
+
* Broadcast an SSE event. If this process owns the SSE server, send directly.
|
|
5
|
+
* Otherwise, relay via HTTP to the process that does (sidecar on port 3456).
|
|
6
|
+
*/
|
|
7
|
+
export declare function broadcast(event: string, data: object): void;
|