@hasna/todos 0.9.23 → 0.9.25
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/dist/mcp/index.js +89 -16
- package/dist/server/index.js +13 -8
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -6196,7 +6196,7 @@ ${text}` }] };
|
|
|
6196
6196
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6197
6197
|
}
|
|
6198
6198
|
});
|
|
6199
|
-
server.tool("get_task", "Get full task details
|
|
6199
|
+
server.tool("get_task", "Get full task details with relations", {
|
|
6200
6200
|
id: exports_external.string().describe("Task ID (full or partial)")
|
|
6201
6201
|
}, async ({ id }) => {
|
|
6202
6202
|
try {
|
|
@@ -6244,7 +6244,7 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
6244
6244
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6245
6245
|
}
|
|
6246
6246
|
});
|
|
6247
|
-
server.tool("update_task", "Update task fields
|
|
6247
|
+
server.tool("update_task", "Update task fields. Version required for optimistic locking.", {
|
|
6248
6248
|
id: exports_external.string().describe("Task ID (full or partial)"),
|
|
6249
6249
|
version: exports_external.number().describe("Current version (for optimistic locking)"),
|
|
6250
6250
|
title: exports_external.string().optional().describe("New title"),
|
|
@@ -6282,7 +6282,7 @@ server.tool("delete_task", "Delete a task permanently", {
|
|
|
6282
6282
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6283
6283
|
}
|
|
6284
6284
|
});
|
|
6285
|
-
server.tool("start_task", "Claim
|
|
6285
|
+
server.tool("start_task", "Claim, lock, and set task status to in_progress.", {
|
|
6286
6286
|
id: exports_external.string().describe("Task ID (full or partial)"),
|
|
6287
6287
|
agent_id: exports_external.string().describe("Agent claiming the task")
|
|
6288
6288
|
}, async ({ id, agent_id }) => {
|
|
@@ -6295,7 +6295,7 @@ ${formatTask(task)}` }] };
|
|
|
6295
6295
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6296
6296
|
}
|
|
6297
6297
|
});
|
|
6298
|
-
server.tool("complete_task", "Mark
|
|
6298
|
+
server.tool("complete_task", "Mark task completed and release lock.", {
|
|
6299
6299
|
id: exports_external.string().describe("Task ID (full or partial)"),
|
|
6300
6300
|
agent_id: exports_external.string().optional().describe("Agent completing the task")
|
|
6301
6301
|
}, async ({ id, agent_id }) => {
|
|
@@ -6335,7 +6335,7 @@ server.tool("unlock_task", "Release exclusive lock on a task", {
|
|
|
6335
6335
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6336
6336
|
}
|
|
6337
6337
|
});
|
|
6338
|
-
server.tool("add_dependency", "Add a dependency
|
|
6338
|
+
server.tool("add_dependency", "Add a dependency: task_id depends on depends_on.", {
|
|
6339
6339
|
task_id: exports_external.string().describe("Task that depends on another"),
|
|
6340
6340
|
depends_on: exports_external.string().describe("Task that must complete first")
|
|
6341
6341
|
}, async ({ task_id, depends_on }) => {
|
|
@@ -6526,7 +6526,7 @@ server.tool("delete_plan", "Delete a plan", {
|
|
|
6526
6526
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6527
6527
|
}
|
|
6528
6528
|
});
|
|
6529
|
-
server.tool("search_tasks", "Full-text search across task titles, descriptions,
|
|
6529
|
+
server.tool("search_tasks", "Full-text search across task titles, descriptions, tags.", {
|
|
6530
6530
|
query: exports_external.string().describe("Search query"),
|
|
6531
6531
|
project_id: exports_external.string().optional().describe("Limit to project"),
|
|
6532
6532
|
task_list_id: exports_external.string().optional().describe("Filter by task list")
|
|
@@ -6546,7 +6546,7 @@ ${text}` }] };
|
|
|
6546
6546
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6547
6547
|
}
|
|
6548
6548
|
});
|
|
6549
|
-
server.tool("sync", "Sync tasks with an agent task list
|
|
6549
|
+
server.tool("sync", "Sync tasks with an agent task list.", {
|
|
6550
6550
|
task_list_id: exports_external.string().optional().describe("Task list ID (required for Claude)"),
|
|
6551
6551
|
agent: exports_external.string().optional().describe("Agent/provider name (default: claude)"),
|
|
6552
6552
|
all_agents: exports_external.boolean().optional().describe("Sync across all configured agents"),
|
|
@@ -6594,7 +6594,7 @@ server.tool("sync", "Sync tasks with an agent task list (Claude uses native task
|
|
|
6594
6594
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6595
6595
|
}
|
|
6596
6596
|
});
|
|
6597
|
-
server.tool("register_agent", "Register an agent
|
|
6597
|
+
server.tool("register_agent", "Register an agent (idempotent by name).", {
|
|
6598
6598
|
name: exports_external.string().describe("Agent name"),
|
|
6599
6599
|
description: exports_external.string().optional().describe("Agent description")
|
|
6600
6600
|
}, async ({ name, description }) => {
|
|
@@ -6754,7 +6754,7 @@ Slug: ${list.slug}`
|
|
|
6754
6754
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6755
6755
|
}
|
|
6756
6756
|
});
|
|
6757
|
-
server.tool("delete_task_list", "Delete a task list. Tasks
|
|
6757
|
+
server.tool("delete_task_list", "Delete a task list. Tasks lose association but keep data.", {
|
|
6758
6758
|
id: exports_external.string().describe("Task list ID (full or partial)")
|
|
6759
6759
|
}, async ({ id }) => {
|
|
6760
6760
|
try {
|
|
@@ -6770,7 +6770,7 @@ server.tool("delete_task_list", "Delete a task list. Tasks in this list keep the
|
|
|
6770
6770
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6771
6771
|
}
|
|
6772
6772
|
});
|
|
6773
|
-
server.tool("get_task_history", "Get
|
|
6773
|
+
server.tool("get_task_history", "Get audit log for a task.", {
|
|
6774
6774
|
task_id: exports_external.string().describe("Task ID (full or partial)")
|
|
6775
6775
|
}, async ({ task_id }) => {
|
|
6776
6776
|
try {
|
|
@@ -6787,7 +6787,7 @@ ${text}` }] };
|
|
|
6787
6787
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6788
6788
|
}
|
|
6789
6789
|
});
|
|
6790
|
-
server.tool("get_recent_activity", "Get recent task changes across all tasks
|
|
6790
|
+
server.tool("get_recent_activity", "Get recent task changes across all tasks.", {
|
|
6791
6791
|
limit: exports_external.number().optional().describe("Max entries (default 50)")
|
|
6792
6792
|
}, async ({ limit }) => {
|
|
6793
6793
|
try {
|
|
@@ -6803,7 +6803,7 @@ ${text}` }] };
|
|
|
6803
6803
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6804
6804
|
}
|
|
6805
6805
|
});
|
|
6806
|
-
server.tool("create_webhook", "Register a webhook
|
|
6806
|
+
server.tool("create_webhook", "Register a webhook to receive task change events.", {
|
|
6807
6807
|
url: exports_external.string().describe("Webhook URL"),
|
|
6808
6808
|
events: exports_external.array(exports_external.string()).optional().describe("Event types to subscribe to (empty = all)"),
|
|
6809
6809
|
secret: exports_external.string().optional().describe("HMAC secret for signature verification")
|
|
@@ -6841,7 +6841,7 @@ server.tool("delete_webhook", "Delete a webhook", {
|
|
|
6841
6841
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6842
6842
|
}
|
|
6843
6843
|
});
|
|
6844
|
-
server.tool("create_template", "Create a reusable task template", {
|
|
6844
|
+
server.tool("create_template", "Create a reusable task template.", {
|
|
6845
6845
|
name: exports_external.string().describe("Template name"),
|
|
6846
6846
|
title_pattern: exports_external.string().describe("Title pattern for tasks created from this template"),
|
|
6847
6847
|
description: exports_external.string().optional().describe("Default description"),
|
|
@@ -6872,7 +6872,7 @@ ${text}` }] };
|
|
|
6872
6872
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6873
6873
|
}
|
|
6874
6874
|
});
|
|
6875
|
-
server.tool("create_task_from_template", "Create a task from a template with optional overrides", {
|
|
6875
|
+
server.tool("create_task_from_template", "Create a task from a template with optional overrides.", {
|
|
6876
6876
|
template_id: exports_external.string().describe("Template ID"),
|
|
6877
6877
|
title: exports_external.string().optional().describe("Override title"),
|
|
6878
6878
|
description: exports_external.string().optional().describe("Override description"),
|
|
@@ -6905,7 +6905,7 @@ server.tool("delete_template", "Delete a task template", { id: exports_external.
|
|
|
6905
6905
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6906
6906
|
}
|
|
6907
6907
|
});
|
|
6908
|
-
server.tool("approve_task", "Approve a task that requires approval
|
|
6908
|
+
server.tool("approve_task", "Approve a task that requires approval.", {
|
|
6909
6909
|
id: exports_external.string().describe("Task ID (full or partial)"),
|
|
6910
6910
|
agent_id: exports_external.string().optional().describe("Agent approving the task")
|
|
6911
6911
|
}, async ({ id, agent_id }) => {
|
|
@@ -6924,7 +6924,7 @@ server.tool("approve_task", "Approve a task that requires approval before comple
|
|
|
6924
6924
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6925
6925
|
}
|
|
6926
6926
|
});
|
|
6927
|
-
server.tool("get_my_tasks", "Get
|
|
6927
|
+
server.tool("get_my_tasks", "Get assigned tasks and stats for an agent.", {
|
|
6928
6928
|
agent_name: exports_external.string().describe("Your agent name")
|
|
6929
6929
|
}, async ({ agent_name }) => {
|
|
6930
6930
|
try {
|
|
@@ -6957,6 +6957,79 @@ In Progress:`);
|
|
|
6957
6957
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
6958
6958
|
}
|
|
6959
6959
|
});
|
|
6960
|
+
server.tool("search_tools", "List tool names matching a query.", { query: exports_external.string().optional().describe("Keyword to filter tools") }, async ({ query }) => {
|
|
6961
|
+
const all = [
|
|
6962
|
+
"create_task",
|
|
6963
|
+
"list_tasks",
|
|
6964
|
+
"get_task",
|
|
6965
|
+
"update_task",
|
|
6966
|
+
"delete_task",
|
|
6967
|
+
"start_task",
|
|
6968
|
+
"complete_task",
|
|
6969
|
+
"lock_task",
|
|
6970
|
+
"unlock_task",
|
|
6971
|
+
"approve_task",
|
|
6972
|
+
"add_dependency",
|
|
6973
|
+
"remove_dependency",
|
|
6974
|
+
"add_comment",
|
|
6975
|
+
"create_project",
|
|
6976
|
+
"list_projects",
|
|
6977
|
+
"create_plan",
|
|
6978
|
+
"list_plans",
|
|
6979
|
+
"get_plan",
|
|
6980
|
+
"update_plan",
|
|
6981
|
+
"delete_plan",
|
|
6982
|
+
"register_agent",
|
|
6983
|
+
"list_agents",
|
|
6984
|
+
"get_agent",
|
|
6985
|
+
"get_my_tasks",
|
|
6986
|
+
"create_task_list",
|
|
6987
|
+
"list_task_lists",
|
|
6988
|
+
"get_task_list",
|
|
6989
|
+
"update_task_list",
|
|
6990
|
+
"delete_task_list",
|
|
6991
|
+
"search_tasks",
|
|
6992
|
+
"sync",
|
|
6993
|
+
"get_task_history",
|
|
6994
|
+
"get_recent_activity",
|
|
6995
|
+
"create_webhook",
|
|
6996
|
+
"list_webhooks",
|
|
6997
|
+
"delete_webhook",
|
|
6998
|
+
"create_template",
|
|
6999
|
+
"list_templates",
|
|
7000
|
+
"create_task_from_template",
|
|
7001
|
+
"delete_template",
|
|
7002
|
+
"search_tools",
|
|
7003
|
+
"describe_tools"
|
|
7004
|
+
];
|
|
7005
|
+
const q = query?.toLowerCase();
|
|
7006
|
+
const matches = q ? all.filter((n) => n.includes(q)) : all;
|
|
7007
|
+
return { content: [{ type: "text", text: matches.join(", ") }] };
|
|
7008
|
+
});
|
|
7009
|
+
server.tool("describe_tools", "Get descriptions for specific tools by name.", { names: exports_external.array(exports_external.string()).describe("Tool names from search_tools") }, async ({ names }) => {
|
|
7010
|
+
const descriptions = {
|
|
7011
|
+
create_task: "Create a task. Params: title(req), description, priority, project_id, plan_id, tags, assigned_to, estimated_minutes, requires_approval",
|
|
7012
|
+
list_tasks: "List tasks. Params: status, priority, project_id, plan_id, assigned_to, tags, limit",
|
|
7013
|
+
get_task: "Get full task details. Params: id",
|
|
7014
|
+
update_task: "Update task fields. Params: id, version(req), title, description, status, priority, tags, assigned_to, due_at",
|
|
7015
|
+
delete_task: "Delete a task. Params: id",
|
|
7016
|
+
start_task: "Claim, lock, and start a task. Params: id",
|
|
7017
|
+
complete_task: "Mark task completed. Params: id, agent_id",
|
|
7018
|
+
approve_task: "Approve task requiring approval. Params: id, agent_id",
|
|
7019
|
+
create_plan: "Create a plan. Params: name, description, project_id, task_list_id, agent_id, status",
|
|
7020
|
+
list_plans: "List plans. Params: project_id",
|
|
7021
|
+
get_plan: "Get plan with tasks. Params: id",
|
|
7022
|
+
search_tasks: "Full-text search tasks. Params: query, project_id, task_list_id",
|
|
7023
|
+
get_my_tasks: "Get your tasks and stats. Params: agent_name",
|
|
7024
|
+
get_task_history: "Get task audit log. Params: task_id",
|
|
7025
|
+
get_recent_activity: "Recent changes across all tasks. Params: limit",
|
|
7026
|
+
create_template: "Create task template. Params: name, title_pattern, description, priority, tags",
|
|
7027
|
+
create_task_from_template: "Create task from template. Params: template_id, title, priority, assigned_to"
|
|
7028
|
+
};
|
|
7029
|
+
const result = names.map((n) => `${n}: ${descriptions[n] || "See tool schema"}`).join(`
|
|
7030
|
+
`);
|
|
7031
|
+
return { content: [{ type: "text", text: result }] };
|
|
7032
|
+
});
|
|
6960
7033
|
server.resource("tasks", "todos://tasks", { description: "All active tasks", mimeType: "application/json" }, async () => {
|
|
6961
7034
|
const tasks = listTasks({ status: ["pending", "in_progress"] });
|
|
6962
7035
|
return { contents: [{ uri: "todos://tasks", text: JSON.stringify(tasks, null, 2), mimeType: "application/json" }] };
|
package/dist/server/index.js
CHANGED
|
@@ -1429,8 +1429,8 @@ function serveStaticFile(filePath) {
|
|
|
1429
1429
|
headers: { "Content-Type": contentType }
|
|
1430
1430
|
});
|
|
1431
1431
|
}
|
|
1432
|
-
function taskToSummary(task) {
|
|
1433
|
-
|
|
1432
|
+
function taskToSummary(task, fields) {
|
|
1433
|
+
const full = {
|
|
1434
1434
|
id: task.id,
|
|
1435
1435
|
short_id: task.short_id,
|
|
1436
1436
|
title: task.title,
|
|
@@ -1450,6 +1450,9 @@ function taskToSummary(task) {
|
|
|
1450
1450
|
completed_at: task.completed_at,
|
|
1451
1451
|
due_at: task.due_at
|
|
1452
1452
|
};
|
|
1453
|
+
if (!fields || fields.length === 0)
|
|
1454
|
+
return full;
|
|
1455
|
+
return Object.fromEntries(fields.map((f) => [f, full[f] ?? null]));
|
|
1453
1456
|
}
|
|
1454
1457
|
async function startServer(port, options) {
|
|
1455
1458
|
const shouldOpen = options?.open ?? true;
|
|
@@ -1532,12 +1535,14 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
1532
1535
|
const status = url.searchParams.get("status") || undefined;
|
|
1533
1536
|
const projectId = url.searchParams.get("project_id") || undefined;
|
|
1534
1537
|
const limitParam = url.searchParams.get("limit");
|
|
1538
|
+
const fieldsParam = url.searchParams.get("fields");
|
|
1539
|
+
const fields = fieldsParam ? fieldsParam.split(",").map((f) => f.trim()).filter(Boolean) : undefined;
|
|
1535
1540
|
const tasks = listTasks({
|
|
1536
1541
|
status,
|
|
1537
1542
|
project_id: projectId,
|
|
1538
1543
|
limit: limitParam ? parseInt(limitParam, 10) : undefined
|
|
1539
1544
|
});
|
|
1540
|
-
return json(tasks.map(taskToSummary), 200, port);
|
|
1545
|
+
return json(tasks.map((t) => taskToSummary(t, fields)), 200, port);
|
|
1541
1546
|
}
|
|
1542
1547
|
if (path === "/api/tasks" && method === "POST") {
|
|
1543
1548
|
try {
|
|
@@ -1561,7 +1566,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
1561
1566
|
const status = url.searchParams.get("status") || undefined;
|
|
1562
1567
|
const projectId = url.searchParams.get("project_id") || undefined;
|
|
1563
1568
|
const tasks = listTasks({ status, project_id: projectId, limit: 1e4 });
|
|
1564
|
-
const summaries = tasks.map(taskToSummary);
|
|
1569
|
+
const summaries = tasks.map((t) => taskToSummary(t));
|
|
1565
1570
|
if (format === "csv") {
|
|
1566
1571
|
const headers = ["id", "short_id", "title", "status", "priority", "project_id", "assigned_to", "agent_id", "created_at", "updated_at", "completed_at", "due_at"];
|
|
1567
1572
|
const rows = summaries.map((t) => headers.map((h) => {
|
|
@@ -1687,8 +1692,8 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
1687
1692
|
const completed = allTasks.filter((t) => t.status === "completed");
|
|
1688
1693
|
return json({
|
|
1689
1694
|
agent,
|
|
1690
|
-
pending_tasks: pending.map(taskToSummary),
|
|
1691
|
-
in_progress_tasks: inProgress.map(taskToSummary),
|
|
1695
|
+
pending_tasks: pending.map((t) => taskToSummary(t)),
|
|
1696
|
+
in_progress_tasks: inProgress.map((t) => taskToSummary(t)),
|
|
1692
1697
|
stats: {
|
|
1693
1698
|
total: allTasks.length,
|
|
1694
1699
|
pending: pending.length,
|
|
@@ -1705,7 +1710,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
1705
1710
|
const queue = pending.filter((t) => t.assigned_to === agentId || t.agent_id === agentId || !t.assigned_to && !t.locked_by);
|
|
1706
1711
|
const order = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
1707
1712
|
queue.sort((a, b) => (order[a.priority] ?? 4) - (order[b.priority] ?? 4) || new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
|
|
1708
|
-
return json(queue.map(taskToSummary), 200, port);
|
|
1713
|
+
return json(queue.map((t) => taskToSummary(t)), 200, port);
|
|
1709
1714
|
}
|
|
1710
1715
|
if (path === "/api/tasks/claim" && method === "POST") {
|
|
1711
1716
|
try {
|
|
@@ -1921,7 +1926,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
1921
1926
|
if (!plan)
|
|
1922
1927
|
return json({ error: "Plan not found" }, 404, port);
|
|
1923
1928
|
const tasks = listTasks({ plan_id: id });
|
|
1924
|
-
return json({ ...plan, tasks: tasks.map(taskToSummary) }, 200, port);
|
|
1929
|
+
return json({ ...plan, tasks: tasks.map((t) => taskToSummary(t)) }, 200, port);
|
|
1925
1930
|
}
|
|
1926
1931
|
if (method === "PATCH") {
|
|
1927
1932
|
try {
|