wolfpack-mcp 1.0.108 → 1.0.110
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 +24 -0
- package/dist/agentBuilderTools.test.js +37 -0
- package/dist/index.js +4 -1
- package/dist/toolCatalogue.js +3 -3
- package/package.json +1 -1
|
@@ -162,6 +162,21 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
162
162
|
type: 'object',
|
|
163
163
|
description: 'The agent\'s own Ghost runtime settings, merged into every session\'s generated config. Two keys are honoured: "options" (e.g. {"max_turn_requests": 150} — the per-turn model request cap, default 200) and "agents" (per-agent overrides, e.g. {"coder": {"disabled_tools": ["agent"]}} to switch the sub-agent tool off). Other keys are ignored. Replaces the stored config as a whole; set to null to clear. Ghost runtime only — Claude Code agents ignore it.',
|
|
164
164
|
},
|
|
165
|
+
disabled_tools: {
|
|
166
|
+
type: 'array',
|
|
167
|
+
items: { type: 'string' },
|
|
168
|
+
description: 'Tools the agent never gets, whatever starts the session (a task, a chat, a work-item pickup). Ghost names ("agent", "fetch"); Claude Code agents use Claude Code\'s own ("Task", "WebFetch") and "mcp__<server>__<tool>" for an MCP tool. Replaces the stored list; an empty array clears it. A task\'s own disabled_tools are added to these — a task narrows further, never widens.',
|
|
169
|
+
},
|
|
170
|
+
disabled_mcp_servers: {
|
|
171
|
+
type: 'array',
|
|
172
|
+
items: { type: 'string' },
|
|
173
|
+
description: 'MCP servers the agent never gets, by name (e.g. ["wolfpack"]). The server is left out of the session config altogether rather than started and denied per tool. Replaces the stored list; an empty array clears it.',
|
|
174
|
+
},
|
|
175
|
+
disabled_skills: {
|
|
176
|
+
type: 'array',
|
|
177
|
+
items: { type: 'string' },
|
|
178
|
+
description: 'Skills the agent never loads, by name (e.g. ["respond-to-notification"]). Replaces the stored list; an empty array clears it.',
|
|
179
|
+
},
|
|
165
180
|
...ORG_SLUG_PROP,
|
|
166
181
|
},
|
|
167
182
|
required: ['agent_id'],
|
|
@@ -1060,6 +1075,9 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1060
1075
|
llm_family: z.string().nullable().optional(),
|
|
1061
1076
|
api_key_permissions: z.array(z.string()).optional(),
|
|
1062
1077
|
config: z.record(z.unknown()).nullable().optional(),
|
|
1078
|
+
disabled_tools: z.array(z.string()).optional(),
|
|
1079
|
+
disabled_mcp_servers: z.array(z.string()).optional(),
|
|
1080
|
+
disabled_skills: z.array(z.string()).optional(),
|
|
1063
1081
|
org_slug: orgSlugField,
|
|
1064
1082
|
})
|
|
1065
1083
|
.parse(args);
|
|
@@ -1085,6 +1103,12 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1085
1103
|
fields.apiKeyPermissions = rest.api_key_permissions;
|
|
1086
1104
|
if (rest.config !== undefined)
|
|
1087
1105
|
fields.config = rest.config;
|
|
1106
|
+
if (rest.disabled_tools !== undefined)
|
|
1107
|
+
fields.disabledTools = rest.disabled_tools;
|
|
1108
|
+
if (rest.disabled_mcp_servers !== undefined)
|
|
1109
|
+
fields.disabledMcpServers = rest.disabled_mcp_servers;
|
|
1110
|
+
if (rest.disabled_skills !== undefined)
|
|
1111
|
+
fields.disabledSkills = rest.disabled_skills;
|
|
1088
1112
|
const agent = await client.updateAgent(agent_id, fields, resolveOrg(parsed));
|
|
1089
1113
|
return { content: [{ type: 'text', text: `Updated agent\n\n${text(agent)}` }] };
|
|
1090
1114
|
}
|
|
@@ -192,3 +192,40 @@ describe('personal agents over MCP (#2273)', () => {
|
|
|
192
192
|
expect(fn.mock.calls[0][1]).toBe(true);
|
|
193
193
|
});
|
|
194
194
|
});
|
|
195
|
+
// #2525 — the three opt-out lists a profile carries, reachable over MCP so an
|
|
196
|
+
// agent can be narrowed without hand-writing its config JSON.
|
|
197
|
+
describe('profile-level disabled tools, MCP servers and skills (#2525)', () => {
|
|
198
|
+
const DISABLED_FIELDS = ['disabled_tools', 'disabled_mcp_servers', 'disabled_skills'];
|
|
199
|
+
function fakeUpdate() {
|
|
200
|
+
const updateAgent = vi.fn().mockResolvedValue({ id: 'agent-1' });
|
|
201
|
+
return { client: { updateAgent }, updateAgent };
|
|
202
|
+
}
|
|
203
|
+
it('update_agent advertises all three lists', () => {
|
|
204
|
+
const properties = toolNamed('update_agent').inputSchema.properties;
|
|
205
|
+
expect(Object.keys(properties)).toEqual(expect.arrayContaining(DISABLED_FIELDS));
|
|
206
|
+
});
|
|
207
|
+
it('sends the three lists under their stored names', async () => {
|
|
208
|
+
const { client, updateAgent } = fakeUpdate();
|
|
209
|
+
await handleAgentBuilderTool('update_agent', {
|
|
210
|
+
agent_id: 'agent-1',
|
|
211
|
+
disabled_tools: ['agent', 'mcp__wolfpack__create_issue'],
|
|
212
|
+
disabled_mcp_servers: ['wolfpack'],
|
|
213
|
+
disabled_skills: ['respond-to-notification'],
|
|
214
|
+
}, client);
|
|
215
|
+
expect(updateAgent.mock.calls[0][1]).toEqual({
|
|
216
|
+
disabledTools: ['agent', 'mcp__wolfpack__create_issue'],
|
|
217
|
+
disabledMcpServers: ['wolfpack'],
|
|
218
|
+
disabledSkills: ['respond-to-notification'],
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
it('an empty array is sent, so a list can be cleared', async () => {
|
|
222
|
+
const { client, updateAgent } = fakeUpdate();
|
|
223
|
+
await handleAgentBuilderTool('update_agent', { agent_id: 'agent-1', disabled_tools: [] }, client);
|
|
224
|
+
expect(updateAgent.mock.calls[0][1]).toEqual({ disabledTools: [] });
|
|
225
|
+
});
|
|
226
|
+
it('a field nobody named is left out, so it stays as stored', async () => {
|
|
227
|
+
const { client, updateAgent } = fakeUpdate();
|
|
228
|
+
await handleAgentBuilderTool('update_agent', { agent_id: 'agent-1', name: 'Scout' }, client);
|
|
229
|
+
expect(updateAgent.mock.calls[0][1]).toEqual({ name: 'Scout' });
|
|
230
|
+
});
|
|
231
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -383,7 +383,10 @@ const CreateWorkItemSchema = z.object({
|
|
|
383
383
|
.enum(['S', 'M', 'L'])
|
|
384
384
|
.optional()
|
|
385
385
|
.describe('Size estimate: "S" (small), "M" (medium), "L" (large)'),
|
|
386
|
-
leading_user_id: z
|
|
386
|
+
leading_user_id: z
|
|
387
|
+
.string()
|
|
388
|
+
.optional()
|
|
389
|
+
.describe('User ID to assign as leading user. AGENTS: you may put your own id here — filing work you already know you will do is the one assignment that is yours to make. Leaving it out is just as normal: the Delivery Lead assigns it instead. Either way the item waits in the backlog for a human to approve before you can pull it.'),
|
|
387
390
|
category_id: z.string().optional().describe('Category ID to organize the work item'),
|
|
388
391
|
radar_item_id: z
|
|
389
392
|
.string()
|
package/dist/toolCatalogue.js
CHANGED
|
@@ -328,7 +328,7 @@ const SHARED_TOOLS = [
|
|
|
328
328
|
},
|
|
329
329
|
leading_user_id: {
|
|
330
330
|
type: ['string', 'null'],
|
|
331
|
-
description: "User ID to assign as leading user, or null to unassign. Agents may
|
|
331
|
+
description: "User ID to assign as leading user, or null to unassign. Agents may assign themselves only to a work item they created; who does anyone else's work is the Delivery Lead's decision.",
|
|
332
332
|
},
|
|
333
333
|
radar_item_id: {
|
|
334
334
|
type: ['string', 'null'],
|
|
@@ -806,7 +806,7 @@ const SHARED_TOOLS = [
|
|
|
806
806
|
name: 'create_work_item',
|
|
807
807
|
permission: 'mcp:work_items:create',
|
|
808
808
|
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. ' +
|
|
809
|
-
'Agents: work you file lands
|
|
809
|
+
'Agents: work you file lands in the backlog whatever status you ask for, and waits there for a human to approve it. Leaving it unassigned is the norm — the Delivery Lead assigns it. Put your own id in leading_user_id when you already know you will do it; that says who, not when, so it still waits for approval before you can pull it. ' +
|
|
810
810
|
'ORDERED WORK: when you file a set of items that must happen in order, give each one depends_on ' +
|
|
811
811
|
'naming the reference numbers it follows, rather than writing "Follows #2322" into the description — ' +
|
|
812
812
|
'that way the board knows the order and the pickup gate enforces it. ' +
|
|
@@ -850,7 +850,7 @@ const SHARED_TOOLS = [
|
|
|
850
850
|
},
|
|
851
851
|
leading_user_id: {
|
|
852
852
|
type: 'string',
|
|
853
|
-
description:
|
|
853
|
+
description: 'User ID to assign as leading user. AGENTS: you may put your own id here — filing work you already know you will do is the one assignment that is yours to make. Leaving it out is just as normal: the Delivery Lead assigns it instead. Either way the item waits in the backlog for a human to approve before you can pull it.',
|
|
854
854
|
},
|
|
855
855
|
category_id: {
|
|
856
856
|
type: 'string',
|