wolfpack-mcp 1.0.87 → 1.0.89
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/agentBuilderTools.js +40 -2
- package/dist/agentBuilderTools.test.js +76 -0
- package/dist/index.js +3 -3
- package/package.json +1 -1
|
@@ -10,6 +10,26 @@ const ORG_SLUG_PROP = {
|
|
|
10
10
|
description: 'Organisation slug. Required when you belong to multiple organisations. Use list_organisations to find slugs.',
|
|
11
11
|
},
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* The per-task model pin, shared by create_agent_task and update_agent_task so
|
|
15
|
+
* both describe it the same way. Null on update clears the pin and the task
|
|
16
|
+
* falls back to the agent's own model; omitting a field leaves it unchanged.
|
|
17
|
+
*/
|
|
18
|
+
const TASK_MODEL_PROPS = {
|
|
19
|
+
llm_provider: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
description: 'Pin this task to an LLM provider ID (e.g. "anthropic") instead of the agent\'s own model. ' +
|
|
22
|
+
'Use list_llm_models for IDs. Set to null to unpin.',
|
|
23
|
+
},
|
|
24
|
+
llm_model: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
description: 'Pin this task to a model ID (e.g. "claude-sonnet-4-6"). Set to null for family auto-select.',
|
|
27
|
+
},
|
|
28
|
+
llm_family: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'Pin this task to a model family (e.g. "sonnet"); the task auto-upgrades to the latest in the family.',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
13
33
|
export const AGENT_BUILDER_TOOLS = [
|
|
14
34
|
// ─── Group 0: Organisations ─────────────────────────────────────────────
|
|
15
35
|
{
|
|
@@ -338,6 +358,7 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
338
358
|
type: 'number',
|
|
339
359
|
description: 'Order within scheduled batch (lower = first)',
|
|
340
360
|
},
|
|
361
|
+
...TASK_MODEL_PROPS,
|
|
341
362
|
disabled_tools: {
|
|
342
363
|
type: 'array',
|
|
343
364
|
items: { type: 'string' },
|
|
@@ -363,7 +384,7 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
363
384
|
},
|
|
364
385
|
{
|
|
365
386
|
name: 'update_agent_task',
|
|
366
|
-
description: "Update a task's prompt, schedule settings, or disabled tools/MCP servers.",
|
|
387
|
+
description: "Update a task's prompt, schedule settings, model pin, or disabled tools/MCP servers.",
|
|
367
388
|
inputSchema: {
|
|
368
389
|
type: 'object',
|
|
369
390
|
properties: {
|
|
@@ -374,6 +395,7 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
374
395
|
scheduled_enabled: { type: 'boolean', description: 'Include in scheduled runs' },
|
|
375
396
|
sort_order: { type: 'number', description: 'Order within scheduled batch' },
|
|
376
397
|
is_active: { type: 'boolean', description: 'Whether this task is active' },
|
|
398
|
+
...TASK_MODEL_PROPS,
|
|
377
399
|
disabled_tools: {
|
|
378
400
|
type: 'array',
|
|
379
401
|
items: { type: 'string' },
|
|
@@ -747,7 +769,8 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
747
769
|
{
|
|
748
770
|
name: 'list_llm_models',
|
|
749
771
|
description: 'List LLM providers and models available to the organisation. ' +
|
|
750
|
-
'Use provider and
|
|
772
|
+
'Use provider, model and family IDs when calling create_agent, update_agent, ' +
|
|
773
|
+
'create_agent_task or update_agent_task.',
|
|
751
774
|
inputSchema: { type: 'object', properties: { ...ORG_SLUG_PROP } },
|
|
752
775
|
},
|
|
753
776
|
];
|
|
@@ -1014,6 +1037,9 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1014
1037
|
prompt: z.string(),
|
|
1015
1038
|
scheduled_enabled: z.boolean().optional(),
|
|
1016
1039
|
sort_order: z.number().optional(),
|
|
1040
|
+
llm_provider: z.string().nullable().optional(),
|
|
1041
|
+
llm_model: z.string().nullable().optional(),
|
|
1042
|
+
llm_family: z.string().nullable().optional(),
|
|
1017
1043
|
disabled_tools: z.array(z.string()).optional(),
|
|
1018
1044
|
disabled_mcp_servers: z.array(z.string()).optional(),
|
|
1019
1045
|
clone_repository: z.boolean().optional(),
|
|
@@ -1025,6 +1051,9 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1025
1051
|
prompt: parsed.prompt,
|
|
1026
1052
|
scheduledEnabled: parsed.scheduled_enabled,
|
|
1027
1053
|
sortOrder: parsed.sort_order,
|
|
1054
|
+
llmProvider: parsed.llm_provider,
|
|
1055
|
+
llmModel: parsed.llm_model,
|
|
1056
|
+
llmFamily: parsed.llm_family,
|
|
1028
1057
|
disabledTools: parsed.disabled_tools,
|
|
1029
1058
|
disabledMcpServers: parsed.disabled_mcp_servers,
|
|
1030
1059
|
cloneRepository: parsed.clone_repository,
|
|
@@ -1041,6 +1070,9 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1041
1070
|
scheduled_enabled: z.boolean().optional(),
|
|
1042
1071
|
sort_order: z.number().optional(),
|
|
1043
1072
|
is_active: z.boolean().optional(),
|
|
1073
|
+
llm_provider: z.string().nullable().optional(),
|
|
1074
|
+
llm_model: z.string().nullable().optional(),
|
|
1075
|
+
llm_family: z.string().nullable().optional(),
|
|
1044
1076
|
disabled_tools: z.array(z.string()).nullable().optional(),
|
|
1045
1077
|
disabled_mcp_servers: z.array(z.string()).nullable().optional(),
|
|
1046
1078
|
clone_repository: z.boolean().optional(),
|
|
@@ -1058,6 +1090,12 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1058
1090
|
fields.sortOrder = parsed.sort_order;
|
|
1059
1091
|
if (parsed.is_active !== undefined)
|
|
1060
1092
|
fields.isActive = parsed.is_active;
|
|
1093
|
+
if (parsed.llm_provider !== undefined)
|
|
1094
|
+
fields.llmProvider = parsed.llm_provider;
|
|
1095
|
+
if (parsed.llm_model !== undefined)
|
|
1096
|
+
fields.llmModel = parsed.llm_model;
|
|
1097
|
+
if (parsed.llm_family !== undefined)
|
|
1098
|
+
fields.llmFamily = parsed.llm_family;
|
|
1061
1099
|
if (parsed.disabled_tools !== undefined)
|
|
1062
1100
|
fields.disabledTools = parsed.disabled_tools;
|
|
1063
1101
|
if (parsed.disabled_mcp_servers !== undefined)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { AGENT_BUILDER_TOOLS, handleAgentBuilderTool } from './agentBuilderTools.js';
|
|
3
|
+
const toolNamed = (name) => {
|
|
4
|
+
const tool = AGENT_BUILDER_TOOLS.find((t) => t.name === name);
|
|
5
|
+
if (!tool)
|
|
6
|
+
throw new Error(`No tool named ${name}`);
|
|
7
|
+
return tool;
|
|
8
|
+
};
|
|
9
|
+
const MODEL_FIELDS = ['llm_provider', 'llm_model', 'llm_family'];
|
|
10
|
+
/** A client that records the one call each test makes and returns a bare task. */
|
|
11
|
+
function fakeClient() {
|
|
12
|
+
const createAgentTask = vi.fn().mockResolvedValue({ id: 'task-1', name: 'Analyse' });
|
|
13
|
+
const updateAgentTask = vi.fn().mockResolvedValue({ id: 'task-1', name: 'Analyse' });
|
|
14
|
+
return {
|
|
15
|
+
client: { createAgentTask, updateAgentTask },
|
|
16
|
+
createAgentTask,
|
|
17
|
+
updateAgentTask,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
describe('per-task model pin over MCP (#2034)', () => {
|
|
21
|
+
it.each(['create_agent_task', 'update_agent_task'])('%s advertises the model fields', (name) => {
|
|
22
|
+
const properties = toolNamed(name).inputSchema.properties;
|
|
23
|
+
expect(Object.keys(properties)).toEqual(expect.arrayContaining(MODEL_FIELDS));
|
|
24
|
+
});
|
|
25
|
+
it('sends the model pin when creating a task', async () => {
|
|
26
|
+
const { client, createAgentTask } = fakeClient();
|
|
27
|
+
await handleAgentBuilderTool('create_agent_task', {
|
|
28
|
+
agent_id: 'agent-1',
|
|
29
|
+
name: 'Analyse',
|
|
30
|
+
prompt: 'Analyse the transcript.',
|
|
31
|
+
llm_provider: 'anthropic',
|
|
32
|
+
llm_model: 'claude-sonnet-4-6',
|
|
33
|
+
llm_family: 'sonnet',
|
|
34
|
+
}, client);
|
|
35
|
+
expect(createAgentTask.mock.calls[0][0]).toBe('agent-1');
|
|
36
|
+
expect(createAgentTask.mock.calls[0][1]).toMatchObject({
|
|
37
|
+
llmProvider: 'anthropic',
|
|
38
|
+
llmModel: 'claude-sonnet-4-6',
|
|
39
|
+
llmFamily: 'sonnet',
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it('sends the model pin when updating a task', async () => {
|
|
43
|
+
const { client, updateAgentTask } = fakeClient();
|
|
44
|
+
await handleAgentBuilderTool('update_agent_task', {
|
|
45
|
+
agent_id: 'agent-1',
|
|
46
|
+
task_id: 'task-1',
|
|
47
|
+
llm_provider: 'anthropic',
|
|
48
|
+
llm_model: 'claude-opus-4-1',
|
|
49
|
+
}, client);
|
|
50
|
+
expect(updateAgentTask.mock.calls[0].slice(0, 3)).toEqual([
|
|
51
|
+
'agent-1',
|
|
52
|
+
'task-1',
|
|
53
|
+
{ llmProvider: 'anthropic', llmModel: 'claude-opus-4-1' },
|
|
54
|
+
]);
|
|
55
|
+
});
|
|
56
|
+
it('unpins a task when the model fields are sent as null', async () => {
|
|
57
|
+
const { client, updateAgentTask } = fakeClient();
|
|
58
|
+
await handleAgentBuilderTool('update_agent_task', {
|
|
59
|
+
agent_id: 'agent-1',
|
|
60
|
+
task_id: 'task-1',
|
|
61
|
+
llm_provider: null,
|
|
62
|
+
llm_model: null,
|
|
63
|
+
llm_family: null,
|
|
64
|
+
}, client);
|
|
65
|
+
expect(updateAgentTask.mock.calls[0][2]).toEqual({
|
|
66
|
+
llmProvider: null,
|
|
67
|
+
llmModel: null,
|
|
68
|
+
llmFamily: null,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
it('leaves an existing pin alone when updating something else', async () => {
|
|
72
|
+
const { client, updateAgentTask } = fakeClient();
|
|
73
|
+
await handleAgentBuilderTool('update_agent_task', { agent_id: 'agent-1', task_id: 'task-1', prompt: 'Analyse the transcript twice.' }, client);
|
|
74
|
+
expect(updateAgentTask.mock.calls[0][2]).toEqual({ prompt: 'Analyse the transcript twice.' });
|
|
75
|
+
});
|
|
76
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -961,7 +961,7 @@ class WolfpackMCPServer {
|
|
|
961
961
|
},
|
|
962
962
|
leading_user_id: {
|
|
963
963
|
type: ['string', 'null'],
|
|
964
|
-
description: "User ID to assign as leading user, or null to unassign. Agents may not assign work to themselves — that is the
|
|
964
|
+
description: "User ID to assign as leading user, or null to unassign. Agents may not assign work to themselves — that is the Delivery Lead's decision.",
|
|
965
965
|
},
|
|
966
966
|
radar_item_id: {
|
|
967
967
|
type: ['string', 'null'],
|
|
@@ -1342,7 +1342,7 @@ class WolfpackMCPServer {
|
|
|
1342
1342
|
{
|
|
1343
1343
|
name: 'create_work_item',
|
|
1344
1344
|
description: 'Create a new work item in your current project (auto-selected for single-project users, or use list_projects first for multi-project). Requires mcp:work_items:create permission. ' +
|
|
1345
|
-
'Agents: work you file lands unassigned in the backlog, whatever status you ask for, and waits there for the
|
|
1345
|
+
'Agents: work you file lands unassigned in the backlog, whatever status you ask for, and waits there for the Delivery Lead to approve and assign it. ' +
|
|
1346
1346
|
CONTENT_LINKING_HELP,
|
|
1347
1347
|
inputSchema: {
|
|
1348
1348
|
type: 'object',
|
|
@@ -1382,7 +1382,7 @@ class WolfpackMCPServer {
|
|
|
1382
1382
|
},
|
|
1383
1383
|
leading_user_id: {
|
|
1384
1384
|
type: 'string',
|
|
1385
|
-
description: "User ID to assign as leading user. Agents may not assign work to themselves — that is the
|
|
1385
|
+
description: "User ID to assign as leading user. Agents may not assign work to themselves — that is the Delivery Lead's decision.",
|
|
1386
1386
|
},
|
|
1387
1387
|
category_id: {
|
|
1388
1388
|
type: 'string',
|