@cyb3rk1d/todo-ai-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/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/api-client.d.ts +13 -0
- package/dist/api-client.js +47 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +212 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gary Kamoto Mhone (cyb3rk1d)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @cyb3rk1d/todo-ai-mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@cyb3rk1d/todo-ai-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that connects Claude Code to [Todo AI](https://cybers-todo.vercel.app). Manage your todo list, view summaries, and get AI recommendations directly from the CLI.
|
|
7
|
+
|
|
8
|
+
## Available Tools
|
|
9
|
+
|
|
10
|
+
| Tool | Description |
|
|
11
|
+
|------|-------------|
|
|
12
|
+
| `list_todos` | List all your todos |
|
|
13
|
+
| `get_todo` | Get a specific todo by ID |
|
|
14
|
+
| `create_todo` | Create a new todo with title, description, category, priority |
|
|
15
|
+
| `update_todo` | Update any field on a todo |
|
|
16
|
+
| `complete_todo` | Mark a todo as completed |
|
|
17
|
+
| `delete_todo` | Delete a todo permanently |
|
|
18
|
+
| `get_todos_by_date` | Get todos for a specific date |
|
|
19
|
+
| `get_todos_by_range` | Get todos within a date range |
|
|
20
|
+
| `get_today_summary` | Get today's daily summary |
|
|
21
|
+
| `list_summaries` | List all daily summaries |
|
|
22
|
+
| `create_summary` | Create a daily achievement summary |
|
|
23
|
+
| `get_current_review` | Get the current week's review |
|
|
24
|
+
| `list_reviews` | List all weekly reviews |
|
|
25
|
+
| `get_recommendations` | Get AI productivity recommendations |
|
|
26
|
+
| `generate_daily_summary` | AI-generate a daily summary from tasks |
|
|
27
|
+
| `generate_weekly_review` | AI-generate a weekly performance review |
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
### 1. Generate an API Token
|
|
32
|
+
|
|
33
|
+
Log into your Todo AI app and generate a long-lived API token:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
curl -X POST https://cybers-todo.vercel.app/api/auth/api-token \
|
|
37
|
+
-H "Authorization: Bearer <your-access-token>" \
|
|
38
|
+
-H "Content-Type: application/json"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This returns a token valid for 30 days.
|
|
42
|
+
|
|
43
|
+
### 2. Configure Claude Code
|
|
44
|
+
|
|
45
|
+
Add the MCP server to your project's `.mcp.json` or `~/.claude/settings.json`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"todo-ai": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["-y", "@cyb3rk1d/todo-ai-mcp"],
|
|
53
|
+
"env": {
|
|
54
|
+
"TODO_AI_API_URL": "https://cybers-todo.vercel.app",
|
|
55
|
+
"TODO_AI_TOKEN": "<your-api-token>"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Use It
|
|
63
|
+
|
|
64
|
+
Once configured, Claude Code will have access to all Todo AI tools. You can say things like:
|
|
65
|
+
|
|
66
|
+
- "Add a todo to fix the login bug with high priority"
|
|
67
|
+
- "Show me my todos for today"
|
|
68
|
+
- "Mark that authentication todo as completed"
|
|
69
|
+
- "What are my AI recommendations?"
|
|
70
|
+
- "Generate a summary of what I did today"
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git clone https://github.com/ZedTechInfo/todo-ai.git
|
|
76
|
+
cd todo-ai/mcp-server
|
|
77
|
+
|
|
78
|
+
# Install dependencies
|
|
79
|
+
npm install
|
|
80
|
+
|
|
81
|
+
# Build
|
|
82
|
+
npm run build
|
|
83
|
+
|
|
84
|
+
# Watch mode
|
|
85
|
+
npm run dev
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Environment Variables
|
|
89
|
+
|
|
90
|
+
| Variable | Required | Default | Description |
|
|
91
|
+
|----------|----------|---------|-------------|
|
|
92
|
+
| `TODO_AI_TOKEN` | Yes | - | API token from Todo AI |
|
|
93
|
+
| `TODO_AI_API_URL` | No | `http://localhost:4000` | Backend API URL |
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
[MIT](LICENSE) - Gary Kamoto Mhone (cyb3rk1d)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Todo AI backend API.
|
|
3
|
+
*/
|
|
4
|
+
interface ApiResponse<T = unknown> {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
status: number;
|
|
7
|
+
data: T;
|
|
8
|
+
}
|
|
9
|
+
export declare function apiGet<T = unknown>(path: string): Promise<ApiResponse<T>>;
|
|
10
|
+
export declare function apiPost<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
|
|
11
|
+
export declare function apiPut<T = unknown>(path: string, body: unknown): Promise<ApiResponse<T>>;
|
|
12
|
+
export declare function apiDelete(path: string): Promise<ApiResponse<null>>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Todo AI backend API.
|
|
3
|
+
*/
|
|
4
|
+
const apiUrl = process.env.TODO_AI_API_URL || "http://localhost:4000";
|
|
5
|
+
const apiToken = process.env.TODO_AI_TOKEN;
|
|
6
|
+
if (!apiToken) {
|
|
7
|
+
console.error("TODO_AI_TOKEN is required. Generate one at your Todo AI app or via POST /api/auth/api-token");
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const headers = {
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
Authorization: `Bearer ${apiToken}`,
|
|
13
|
+
};
|
|
14
|
+
export async function apiGet(path) {
|
|
15
|
+
const res = await fetch(`${apiUrl}${path}`, { headers });
|
|
16
|
+
const data = await res.json();
|
|
17
|
+
return { ok: res.ok, status: res.status, data: data };
|
|
18
|
+
}
|
|
19
|
+
export async function apiPost(path, body) {
|
|
20
|
+
const res = await fetch(`${apiUrl}${path}`, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers,
|
|
23
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
24
|
+
});
|
|
25
|
+
const data = await res.json();
|
|
26
|
+
return { ok: res.ok, status: res.status, data: data };
|
|
27
|
+
}
|
|
28
|
+
export async function apiPut(path, body) {
|
|
29
|
+
const res = await fetch(`${apiUrl}${path}`, {
|
|
30
|
+
method: "PUT",
|
|
31
|
+
headers,
|
|
32
|
+
body: JSON.stringify(body),
|
|
33
|
+
});
|
|
34
|
+
const data = await res.json();
|
|
35
|
+
return { ok: res.ok, status: res.status, data: data };
|
|
36
|
+
}
|
|
37
|
+
export async function apiDelete(path) {
|
|
38
|
+
const res = await fetch(`${apiUrl}${path}`, {
|
|
39
|
+
method: "DELETE",
|
|
40
|
+
headers,
|
|
41
|
+
});
|
|
42
|
+
if (res.status === 204) {
|
|
43
|
+
return { ok: true, status: 204, data: null };
|
|
44
|
+
}
|
|
45
|
+
const data = await res.json();
|
|
46
|
+
return { ok: res.ok, status: res.status, data: data };
|
|
47
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { apiGet, apiPost, apiPut, apiDelete } from "./api-client.js";
|
|
6
|
+
const server = new McpServer({
|
|
7
|
+
name: "todo-ai",
|
|
8
|
+
version: "1.0.0",
|
|
9
|
+
});
|
|
10
|
+
// ── Todo Tools ──────────────────────────────────────────────────────────
|
|
11
|
+
server.tool("list_todos", "List all todos for the authenticated user. Returns todos with title, description, category, priority, and status.", {}, async () => {
|
|
12
|
+
const res = await apiGet("/api/todos");
|
|
13
|
+
if (!res.ok) {
|
|
14
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
15
|
+
}
|
|
16
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
17
|
+
});
|
|
18
|
+
server.tool("get_todo", "Get a specific todo by ID", {
|
|
19
|
+
id: z.string().describe("The UUID of the todo"),
|
|
20
|
+
}, async ({ id }) => {
|
|
21
|
+
const res = await apiGet(`/api/todos/${id}`);
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
24
|
+
}
|
|
25
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
26
|
+
});
|
|
27
|
+
server.tool("create_todo", "Create a new todo item. Use this when the user wants to track a task, bug, feature, or any work item.", {
|
|
28
|
+
title: z.string().describe("Title of the todo"),
|
|
29
|
+
description: z.string().optional().describe("Detailed description"),
|
|
30
|
+
category: z
|
|
31
|
+
.enum(["development", "design", "meeting", "review", "personal"])
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Category (default: development)"),
|
|
34
|
+
priority: z
|
|
35
|
+
.enum(["low", "medium", "high"])
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("Priority level (default: medium)"),
|
|
38
|
+
}, async ({ title, description, category, priority }) => {
|
|
39
|
+
const todo = { title };
|
|
40
|
+
if (description)
|
|
41
|
+
todo.description = description;
|
|
42
|
+
if (category)
|
|
43
|
+
todo.category = category;
|
|
44
|
+
if (priority)
|
|
45
|
+
todo.priority = priority;
|
|
46
|
+
const res = await apiPost("/api/todos", { todo });
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
49
|
+
}
|
|
50
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
51
|
+
});
|
|
52
|
+
server.tool("update_todo", "Update an existing todo's title, description, category, priority, or status", {
|
|
53
|
+
id: z.string().describe("The UUID of the todo to update"),
|
|
54
|
+
title: z.string().optional().describe("New title"),
|
|
55
|
+
description: z.string().optional().describe("New description"),
|
|
56
|
+
category: z
|
|
57
|
+
.enum(["development", "design", "meeting", "review", "personal"])
|
|
58
|
+
.optional()
|
|
59
|
+
.describe("New category"),
|
|
60
|
+
priority: z
|
|
61
|
+
.enum(["low", "medium", "high"])
|
|
62
|
+
.optional()
|
|
63
|
+
.describe("New priority"),
|
|
64
|
+
status: z
|
|
65
|
+
.enum(["pending", "completed"])
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("New status"),
|
|
68
|
+
}, async ({ id, title, description, category, priority, status }) => {
|
|
69
|
+
const todo = {};
|
|
70
|
+
if (title)
|
|
71
|
+
todo.title = title;
|
|
72
|
+
if (description)
|
|
73
|
+
todo.description = description;
|
|
74
|
+
if (category)
|
|
75
|
+
todo.category = category;
|
|
76
|
+
if (priority)
|
|
77
|
+
todo.priority = priority;
|
|
78
|
+
if (status)
|
|
79
|
+
todo.status = status;
|
|
80
|
+
const res = await apiPut(`/api/todos/${id}`, { todo });
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
83
|
+
}
|
|
84
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
85
|
+
});
|
|
86
|
+
server.tool("complete_todo", "Mark a todo as completed", {
|
|
87
|
+
id: z.string().describe("The UUID of the todo to complete"),
|
|
88
|
+
}, async ({ id }) => {
|
|
89
|
+
const res = await apiPut(`/api/todos/${id}`, {
|
|
90
|
+
todo: { status: "completed", completed_at: new Date().toISOString() },
|
|
91
|
+
});
|
|
92
|
+
if (!res.ok) {
|
|
93
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
94
|
+
}
|
|
95
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
96
|
+
});
|
|
97
|
+
server.tool("delete_todo", "Delete a todo item permanently", {
|
|
98
|
+
id: z.string().describe("The UUID of the todo to delete"),
|
|
99
|
+
}, async ({ id }) => {
|
|
100
|
+
const res = await apiDelete(`/api/todos/${id}`);
|
|
101
|
+
if (!res.ok) {
|
|
102
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
103
|
+
}
|
|
104
|
+
return { content: [{ type: "text", text: "Todo deleted successfully." }] };
|
|
105
|
+
});
|
|
106
|
+
server.tool("get_todos_by_date", "Get all todos for a specific date", {
|
|
107
|
+
date: z.string().describe("Date in YYYY-MM-DD format"),
|
|
108
|
+
}, async ({ date }) => {
|
|
109
|
+
const res = await apiGet(`/api/todos/by-date/${date}`);
|
|
110
|
+
if (!res.ok) {
|
|
111
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
112
|
+
}
|
|
113
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
114
|
+
});
|
|
115
|
+
server.tool("get_todos_by_range", "Get all todos within a date range", {
|
|
116
|
+
start_date: z.string().describe("Start date in YYYY-MM-DD format"),
|
|
117
|
+
end_date: z.string().describe("End date in YYYY-MM-DD format"),
|
|
118
|
+
}, async ({ start_date, end_date }) => {
|
|
119
|
+
const res = await apiGet(`/api/todos/by-range?start_date=${start_date}&end_date=${end_date}`);
|
|
120
|
+
if (!res.ok) {
|
|
121
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
122
|
+
}
|
|
123
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
124
|
+
});
|
|
125
|
+
// ── Summary Tools ───────────────────────────────────────────────────────
|
|
126
|
+
server.tool("get_today_summary", "Get today's daily achievement summary", {}, async () => {
|
|
127
|
+
const res = await apiGet("/api/summaries/today");
|
|
128
|
+
if (!res.ok) {
|
|
129
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
130
|
+
}
|
|
131
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
132
|
+
});
|
|
133
|
+
server.tool("list_summaries", "List all daily summaries", {}, async () => {
|
|
134
|
+
const res = await apiGet("/api/summaries");
|
|
135
|
+
if (!res.ok) {
|
|
136
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
137
|
+
}
|
|
138
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
139
|
+
});
|
|
140
|
+
server.tool("create_summary", "Create a daily achievement summary", {
|
|
141
|
+
date: z.string().describe("Date in YYYY-MM-DD format"),
|
|
142
|
+
achievements: z.string().describe("Description of achievements for the day"),
|
|
143
|
+
notes: z.string().optional().describe("Additional notes"),
|
|
144
|
+
mood: z
|
|
145
|
+
.enum(["great", "good", "okay", "tough"])
|
|
146
|
+
.optional()
|
|
147
|
+
.describe("How the day went (default: good)"),
|
|
148
|
+
completed_count: z.number().optional().describe("Number of tasks completed"),
|
|
149
|
+
}, async ({ date, achievements, notes, mood, completed_count }) => {
|
|
150
|
+
const summary = { date, achievements };
|
|
151
|
+
if (notes)
|
|
152
|
+
summary.notes = notes;
|
|
153
|
+
if (mood)
|
|
154
|
+
summary.mood = mood;
|
|
155
|
+
if (completed_count !== undefined)
|
|
156
|
+
summary.completed_count = completed_count;
|
|
157
|
+
const res = await apiPost("/api/summaries", { summary });
|
|
158
|
+
if (!res.ok) {
|
|
159
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
160
|
+
}
|
|
161
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
162
|
+
});
|
|
163
|
+
// ── Review Tools ────────────────────────────────────────────────────────
|
|
164
|
+
server.tool("get_current_review", "Get the current week's performance review", {}, async () => {
|
|
165
|
+
const res = await apiGet("/api/reviews/current");
|
|
166
|
+
if (!res.ok) {
|
|
167
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
168
|
+
}
|
|
169
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
170
|
+
});
|
|
171
|
+
server.tool("list_reviews", "List all weekly performance reviews", {}, async () => {
|
|
172
|
+
const res = await apiGet("/api/reviews");
|
|
173
|
+
if (!res.ok) {
|
|
174
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
175
|
+
}
|
|
176
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
177
|
+
});
|
|
178
|
+
// ── AI Tools ────────────────────────────────────────────────────────────
|
|
179
|
+
server.tool("get_recommendations", "Get AI-powered productivity recommendations based on your todo history", {}, async () => {
|
|
180
|
+
const res = await apiPost("/api/ai/recommendations");
|
|
181
|
+
if (!res.ok) {
|
|
182
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
183
|
+
}
|
|
184
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
185
|
+
});
|
|
186
|
+
server.tool("generate_daily_summary", "Use AI to generate a daily summary from completed tasks", {
|
|
187
|
+
date: z.string().describe("Date in YYYY-MM-DD format"),
|
|
188
|
+
}, async ({ date }) => {
|
|
189
|
+
const res = await apiPost("/api/ai/generate-summary", { date });
|
|
190
|
+
if (!res.ok) {
|
|
191
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
192
|
+
}
|
|
193
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
194
|
+
});
|
|
195
|
+
server.tool("generate_weekly_review", "Use AI to generate a weekly performance review", {
|
|
196
|
+
week_start: z.string().describe("Start of week date in YYYY-MM-DD format"),
|
|
197
|
+
}, async ({ week_start }) => {
|
|
198
|
+
const res = await apiPost("/api/ai/generate-review", { week_start });
|
|
199
|
+
if (!res.ok) {
|
|
200
|
+
return { content: [{ type: "text", text: `Error: ${JSON.stringify(res.data)}` }], isError: true };
|
|
201
|
+
}
|
|
202
|
+
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
|
203
|
+
});
|
|
204
|
+
// ── Start Server ────────────────────────────────────────────────────────
|
|
205
|
+
async function main() {
|
|
206
|
+
const transport = new StdioServerTransport();
|
|
207
|
+
await server.connect(transport);
|
|
208
|
+
}
|
|
209
|
+
main().catch((err) => {
|
|
210
|
+
console.error("Fatal error:", err);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cyb3rk1d/todo-ai-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for Todo AI - allows Claude Code to manage your todo list",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"todo-ai-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"claude-code",
|
|
18
|
+
"model-context-protocol",
|
|
19
|
+
"todo",
|
|
20
|
+
"todo-ai",
|
|
21
|
+
"productivity",
|
|
22
|
+
"cyb3rk1d",
|
|
23
|
+
"gary-kamoto-mhone"
|
|
24
|
+
],
|
|
25
|
+
"author": "Gary Kamoto Mhone (cyb3rk1d)",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"homepage": "https://cybers-todo.vercel.app",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/ZedTechInfo/todo-ai.git",
|
|
31
|
+
"directory": "mcp-server"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/ZedTechInfo/todo-ai/issues"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
41
|
+
"zod": "^3.24.4"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"typescript": "^5.8.3",
|
|
45
|
+
"@types/node": "^22.15.2"
|
|
46
|
+
},
|
|
47
|
+
"files": [
|
|
48
|
+
"dist",
|
|
49
|
+
"LICENSE",
|
|
50
|
+
"README.md"
|
|
51
|
+
]
|
|
52
|
+
}
|