@xihe-lab/tapd-mcp-server 1.3.0 → 1.4.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 (97) hide show
  1. package/README.md +88 -26
  2. package/dist/integration-test.d.ts +10 -0
  3. package/dist/integration-test.d.ts.map +1 -0
  4. package/dist/integration-test.js +117 -0
  5. package/dist/integration-test.js.map +1 -0
  6. package/dist/tapd-client.d.ts +32 -1
  7. package/dist/tapd-client.d.ts.map +1 -1
  8. package/dist/tapd-client.js +96 -19
  9. package/dist/tapd-client.js.map +1 -1
  10. package/dist/tools/attachment.d.ts.map +1 -1
  11. package/dist/tools/attachment.js +35 -10
  12. package/dist/tools/attachment.js.map +1 -1
  13. package/dist/tools/board.d.ts +3 -0
  14. package/dist/tools/board.d.ts.map +1 -0
  15. package/dist/tools/board.js +98 -0
  16. package/dist/tools/board.js.map +1 -0
  17. package/dist/tools/bug.d.ts.map +1 -1
  18. package/dist/tools/bug.js +382 -7
  19. package/dist/tools/bug.js.map +1 -1
  20. package/dist/tools/changes.d.ts.map +1 -1
  21. package/dist/tools/changes.js +25 -34
  22. package/dist/tools/changes.js.map +1 -1
  23. package/dist/tools/comment.d.ts.map +1 -1
  24. package/dist/tools/comment.js +53 -3
  25. package/dist/tools/comment.js.map +1 -1
  26. package/dist/tools/custom-fields.d.ts.map +1 -1
  27. package/dist/tools/custom-fields.js +43 -36
  28. package/dist/tools/custom-fields.js.map +1 -1
  29. package/dist/tools/image.d.ts +3 -0
  30. package/dist/tools/image.d.ts.map +1 -0
  31. package/dist/tools/image.js +23 -0
  32. package/dist/tools/image.js.map +1 -0
  33. package/dist/tools/index.d.ts.map +1 -1
  34. package/dist/tools/index.js +12 -0
  35. package/dist/tools/index.js.map +1 -1
  36. package/dist/tools/iteration.d.ts.map +1 -1
  37. package/dist/tools/iteration.js +95 -6
  38. package/dist/tools/iteration.js.map +1 -1
  39. package/dist/tools/mini-comment.d.ts.map +1 -1
  40. package/dist/tools/mini-comment.js +18 -5
  41. package/dist/tools/mini-comment.js.map +1 -1
  42. package/dist/tools/mini-item.d.ts.map +1 -1
  43. package/dist/tools/mini-item.js +36 -11
  44. package/dist/tools/mini-item.js.map +1 -1
  45. package/dist/tools/mini-workspace.d.ts.map +1 -1
  46. package/dist/tools/mini-workspace.js +13 -4
  47. package/dist/tools/mini-workspace.js.map +1 -1
  48. package/dist/tools/program.d.ts +3 -0
  49. package/dist/tools/program.d.ts.map +1 -0
  50. package/dist/tools/program.js +27 -0
  51. package/dist/tools/program.js.map +1 -0
  52. package/dist/tools/relations.d.ts.map +1 -1
  53. package/dist/tools/relations.js +25 -30
  54. package/dist/tools/relations.js.map +1 -1
  55. package/dist/tools/release.d.ts.map +1 -1
  56. package/dist/tools/release.js +228 -2
  57. package/dist/tools/release.js.map +1 -1
  58. package/dist/tools/report.d.ts +3 -0
  59. package/dist/tools/report.d.ts.map +1 -0
  60. package/dist/tools/report.js +38 -0
  61. package/dist/tools/report.js.map +1 -0
  62. package/dist/tools/settings.d.ts.map +1 -1
  63. package/dist/tools/settings.js +379 -31
  64. package/dist/tools/settings.js.map +1 -1
  65. package/dist/tools/source.d.ts +3 -0
  66. package/dist/tools/source.d.ts.map +1 -0
  67. package/dist/tools/source.js +69 -0
  68. package/dist/tools/source.js.map +1 -0
  69. package/dist/tools/story.d.ts.map +1 -1
  70. package/dist/tools/story.js +650 -160
  71. package/dist/tools/story.js.map +1 -1
  72. package/dist/tools/task.d.ts.map +1 -1
  73. package/dist/tools/task.js +104 -11
  74. package/dist/tools/task.js.map +1 -1
  75. package/dist/tools/test.d.ts.map +1 -1
  76. package/dist/tools/test.js +505 -75
  77. package/dist/tools/test.js.map +1 -1
  78. package/dist/tools/timesheet.d.ts.map +1 -1
  79. package/dist/tools/timesheet.js +72 -11
  80. package/dist/tools/timesheet.js.map +1 -1
  81. package/dist/tools/user.d.ts.map +1 -1
  82. package/dist/tools/user.js +36 -4
  83. package/dist/tools/user.js.map +1 -1
  84. package/dist/tools/utility.d.ts +3 -0
  85. package/dist/tools/utility.d.ts.map +1 -0
  86. package/dist/tools/utility.js +132 -0
  87. package/dist/tools/utility.js.map +1 -0
  88. package/dist/tools/wiki.d.ts.map +1 -1
  89. package/dist/tools/wiki.js +75 -20
  90. package/dist/tools/wiki.js.map +1 -1
  91. package/dist/tools/workflow.d.ts.map +1 -1
  92. package/dist/tools/workflow.js +78 -6
  93. package/dist/tools/workflow.js.map +1 -1
  94. package/dist/tools/workspace.d.ts.map +1 -1
  95. package/dist/tools/workspace.js +93 -4
  96. package/dist/tools/workspace.js.map +1 -1
  97. package/package.json +2 -1
@@ -1,96 +1,121 @@
1
1
  import { z } from 'zod';
2
2
  import { TapdClient } from '../tapd-client.js';
3
3
  export const storyTools = [
4
+ // 需求 CRUD
4
5
  {
5
6
  name: 'tapd_get_stories',
6
- description: 'Query TAPD stories with filters',
7
- inputSchema: z.object({
8
- workspace_id: z.number().describe('Project ID'),
9
- id: z.string().optional().describe('Supports multiple IDs'),
10
- name: z.string().optional().describe('Story title, supports fuzzy matching'),
11
- priority: z.string().optional().describe('Priority, recommend using priority_label'),
12
- priority_label: z.string().optional().describe('Priority (recommended)'),
13
- status: z.string().optional().describe('Status, supports enum query'),
14
- v_status: z.string().optional().describe('Status (Chinese)'),
15
- with_v_status: z.string().optional().describe('Set to 1 to return Chinese status'),
16
- label: z.string().optional().describe('Label, supports enum query'),
17
- workitem_type_id: z.string().optional().describe('Story category ID, supports enum query'),
18
- owner: z.string().optional().describe('Owner, supports fuzzy matching'),
19
- creator: z.string().optional().describe('Creator, supports multiple users query'),
20
- developer: z.string().optional().describe('Developer'),
21
- cc: z.string().optional().describe('CC person, supports fuzzy matching'),
22
- iteration_id: z.string().optional().describe('Iteration ID, supports enum query'),
23
- include_sub_iteration: z.string().optional().describe('Include sub-iteration, 0 or 1, default 0'),
24
- category_id: z.string().optional().describe('Story category, supports enum query'),
25
- include_sub_category: z.string().optional().describe('Include sub-category, 0 or 1, default 0'),
26
- parent_id: z.string().optional().describe('Parent story ID'),
27
- ancestor_id: z.string().optional().describe('Ancestor story ID, query all child stories'),
28
- children_id: z.string().optional().describe('Child story ID'),
29
- begin: z.string().optional().describe('Estimated start date, Format: YYYY-MM-DD'),
30
- due: z.string().optional().describe('Estimated end date, Format: YYYY-MM-DD'),
31
- created: z.string().optional().describe('Creation time, Format: YYYY-MM-DD HH:mm'),
32
- modified: z.string().optional().describe('Modification time, Format: YYYY-MM-DD HH:mm'),
33
- completed: z.string().optional().describe('Completion time, Format: YYYY-MM-DD HH:mm'),
34
- effort: z.string().optional().describe('Estimated effort'),
35
- effort_completed: z.string().optional().describe('Completed effort'),
36
- remain: z.number().optional().describe('Remaining effort'),
37
- exceed: z.number().optional().describe('Exceeded effort'),
38
- release_id: z.string().optional().describe('Release plan'),
39
- module: z.string().optional().describe('Module'),
40
- feature: z.string().optional().describe('Feature'),
41
- version: z.string().optional().describe('Version'),
42
- source: z.string().optional().describe('Story source'),
43
- type: z.string().optional().describe('Story type'),
44
- description: z.string().optional().describe('Detailed description, supports fuzzy matching'),
45
- business_value: z.string().optional().describe('Business value'),
46
- test_focus: z.string().optional().describe('Test focus'),
47
- size: z.string().optional().describe('Size/scale'),
48
- custom_field_one: z.string().optional().describe('Custom field 1 (supports 1-200)'),
49
- limit: z.number().optional().describe('Return count, default 30, max 200'),
50
- page: z.number().optional().describe('Page number, default 1'),
51
- order: z.string().optional().describe('Sort order'),
52
- fields: z.string().optional().describe('Specify return fields'),
53
- }),
54
- handler: async (client, params) => {
55
- return client.get('/stories', params);
7
+ description: '获取需求列表',
8
+ inputSchema: z.object({
9
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
10
+ id: z.string().optional().describe('需求ID,支持多ID查询'),
11
+ name: z.string().optional().describe('需求标题,支持模糊匹配'),
12
+ priority: z.string().optional().describe('优先级'),
13
+ priority_label: z.string().optional().describe('优先级标签(推荐)'),
14
+ status: z.string().optional().describe('状态'),
15
+ v_status: z.string().optional().describe('状态(中文)'),
16
+ with_v_status: z.string().optional().describe('设为1返回中文状态'),
17
+ label: z.string().optional().describe('标签'),
18
+ workitem_type_id: z.string().optional().describe('需求类别ID'),
19
+ owner: z.string().optional().describe('处理人,支持模糊匹配'),
20
+ creator: z.string().optional().describe('创建人'),
21
+ developer: z.string().optional().describe('开发人员'),
22
+ cc: z.string().optional().describe('抄送人'),
23
+ iteration_id: z.string().optional().describe('迭代ID'),
24
+ include_sub_iteration: z.string().optional().describe('包含子迭代:01'),
25
+ category_id: z.string().optional().describe('需求分类'),
26
+ include_sub_category: z.string().optional().describe('包含子分类:01'),
27
+ parent_id: z.string().optional().describe('父需求ID'),
28
+ ancestor_id: z.string().optional().describe('祖先需求ID'),
29
+ children_id: z.string().optional().describe('子需求ID'),
30
+ begin: z.string().optional().describe('预计开始日期 YYYY-MM-DD'),
31
+ due: z.string().optional().describe('预计结束日期 YYYY-MM-DD'),
32
+ created: z.string().optional().describe('创建时间 YYYY-MM-DD HH:mm'),
33
+ modified: z.string().optional().describe('修改时间'),
34
+ completed: z.string().optional().describe('完成时间'),
35
+ effort: z.string().optional().describe('预估工时'),
36
+ effort_completed: z.string().optional().describe('完成工时'),
37
+ remain: z.number().optional().describe('剩余工时'),
38
+ exceed: z.number().optional().describe('超出工时'),
39
+ release_id: z.string().optional().describe('发布计划'),
40
+ module: z.string().optional().describe('模块'),
41
+ feature: z.string().optional().describe('特性'),
42
+ version: z.string().optional().describe('版本'),
43
+ source: z.string().optional().describe('需求来源'),
44
+ type: z.string().optional().describe('需求类型'),
45
+ description: z.string().optional().describe('详细描述'),
46
+ custom_field_one: z.string().optional().describe('自定义字段 (支持1-200)'),
47
+ limit: z.number().optional().describe('返回数量,默认30'),
48
+ page: z.number().optional().describe('页码,默认1'),
49
+ order: z.string().optional().describe('排序'),
50
+ fields: z.string().optional().describe('返回字段'),
51
+ }),
52
+ handler: async (client, params) => {
53
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
54
+ if (!workspaceId) {
55
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
56
+ }
57
+ const convertedParams = {
58
+ ...params,
59
+ id: params.id ? TapdClient.toLongId(params.id, workspaceId) : undefined,
60
+ workspace_id: workspaceId,
61
+ };
62
+ return client.get('/stories', convertedParams);
56
63
  },
57
64
  },
58
65
  {
59
66
  name: 'tapd_create_story',
60
- description: 'Create a new story in TAPD',
61
- inputSchema: z.object({
62
- workspace_id: z.number().describe('Project ID (required)'),
63
- name: z.string().describe('Story name (required)'),
64
- priority: z.string().optional().describe('Priority'),
65
- priority_label: z.string().optional().describe('Priority label (recommended)'),
66
- description: z.string().optional().describe('Detailed description'),
67
- owner: z.string().optional().describe('Owner (defaults to TAPD_NICK_NAME env)'),
68
- creator: z.string().optional().describe('Creator (defaults to TAPD_NICK_NAME env)'),
69
- developer: z.string().optional().describe('Developer'),
70
- cc: z.string().optional().describe('CC person'),
71
- iteration_id: z.string().optional().describe('Iteration ID'),
72
- category_id: z.string().optional().describe('Story category'),
73
- parent_id: z.string().optional().describe('Parent story ID'),
74
- begin: z.string().optional().describe('Estimated start date, Format: YYYY-MM-DD'),
75
- due: z.string().optional().describe('Estimated end date, Format: YYYY-MM-DD'),
76
- effort: z.string().optional().describe('Estimated effort'),
77
- release_id: z.string().optional().describe('Release plan'),
78
- module: z.string().optional().describe('Module'),
79
- feature: z.string().optional().describe('Feature'),
80
- version: z.string().optional().describe('Version'),
81
- source: z.string().optional().describe('Story source'),
82
- type: z.string().optional().describe('Story type'),
83
- label: z.string().optional().describe('Label'),
84
- template_id: z.string().optional().describe('Template ID'),
85
- business_value: z.string().optional().describe('Business value'),
86
- test_focus: z.string().optional().describe('Test focus'),
87
- size: z.string().optional().describe('Size/scale'),
88
- custom_field_one: z.string().optional().describe('Custom field 1 (supports 1-200)'),
67
+ description: '创建需求(也可创建任务:传入 workitem_type_id TASK 类型 ID 即可创建任务,适合仅有 stories::create 权限而无 tasks::create 权限的场景)',
68
+ inputSchema: z.object({
69
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
70
+ name: z.string().describe('需求标题 (必填)'),
71
+ description: z.string().optional().describe('详细描述'),
72
+ priority: z.string().optional().describe('优先级'),
73
+ priority_label: z.string().optional().describe('优先级标签(推荐)'),
74
+ owner: z.string().optional().describe('处理人(默认当前用户)'),
75
+ creator: z.string().optional().describe('创建人(默认当前用户)'),
76
+ developer: z.string().optional().describe('开发人员'),
77
+ cc: z.string().optional().describe('抄送人'),
78
+ iteration_id: z.string().optional().describe('迭代ID'),
79
+ category_id: z.string().optional().describe('需求分类'),
80
+ parent_id: z.string().optional().describe('父需求ID'),
81
+ begin: z.string().optional().describe('预计开始日期 YYYY-MM-DD'),
82
+ due: z.string().optional().describe('预计结束日期 YYYY-MM-DD'),
83
+ effort: z.string().optional().describe('预估工时'),
84
+ release_id: z.string().optional().describe('发布计划'),
85
+ module: z.string().optional().describe('模块'),
86
+ feature: z.string().optional().describe('特性'),
87
+ version: z.string().optional().describe('版本'),
88
+ source: z.string().optional().describe('需求来源'),
89
+ type: z.string().optional().describe('需求类型'),
90
+ label: z.string().optional().describe('标签'),
91
+ template_id: z.string().optional().describe('模板ID'),
92
+ business_value: z.string().optional().describe('业务价值'),
93
+ test_focus: z.string().optional().describe('测试关注点'),
94
+ size: z.string().optional().describe('规模/大小'),
95
+ custom_field_one: z.string().optional().describe('自定义字段'),
96
+ workitem_type_id: z.string().optional().describe('工作项类型ID(可选,默认创建需求;传入 TASK 类型 ID 可创建任务。可通过 tapd_get_workitem_types 查询可用类型)'),
89
97
  }),
90
98
  handler: async (client, params) => {
91
99
  const nickName = TapdClient.getNickName();
100
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
101
+ if (!workspaceId) {
102
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
103
+ }
104
+ // Resolve workitem_type_id: user param > env default > auto-detect via API
105
+ let workitemTypeId = params.workitem_type_id
106
+ ?? TapdClient.getDefaultStoryWorkitemTypeId();
107
+ if (!workitemTypeId) {
108
+ const response = await client.get('/workitem_types', { workspace_id: workspaceId });
109
+ const types = response?.data ?? [];
110
+ const storyType = types.find((item) => item.WorkitemType?.english_name === 'STORY');
111
+ if (storyType) {
112
+ workitemTypeId = storyType.WorkitemType.id;
113
+ }
114
+ }
92
115
  const finalParams = {
93
116
  ...params,
117
+ workspace_id: workspaceId,
118
+ workitem_type_id: workitemTypeId,
94
119
  owner: params.owner ?? nickName,
95
120
  creator: params.creator ?? nickName,
96
121
  };
@@ -99,91 +124,556 @@ export const storyTools = [
99
124
  },
100
125
  {
101
126
  name: 'tapd_update_story',
102
- description: 'Update an existing story in TAPD',
103
- inputSchema: z.object({
104
- id: z.string().describe('Story ID (required)'),
105
- workspace_id: z.number().describe('Project ID (required)'),
106
- name: z.string().optional().describe('Story name'),
107
- priority: z.string().optional().describe('Priority'),
108
- priority_label: z.string().optional().describe('Priority label (recommended)'),
109
- description: z.string().optional().describe('Detailed description'),
110
- owner: z.string().optional().describe('Owner'),
111
- developer: z.string().optional().describe('Developer'),
112
- cc: z.string().optional().describe('CC person'),
113
- iteration_id: z.string().optional().describe('Iteration ID'),
114
- category_id: z.string().optional().describe('Story category'),
115
- parent_id: z.string().optional().describe('Parent story ID'),
116
- begin: z.string().optional().describe('Estimated start date, Format: YYYY-MM-DD'),
117
- due: z.string().optional().describe('Estimated end date, Format: YYYY-MM-DD'),
118
- effort: z.string().optional().describe('Estimated effort'),
119
- effort_completed: z.string().optional().describe('Completed effort'),
120
- remain: z.number().optional().describe('Remaining effort'),
121
- exceed: z.number().optional().describe('Exceeded effort'),
122
- release_id: z.string().optional().describe('Release plan'),
123
- module: z.string().optional().describe('Module'),
124
- feature: z.string().optional().describe('Feature'),
125
- version: z.string().optional().describe('Version'),
126
- source: z.string().optional().describe('Story source'),
127
- type: z.string().optional().describe('Story type'),
128
- label: z.string().optional().describe('Label'),
129
- status: z.string().optional().describe('Status'),
130
- business_value: z.string().optional().describe('Business value'),
131
- test_focus: z.string().optional().describe('Test focus'),
132
- size: z.string().optional().describe('Size/scale'),
133
- custom_field_one: z.string().optional().describe('Custom field 1 (supports 1-200)'),
134
- }),
135
- handler: async (client, params) => {
136
- return client.post('/stories', params);
127
+ description: '更新需求',
128
+ inputSchema: z.object({
129
+ id: z.string().describe('需求ID (必填)'),
130
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
131
+ name: z.string().optional().describe('需求标题'),
132
+ description: z.string().optional().describe('详细描述'),
133
+ status: z.string().optional().describe('状态'),
134
+ owner: z.string().optional().describe('处理人'),
135
+ priority: z.string().optional().describe('优先级'),
136
+ priority_label: z.string().optional().describe('优先级标签'),
137
+ iteration_id: z.string().optional().describe('迭代ID'),
138
+ category_id: z.string().optional().describe('需求分类'),
139
+ begin: z.string().optional().describe('预计开始日期'),
140
+ due: z.string().optional().describe('预计结束日期'),
141
+ effort: z.string().optional().describe('预估工时'),
142
+ effort_completed: z.string().optional().describe('已完成工时'),
143
+ remain: z.number().optional().describe('剩余工时'),
144
+ exceed: z.number().optional().describe('超出工时'),
145
+ business_value: z.string().optional().describe('业务价值'),
146
+ test_focus: z.string().optional().describe('测试关注点'),
147
+ size: z.string().optional().describe('规模'),
148
+ current_user: z.string().optional().describe('操作人'),
149
+ custom_field_one: z.string().optional().describe('自定义字段'),
150
+ }),
151
+ handler: async (client, params) => {
152
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
153
+ if (!workspaceId) {
154
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
155
+ }
156
+ const convertedParams = {
157
+ ...params,
158
+ id: TapdClient.toLongId(params.id, workspaceId),
159
+ workspace_id: workspaceId,
160
+ };
161
+ return client.post('/stories', convertedParams);
137
162
  },
138
163
  },
139
164
  {
140
165
  name: 'tapd_get_story_count',
141
- description: 'Get the count of stories matching filters',
142
- inputSchema: z.object({
143
- workspace_id: z.number().describe('Project ID (required)'),
144
- id: z.string().optional().describe('Supports multiple IDs'),
145
- name: z.string().optional().describe('Story title, supports fuzzy matching'),
146
- priority: z.string().optional().describe('Priority, recommend using priority_label'),
147
- priority_label: z.string().optional().describe('Priority (recommended)'),
148
- status: z.string().optional().describe('Status, supports enum query'),
149
- v_status: z.string().optional().describe('Status (Chinese)'),
150
- with_v_status: z.string().optional().describe('Set to 1 to return Chinese status'),
151
- label: z.string().optional().describe('Label, supports enum query'),
152
- workitem_type_id: z.string().optional().describe('Story category ID, supports enum query'),
153
- owner: z.string().optional().describe('Owner, supports fuzzy matching'),
154
- creator: z.string().optional().describe('Creator, supports multiple users query'),
155
- developer: z.string().optional().describe('Developer'),
156
- cc: z.string().optional().describe('CC person, supports fuzzy matching'),
157
- iteration_id: z.string().optional().describe('Iteration ID, supports enum query'),
158
- include_sub_iteration: z.string().optional().describe('Include sub-iteration, 0 or 1, default 0'),
159
- category_id: z.string().optional().describe('Story category, supports enum query'),
160
- include_sub_category: z.string().optional().describe('Include sub-category, 0 or 1, default 0'),
161
- parent_id: z.string().optional().describe('Parent story ID'),
162
- ancestor_id: z.string().optional().describe('Ancestor story ID, query all child stories'),
163
- children_id: z.string().optional().describe('Child story ID'),
164
- begin: z.string().optional().describe('Estimated start date, Format: YYYY-MM-DD'),
165
- due: z.string().optional().describe('Estimated end date, Format: YYYY-MM-DD'),
166
- created: z.string().optional().describe('Creation time, Format: YYYY-MM-DD HH:mm'),
167
- modified: z.string().optional().describe('Modification time, Format: YYYY-MM-DD HH:mm'),
168
- completed: z.string().optional().describe('Completion time, Format: YYYY-MM-DD HH:mm'),
169
- effort: z.string().optional().describe('Estimated effort'),
170
- effort_completed: z.string().optional().describe('Completed effort'),
171
- remain: z.number().optional().describe('Remaining effort'),
172
- exceed: z.number().optional().describe('Exceeded effort'),
173
- release_id: z.string().optional().describe('Release plan'),
174
- module: z.string().optional().describe('Module'),
175
- feature: z.string().optional().describe('Feature'),
176
- version: z.string().optional().describe('Version'),
177
- source: z.string().optional().describe('Story source'),
178
- type: z.string().optional().describe('Story type'),
179
- description: z.string().optional().describe('Detailed description, supports fuzzy matching'),
180
- business_value: z.string().optional().describe('Business value'),
181
- test_focus: z.string().optional().describe('Test focus'),
182
- size: z.string().optional().describe('Size/scale'),
183
- custom_field_one: z.string().optional().describe('Custom field 1 (supports 1-200)'),
184
- }),
185
- handler: async (client, params) => {
186
- return client.get('/stories/count', params);
166
+ description: '获取需求数量',
167
+ inputSchema: z.object({
168
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
169
+ id: z.string().optional().describe('需求ID'),
170
+ name: z.string().optional().describe('需求标题'),
171
+ priority: z.string().optional().describe('优先级'),
172
+ priority_label: z.string().optional().describe('优先级标签(推荐)'),
173
+ status: z.string().optional().describe('状态'),
174
+ owner: z.string().optional().describe('处理人'),
175
+ creator: z.string().optional().describe('创建人'),
176
+ developer: z.string().optional().describe('开发人员'),
177
+ cc: z.string().optional().describe('抄送人'),
178
+ iteration_id: z.string().optional().describe('迭代ID'),
179
+ category_id: z.string().optional().describe('需求分类'),
180
+ parent_id: z.string().optional().describe('父需求ID'),
181
+ ancestor_id: z.string().optional().describe('祖先需求ID'),
182
+ begin: z.string().optional().describe('预计开始日期'),
183
+ due: z.string().optional().describe('预计结束日期'),
184
+ created: z.string().optional().describe('创建时间'),
185
+ modified: z.string().optional().describe('修改时间'),
186
+ completed: z.string().optional().describe('完成时间'),
187
+ release_id: z.string().optional().describe('发布计划'),
188
+ module: z.string().optional().describe('模块'),
189
+ feature: z.string().optional().describe('特性'),
190
+ version: z.string().optional().describe('版本'),
191
+ source: z.string().optional().describe('需求来源'),
192
+ type: z.string().optional().describe('需求类型'),
193
+ label: z.string().optional().describe('标签'),
194
+ }),
195
+ handler: async (client, params) => {
196
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
197
+ if (!workspaceId) {
198
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
199
+ }
200
+ return client.get('/stories/count', { ...params, workspace_id: workspaceId });
201
+ },
202
+ },
203
+ {
204
+ name: 'tapd_copy_story',
205
+ description: '复制需求',
206
+ inputSchema: z.object({
207
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
208
+ id: z.string().describe('要复制的需求ID (必填)'),
209
+ name: z.string().optional().describe('新需求标题(默认为原标题)'),
210
+ owner: z.string().optional().describe('处理人'),
211
+ iteration_id: z.string().optional().describe('迭代ID'),
212
+ copy_attachments: z.number().optional().describe('是否复制附件,值=1复制'),
213
+ copy_comments: z.number().optional().describe('是否复制评论,值=1复制'),
214
+ copy_sub_tasks: z.number().optional().describe('是否复制子任务,值=1复制'),
215
+ }),
216
+ handler: async (client, params) => {
217
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
218
+ if (!workspaceId) {
219
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
220
+ }
221
+ const convertedParams = {
222
+ ...params,
223
+ id: TapdClient.toLongId(params.id, workspaceId),
224
+ workspace_id: workspaceId,
225
+ };
226
+ return client.post('/stories/copy', convertedParams);
227
+ },
228
+ },
229
+ {
230
+ name: 'tapd_batch_update_stories',
231
+ description: '批量更新需求',
232
+ inputSchema: z.object({
233
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
234
+ stories: z.string().describe('需求更新数组JSON,最多50条 (必填)'),
235
+ }),
236
+ handler: async (client, params) => {
237
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
238
+ if (!workspaceId) {
239
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
240
+ }
241
+ return client.post('/stories/batch_update', { ...params, workspace_id: workspaceId });
242
+ },
243
+ },
244
+ // 需求分类
245
+ {
246
+ name: 'tapd_get_story_categories',
247
+ description: '获取需求分类列表',
248
+ inputSchema: z.object({
249
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
250
+ id: z.string().optional().describe('分类ID,支持多ID查询'),
251
+ name: z.string().optional().describe('分类名称,支持模糊匹配'),
252
+ parent_id: z.number().optional().describe('父分类ID'),
253
+ created: z.string().optional().describe('创建时间'),
254
+ modified: z.string().optional().describe('修改时间'),
255
+ limit: z.number().optional().describe('返回数量'),
256
+ page: z.number().optional().describe('页码'),
257
+ order: z.string().optional().describe('排序'),
258
+ fields: z.string().optional().describe('返回字段'),
259
+ }),
260
+ handler: async (client, params) => {
261
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
262
+ if (!workspaceId) {
263
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
264
+ }
265
+ return client.get('/story_categories', { ...params, workspace_id: workspaceId });
266
+ },
267
+ },
268
+ {
269
+ name: 'tapd_get_story_categories_count',
270
+ description: '获取需求分类数量',
271
+ inputSchema: z.object({
272
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
273
+ id: z.string().optional().describe('分类ID'),
274
+ name: z.string().optional().describe('分类名称'),
275
+ parent_id: z.number().optional().describe('父分类ID'),
276
+ }),
277
+ handler: async (client, params) => {
278
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
279
+ if (!workspaceId) {
280
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
281
+ }
282
+ return client.get('/story_categories/count', { ...params, workspace_id: workspaceId });
283
+ },
284
+ },
285
+ {
286
+ name: 'tapd_add_story_category',
287
+ description: '创建需求分类',
288
+ inputSchema: z.object({
289
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
290
+ name: z.string().describe('分类名称 (必填)'),
291
+ parent_id: z.number().optional().describe('父分类ID'),
292
+ }),
293
+ handler: async (client, params) => {
294
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
295
+ if (!workspaceId) {
296
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
297
+ }
298
+ return client.post('/story_categories/add', { ...params, workspace_id: workspaceId });
299
+ },
300
+ },
301
+ {
302
+ name: 'tapd_update_story_category',
303
+ description: '更新需求分类',
304
+ inputSchema: z.object({
305
+ id: z.string().describe('分类ID (必填)'),
306
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
307
+ name: z.string().optional().describe('分类名称'),
308
+ parent_id: z.number().optional().describe('父分类ID'),
309
+ }),
310
+ handler: async (client, params) => {
311
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
312
+ if (!workspaceId) {
313
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
314
+ }
315
+ return client.post('/story_categories/update', { ...params, workspace_id: workspaceId });
316
+ },
317
+ },
318
+ // 需求类别
319
+ {
320
+ name: 'tapd_get_workitem_types',
321
+ description: '获取需求类别列表',
322
+ inputSchema: z.object({
323
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
324
+ }),
325
+ handler: async (client, params) => {
326
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
327
+ if (!workspaceId) {
328
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
329
+ }
330
+ return client.get('/workitem_types', { ...params, workspace_id: workspaceId });
331
+ },
332
+ },
333
+ {
334
+ name: 'tapd_change_workitem_type',
335
+ description: '更新需求类别',
336
+ inputSchema: z.object({
337
+ id: z.string().describe('需求ID (必填)'),
338
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
339
+ workitem_type_id: z.string().describe('新的需求类别ID (必填)'),
340
+ }),
341
+ handler: async (client, params) => {
342
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
343
+ if (!workspaceId) {
344
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
345
+ }
346
+ const convertedParams = {
347
+ ...params,
348
+ id: TapdClient.toLongId(params.id, workspaceId),
349
+ workspace_id: workspaceId,
350
+ };
351
+ return client.post('/stories/change_workitem_type', convertedParams);
352
+ },
353
+ },
354
+ // 字段配置
355
+ {
356
+ name: 'tapd_get_story_fields_info',
357
+ description: '获取需求字段信息',
358
+ inputSchema: z.object({
359
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
360
+ workitem_type_id: z.string().optional().describe('需求类别ID'),
361
+ }),
362
+ handler: async (client, params) => {
363
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
364
+ if (!workspaceId) {
365
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
366
+ }
367
+ return client.get('/stories/fields_info', { ...params, workspace_id: workspaceId });
368
+ },
369
+ },
370
+ {
371
+ name: 'tapd_get_story_fields_lable',
372
+ description: '获取需求字段中英文映射',
373
+ inputSchema: z.object({
374
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
375
+ }),
376
+ handler: async (client, params) => {
377
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
378
+ if (!workspaceId) {
379
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
380
+ }
381
+ return client.get('/stories/fields_lable', { ...params, workspace_id: workspaceId });
382
+ },
383
+ },
384
+ // 模板
385
+ {
386
+ name: 'tapd_get_story_template_list',
387
+ description: '获取需求模板列表',
388
+ inputSchema: z.object({
389
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
390
+ workitem_type_id: z.string().optional().describe('需求类别ID'),
391
+ limit: z.number().optional().describe('返回数量'),
392
+ page: z.number().optional().describe('页码'),
393
+ fields: z.string().optional().describe('返回字段'),
394
+ }),
395
+ handler: async (client, params) => {
396
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
397
+ if (!workspaceId) {
398
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
399
+ }
400
+ return client.get('/stories/templates', { ...params, workspace_id: workspaceId });
401
+ },
402
+ },
403
+ {
404
+ name: 'tapd_get_default_story_template',
405
+ description: '获取需求默认模板',
406
+ inputSchema: z.object({
407
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
408
+ workitem_type_id: z.string().optional().describe('需求类别ID'),
409
+ }),
410
+ handler: async (client, params) => {
411
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
412
+ if (!workspaceId) {
413
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
414
+ }
415
+ return client.get('/stories/default_template', { ...params, workspace_id: workspaceId });
416
+ },
417
+ },
418
+ // 关联关系
419
+ {
420
+ name: 'tapd_get_story_related_bugs',
421
+ description: '获取需求关联的缺陷',
422
+ inputSchema: z.object({
423
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
424
+ story_id: z.string().describe('需求ID (必填)'),
425
+ limit: z.number().optional().describe('返回数量'),
426
+ page: z.number().optional().describe('页码'),
427
+ fields: z.string().optional().describe('返回字段'),
428
+ }),
429
+ handler: async (client, params) => {
430
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
431
+ if (!workspaceId) {
432
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
433
+ }
434
+ const convertedParams = {
435
+ ...params,
436
+ story_id: TapdClient.toLongId(params.story_id, workspaceId),
437
+ workspace_id: workspaceId,
438
+ };
439
+ return client.get('/stories/related_bugs', convertedParams);
440
+ },
441
+ },
442
+ {
443
+ name: 'tapd_create_story_bug',
444
+ description: '创建需求缺陷关联',
445
+ inputSchema: z.object({
446
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
447
+ story_id: z.string().describe('需求ID (必填)'),
448
+ bug_id: z.string().describe('缺陷ID (必填)'),
449
+ }),
450
+ handler: async (client, params) => {
451
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
452
+ if (!workspaceId) {
453
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
454
+ }
455
+ const convertedParams = {
456
+ ...params,
457
+ story_id: TapdClient.toLongId(params.story_id, workspaceId),
458
+ bug_id: TapdClient.toLongId(params.bug_id, workspaceId),
459
+ workspace_id: workspaceId,
460
+ };
461
+ return client.post('/stories/create_story_bug', convertedParams);
462
+ },
463
+ },
464
+ {
465
+ name: 'tapd_remove_story_bug_relations',
466
+ description: '解除需求缺陷关联',
467
+ inputSchema: z.object({
468
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
469
+ story_id: z.string().describe('需求ID (必填)'),
470
+ bug_id: z.string().describe('缺陷ID (必填)'),
471
+ }),
472
+ handler: async (client, params) => {
473
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
474
+ if (!workspaceId) {
475
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
476
+ }
477
+ const convertedParams = {
478
+ ...params,
479
+ story_id: TapdClient.toLongId(params.story_id, workspaceId),
480
+ bug_id: TapdClient.toLongId(params.bug_id, workspaceId),
481
+ workspace_id: workspaceId,
482
+ };
483
+ return client.post('/stories/remove_story_bug_relations', convertedParams);
484
+ },
485
+ },
486
+ {
487
+ name: 'tapd_get_story_tcase',
488
+ description: '获取需求测试用例关联',
489
+ inputSchema: z.object({
490
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
491
+ story_id: z.string().describe('需求ID (必填)'),
492
+ tcase_id: z.string().optional().describe('测试用例ID'),
493
+ limit: z.number().optional().describe('返回数量'),
494
+ page: z.number().optional().describe('页码'),
495
+ fields: z.string().optional().describe('返回字段'),
496
+ }),
497
+ handler: async (client, params) => {
498
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
499
+ if (!workspaceId) {
500
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
501
+ }
502
+ const convertedParams = {
503
+ ...params,
504
+ story_id: TapdClient.toLongId(params.story_id, workspaceId),
505
+ workspace_id: workspaceId,
506
+ };
507
+ return client.get('/stories/story_tcase', convertedParams);
508
+ },
509
+ },
510
+ {
511
+ name: 'tapd_create_story_tcase',
512
+ description: '创建需求测试用例关联',
513
+ inputSchema: z.object({
514
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
515
+ story_id: z.string().describe('需求ID (必填)'),
516
+ tcase_id: z.string().describe('测试用例ID (必填)'),
517
+ }),
518
+ handler: async (client, params) => {
519
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
520
+ if (!workspaceId) {
521
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
522
+ }
523
+ const convertedParams = {
524
+ ...params,
525
+ story_id: TapdClient.toLongId(params.story_id, workspaceId),
526
+ workspace_id: workspaceId,
527
+ };
528
+ return client.post('/stories/create_story_tcase', convertedParams);
529
+ },
530
+ },
531
+ // 前后置关系
532
+ {
533
+ name: 'tapd_get_time_relative_stories',
534
+ description: '获取需求前后置关系',
535
+ inputSchema: z.object({
536
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
537
+ story_id: z.string().optional().describe('需求ID'),
538
+ predecessor_id: z.string().optional().describe('前置需求ID'),
539
+ successor_id: z.string().optional().describe('后置需求ID'),
540
+ relation_type: z.string().optional().describe('关系类型'),
541
+ limit: z.number().optional().describe('返回数量'),
542
+ page: z.number().optional().describe('页码'),
543
+ fields: z.string().optional().describe('返回字段'),
544
+ }),
545
+ handler: async (client, params) => {
546
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
547
+ if (!workspaceId) {
548
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
549
+ }
550
+ const convertedParams = {
551
+ ...params,
552
+ story_id: params.story_id ? TapdClient.toLongId(params.story_id, workspaceId) : undefined,
553
+ predecessor_id: params.predecessor_id ? TapdClient.toLongId(params.predecessor_id, workspaceId) : undefined,
554
+ successor_id: params.successor_id ? TapdClient.toLongId(params.successor_id, workspaceId) : undefined,
555
+ workspace_id: workspaceId,
556
+ };
557
+ return client.get('/stories/time_relative_stories', convertedParams);
558
+ },
559
+ },
560
+ {
561
+ name: 'tapd_save_time_relations',
562
+ description: '批量新增/修改前后置关系',
563
+ inputSchema: z.object({
564
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
565
+ relations: z.string().describe('前后置关系数组JSON (必填)'),
566
+ }),
567
+ handler: async (client, params) => {
568
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
569
+ if (!workspaceId) {
570
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
571
+ }
572
+ return client.post('/stories/save_time_relations', { ...params, workspace_id: workspaceId });
573
+ },
574
+ },
575
+ {
576
+ name: 'tapd_delete_time_relations',
577
+ description: '批量删除前后置关系',
578
+ inputSchema: z.object({
579
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
580
+ relations: z.string().describe('要删除的前后置关系数组JSON (必填)'),
581
+ }),
582
+ handler: async (client, params) => {
583
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
584
+ if (!workspaceId) {
585
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
586
+ }
587
+ return client.post('/stories/delete_time_relations', { ...params, workspace_id: workspaceId });
588
+ },
589
+ },
590
+ // 其他
591
+ {
592
+ name: 'tapd_get_removed_stories',
593
+ description: '获取回收站的需求',
594
+ inputSchema: z.object({
595
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
596
+ id: z.string().optional().describe('需求ID'),
597
+ name: z.string().optional().describe('标题'),
598
+ owner: z.string().optional().describe('处理人'),
599
+ creator: z.string().optional().describe('创建人'),
600
+ created: z.string().optional().describe('创建时间'),
601
+ deleted: z.string().optional().describe('删除时间'),
602
+ limit: z.number().optional().describe('返回数量'),
603
+ page: z.number().optional().describe('页码'),
604
+ order: z.string().optional().describe('排序'),
605
+ fields: z.string().optional().describe('返回字段'),
606
+ }),
607
+ handler: async (client, params) => {
608
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
609
+ if (!workspaceId) {
610
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
611
+ }
612
+ return client.get('/stories/removed', { ...params, workspace_id: workspaceId });
613
+ },
614
+ },
615
+ {
616
+ name: 'tapd_update_story_parent',
617
+ description: '更新父需求',
618
+ inputSchema: z.object({
619
+ id: z.string().describe('需求ID (必填)'),
620
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
621
+ parent_id: z.string().describe('新的父需求ID (必填),设为0取消父子关系'),
622
+ }),
623
+ handler: async (client, params) => {
624
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
625
+ if (!workspaceId) {
626
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
627
+ }
628
+ // parent_id can be "0" to cancel relationship, only convert if not "0"
629
+ const convertedParams = {
630
+ ...params,
631
+ id: TapdClient.toLongId(params.id, workspaceId),
632
+ parent_id: params.parent_id !== '0' ? TapdClient.toLongId(params.parent_id, workspaceId) : params.parent_id,
633
+ workspace_id: workspaceId,
634
+ };
635
+ return client.post('/stories/update_parent', convertedParams);
636
+ },
637
+ },
638
+ {
639
+ name: 'tapd_get_stories_by_view_conf_id',
640
+ description: '获取视图需求列表',
641
+ inputSchema: z.object({
642
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
643
+ view_conf_id: z.string().describe('视图配置ID (必填)'),
644
+ limit: z.number().optional().describe('返回数量'),
645
+ page: z.number().optional().describe('页码'),
646
+ fields: z.string().optional().describe('返回字段'),
647
+ }),
648
+ handler: async (client, params) => {
649
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
650
+ if (!workspaceId) {
651
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
652
+ }
653
+ return client.get('/stories/by_view_conf_id', { ...params, workspace_id: workspaceId });
654
+ },
655
+ },
656
+ {
657
+ name: 'tapd_get_story_steps',
658
+ description: '获取需求节点信息',
659
+ inputSchema: z.object({
660
+ workspace_id: z.number().optional().describe('项目ID(可省略,使用默认配置)'),
661
+ story_id: z.string().describe('需求ID (必填)'),
662
+ limit: z.number().optional().describe('返回数量'),
663
+ page: z.number().optional().describe('页码'),
664
+ fields: z.string().optional().describe('返回字段'),
665
+ }),
666
+ handler: async (client, params) => {
667
+ const workspaceId = params.workspace_id ?? TapdClient.getDefaultWorkspaceId();
668
+ if (!workspaceId) {
669
+ throw new Error('workspace_id is required (either provide it or set TAPD_DEFAULT_WORKSPACE_ID env)');
670
+ }
671
+ const convertedParams = {
672
+ ...params,
673
+ story_id: TapdClient.toLongId(params.story_id, workspaceId),
674
+ workspace_id: workspaceId,
675
+ };
676
+ return client.get('/stories/steps', convertedParams);
187
677
  },
188
678
  },
189
679
  ];