tempo-api-mcp 2.0.0 → 2.0.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.
- package/dist/bundle.js +14681 -5760
- package/dist/index.js +12 -47
- package/dist/tools/accounts.js +97 -154
- package/dist/tools/plans.js +81 -134
- package/dist/tools/projects.js +89 -164
- package/dist/tools/teams.js +94 -147
- package/dist/tools/worklogs.js +163 -245
- package/package.json +4 -3
package/dist/tools/projects.js
CHANGED
|
@@ -1,203 +1,128 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function register(server, client) {
|
|
3
|
+
server.registerTool('tempo_get_projects', {
|
|
4
4
|
description: 'Retrieve a paginated list of all Tempo Financial Manager projects.',
|
|
5
5
|
annotations: { readOnlyHint: true },
|
|
6
6
|
inputSchema: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
10
|
-
limit: { type: 'integer', description: 'Max results (default 50)' },
|
|
11
|
-
},
|
|
12
|
-
required: [],
|
|
7
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
8
|
+
limit: z.number().int().optional().describe('Max results (default 50)'),
|
|
13
9
|
},
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
}, async ({ offset, limit }) => {
|
|
11
|
+
const data = await client.request('GET', '/4/projects', undefined, { offset, limit });
|
|
12
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
13
|
+
});
|
|
14
|
+
server.registerTool('tempo_get_project', {
|
|
17
15
|
description: 'Retrieve a single Tempo Financial Manager project by id.',
|
|
18
16
|
annotations: { readOnlyHint: true },
|
|
19
17
|
inputSchema: {
|
|
20
|
-
|
|
21
|
-
properties: {
|
|
22
|
-
id: { type: 'string', description: 'Project id' },
|
|
23
|
-
},
|
|
24
|
-
required: ['id'],
|
|
18
|
+
id: z.string().describe('Project id'),
|
|
25
19
|
},
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
}, async ({ id }) => {
|
|
21
|
+
const data = await client.request('GET', `/4/projects/${id}`);
|
|
22
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
23
|
+
});
|
|
24
|
+
server.registerTool('tempo_get_timesheet_approval_status', {
|
|
29
25
|
description: 'Retrieve the current timesheet approval status for a user in the given period.',
|
|
30
26
|
annotations: { readOnlyHint: true },
|
|
31
27
|
inputSchema: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
from: { type: 'string', description: 'Period start date (YYYY-MM-DD)' },
|
|
36
|
-
to: { type: 'string', description: 'Period end date (YYYY-MM-DD)' },
|
|
37
|
-
},
|
|
38
|
-
required: ['accountId'],
|
|
28
|
+
accountId: z.string().describe('Atlassian account id of the user'),
|
|
29
|
+
from: z.string().optional().describe('Period start date (YYYY-MM-DD)'),
|
|
30
|
+
to: z.string().optional().describe('Period end date (YYYY-MM-DD)'),
|
|
39
31
|
},
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
}, async ({ accountId, from, to }) => {
|
|
33
|
+
const data = await client.request('GET', `/4/timesheet-approvals/user/${accountId}`, undefined, { from, to });
|
|
34
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
35
|
+
});
|
|
36
|
+
server.registerTool('tempo_get_timesheet_approvals_waiting', {
|
|
43
37
|
description: 'Retrieve all timesheets that are currently waiting for approval.',
|
|
44
38
|
annotations: { readOnlyHint: true },
|
|
45
39
|
inputSchema: {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
49
|
-
limit: { type: 'integer', description: 'Max results' },
|
|
50
|
-
},
|
|
51
|
-
required: [],
|
|
40
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
41
|
+
limit: z.number().int().optional().describe('Max results'),
|
|
52
42
|
},
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
}, async ({ offset, limit }) => {
|
|
44
|
+
const data = await client.request('GET', '/4/timesheet-approvals/waiting', undefined, { offset, limit });
|
|
45
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
46
|
+
});
|
|
47
|
+
server.registerTool('tempo_search_timesheet_approval_logs', {
|
|
56
48
|
description: 'Search timesheet approval audit logs.',
|
|
57
49
|
annotations: { readOnlyHint: true },
|
|
58
50
|
inputSchema: {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
66
|
-
limit: { type: 'integer', description: 'Max results' },
|
|
67
|
-
},
|
|
68
|
-
required: [],
|
|
51
|
+
accountIds: z.array(z.string()).optional().describe('Filter by Atlassian account ids'),
|
|
52
|
+
reviewerIds: z.array(z.string()).optional().describe('Filter by reviewer account ids'),
|
|
53
|
+
from: z.string().optional().describe('Start date (YYYY-MM-DD)'),
|
|
54
|
+
to: z.string().optional().describe('End date (YYYY-MM-DD)'),
|
|
55
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
56
|
+
limit: z.number().int().optional().describe('Max results'),
|
|
69
57
|
},
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
|
|
58
|
+
}, async ({ accountIds, reviewerIds, from, to, offset, limit }) => {
|
|
59
|
+
const qs = {};
|
|
60
|
+
if (offset !== undefined)
|
|
61
|
+
qs.offset = offset;
|
|
62
|
+
if (limit !== undefined)
|
|
63
|
+
qs.limit = limit;
|
|
64
|
+
const body = {};
|
|
65
|
+
if (accountIds)
|
|
66
|
+
body.accountIds = accountIds;
|
|
67
|
+
if (reviewerIds)
|
|
68
|
+
body.reviewerIds = reviewerIds;
|
|
69
|
+
if (from)
|
|
70
|
+
body.from = from;
|
|
71
|
+
if (to)
|
|
72
|
+
body.to = to;
|
|
73
|
+
const data = await client.request('POST', '/4/timesheet-approvals/logs/search', body, qs);
|
|
74
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
75
|
+
});
|
|
76
|
+
server.registerTool('tempo_get_periods', {
|
|
73
77
|
description: 'Retrieve Tempo period definitions (used for timesheet approval cycles).',
|
|
74
78
|
annotations: { readOnlyHint: true },
|
|
75
79
|
inputSchema: {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
from: { type: 'string', description: 'Start date (YYYY-MM-DD)' },
|
|
79
|
-
to: { type: 'string', description: 'End date (YYYY-MM-DD)' },
|
|
80
|
-
},
|
|
81
|
-
required: [],
|
|
80
|
+
from: z.string().optional().describe('Start date (YYYY-MM-DD)'),
|
|
81
|
+
to: z.string().optional().describe('End date (YYYY-MM-DD)'),
|
|
82
82
|
},
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
}, async ({ from, to }) => {
|
|
84
|
+
const data = await client.request('GET', '/4/periods', undefined, { from, to });
|
|
85
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
86
|
+
});
|
|
87
|
+
server.registerTool('tempo_get_user_schedule', {
|
|
86
88
|
description: 'Retrieve the work schedule for a user, including planned working hours per day.',
|
|
87
89
|
annotations: { readOnlyHint: true },
|
|
88
90
|
inputSchema: {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
from: { type: 'string', description: 'Start date (YYYY-MM-DD)' },
|
|
93
|
-
to: { type: 'string', description: 'End date (YYYY-MM-DD)' },
|
|
94
|
-
},
|
|
95
|
-
required: ['accountId', 'from', 'to'],
|
|
91
|
+
accountId: z.string().describe('Atlassian account id of the user'),
|
|
92
|
+
from: z.string().describe('Start date (YYYY-MM-DD)'),
|
|
93
|
+
to: z.string().describe('End date (YYYY-MM-DD)'),
|
|
96
94
|
},
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
}, async ({ accountId, from, to }) => {
|
|
96
|
+
const data = await client.request('GET', `/4/user-schedule`, undefined, { accountId, from, to });
|
|
97
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
98
|
+
});
|
|
99
|
+
server.registerTool('tempo_get_global_configuration', {
|
|
100
100
|
description: 'Retrieve the global Tempo configuration settings.',
|
|
101
101
|
annotations: { readOnlyHint: true },
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
name: 'tempo_get_work_attributes',
|
|
102
|
+
}, async () => {
|
|
103
|
+
const data = await client.request('GET', '/4/globalconfiguration');
|
|
104
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
105
|
+
});
|
|
106
|
+
server.registerTool('tempo_get_work_attributes', {
|
|
110
107
|
description: 'Retrieve all Tempo work attributes (custom fields on worklogs).',
|
|
111
108
|
annotations: { readOnlyHint: true },
|
|
112
109
|
inputSchema: {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
116
|
-
limit: { type: 'integer', description: 'Max results' },
|
|
117
|
-
},
|
|
118
|
-
required: [],
|
|
110
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
111
|
+
limit: z.number().int().optional().describe('Max results'),
|
|
119
112
|
},
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
|
|
113
|
+
}, async ({ offset, limit }) => {
|
|
114
|
+
const data = await client.request('GET', '/4/work-attributes', undefined, { offset, limit });
|
|
115
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
116
|
+
});
|
|
117
|
+
server.registerTool('tempo_get_roles', {
|
|
123
118
|
description: 'Retrieve all Tempo roles.',
|
|
124
119
|
annotations: { readOnlyHint: true },
|
|
125
120
|
inputSchema: {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
129
|
-
limit: { type: 'integer', description: 'Max results' },
|
|
130
|
-
},
|
|
131
|
-
required: [],
|
|
121
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
122
|
+
limit: z.number().int().optional().describe('Max results'),
|
|
132
123
|
},
|
|
133
|
-
},
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
case 'tempo_get_projects': {
|
|
138
|
-
const { offset, limit } = args;
|
|
139
|
-
const data = await client.request('GET', '/4/projects', undefined, { offset, limit });
|
|
140
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
141
|
-
}
|
|
142
|
-
case 'tempo_get_project': {
|
|
143
|
-
const { id } = args;
|
|
144
|
-
const data = await client.request('GET', `/4/projects/${id}`);
|
|
145
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
146
|
-
}
|
|
147
|
-
case 'tempo_get_timesheet_approval_status': {
|
|
148
|
-
const { accountId, from, to } = args;
|
|
149
|
-
const data = await client.request('GET', `/4/timesheet-approvals/user/${accountId}`, undefined, { from, to });
|
|
150
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
151
|
-
}
|
|
152
|
-
case 'tempo_get_timesheet_approvals_waiting': {
|
|
153
|
-
const { offset, limit } = args;
|
|
154
|
-
const data = await client.request('GET', '/4/timesheet-approvals/waiting', undefined, { offset, limit });
|
|
155
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
156
|
-
}
|
|
157
|
-
case 'tempo_search_timesheet_approval_logs': {
|
|
158
|
-
const { accountIds, reviewerIds, from, to, offset, limit } = args;
|
|
159
|
-
const qs = {};
|
|
160
|
-
if (offset !== undefined)
|
|
161
|
-
qs.offset = offset;
|
|
162
|
-
if (limit !== undefined)
|
|
163
|
-
qs.limit = limit;
|
|
164
|
-
const body = {};
|
|
165
|
-
if (accountIds)
|
|
166
|
-
body.accountIds = accountIds;
|
|
167
|
-
if (reviewerIds)
|
|
168
|
-
body.reviewerIds = reviewerIds;
|
|
169
|
-
if (from)
|
|
170
|
-
body.from = from;
|
|
171
|
-
if (to)
|
|
172
|
-
body.to = to;
|
|
173
|
-
const data = await client.request('POST', '/4/timesheet-approvals/logs/search', body, qs);
|
|
174
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
175
|
-
}
|
|
176
|
-
case 'tempo_get_periods': {
|
|
177
|
-
const { from, to } = args;
|
|
178
|
-
const data = await client.request('GET', '/4/periods', undefined, { from, to });
|
|
179
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
180
|
-
}
|
|
181
|
-
case 'tempo_get_user_schedule': {
|
|
182
|
-
const { accountId, from, to } = args;
|
|
183
|
-
const data = await client.request('GET', `/4/user-schedule`, undefined, { accountId, from, to });
|
|
184
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
185
|
-
}
|
|
186
|
-
case 'tempo_get_global_configuration': {
|
|
187
|
-
const data = await client.request('GET', '/4/globalconfiguration');
|
|
188
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
189
|
-
}
|
|
190
|
-
case 'tempo_get_work_attributes': {
|
|
191
|
-
const { offset, limit } = args;
|
|
192
|
-
const data = await client.request('GET', '/4/work-attributes', undefined, { offset, limit });
|
|
193
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
194
|
-
}
|
|
195
|
-
case 'tempo_get_roles': {
|
|
196
|
-
const { offset, limit } = args;
|
|
197
|
-
const data = await client.request('GET', '/4/roles', undefined, { offset, limit });
|
|
198
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
199
|
-
}
|
|
200
|
-
default:
|
|
201
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
202
|
-
}
|
|
124
|
+
}, async ({ offset, limit }) => {
|
|
125
|
+
const data = await client.request('GET', '/4/roles', undefined, { offset, limit });
|
|
126
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
127
|
+
});
|
|
203
128
|
}
|
package/dist/tools/teams.js
CHANGED
|
@@ -1,176 +1,123 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
function buildTeamBody(args) {
|
|
3
|
+
const body = { name: args.name };
|
|
4
|
+
if (args.summary !== undefined)
|
|
5
|
+
body.summary = args.summary;
|
|
6
|
+
if (args.leadAccountId !== undefined)
|
|
7
|
+
body.leadAccountId = args.leadAccountId;
|
|
8
|
+
if (args.programId !== undefined)
|
|
9
|
+
body.programId = args.programId;
|
|
10
|
+
return body;
|
|
11
|
+
}
|
|
12
|
+
export function register(server, client) {
|
|
13
|
+
server.registerTool('tempo_get_teams', {
|
|
4
14
|
description: 'Retrieve a list of Tempo teams. Can filter by name, member account ids, or specific team ids.',
|
|
5
15
|
annotations: { readOnlyHint: true },
|
|
6
16
|
inputSchema: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
14
|
-
limit: { type: 'integer', description: 'Max results (default 50)' },
|
|
15
|
-
},
|
|
16
|
-
required: [],
|
|
17
|
+
name: z.string().optional().describe('Filter by team name'),
|
|
18
|
+
teamIds: z.array(z.number().int()).optional().describe('Filter by specific team ids'),
|
|
19
|
+
teamMembers: z.array(z.string()).optional().describe('Filter by member Atlassian account ids'),
|
|
20
|
+
includeMemberships: z.boolean().optional().describe('Include team member memberships in response'),
|
|
21
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
22
|
+
limit: z.number().int().optional().describe('Max results (default 50)'),
|
|
17
23
|
},
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
}, async ({ name: teamName, teamIds, teamMembers, includeMemberships, offset, limit }) => {
|
|
25
|
+
const data = await client.request('GET', '/4/teams', undefined, {
|
|
26
|
+
name: teamName, teamIds, teamMembers, includeMemberships, offset, limit,
|
|
27
|
+
});
|
|
28
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
29
|
+
});
|
|
30
|
+
server.registerTool('tempo_get_team', {
|
|
21
31
|
description: 'Retrieve a single Tempo team by id.',
|
|
22
32
|
annotations: { readOnlyHint: true },
|
|
23
33
|
inputSchema: {
|
|
24
|
-
|
|
25
|
-
properties: {
|
|
26
|
-
id: { type: 'integer', description: 'Team id' },
|
|
27
|
-
},
|
|
28
|
-
required: ['id'],
|
|
34
|
+
id: z.number().int().describe('Team id'),
|
|
29
35
|
},
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
}, async ({ id }) => {
|
|
37
|
+
const data = await client.request('GET', `/4/teams/${id}`);
|
|
38
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
39
|
+
});
|
|
40
|
+
server.registerTool('tempo_create_team', {
|
|
33
41
|
description: 'Create a new Tempo team.',
|
|
34
42
|
annotations: { readOnlyHint: false },
|
|
35
43
|
inputSchema: {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
leadAccountId: { type: 'string', description: 'Atlassian account id of the team lead' },
|
|
41
|
-
programId: { type: 'integer', description: 'Id of the program this team belongs to' },
|
|
42
|
-
},
|
|
43
|
-
required: ['name'],
|
|
44
|
+
name: z.string().describe('Team name'),
|
|
45
|
+
summary: z.string().optional().describe('Short description of the team'),
|
|
46
|
+
leadAccountId: z.string().optional().describe('Atlassian account id of the team lead'),
|
|
47
|
+
programId: z.number().int().optional().describe('Id of the program this team belongs to'),
|
|
44
48
|
},
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
}, async (args) => {
|
|
50
|
+
const body = buildTeamBody(args);
|
|
51
|
+
const data = await client.request('POST', '/4/teams', body);
|
|
52
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
53
|
+
});
|
|
54
|
+
server.registerTool('tempo_update_team', {
|
|
48
55
|
description: 'Update an existing Tempo team by id.',
|
|
49
56
|
annotations: { readOnlyHint: false },
|
|
50
57
|
inputSchema: {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
leadAccountId: { type: 'string', description: 'Atlassian account id of the team lead' },
|
|
57
|
-
programId: { type: 'integer', description: 'Id of the program this team belongs to' },
|
|
58
|
-
},
|
|
59
|
-
required: ['id', 'name'],
|
|
58
|
+
id: z.number().int().describe('Team id'),
|
|
59
|
+
name: z.string().describe('Team name'),
|
|
60
|
+
summary: z.string().optional().describe('Short description of the team'),
|
|
61
|
+
leadAccountId: z.string().optional().describe('Atlassian account id of the team lead'),
|
|
62
|
+
programId: z.number().int().optional().describe('Id of the program this team belongs to'),
|
|
60
63
|
},
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
}, async ({ id, ...rest }) => {
|
|
65
|
+
const body = buildTeamBody(rest);
|
|
66
|
+
const data = await client.request('PUT', `/4/teams/${id}`, body);
|
|
67
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
68
|
+
});
|
|
69
|
+
server.registerTool('tempo_delete_team', {
|
|
64
70
|
description: 'Delete a Tempo team by id.',
|
|
65
71
|
annotations: { readOnlyHint: false },
|
|
66
72
|
inputSchema: {
|
|
67
|
-
|
|
68
|
-
properties: {
|
|
69
|
-
id: { type: 'integer', description: 'Team id' },
|
|
70
|
-
},
|
|
71
|
-
required: ['id'],
|
|
73
|
+
id: z.number().int().describe('Team id'),
|
|
72
74
|
},
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
}, async ({ id }) => {
|
|
76
|
+
await client.request('DELETE', `/4/teams/${id}`);
|
|
77
|
+
return { content: [{ type: 'text', text: `Team ${id} deleted successfully` }] };
|
|
78
|
+
});
|
|
79
|
+
server.registerTool('tempo_get_team_memberships', {
|
|
76
80
|
description: 'Retrieve team memberships, optionally filtered by account id or team id.',
|
|
77
81
|
annotations: { readOnlyHint: true },
|
|
78
82
|
inputSchema: {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
84
|
-
limit: { type: 'integer', description: 'Max results (default 50)' },
|
|
85
|
-
},
|
|
86
|
-
required: [],
|
|
83
|
+
accountIds: z.array(z.string()).optional().describe('Filter by Atlassian account ids'),
|
|
84
|
+
teamIds: z.array(z.number().int()).optional().describe('Filter by team ids'),
|
|
85
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
86
|
+
limit: z.number().int().optional().describe('Max results (default 50)'),
|
|
87
87
|
},
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
}, async ({ accountIds, teamIds, offset, limit }) => {
|
|
89
|
+
const data = await client.request('GET', '/4/team-memberships', undefined, {
|
|
90
|
+
accountIds, teamIds, offset, limit,
|
|
91
|
+
});
|
|
92
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
93
|
+
});
|
|
94
|
+
server.registerTool('tempo_search_team_memberships', {
|
|
91
95
|
description: 'Search Tempo team memberships with advanced filters via POST.',
|
|
92
96
|
annotations: { readOnlyHint: true },
|
|
93
97
|
inputSchema: {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
offset: { type: 'integer', description: 'Pagination offset' },
|
|
101
|
-
limit: { type: 'integer', description: 'Max results' },
|
|
102
|
-
},
|
|
103
|
-
required: [],
|
|
98
|
+
teamIds: z.array(z.number().int()).optional().describe('Filter by team ids'),
|
|
99
|
+
accountIds: z.array(z.string()).optional().describe('Filter by Atlassian account ids'),
|
|
100
|
+
from: z.string().optional().describe('Membership active from date (YYYY-MM-DD)'),
|
|
101
|
+
to: z.string().optional().describe('Membership active to date (YYYY-MM-DD)'),
|
|
102
|
+
offset: z.number().int().optional().describe('Pagination offset'),
|
|
103
|
+
limit: z.number().int().optional().describe('Max results'),
|
|
104
104
|
},
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
});
|
|
124
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
125
|
-
}
|
|
126
|
-
case 'tempo_get_team': {
|
|
127
|
-
const { id } = args;
|
|
128
|
-
const data = await client.request('GET', `/4/teams/${id}`);
|
|
129
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
130
|
-
}
|
|
131
|
-
case 'tempo_create_team': {
|
|
132
|
-
const body = buildTeamBody(args);
|
|
133
|
-
const data = await client.request('POST', '/4/teams', body);
|
|
134
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
135
|
-
}
|
|
136
|
-
case 'tempo_update_team': {
|
|
137
|
-
const { id, ...rest } = args;
|
|
138
|
-
const body = buildTeamBody(rest);
|
|
139
|
-
const data = await client.request('PUT', `/4/teams/${id}`, body);
|
|
140
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
141
|
-
}
|
|
142
|
-
case 'tempo_delete_team': {
|
|
143
|
-
const { id } = args;
|
|
144
|
-
await client.request('DELETE', `/4/teams/${id}`);
|
|
145
|
-
return { content: [{ type: 'text', text: `Team ${id} deleted successfully` }] };
|
|
146
|
-
}
|
|
147
|
-
case 'tempo_get_team_memberships': {
|
|
148
|
-
const { accountIds, teamIds, offset, limit } = args;
|
|
149
|
-
const data = await client.request('GET', '/4/team-memberships', undefined, {
|
|
150
|
-
accountIds, teamIds, offset, limit,
|
|
151
|
-
});
|
|
152
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
153
|
-
}
|
|
154
|
-
case 'tempo_search_team_memberships': {
|
|
155
|
-
const { teamIds, accountIds, from, to, offset, limit } = args;
|
|
156
|
-
const query = {};
|
|
157
|
-
if (offset !== undefined)
|
|
158
|
-
query.offset = offset;
|
|
159
|
-
if (limit !== undefined)
|
|
160
|
-
query.limit = limit;
|
|
161
|
-
const body = {};
|
|
162
|
-
if (teamIds)
|
|
163
|
-
body.teamIds = teamIds;
|
|
164
|
-
if (accountIds)
|
|
165
|
-
body.accountIds = accountIds;
|
|
166
|
-
if (from)
|
|
167
|
-
body.from = from;
|
|
168
|
-
if (to)
|
|
169
|
-
body.to = to;
|
|
170
|
-
const data = await client.request('POST', '/4/team-memberships/search', body, query);
|
|
171
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
172
|
-
}
|
|
173
|
-
default:
|
|
174
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
175
|
-
}
|
|
105
|
+
}, async ({ teamIds, accountIds, from, to, offset, limit }) => {
|
|
106
|
+
const query = {};
|
|
107
|
+
if (offset !== undefined)
|
|
108
|
+
query.offset = offset;
|
|
109
|
+
if (limit !== undefined)
|
|
110
|
+
query.limit = limit;
|
|
111
|
+
const body = {};
|
|
112
|
+
if (teamIds)
|
|
113
|
+
body.teamIds = teamIds;
|
|
114
|
+
if (accountIds)
|
|
115
|
+
body.accountIds = accountIds;
|
|
116
|
+
if (from)
|
|
117
|
+
body.from = from;
|
|
118
|
+
if (to)
|
|
119
|
+
body.to = to;
|
|
120
|
+
const data = await client.request('POST', '/4/team-memberships/search', body, query);
|
|
121
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
122
|
+
});
|
|
176
123
|
}
|