wolfpack-mcp 1.0.109 → 1.0.111

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.
@@ -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/brand.js CHANGED
@@ -9,5 +9,5 @@
9
9
  * `WOLFPACK_*` variables are this package's public configuration contract with the MCP
10
10
  * clients that already set them, so they are deliberately not renamed here.
11
11
  */
12
- export const productName = process.env.PRODUCT_NAME || 'Wolfpack';
12
+ export const productName = process.env.PRODUCT_NAME || 'Clachan';
13
13
  export const productDomain = process.env.PRODUCT_DOMAIN || 'wolfpacks.work';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolfpack-mcp",
3
- "version": "1.0.109",
3
+ "version": "1.0.111",
4
4
  "description": "MCP server for Wolfpack AI-enhanced software delivery tools",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",