wolfpack-mcp 1.0.92 → 1.0.94
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/README.md +45 -0
- package/dist/agentBuilderTools.js +3 -35
- package/dist/agentBuilderTools.test.js +10 -29
- package/dist/client.js +22 -0
- package/dist/index.js +198 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -355,6 +355,51 @@ Get a specific radar item.
|
|
|
355
355
|
- `item_id` (required): UUID or reference number
|
|
356
356
|
- `team_id` (optional): Required when using reference number
|
|
357
357
|
|
|
358
|
+
### Tags
|
|
359
|
+
|
|
360
|
+
Tags label work items, issues, wiki pages and journal entries, and are filed under nestable groups. Project admins define them; a key with `mcp:tags:manage` lets an admin's agent keep them in step with an external system (for example, one tag per CRM customer account keyed on `external_id`). There is no delete tool — removing a tag is done in the browser.
|
|
361
|
+
|
|
362
|
+
#### `list_tags`
|
|
363
|
+
|
|
364
|
+
List a project's tags with id, name, colour, `externalId` and the group each is filed under. Any key that can read a tagged module may list them.
|
|
365
|
+
|
|
366
|
+
- `project_slug` (optional): Project slug
|
|
367
|
+
|
|
368
|
+
#### `create_tag`
|
|
369
|
+
|
|
370
|
+
- `name` (required): Tag name, unique within the project
|
|
371
|
+
- `colour` (optional): Hex colour such as `#e879f9`
|
|
372
|
+
- `group` (optional): Tag group name or id
|
|
373
|
+
- `external_id` (optional): Id of this tag in the system that maintains it, unique within the project
|
|
374
|
+
- `project_slug` (optional): Project slug
|
|
375
|
+
|
|
376
|
+
#### `update_tag`
|
|
377
|
+
|
|
378
|
+
Only the fields given change; pass `null` for `colour`, `group` or `external_id` to clear it.
|
|
379
|
+
|
|
380
|
+
- `tag` (required): Tag id or current name
|
|
381
|
+
- `name`, `colour`, `group`, `external_id` (optional)
|
|
382
|
+
- `project_slug` (optional): Project slug
|
|
383
|
+
|
|
384
|
+
#### `list_tag_groups`
|
|
385
|
+
|
|
386
|
+
List a project's tag groups with their parent and full path (e.g. `Customers › EMEA`).
|
|
387
|
+
|
|
388
|
+
- `project_slug` (optional): Project slug
|
|
389
|
+
|
|
390
|
+
#### `create_tag_group`
|
|
391
|
+
|
|
392
|
+
- `name` (required): Group name, unique within the project
|
|
393
|
+
- `parent` (optional): Parent group name or id
|
|
394
|
+
- `project_slug` (optional): Project slug
|
|
395
|
+
|
|
396
|
+
#### `update_tag_group`
|
|
397
|
+
|
|
398
|
+
- `group` (required): Group id or current name
|
|
399
|
+
- `name` (optional): New name
|
|
400
|
+
- `parent` (optional): Parent group name or id, or `null` for the top level
|
|
401
|
+
- `project_slug` (optional): Project slug
|
|
402
|
+
|
|
358
403
|
### Images
|
|
359
404
|
|
|
360
405
|
#### `upload_image`
|
|
@@ -113,10 +113,6 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
113
113
|
items: { type: 'string' },
|
|
114
114
|
description: 'Replace the full set of MCP permissions granted to the agent\'s session API key (e.g. ["mcp:work_items:read", "mcp:comments:create"]). Grant only what the agent\'s tasks need. An empty array falls back to a read-only default.',
|
|
115
115
|
},
|
|
116
|
-
scheduling_enabled: {
|
|
117
|
-
type: 'boolean',
|
|
118
|
-
description: "The agent-level scheduling switch. No schedule fires while it is off, whatever the schedule's own enabled flag says.",
|
|
119
|
-
},
|
|
120
116
|
...ORG_SLUG_PROP,
|
|
121
117
|
},
|
|
122
118
|
required: ['agent_id'],
|
|
@@ -354,10 +350,6 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
354
350
|
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
355
351
|
name: { type: 'string', description: 'Task name' },
|
|
356
352
|
prompt: { type: 'string', description: 'What the agent should do when this task runs' },
|
|
357
|
-
scheduled_enabled: {
|
|
358
|
-
type: 'boolean',
|
|
359
|
-
description: 'Whether this task is included in scheduled runs (default false)',
|
|
360
|
-
},
|
|
361
353
|
sort_order: {
|
|
362
354
|
type: 'number',
|
|
363
355
|
description: 'Order within scheduled batch (lower = first)',
|
|
@@ -388,7 +380,7 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
388
380
|
},
|
|
389
381
|
{
|
|
390
382
|
name: 'update_agent_task',
|
|
391
|
-
description: "Update a task's prompt,
|
|
383
|
+
description: "Update a task's prompt, sort order, model pin, or disabled tools/MCP servers.",
|
|
392
384
|
inputSchema: {
|
|
393
385
|
type: 'object',
|
|
394
386
|
properties: {
|
|
@@ -396,7 +388,6 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
396
388
|
task_id: { type: 'string', description: 'Task ID' },
|
|
397
389
|
name: { type: 'string', description: 'Updated task name' },
|
|
398
390
|
prompt: { type: 'string', description: 'Updated prompt' },
|
|
399
|
-
scheduled_enabled: { type: 'boolean', description: 'Include in scheduled runs' },
|
|
400
391
|
sort_order: { type: 'number', description: 'Order within scheduled batch' },
|
|
401
392
|
is_active: { type: 'boolean', description: 'Whether this task is active' },
|
|
402
393
|
...TASK_MODEL_PROPS,
|
|
@@ -836,19 +827,6 @@ const AgentTaskSchema = z.object({
|
|
|
836
827
|
org_slug: orgSlugField,
|
|
837
828
|
});
|
|
838
829
|
const SkillIdSchema = z.object({ skill_id: z.string(), org_slug: orgSlugField });
|
|
839
|
-
/**
|
|
840
|
-
* A schedule enabled on an agent whose own scheduling switch is off never
|
|
841
|
-
* fires (#2083) — say so in the result rather than letting the caller find
|
|
842
|
-
* out from a schedule that stays silent.
|
|
843
|
-
*/
|
|
844
|
-
async function schedulingOffWarning(client, agentId, scheduleEnabled, orgSlug) {
|
|
845
|
-
if (!scheduleEnabled)
|
|
846
|
-
return '';
|
|
847
|
-
const agent = await client.getAgent(agentId, orgSlug);
|
|
848
|
-
return !agent || agent.schedulingEnabled
|
|
849
|
-
? ''
|
|
850
|
-
: "\n\nWARNING: this agent's scheduling is switched off, so the schedule will not fire until update_agent sets scheduling_enabled: true.";
|
|
851
|
-
}
|
|
852
830
|
export async function handleAgentBuilderTool(name, args, client) {
|
|
853
831
|
const text = (t) => JSON.stringify(t, null, 2);
|
|
854
832
|
switch (name) {
|
|
@@ -906,7 +884,6 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
906
884
|
llm_model: z.string().nullable().optional(),
|
|
907
885
|
llm_family: z.string().nullable().optional(),
|
|
908
886
|
api_key_permissions: z.array(z.string()).optional(),
|
|
909
|
-
scheduling_enabled: z.boolean().optional(),
|
|
910
887
|
org_slug: orgSlugField,
|
|
911
888
|
})
|
|
912
889
|
.parse(args);
|
|
@@ -930,8 +907,6 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
930
907
|
fields.llmFamily = rest.llm_family;
|
|
931
908
|
if (rest.api_key_permissions !== undefined)
|
|
932
909
|
fields.apiKeyPermissions = rest.api_key_permissions;
|
|
933
|
-
if (rest.scheduling_enabled !== undefined)
|
|
934
|
-
fields.schedulingEnabled = rest.scheduling_enabled;
|
|
935
910
|
const agent = await client.updateAgent(agent_id, fields, resolveOrg(parsed));
|
|
936
911
|
return { content: [{ type: 'text', text: `Updated agent\n\n${text(agent)}` }] };
|
|
937
912
|
}
|
|
@@ -1095,7 +1070,6 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1095
1070
|
agent_id: z.string(),
|
|
1096
1071
|
name: z.string(),
|
|
1097
1072
|
prompt: z.string(),
|
|
1098
|
-
scheduled_enabled: z.boolean().optional(),
|
|
1099
1073
|
sort_order: z.number().optional(),
|
|
1100
1074
|
llm_provider: z.string().nullable().optional(),
|
|
1101
1075
|
llm_model: z.string().nullable().optional(),
|
|
@@ -1109,7 +1083,6 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1109
1083
|
const task = await client.createAgentTask(parsed.agent_id, {
|
|
1110
1084
|
name: parsed.name,
|
|
1111
1085
|
prompt: parsed.prompt,
|
|
1112
|
-
scheduledEnabled: parsed.scheduled_enabled,
|
|
1113
1086
|
sortOrder: parsed.sort_order,
|
|
1114
1087
|
llmProvider: parsed.llm_provider,
|
|
1115
1088
|
llmModel: parsed.llm_model,
|
|
@@ -1127,7 +1100,6 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1127
1100
|
task_id: z.string(),
|
|
1128
1101
|
name: z.string().optional(),
|
|
1129
1102
|
prompt: z.string().optional(),
|
|
1130
|
-
scheduled_enabled: z.boolean().optional(),
|
|
1131
1103
|
sort_order: z.number().optional(),
|
|
1132
1104
|
is_active: z.boolean().optional(),
|
|
1133
1105
|
llm_provider: z.string().nullable().optional(),
|
|
@@ -1144,8 +1116,6 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1144
1116
|
fields.name = parsed.name;
|
|
1145
1117
|
if (parsed.prompt !== undefined)
|
|
1146
1118
|
fields.prompt = parsed.prompt;
|
|
1147
|
-
if (parsed.scheduled_enabled !== undefined)
|
|
1148
|
-
fields.scheduledEnabled = parsed.scheduled_enabled;
|
|
1149
1119
|
if (parsed.sort_order !== undefined)
|
|
1150
1120
|
fields.sortOrder = parsed.sort_order;
|
|
1151
1121
|
if (parsed.is_active !== undefined)
|
|
@@ -1256,12 +1226,11 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1256
1226
|
if (rest.task_ids !== undefined)
|
|
1257
1227
|
body.taskIds = rest.task_ids;
|
|
1258
1228
|
const schedule = await client.createAgentSchedule(agent_id, body, resolveOrg(parsed));
|
|
1259
|
-
const warning = await schedulingOffWarning(client, agent_id, schedule.enabled, resolveOrg(parsed));
|
|
1260
1229
|
return {
|
|
1261
1230
|
content: [
|
|
1262
1231
|
{
|
|
1263
1232
|
type: 'text',
|
|
1264
|
-
text: `Created schedule "${schedule.name}"
|
|
1233
|
+
text: `Created schedule "${schedule.name}"\n\n${text(schedule)}`,
|
|
1265
1234
|
},
|
|
1266
1235
|
],
|
|
1267
1236
|
};
|
|
@@ -1316,9 +1285,8 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1316
1285
|
if (rest.task_ids !== undefined)
|
|
1317
1286
|
body.taskIds = rest.task_ids;
|
|
1318
1287
|
const schedule = await client.updateAgentSchedule(agent_id, schedule_id, body, resolveOrg(parsed));
|
|
1319
|
-
const warning = await schedulingOffWarning(client, agent_id, schedule.enabled, resolveOrg(parsed));
|
|
1320
1288
|
return {
|
|
1321
|
-
content: [{ type: 'text', text: `Updated schedule
|
|
1289
|
+
content: [{ type: 'text', text: `Updated schedule\n\n${text(schedule)}` }],
|
|
1322
1290
|
};
|
|
1323
1291
|
}
|
|
1324
1292
|
// ─── Skills ─────────────────────────────────────────────────────────────
|
|
@@ -98,38 +98,28 @@ describe('extra instructions on a task run over MCP (#2048)', () => {
|
|
|
98
98
|
expect(runAgentTask.mock.calls[0][6]).toBeUndefined();
|
|
99
99
|
});
|
|
100
100
|
});
|
|
101
|
-
// #2083: everything the schedule editor can set is settable over MCP
|
|
102
|
-
|
|
103
|
-
describe('schedule pre-flight and scheduling switch over MCP (#2083)', () => {
|
|
101
|
+
// #2083: everything the schedule editor can set is settable over MCP.
|
|
102
|
+
describe('schedule pre-flight over MCP (#2083)', () => {
|
|
104
103
|
const SCHEDULE_FIELDS = ['preflight_check', 'check_kinds', 'skip_while_active'];
|
|
105
104
|
it.each(['create_agent_schedule', 'update_agent_schedule'])('%s advertises the pre-flight fields', (name) => {
|
|
106
105
|
const properties = toolNamed(name).inputSchema.properties;
|
|
107
106
|
expect(Object.keys(properties)).toEqual(expect.arrayContaining(SCHEDULE_FIELDS));
|
|
108
107
|
});
|
|
109
|
-
|
|
110
|
-
const properties = toolNamed('update_agent').inputSchema.properties;
|
|
111
|
-
expect(Object.keys(properties)).toContain('scheduling_enabled');
|
|
112
|
-
});
|
|
113
|
-
function scheduleClient(schedulingEnabled) {
|
|
108
|
+
function scheduleClient() {
|
|
114
109
|
const schedule = { id: 'sched-1', name: 'Reviews', enabled: true };
|
|
115
110
|
const createAgentSchedule = vi.fn().mockResolvedValue(schedule);
|
|
116
111
|
const updateAgentSchedule = vi.fn().mockResolvedValue(schedule);
|
|
117
|
-
const updateAgent = vi.fn().mockResolvedValue({ id: 'agent-1', schedulingEnabled });
|
|
118
|
-
const getAgent = vi.fn().mockResolvedValue({ id: 'agent-1', schedulingEnabled });
|
|
119
112
|
return {
|
|
120
113
|
client: {
|
|
121
114
|
createAgentSchedule,
|
|
122
115
|
updateAgentSchedule,
|
|
123
|
-
updateAgent,
|
|
124
|
-
getAgent,
|
|
125
116
|
},
|
|
126
117
|
createAgentSchedule,
|
|
127
118
|
updateAgentSchedule,
|
|
128
|
-
updateAgent,
|
|
129
119
|
};
|
|
130
120
|
}
|
|
131
121
|
it('sends the pre-flight, kinds and skip-while-active when creating a schedule', async () => {
|
|
132
|
-
const { client, createAgentSchedule } = scheduleClient(
|
|
122
|
+
const { client, createAgentSchedule } = scheduleClient();
|
|
133
123
|
await handleAgentBuilderTool('create_agent_schedule', {
|
|
134
124
|
agent_id: 'agent-1',
|
|
135
125
|
preflight_check: 'claimable-check',
|
|
@@ -143,23 +133,14 @@ describe('schedule pre-flight and scheduling switch over MCP (#2083)', () => {
|
|
|
143
133
|
});
|
|
144
134
|
});
|
|
145
135
|
it('sends the same fields when updating a schedule', async () => {
|
|
146
|
-
const { client, updateAgentSchedule } = scheduleClient(
|
|
136
|
+
const { client, updateAgentSchedule } = scheduleClient();
|
|
147
137
|
await handleAgentBuilderTool('update_agent_schedule', { agent_id: 'agent-1', schedule_id: 'sched-1', preflight_check: null, check_kinds: [] }, client);
|
|
148
138
|
expect(updateAgentSchedule.mock.calls[0][2]).toEqual({ preflightCheck: null, checkKinds: [] });
|
|
149
139
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
it('warns when an enabled schedule lands on an agent whose scheduling is off', async () => {
|
|
156
|
-
const { client } = scheduleClient(false);
|
|
157
|
-
const result = await handleAgentBuilderTool('create_agent_schedule', { agent_id: 'agent-1', enabled: true }, client);
|
|
158
|
-
expect(result.content[0].text).toContain('scheduling is switched off');
|
|
159
|
-
});
|
|
160
|
-
it('stays quiet when the agent is scheduling', async () => {
|
|
161
|
-
const { client } = scheduleClient(true);
|
|
162
|
-
const result = await handleAgentBuilderTool('create_agent_schedule', { agent_id: 'agent-1', enabled: true }, client);
|
|
163
|
-
expect(result.content[0].text).not.toContain('WARNING');
|
|
140
|
+
// #2067 retired the profile-level scheduling switch: a schedule's own
|
|
141
|
+
// enabled flag is the only switch, so update_agent must not offer another.
|
|
142
|
+
it('update_agent no longer advertises a scheduling switch', () => {
|
|
143
|
+
const properties = toolNamed('update_agent').inputSchema.properties;
|
|
144
|
+
expect(Object.keys(properties)).not.toContain('scheduling_enabled');
|
|
164
145
|
});
|
|
165
146
|
});
|
package/dist/client.js
CHANGED
|
@@ -525,6 +525,28 @@ export class WolfpackClient {
|
|
|
525
525
|
const query = params.toString();
|
|
526
526
|
return this.api.get(`/tags${query ? `?${query}` : ''}`);
|
|
527
527
|
}
|
|
528
|
+
async createTag(input, teamSlug) {
|
|
529
|
+
return this.api.post('/tags', { ...input, teamSlug });
|
|
530
|
+
}
|
|
531
|
+
async updateTag(tag, input, teamSlug) {
|
|
532
|
+
return this.api.patch(`/tags/${encodeURIComponent(tag)}`, { ...input, teamSlug });
|
|
533
|
+
}
|
|
534
|
+
async listTagGroups(teamSlug) {
|
|
535
|
+
const params = new URLSearchParams();
|
|
536
|
+
if (teamSlug)
|
|
537
|
+
params.append('teamSlug', teamSlug);
|
|
538
|
+
const query = params.toString();
|
|
539
|
+
return this.api.get(`/tag-groups${query ? `?${query}` : ''}`);
|
|
540
|
+
}
|
|
541
|
+
async createTagGroup(input, teamSlug) {
|
|
542
|
+
return this.api.post('/tag-groups', { ...input, teamSlug });
|
|
543
|
+
}
|
|
544
|
+
async updateTagGroup(group, input, teamSlug) {
|
|
545
|
+
return this.api.patch(`/tag-groups/${encodeURIComponent(group)}`, {
|
|
546
|
+
...input,
|
|
547
|
+
teamSlug,
|
|
548
|
+
});
|
|
549
|
+
}
|
|
528
550
|
/**
|
|
529
551
|
* Upload an image and get back a URL that can be used in markdown content.
|
|
530
552
|
*/
|
package/dist/index.js
CHANGED
|
@@ -600,6 +600,55 @@ const ListTagsSchema = z.object({
|
|
|
600
600
|
.optional()
|
|
601
601
|
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
602
602
|
});
|
|
603
|
+
const CreateTagSchema = z.object({
|
|
604
|
+
project_slug: z
|
|
605
|
+
.string()
|
|
606
|
+
.optional()
|
|
607
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
608
|
+
name: z.string().describe('Tag name, unique within the project'),
|
|
609
|
+
colour: z.string().optional().describe('Hex colour such as #e879f9'),
|
|
610
|
+
group: z.string().optional().describe('Tag group name or id to file the tag under'),
|
|
611
|
+
external_id: z
|
|
612
|
+
.string()
|
|
613
|
+
.optional()
|
|
614
|
+
.describe('Id of this tag in the system that maintains it, unique within the project'),
|
|
615
|
+
});
|
|
616
|
+
const UpdateTagSchema = z.object({
|
|
617
|
+
project_slug: z
|
|
618
|
+
.string()
|
|
619
|
+
.optional()
|
|
620
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
621
|
+
tag: z.string().describe('Tag id or current name'),
|
|
622
|
+
name: z.string().optional().describe('New name'),
|
|
623
|
+
colour: z.string().nullable().optional().describe('Hex colour, or null to clear'),
|
|
624
|
+
group: z
|
|
625
|
+
.string()
|
|
626
|
+
.nullable()
|
|
627
|
+
.optional()
|
|
628
|
+
.describe('Tag group name or id, or null to move the tag out of its group'),
|
|
629
|
+
external_id: z.string().nullable().optional().describe('External id, or null to clear'),
|
|
630
|
+
});
|
|
631
|
+
const CreateTagGroupSchema = z.object({
|
|
632
|
+
project_slug: z
|
|
633
|
+
.string()
|
|
634
|
+
.optional()
|
|
635
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
636
|
+
name: z.string().describe('Group name, unique within the project'),
|
|
637
|
+
parent: z.string().optional().describe('Parent group name or id'),
|
|
638
|
+
});
|
|
639
|
+
const UpdateTagGroupSchema = z.object({
|
|
640
|
+
project_slug: z
|
|
641
|
+
.string()
|
|
642
|
+
.optional()
|
|
643
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
644
|
+
group: z.string().describe('Group id or current name'),
|
|
645
|
+
name: z.string().optional().describe('New name'),
|
|
646
|
+
parent: z
|
|
647
|
+
.string()
|
|
648
|
+
.nullable()
|
|
649
|
+
.optional()
|
|
650
|
+
.describe('Parent group name or id, or null for the top level'),
|
|
651
|
+
});
|
|
603
652
|
// Team member schemas
|
|
604
653
|
const ListTeamMembersSchema = z.object({
|
|
605
654
|
project_slug: z
|
|
@@ -1937,8 +1986,9 @@ class WolfpackMCPServer {
|
|
|
1937
1986
|
// Tag tools
|
|
1938
1987
|
{
|
|
1939
1988
|
name: 'list_tags',
|
|
1940
|
-
description: 'List all tags available in a project
|
|
1941
|
-
'
|
|
1989
|
+
description: 'List all tags available in a project: id, name, colour, external id and the group each is filed under. ' +
|
|
1990
|
+
'Items are tagged by name via update_work_item / update_issue. ' +
|
|
1991
|
+
'A sync from an external system (e.g. a CRM) keys on externalId.',
|
|
1942
1992
|
inputSchema: {
|
|
1943
1993
|
type: 'object',
|
|
1944
1994
|
properties: {
|
|
@@ -1949,6 +1999,107 @@ class WolfpackMCPServer {
|
|
|
1949
1999
|
},
|
|
1950
2000
|
},
|
|
1951
2001
|
},
|
|
2002
|
+
{
|
|
2003
|
+
name: 'create_tag',
|
|
2004
|
+
description: 'Create a tag in a project. Project admins only (mcp:tags:manage). ' +
|
|
2005
|
+
'Set external_id when the tag mirrors a record in another system, so a later sync can find it by id rather than name.',
|
|
2006
|
+
inputSchema: {
|
|
2007
|
+
type: 'object',
|
|
2008
|
+
properties: {
|
|
2009
|
+
project_slug: {
|
|
2010
|
+
type: 'string',
|
|
2011
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
2012
|
+
},
|
|
2013
|
+
name: { type: 'string', description: 'Tag name, unique within the project' },
|
|
2014
|
+
colour: { type: 'string', description: 'Hex colour such as #e879f9 (optional)' },
|
|
2015
|
+
group: {
|
|
2016
|
+
type: 'string',
|
|
2017
|
+
description: 'Tag group name or id to file the tag under (optional, see list_tag_groups)',
|
|
2018
|
+
},
|
|
2019
|
+
external_id: {
|
|
2020
|
+
type: 'string',
|
|
2021
|
+
description: 'Id of this tag in the system that maintains it, unique within the project (optional)',
|
|
2022
|
+
},
|
|
2023
|
+
},
|
|
2024
|
+
required: ['name'],
|
|
2025
|
+
},
|
|
2026
|
+
},
|
|
2027
|
+
{
|
|
2028
|
+
name: 'update_tag',
|
|
2029
|
+
description: 'Rename, recolour, regroup or re-key a tag. Project admins only (mcp:tags:manage). ' +
|
|
2030
|
+
'Only the fields given change; pass null for colour, group or external_id to clear it.',
|
|
2031
|
+
inputSchema: {
|
|
2032
|
+
type: 'object',
|
|
2033
|
+
properties: {
|
|
2034
|
+
project_slug: {
|
|
2035
|
+
type: 'string',
|
|
2036
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
2037
|
+
},
|
|
2038
|
+
tag: { type: 'string', description: 'Tag id or current name' },
|
|
2039
|
+
name: { type: 'string', description: 'New name' },
|
|
2040
|
+
colour: { type: ['string', 'null'], description: 'Hex colour, or null to clear' },
|
|
2041
|
+
group: {
|
|
2042
|
+
type: ['string', 'null'],
|
|
2043
|
+
description: 'Tag group name or id, or null to move the tag out of its group',
|
|
2044
|
+
},
|
|
2045
|
+
external_id: {
|
|
2046
|
+
type: ['string', 'null'],
|
|
2047
|
+
description: 'External id, or null to clear',
|
|
2048
|
+
},
|
|
2049
|
+
},
|
|
2050
|
+
required: ['tag'],
|
|
2051
|
+
},
|
|
2052
|
+
},
|
|
2053
|
+
{
|
|
2054
|
+
name: 'list_tag_groups',
|
|
2055
|
+
description: 'List the tag groups of a project with their parent and full path (groups nest, e.g. "Customers › EMEA").',
|
|
2056
|
+
inputSchema: {
|
|
2057
|
+
type: 'object',
|
|
2058
|
+
properties: {
|
|
2059
|
+
project_slug: {
|
|
2060
|
+
type: 'string',
|
|
2061
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
2062
|
+
},
|
|
2063
|
+
},
|
|
2064
|
+
},
|
|
2065
|
+
},
|
|
2066
|
+
{
|
|
2067
|
+
name: 'create_tag_group',
|
|
2068
|
+
description: 'Create a tag group, optionally inside a parent group. Project admins only (mcp:tags:manage).',
|
|
2069
|
+
inputSchema: {
|
|
2070
|
+
type: 'object',
|
|
2071
|
+
properties: {
|
|
2072
|
+
project_slug: {
|
|
2073
|
+
type: 'string',
|
|
2074
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
2075
|
+
},
|
|
2076
|
+
name: { type: 'string', description: 'Group name, unique within the project' },
|
|
2077
|
+
parent: { type: 'string', description: 'Parent group name or id (optional)' },
|
|
2078
|
+
},
|
|
2079
|
+
required: ['name'],
|
|
2080
|
+
},
|
|
2081
|
+
},
|
|
2082
|
+
{
|
|
2083
|
+
name: 'update_tag_group',
|
|
2084
|
+
description: 'Rename a tag group or move it under another parent. Project admins only (mcp:tags:manage). ' +
|
|
2085
|
+
'Pass parent: null for the top level.',
|
|
2086
|
+
inputSchema: {
|
|
2087
|
+
type: 'object',
|
|
2088
|
+
properties: {
|
|
2089
|
+
project_slug: {
|
|
2090
|
+
type: 'string',
|
|
2091
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
2092
|
+
},
|
|
2093
|
+
group: { type: 'string', description: 'Group id or current name' },
|
|
2094
|
+
name: { type: 'string', description: 'New name' },
|
|
2095
|
+
parent: {
|
|
2096
|
+
type: ['string', 'null'],
|
|
2097
|
+
description: 'Parent group name or id, or null for the top level',
|
|
2098
|
+
},
|
|
2099
|
+
},
|
|
2100
|
+
required: ['group'],
|
|
2101
|
+
},
|
|
2102
|
+
},
|
|
1952
2103
|
// Team member tools
|
|
1953
2104
|
{
|
|
1954
2105
|
name: 'list_team_members',
|
|
@@ -3086,6 +3237,51 @@ class WolfpackMCPServer {
|
|
|
3086
3237
|
content: [{ type: 'text', text: JSON.stringify(tags, null, 2) }],
|
|
3087
3238
|
};
|
|
3088
3239
|
}
|
|
3240
|
+
case 'create_tag': {
|
|
3241
|
+
const parsed = CreateTagSchema.parse(args);
|
|
3242
|
+
const tag = await this.client.createTag({
|
|
3243
|
+
name: parsed.name,
|
|
3244
|
+
colour: parsed.colour,
|
|
3245
|
+
group: parsed.group,
|
|
3246
|
+
externalId: parsed.external_id,
|
|
3247
|
+
}, parsed.project_slug || this.client.getProjectSlug() || undefined);
|
|
3248
|
+
return {
|
|
3249
|
+
content: [{ type: 'text', text: JSON.stringify(tag, null, 2) }],
|
|
3250
|
+
};
|
|
3251
|
+
}
|
|
3252
|
+
case 'update_tag': {
|
|
3253
|
+
const parsed = UpdateTagSchema.parse(args);
|
|
3254
|
+
const tag = await this.client.updateTag(parsed.tag, {
|
|
3255
|
+
name: parsed.name,
|
|
3256
|
+
colour: parsed.colour,
|
|
3257
|
+
group: parsed.group,
|
|
3258
|
+
externalId: parsed.external_id,
|
|
3259
|
+
}, parsed.project_slug || this.client.getProjectSlug() || undefined);
|
|
3260
|
+
return {
|
|
3261
|
+
content: [{ type: 'text', text: JSON.stringify(tag, null, 2) }],
|
|
3262
|
+
};
|
|
3263
|
+
}
|
|
3264
|
+
case 'list_tag_groups': {
|
|
3265
|
+
const parsed = ListTagsSchema.parse(args);
|
|
3266
|
+
const groups = await this.client.listTagGroups(parsed.project_slug || this.client.getProjectSlug() || undefined);
|
|
3267
|
+
return {
|
|
3268
|
+
content: [{ type: 'text', text: JSON.stringify(groups, null, 2) }],
|
|
3269
|
+
};
|
|
3270
|
+
}
|
|
3271
|
+
case 'create_tag_group': {
|
|
3272
|
+
const parsed = CreateTagGroupSchema.parse(args);
|
|
3273
|
+
const group = await this.client.createTagGroup({ name: parsed.name, parent: parsed.parent }, parsed.project_slug || this.client.getProjectSlug() || undefined);
|
|
3274
|
+
return {
|
|
3275
|
+
content: [{ type: 'text', text: JSON.stringify(group, null, 2) }],
|
|
3276
|
+
};
|
|
3277
|
+
}
|
|
3278
|
+
case 'update_tag_group': {
|
|
3279
|
+
const parsed = UpdateTagGroupSchema.parse(args);
|
|
3280
|
+
const group = await this.client.updateTagGroup(parsed.group, { name: parsed.name, parent: parsed.parent }, parsed.project_slug || this.client.getProjectSlug() || undefined);
|
|
3281
|
+
return {
|
|
3282
|
+
content: [{ type: 'text', text: JSON.stringify(group, null, 2) }],
|
|
3283
|
+
};
|
|
3284
|
+
}
|
|
3089
3285
|
// Team member handlers
|
|
3090
3286
|
case 'list_team_members': {
|
|
3091
3287
|
const parsed = ListTeamMembersSchema.parse(args);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wolfpack-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.94",
|
|
4
4
|
"description": "MCP server for Wolfpack AI-enhanced software delivery tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"@eslint/js": "^9.17.0",
|
|
46
46
|
"@types/node": "^22.12.0",
|
|
47
47
|
"eslint": "^9.17.0",
|
|
48
|
-
"tsx": "^4.
|
|
48
|
+
"tsx": "^4.23.12",
|
|
49
49
|
"typescript": "^5.7.3",
|
|
50
|
-
"typescript-eslint": "^8.
|
|
51
|
-
"vitest": "^4.
|
|
50
|
+
"typescript-eslint": "^8.68.0",
|
|
51
|
+
"vitest": "^4.1.11"
|
|
52
52
|
}
|
|
53
53
|
}
|