roadmap-skill 0.2.9 → 0.2.10

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/CHANGELOG.md CHANGED
@@ -5,6 +5,65 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.10] - 2026-02-27
9
+
10
+ ### Added
11
+ - **Contributing Section**: Added Contributing section to README (en/zh)
12
+
13
+ ### Changed
14
+ - **README**: Revamped copy for both en/zh versions, improved clarity and tone
15
+ - **Tag ID Workflow**: Unified tag-id handling with deterministic color fallback
16
+
17
+
18
+ ## [0.2.9] - 2026-02-26
19
+
20
+ ### Added
21
+ - **Development Scripts**: Added `dev:web`, `dev:server`, `dev:full`, and `inspector` npm scripts
22
+ - **Vite Proxy**: Frontend dev server now proxies API requests to backend automatically
23
+ - **Verbose Parameter**: Tools now support `verbose` parameter for compact vs full data responses
24
+ - **Summary Types**: Added `TaskSummary` and `ProjectSummary` types for lightweight responses
25
+ - **MCP Inspector**: Added `npm run inspector` command for debugging MCP server
26
+
27
+ ### Changed
28
+ - **UI Layout**: Moved filter bar to header alongside title for better space usage
29
+ - **Compact Mode**: Optimized spacing, removed tags, reduced margins and padding
30
+ - **Hover Animation**: Reduced card hover displacement from `-translate-y-1` to `-translate-y-0.5`
31
+ - **Create Button**: Changed task creation button color to project theme green
32
+
33
+ ### Fixed
34
+ - **Completed Tasks**: Fixed "All" filter to properly include completed tasks via `includeCompleted` parameter
35
+
36
+ ## [0.2.8] - 2026-02-26
37
+
38
+ ### Fixed
39
+ - **MCP Transport**: Resolved stdio transport issues for better CLI compatibility
40
+ - **Tag System**: Improved tag management and display in task cards
41
+
42
+ ### Changed
43
+ - Updated README with latest features and improvements
44
+
45
+ ## [0.2.7] - 2026-02-26
46
+
47
+ ### Fixed
48
+ - **Static Files Path**: Corrected bundled static files path for npx environment execution
49
+
50
+ ### Added
51
+ - **Release Documentation**: Added release workflow documentation to AGENTS.md
52
+
53
+ ## [0.2.6] - 2026-02-26
54
+
55
+ ### Fixed
56
+ - **Static Files Path**: Resolved static files path resolution for npx execution environment
57
+
58
+ ## [0.2.5] - 2026-02-26
59
+
60
+ ### Added
61
+ - **NovaBoard UI**: Integrated tag system with NovaBoard-style dashboard design
62
+ - **Tag System**: Full tag management with color coding and filtering
63
+
64
+ ### Fixed
65
+ - **Server Path**: Use `__dirname` instead of `process.cwd()` for reliable static files path resolution
66
+
8
67
  ## [0.2.0] - 2026-02-10
9
68
 
10
69
  ### Added
package/README.md CHANGED
@@ -5,8 +5,8 @@
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
- <strong>Let AI manage your projects, keep Kanban simple</strong><br>
9
- Zero-config startup, local data, Agent-native support
8
+ <strong>Shared roadmap for humans and AI Agents</strong><br>
9
+ Visual kanban for you. MCP server for Agents. Local-first.
10
10
  </p>
11
11
 
12
12
  <p align="center">
@@ -26,15 +26,15 @@
26
26
 
27
27
  ---
28
28
 
29
- ## Why Roadmap Skill?
29
+ ## What Makes It Different
30
30
 
31
- | Your Pain Point | How Roadmap Skill Solves It |
32
- |----------------|----------------------------|
33
- | Project data scattered in third-party clouds | **Local-first** All data stored on your machine, full control, works offline |
34
- | Copy-pasting task lists when chatting with AI | **Agent-native** — AI reads/writes tasks directly, zero friction in conversation |
35
- | Text-only management lacks visuals, but traditional tools are bloated | **Beautiful Kanban** Open browser when needed, drag and drop, doesn't interrupt coding flow |
36
- | Ideas and bugs from Vibe Coding get forgotten | **Collection Box** — Let Agent capture scattered thoughts, auto-organize todos |
37
- | Too many tasks, don't know where to start | **Smart Recommendations** — Agent analyzes context, proactively suggests next steps |
31
+ **Shared context** Chat with your Agent to plan tasks, or edit directly in the Kanban — both stay in sync. Your Agent always sees the latest state.
32
+
33
+ **Agent-native** Built as an MCP server. Your AI can create, update, and query tasks directly in conversation.
34
+
35
+ **Lightweight Kanban** Open `localhost:7860` when you feel like it, or ask your Agent to open it with `open_web_interface`. Or just stay in chat. All three work.
36
+
37
+ **Local-first** Your data lives on your machine. No accounts, no cloud sync, no vendor lock-in.
38
38
 
39
39
  ---
40
40
 
@@ -282,69 +282,35 @@ The AI will immediately create the project and tasks, saving them to local stora
282
282
 
283
283
  ## Who Is This For?
284
284
 
285
- | Scenario | What Roadmap Skill Does For You |
286
- |---------|--------------------------------|
287
- | **Solo Developers** | Manage personal projects through conversation, avoid getting lost in complex tools |
288
- | **AI Power Users** | Let Agent directly read/write tasks, goodbye to copy-pasting hassle |
289
- | **Vibe Coders** | Capture inspirations on the fly, automatically save to collection box |
290
- | **Small Teams** | Simple task assignment and progress tracking, zero learning curve |
291
- | **Privacy-conscious Users** | Data stored completely locally, never uploaded to any cloud service |
285
+ Solo developers, AI power users, and vibe coders who want their Agent to be a real collaborator — not just a code generator.
292
286
 
293
287
  ---
294
288
 
295
289
  ## Typical Use Cases
296
290
 
297
- ### 1. Capture Inspiration During Vibe Coding
298
-
299
- When discussing new features with AI, suddenly think of an optimization:
300
-
301
- > "Add this to my collection: Refactor user auth module using JWT + Refresh Token scheme"
302
-
303
- AI automatically creates the task, and you'll see it in the Kanban later.
304
-
305
- ### 2. Let AI Plan Project Structure
306
-
307
- Starting a new project? Just ask AI to break it down:
308
-
309
- > "Create an e-commerce admin dashboard project with product management, order processing, and user permissions modules, broken down into specific development tasks"
310
-
311
- AI auto-creates the project structure. Just open the Kanban in browser and drag tasks to start working.
291
+ ### 1. Capture Ideas Without Breaking Flow
312
292
 
313
- ### 3. Progress Tracking and Status Updates
293
+ Mid-session, something comes to mind:
314
294
 
315
- Check progress anytime during coding:
295
+ > "Note this down: switch the auth module to JWT + refresh token rotation"
316
296
 
317
- > "What's the completion percentage of my current project? What high-priority tasks haven't started yet?"
297
+ Your Agent creates the task. You stay in flow. Open the Kanban later to review.
318
298
 
319
- > "Mark the user login feature as completed and create corresponding test tasks"
299
+ ### 2. Let AI Bootstrap Your Project Plan
320
300
 
321
- ### 4. Team Collaboration and Assignment
301
+ Starting something new:
322
302
 
323
- Quickly assign in conversation:
303
+ > "Set up a project for the admin dashboard — product management, orders, and user permissions. Break each into tasks."
324
304
 
325
- > "Assign frontend page tasks to @zhangsan, deadline this Friday, priority high"
305
+ Agent scaffolds the whole structure. You open the board and start dragging.
326
306
 
327
- Team members can view their task list in the Kanban.
307
+ ### 3. Check In Without Leaving the Chat
328
308
 
329
- ---
330
-
331
- ## Installation
332
-
333
- ### Requirements
334
-
335
- - Node.js 18+ (recommended 20+)
336
-
337
- ### Global Install
309
+ > "What's left on the current project? Anything high priority I haven't touched?"
338
310
 
339
- ```bash
340
- npm install -g roadmap-skill
341
- ```
342
-
343
- ### Use Without Installing
311
+ > "Mark the login feature done and add a task for writing tests."
344
312
 
345
- ```bash
346
- npx roadmap-skill # Full MCP server
347
- ```
313
+ No tab switching. No copy-pasting. Just ask.
348
314
 
349
315
  ---
350
316
 
package/README.zh.md CHANGED
@@ -5,8 +5,8 @@
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
- <strong>让 AI 帮你管理项目,让看板回归简洁</strong><br>
9
- 零配置启动,本地数据,Agent 原生支持
8
+ <strong>人类与 AI Agent 共享的项目看板</strong><br>
9
+ 你看到的,Agent 也看到。对话里规划,看板里审阅。或者相反。
10
10
  </p>
11
11
 
12
12
  <p align="center">
@@ -26,15 +26,15 @@
26
26
 
27
27
  ---
28
28
 
29
- ## 为什么选择 Roadmap Skill?
29
+ ## 这个 MCP 有什么不同?
30
30
 
31
- | 你的困扰 | Roadmap Skill 的解决方式 |
32
- |---------|-------------------------|
33
- | 项目数据散落在第三方云端,缺乏安全感 | **本地优先** 所有数据存储在你的电脑,完全掌控,离线可用 |
34
- | 和 AI 对话时需要来回粘贴任务列表 | **Agent 原生** — AI 直接读写任务,对话中自然管理,零摩擦 |
35
- | 纯文本管理缺乏直观性,但传统工具太重 | **美观看板** 需要时打开浏览器,拖拽即可,不打扰编码流 |
36
- | Vibe Coding 中的灵感、Bug 随手记在某处就忘了 | **收集箱** — 让 Agent 帮你沉淀零散想法,自动整理待办 |
37
- | 任务太多不知从何开始,优先级全靠猜 | **智能推荐** Agent 分析项目上下文,主动建议下一步工作 |
31
+ **人机共享视图** 在对话里和 Agent 一起规划任务,也可以直接在看板上手动编辑,两种方式实时互通。你和Agent 始终能获取到最新状态。
32
+
33
+ **Agent 原生** MCP 服务器形式运行。AI 可以在对话中直接创建、更新、查询任务。
34
+
35
+ **轻量看板** 你想看的时候打开 `localhost:7860`。懒得开浏览器?直接让 Agent `/open-web-ui` 也行。
36
+
37
+ **本地优先**数据存在你的机器上。无需账号,无云同步,不依赖任何第三方服务。
38
38
 
39
39
  ---
40
40
 
@@ -279,69 +279,33 @@ AI 会立即为你创建项目和任务,并自动写入本地存储。你可
279
279
 
280
280
  ## 适合谁使用
281
281
 
282
- | 场景 | Roadmap Skill 能为你做什么 |
283
- |------|---------------------------|
284
- | **独立开发者** | 用对话管理个人项目,避免在复杂工具中迷失 |
285
- | **AI 重度用户** | 让 Agent 直接读写任务,告别来回粘贴的繁琐 |
286
- | **Vibe Coder** | 随手让 AI 记录灵感,自动沉淀到收集箱 |
287
- | **小团队协作** | 简单的任务分配与进度追踪,无需学习成本 |
288
- | **隐私敏感者** | 数据完全本地存储,不上传任何云端服务 |
289
-
290
- ---
282
+ 独立开发者、AI 重度用户、Vibe Coder 想让 Agent 真正参与项目协作,而不只是写代码的人。
291
283
 
292
284
  ## 典型使用场景
293
285
 
294
- ### 1. Vibe Coding 中的灵感收集
295
-
296
- 正在和 AI 讨论新功能时,突然想到一个优化点:
297
-
298
- > "帮我把这个想法记到收集箱:重构用户认证模块,使用 JWT + Refresh Token 方案"
299
-
300
- AI 自动创建任务,稍后你打开看板就能看到待整理的想法。
301
-
302
- ### 2. 让 AI 规划项目结构
303
-
304
- 开始一个新项目时,直接让 AI 帮你分解:
305
-
306
- > "创建一个电商后台管理项目,包含商品管理、订单处理、用户权限三个模块,每个模块分解为具体的开发任务"
286
+ ### 1. 不打断流地记录想法
307
287
 
308
- AI 自动创建项目结构,你只需要在浏览器中打开看板,拖拽任务开始工作。
288
+ 编着编着突然想到一个优化点:
309
289
 
310
- ### 3. 进度追踪与状态更新
290
+ > "记一下:把认证模块改成 JWT + refresh token 方案"
311
291
 
312
- 编码过程中随时询问:
292
+ Agent 创建任务。你继续写代码。稍后打开看板再回顾。
313
293
 
314
- > "我当前项目完成了多少百分比?有哪些高优先级任务还没开始?"
294
+ ### 2. 让 AI 帮你搭建项目结构
315
295
 
316
- > "把用户登录功能的状态改为已完成,并创建对应的测试任务"
296
+ 开始一个新项目:
317
297
 
318
- ### 4. 团队协作分配
298
+ > "创建一个电商后台项目,包含商品管理、订单处理、用户权限三个模块,每个模块拆分为具体任务"
319
299
 
320
- 在对话中快速分配:
300
+ Agent 直接搭好整个结构。你打开看板开始拖拽。
321
301
 
322
- > "把前端页面的任务分配给 @张三,截止日期设为本周五,优先级设为高"
302
+ ### 3. 不离开对话窗口就能检查进度
323
303
 
324
- 团队成员可以在看板中查看自己的任务列表。
304
+ > "当前项目还剩什么?有没有高优先级的任务还没动?"
325
305
 
326
- ---
327
-
328
- ## 安装
329
-
330
- ### 环境要求
306
+ > "把登录功能标为已完成,再加一个写测试的任务"
331
307
 
332
- - Node.js 18+ (推荐 20+)
333
-
334
- ### 全局安装
335
-
336
- ```bash
337
- npm install -g roadmap-skill
338
- ```
339
-
340
- ### 免安装使用
341
-
342
- ```bash
343
- npx roadmap-skill # 完整 MCP 服务器
344
- ```
308
+ 不用切换标签页,不用复制粘贴。直接问就行。
345
309
 
346
310
  ---
347
311
 
@@ -359,11 +323,9 @@ npx roadmap-skill # 完整 MCP 服务器
359
323
 
360
324
  ## 支持平台
361
325
 
362
- - ✅ **Claude Code** — 命令行 AI 助手
363
- - ✅ **Claude Desktop** — 完整 MCP 集成
364
- - ✅ **Cursor**AI 驱动的 IDE
365
- - ✅ **VS Code** — 通过 Cline 或 Roo Code 扩展
366
- - ✅ **任意 MCP 客户端** — 标准 MCP 协议支持
326
+ - ✅ **Claude Code, Codex, OpenCode** — 命令行 AI 助手
327
+ - ✅ **Cursor, VS Code** — AI 驱动的 IDE
328
+ - ✅ **任意支持 MCP 的客户端** 标准 MCP 协议支持
367
329
 
368
330
  ---
369
331
 
package/dist/index.js CHANGED
@@ -345,14 +345,15 @@ var storage = new ProjectStorage();
345
345
  // src/tools/project-tools.ts
346
346
  var ProjectTypeEnum = z.enum(["roadmap", "skill-tree", "kanban"]);
347
347
  var ProjectStatusEnum = z.enum(["active", "completed", "archived"]);
348
- function toProjectSummary(project, taskCount) {
348
+ function toProjectSummary(project, taskCount, tags) {
349
349
  return {
350
350
  id: project.id,
351
351
  name: project.name,
352
352
  projectType: project.projectType,
353
353
  status: project.status,
354
354
  targetDate: project.targetDate,
355
- taskCount
355
+ taskCount,
356
+ ...tags ? { tags } : {}
356
357
  };
357
358
  }
358
359
  function toTaskSummary(task) {
@@ -401,16 +402,33 @@ var createProjectTool = {
401
402
  };
402
403
  var listProjectsTool = {
403
404
  name: "list_projects",
404
- description: "List all projects. Returns summaries by default; set verbose=true for full project data.",
405
+ description: "List all projects. Summary mode includes current project tags for Agent reuse. Set verbose=true for full project data.",
405
406
  inputSchema: z.object({
406
407
  verbose: z.boolean().optional()
407
408
  }),
408
409
  async execute(input) {
409
410
  try {
410
411
  const projects = await storage.listProjects();
412
+ if (input.verbose) {
413
+ return {
414
+ success: true,
415
+ data: projects
416
+ };
417
+ }
418
+ const summaries = await Promise.all(
419
+ projects.map(async (projectSummary) => {
420
+ const projectData = await storage.readProject(projectSummary.project.id);
421
+ const tags = (projectData?.tags ?? []).map((tag) => ({
422
+ id: tag.id,
423
+ name: tag.name,
424
+ color: tag.color
425
+ }));
426
+ return toProjectSummary(projectSummary.project, projectSummary.taskCount, tags);
427
+ })
428
+ );
411
429
  return {
412
430
  success: true,
413
- data: input.verbose ? projects : projects.map((p) => toProjectSummary(p.project, p.taskCount))
431
+ data: summaries
414
432
  };
415
433
  } catch (error) {
416
434
  return {
@@ -533,6 +551,39 @@ init_esm_shims();
533
551
  function generateTagId() {
534
552
  return `tag_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
535
553
  }
554
+ var HEX_COLOR_PATTERN = /^#[0-9A-Fa-f]{6}$/;
555
+ var TAG_COLOR_PALETTE = [
556
+ "#FF6B6B",
557
+ "#FF9F43",
558
+ "#FDCB6E",
559
+ "#6C5CE7",
560
+ "#74B9FF",
561
+ "#00B894",
562
+ "#00CEC9",
563
+ "#E17055",
564
+ "#FAB1A0",
565
+ "#55A3FF",
566
+ "#A29BFE",
567
+ "#FD79A8"
568
+ ];
569
+ function hashTagName(value) {
570
+ let hash = 5381;
571
+ for (const char of value.toLowerCase()) {
572
+ hash = hash * 33 ^ char.charCodeAt(0);
573
+ }
574
+ return Math.abs(hash >>> 0);
575
+ }
576
+ function resolveTagColor(tagName, inputColor) {
577
+ if (inputColor) {
578
+ return inputColor;
579
+ }
580
+ const normalizedTagName = tagName.trim();
581
+ if (normalizedTagName.length === 0) {
582
+ return TAG_COLOR_PALETTE[0];
583
+ }
584
+ const colorIndex = hashTagName(normalizedTagName) % TAG_COLOR_PALETTE.length;
585
+ return TAG_COLOR_PALETTE[colorIndex];
586
+ }
536
587
  var TagService = class {
537
588
  storage;
538
589
  constructor(storage2) {
@@ -564,11 +615,19 @@ var TagService = class {
564
615
  code: "DUPLICATE_ERROR"
565
616
  };
566
617
  }
618
+ const resolvedColor = resolveTagColor(data.name, data.color);
619
+ if (!HEX_COLOR_PATTERN.test(resolvedColor)) {
620
+ return {
621
+ success: false,
622
+ error: `Color must be a valid hex code (e.g., #FF5733), received '${resolvedColor}'`,
623
+ code: "VALIDATION_ERROR"
624
+ };
625
+ }
567
626
  const now = (/* @__PURE__ */ new Date()).toISOString();
568
627
  const tag = {
569
628
  id: generateTagId(),
570
629
  name: data.name,
571
- color: data.color,
630
+ color: resolvedColor,
572
631
  description: data.description || "",
573
632
  createdAt: now
574
633
  };
@@ -667,6 +726,13 @@ var TagService = class {
667
726
  };
668
727
  }
669
728
  }
729
+ if (data.color && !HEX_COLOR_PATTERN.test(data.color)) {
730
+ return {
731
+ success: false,
732
+ error: `Color must be a valid hex code (e.g., #FF5733), received '${data.color}'`,
733
+ code: "VALIDATION_ERROR"
734
+ };
735
+ }
670
736
  const now = (/* @__PURE__ */ new Date()).toISOString();
671
737
  const existingTag = projectData.tags[tagIndex];
672
738
  const updatedTag = {
@@ -818,6 +884,10 @@ function calculateCompletedAt(currentStatus, newStatus, existingCompletedAt, now
818
884
  }
819
885
  return existingCompletedAt;
820
886
  }
887
+ function findInvalidTagIds(projectData, tagIds) {
888
+ const validTagIds = new Set(projectData.tags.map((tag) => tag.id));
889
+ return tagIds.filter((tagId) => !validTagIds.has(tagId));
890
+ }
821
891
  var TaskService = {
822
892
  /**
823
893
  * Create a new task in a project
@@ -835,6 +905,15 @@ var TaskService = {
835
905
  code: "NOT_FOUND"
836
906
  };
837
907
  }
908
+ const incomingTagIds = data.tags ?? [];
909
+ const invalidTagIds = findInvalidTagIds(projectData, incomingTagIds);
910
+ if (invalidTagIds.length > 0) {
911
+ return {
912
+ success: false,
913
+ error: `Invalid tag IDs for project '${projectId}': ${invalidTagIds.join(", ")}`,
914
+ code: "VALIDATION_ERROR"
915
+ };
916
+ }
838
917
  const now = (/* @__PURE__ */ new Date()).toISOString();
839
918
  const task = {
840
919
  id: generateTaskId(),
@@ -843,7 +922,7 @@ var TaskService = {
843
922
  description: data.description,
844
923
  status: "todo",
845
924
  priority: data.priority ?? "medium",
846
- tags: data.tags ?? [],
925
+ tags: incomingTagIds,
847
926
  dueDate: data.dueDate ?? null,
848
927
  assignee: data.assignee ?? null,
849
928
  createdAt: now,
@@ -936,6 +1015,16 @@ var TaskService = {
936
1015
  code: "VALIDATION_ERROR"
937
1016
  };
938
1017
  }
1018
+ if (data.tags) {
1019
+ const invalidTagIds = findInvalidTagIds(projectData, data.tags);
1020
+ if (invalidTagIds.length > 0) {
1021
+ return {
1022
+ success: false,
1023
+ error: `Invalid tag IDs for project '${projectId}': ${invalidTagIds.join(", ")}`,
1024
+ code: "VALIDATION_ERROR"
1025
+ };
1026
+ }
1027
+ }
939
1028
  const now = (/* @__PURE__ */ new Date()).toISOString();
940
1029
  const existingTask = projectData.tasks[taskIndex];
941
1030
  const completedAt = calculateCompletedAt(
@@ -1067,9 +1156,19 @@ var TaskService = {
1067
1156
  continue;
1068
1157
  }
1069
1158
  const existingTask = projectData.tasks[taskIndex];
1070
- let updatedTags = existingTask.tags;
1071
- if (data.tags && data.tags.length > 0) {
1072
- const existingTags = existingTask.tags || [];
1159
+ let updatedTags = existingTask.tags ?? [];
1160
+ if (data.tags) {
1161
+ const invalidTagIds = findInvalidTagIds(projectData, data.tags);
1162
+ if (invalidTagIds.length > 0) {
1163
+ return {
1164
+ success: false,
1165
+ error: `Invalid tag IDs for project '${projectId}': ${invalidTagIds.join(", ")}`,
1166
+ code: "VALIDATION_ERROR"
1167
+ };
1168
+ }
1169
+ }
1170
+ if (data.tags) {
1171
+ const existingTags = existingTask.tags ?? [];
1073
1172
  switch (data.tagOperation) {
1074
1173
  case "add":
1075
1174
  updatedTags = [.../* @__PURE__ */ new Set([...existingTags, ...data.tags])];
@@ -1147,7 +1246,7 @@ function toTaskSummary2(task) {
1147
1246
  }
1148
1247
  var createTaskTool = {
1149
1248
  name: "create_task",
1150
- description: "Create a new task in a project. Returns summary by default; set verbose=true for full data.",
1249
+ description: "Create a new task in a project. tags must be existing tag IDs from the same project. Returns summary by default; set verbose=true for full data.",
1151
1250
  inputSchema: z2.object({
1152
1251
  projectId: z2.string().min(1, "Project ID is required"),
1153
1252
  title: z2.string().min(1, "Task title is required"),
@@ -1227,7 +1326,7 @@ var getTaskTool = {
1227
1326
  };
1228
1327
  var updateTaskTool = {
1229
1328
  name: "update_task",
1230
- description: "Update an existing task. Returns summary by default; set verbose=true for full data.",
1329
+ description: "Update an existing task. tags must be existing tag IDs from the same project. Returns summary by default; set verbose=true for full data.",
1231
1330
  inputSchema: z2.object({
1232
1331
  projectId: z2.string().min(1, "Project ID is required"),
1233
1332
  taskId: z2.string().min(1, "Task ID is required"),
@@ -1270,7 +1369,7 @@ var deleteTaskTool = {
1270
1369
  };
1271
1370
  var batchUpdateTasksTool = {
1272
1371
  name: "batch_update_tasks",
1273
- description: "Update multiple tasks at once. Returns summaries by default; set verbose=true for full task data.",
1372
+ description: "Update multiple tasks at once. tags must be existing tag IDs from the same project. Returns summaries by default; set verbose=true for full task data.",
1274
1373
  inputSchema: z2.object({
1275
1374
  projectId: z2.string().min(1, "Project ID is required"),
1276
1375
  taskIds: z2.array(z2.string()).min(1, "At least one task ID is required"),
@@ -1304,11 +1403,11 @@ import { z as z3 } from "zod";
1304
1403
  var tagService = new TagService(storage);
1305
1404
  var createTagTool = {
1306
1405
  name: "create_tag",
1307
- description: "Create a new tag in a project",
1406
+ description: "Create a new tag in a project. If color is omitted, it is generated deterministically from tag name.",
1308
1407
  inputSchema: z3.object({
1309
1408
  projectId: z3.string().min(1, "Project ID is required"),
1310
1409
  name: z3.string().min(1, "Tag name is required"),
1311
- color: z3.string().regex(/^#[0-9A-Fa-f]{6}$/, "Color must be a valid hex code (e.g., #FF5733)"),
1410
+ color: z3.string().regex(/^#[0-9A-Fa-f]{6}$/, "Color must be a valid hex code (e.g., #FF5733)").optional(),
1312
1411
  description: z3.string().default("")
1313
1412
  }),
1314
1413
  async execute(input) {
@@ -2462,8 +2561,18 @@ Suggest relevant tags:
2462
2561
  - Priority tags: urgent, important
2463
2562
  - Domain tags: frontend, backend, design, testing (if applicable)
2464
2563
 
2564
+ Tag consistency rules:
2565
+ - list_tags first, then prefer reusing existing tags in that project
2566
+ - If no suitable tag exists, create_tag first (color optional, system can auto-generate) and then use the returned tag ID
2567
+ - create_task.tags must contain tag IDs only (not tag names)
2568
+
2465
2569
  ### 4. Create Task
2466
2570
  Use create_task to create the task immediately \u2014 no confirmation needed.
2571
+ Before create_task:
2572
+ 1. Call list_tags(projectId)
2573
+ 2. Match suggested tags to existing tags by name (case-insensitive)
2574
+ 3. For missing tags, call create_tag(projectId, name, color?)
2575
+ 4. Build create_task.tags from tag IDs only
2467
2576
 
2468
2577
  ### 5. Status
2469
2578
  After creating, if work starts immediately, use update_task to set status to in-progress.
@@ -2478,6 +2587,7 @@ After creating, if work starts immediately, use update_task to set status to in-
2478
2587
  - Type: Bug
2479
2588
  - Priority: High (affects user experience)
2480
2589
  - Suggested Tags: bug, frontend, mobile
2590
+ - create_task.tags: [existing_or_new_tag_ids]
2481
2591
  - Recommended Project: [Recommend if there's a web project]
2482
2592
 
2483
2593
  ## Current Idea: