wolfpack-mcp 1.0.79 → 1.0.81

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.
@@ -116,7 +116,8 @@ export const AGENT_BUILDER_TOOLS = [
116
116
  description: 'Create an alias of an agent, so the same definition can run work in parallel. ' +
117
117
  'An agent runs one session at a time, so N concurrent workers means N aliases. ' +
118
118
  'The alias live-tracks the source for container image, prompts, instructions, LLM, tools, skills and tasks — edit those once on the source. ' +
119
- 'It does NOT inherit project assignment, API key permissions, secrets or schedules: set those on the alias afterwards, or it will start with a read-only key and no repository. ' +
119
+ 'It does NOT inherit project assignment, API key permissions or schedules: set those on the alias afterwards, or it will start with a read-only key and no repository. ' +
120
+ 'Secrets are inherited only when marked shared_with_aliases on the source (same-org only); an alias-local secret of the same name overrides. ' +
120
121
  'Aliases are auto-named from the source (e.g. "Coder (2)"). You cannot alias an alias.',
121
122
  inputSchema: {
122
123
  type: 'object',
@@ -714,16 +715,21 @@ export const AGENT_BUILDER_TOOLS = [
714
715
  {
715
716
  name: 'set_agent_secret',
716
717
  description: 'Create or update a secret for an agent. ' +
717
- 'Name must be uppercase letters, digits, and underscores (e.g. MY_API_KEY).',
718
+ 'Name must be uppercase letters, digits, and underscores (e.g. MY_API_KEY). ' +
719
+ 'Omit value to change only shared_with_aliases on an existing secret.',
718
720
  inputSchema: {
719
721
  type: 'object',
720
722
  properties: {
721
723
  agent_id: { type: 'string', description: 'Agent profile ID' },
722
724
  name: { type: 'string', description: 'Secret name (e.g. MY_API_KEY)' },
723
725
  value: { type: 'string', description: 'Secret value (encrypted at rest)' },
726
+ shared_with_aliases: {
727
+ type: 'boolean',
728
+ description: 'Share with same-org aliases of this agent (default false)',
729
+ },
724
730
  ...ORG_SLUG_PROP,
725
731
  },
726
- required: ['agent_id', 'name', 'value'],
732
+ required: ['agent_id', 'name'],
727
733
  },
728
734
  },
729
735
  // ─── Group 7: Discovery ───────────────────────────────────────────────────
@@ -1315,11 +1321,12 @@ export async function handleAgentBuilderTool(name, args, client) {
1315
1321
  .object({
1316
1322
  agent_id: z.string(),
1317
1323
  name: z.string(),
1318
- value: z.string(),
1324
+ value: z.string().optional(),
1325
+ shared_with_aliases: z.boolean().optional(),
1319
1326
  org_slug: orgSlugField,
1320
1327
  })
1321
1328
  .parse(args);
1322
- const secret = await client.setAgentSecret(parsed.agent_id, parsed.name, parsed.value, resolveOrg(parsed));
1329
+ const secret = await client.setAgentSecret(parsed.agent_id, parsed.name, parsed.value, parsed.shared_with_aliases, resolveOrg(parsed));
1323
1330
  return { content: [{ type: 'text', text: `Set secret "${secret.name}"` }] };
1324
1331
  }
1325
1332
  // ─── Discovery ────────────────────────────────────────────────────────────
@@ -0,0 +1,19 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { AGENT_SELF_TOOLS, AGENT_MEMORY_TOOLS } from './agentSelfTools.js';
3
+ const names = (tools) => tools.map((t) => t.name);
4
+ describe('agent self and memory tool split (#1776)', () => {
5
+ it('keeps the memory tools out of the self tools, so they can be withheld separately', () => {
6
+ expect(names(AGENT_SELF_TOOLS)).toEqual(['get_self', 'get_own_sessions']);
7
+ });
8
+ it('groups every memory tool under the separately gated set', () => {
9
+ expect(names(AGENT_MEMORY_TOOLS).sort()).toEqual([
10
+ 'get_memory',
11
+ 'list_memories',
12
+ 'save_memory',
13
+ ]);
14
+ });
15
+ it('never lists the same tool twice', () => {
16
+ const all = [...names(AGENT_SELF_TOOLS), ...names(AGENT_MEMORY_TOOLS)];
17
+ expect(new Set(all).size).toBe(all.length);
18
+ });
19
+ });
@@ -23,6 +23,12 @@ export const AGENT_SELF_TOOLS = [
23
23
  },
24
24
  },
25
25
  },
26
+ ];
27
+ /**
28
+ * Memory tools, gated by the `agent_memory` capability so an agent whose
29
+ * memory is disabled (#1776) is never offered them.
30
+ */
31
+ export const AGENT_MEMORY_TOOLS = [
26
32
  {
27
33
  name: 'list_memories',
28
34
  description: 'List all your persistent memory entries. Memory persists across sessions and is scoped to you. ' +
package/dist/client.js CHANGED
@@ -240,6 +240,22 @@ export class WolfpackClient {
240
240
  throw error;
241
241
  }
242
242
  }
243
+ // Review check methods
244
+ async listWorkItemChecks(filter, teamSlug) {
245
+ const params = new URLSearchParams();
246
+ if (filter.workItemId)
247
+ params.set('workItemId', filter.workItemId);
248
+ if (filter.status)
249
+ params.set('status', filter.status);
250
+ const query = params.toString();
251
+ return this.api.get(this.withTeamSlug(`/work-item-checks${query ? `?${query}` : ''}`, teamSlug));
252
+ }
253
+ async claimWorkItemCheck(workItemId, checkId, teamSlug) {
254
+ return this.api.post(this.withTeamSlug(`/work-items/${workItemId}/checks/${checkId}/claim`, teamSlug), {});
255
+ }
256
+ async completeWorkItemCheck(workItemId, checkId, data, teamSlug) {
257
+ return this.api.post(this.withTeamSlug(`/work-items/${workItemId}/checks/${checkId}/complete`, teamSlug), data);
258
+ }
243
259
  // Radar Item (Initiative/Roadmap) methods
244
260
  async listRadarItems(options) {
245
261
  const params = new URLSearchParams();
@@ -762,8 +778,12 @@ export class WolfpackClient {
762
778
  async listAgentSecrets(agentId, orgSlug) {
763
779
  return this.api.get(this.withOrgSlug(`/agents/${agentId}/secrets`, orgSlug));
764
780
  }
765
- async setAgentSecret(agentId, name, value, orgSlug) {
766
- return this.api.post(this.withOrgSlug(`/agents/${agentId}/secrets`, orgSlug), { name, value });
781
+ async setAgentSecret(agentId, name, value, sharedWithAliases, orgSlug) {
782
+ return this.api.post(this.withOrgSlug(`/agents/${agentId}/secrets`, orgSlug), {
783
+ name,
784
+ value,
785
+ sharedWithAliases,
786
+ });
767
787
  }
768
788
  // ─── Agent Builder: Skills (write) ────────────────────────────────────────
769
789
  async createSkill(body, orgSlug) {
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import { allTasksChecked, getWorkItemReminders } from './workItemReminders.js';
11
11
  import { validateConfig, config } from './config.js';
12
12
  import { AGENT_BUILDER_TOOLS, handleAgentBuilderTool } from './agentBuilderTools.js';
13
13
  import { PROCEDURE_TOOLS, handleProcedureTool } from './procedureTools.js';
14
- import { AGENT_SELF_TOOLS, handleAgentSelfTool } from './agentSelfTools.js';
14
+ import { AGENT_SELF_TOOLS, AGENT_MEMORY_TOOLS, handleAgentSelfTool } from './agentSelfTools.js';
15
15
  import { resolveRadarItemId } from './resolveRadarItemId.js';
16
16
  import { fetch as proxyFetch } from './proxyFetch.js';
17
17
  // Get current package version
@@ -214,6 +214,28 @@ const SubmitWorkItemFormSchema = z.object({
214
214
  .optional()
215
215
  .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
216
216
  });
217
+ const ListWorkItemChecksSchema = z.object({
218
+ work_item_id: refIdString()
219
+ .optional()
220
+ .describe('The refId of a work item; omit for your reviewer inbox'),
221
+ status: z.enum(['pending', 'passed', 'failed']).optional().describe('Filter by check status'),
222
+ project_slug: z
223
+ .string()
224
+ .optional()
225
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
226
+ });
227
+ const ClaimWorkItemCheckSchema = z.object({
228
+ work_item_id: refIdString().describe('The refId of the work item'),
229
+ check_id: z.string().describe('The check ID (from list_work_item_checks)'),
230
+ project_slug: z
231
+ .string()
232
+ .optional()
233
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
234
+ });
235
+ const CompleteWorkItemCheckSchema = ClaimWorkItemCheckSchema.extend({
236
+ status: z.enum(['passed', 'failed']).describe('The verdict'),
237
+ summary: z.string().optional().describe('Short summary of the review findings'),
238
+ });
217
239
  // Radar Item (Initiative/Roadmap) schemas
218
240
  const ListRadarItemsSchema = z.object({
219
241
  project_slug: z.string().optional().describe('Project slug to filter radar items'),
@@ -641,6 +663,11 @@ const AddDiscussionCommentSchema = z.object({
641
663
  const PASSTHROUGH_FIELDS = new Set(['formDefinition', 'formValues', 'formContent']);
642
664
  // Strip UUID v4 fields from response objects so agents use refId/slug instead.
643
665
  // Preserves Clerk user IDs (user_xxx format) and operational fields (categoryId, radarItemId).
666
+ /** Present a review check with its ID under `checkId` (stripUuids would drop `id`). */
667
+ function formatWorkItemCheck(check) {
668
+ const { id, workItemId: _workItemId, ...rest } = check;
669
+ return { checkId: id, ...rest };
670
+ }
644
671
  function stripUuids(obj) {
645
672
  if (obj === null || obj === undefined)
646
673
  return obj;
@@ -758,6 +785,8 @@ class WolfpackMCPServer {
758
785
  'AGENTS: unless granted the mcp:work_items:read_all permission, your results are always ' +
759
786
  'narrowed to items assigned to you or routed to a work pool you belong to, whatever ' +
760
787
  'assigned_to_id you pass; the response says so when this applies. ' +
788
+ 'AGENTS: when more than one item is claimable, the response also states the order to take ' +
789
+ 'them in (bug fixes first, then higher priority, then oldest) and which to pull next. ' +
761
790
  'TERMINOLOGY: "board" and "kanban" are synonymous - both refer to the Kanban board of work items. ' +
762
791
  'The board has columns: "new" (to do), "doing" (in progress), "review" (pending review), "ready" (code done, awaiting deployment), "blocked", "completed" (deployed). ' +
763
792
  'The "backlog" or "pending" status represents items not yet on the board. ' +
@@ -836,6 +865,7 @@ class WolfpackMCPServer {
836
865
  'blocked/ready/completed/closed→new→doing, then review when done). ' +
837
866
  'PLANNING: Check if the description contains a plan (markdown checklist). If not, APPEND one using update_work_progress - preserve all original description text and add your plan below a "---" separator. ' +
838
867
  'FORMS: Procedure-created work items may include formDefinition (field definitions with name, label, type, required, options) and formValues (current values). Use submit_work_item_form to fill in form values. ' +
868
+ 'REVIEW CHECKS: items under review may carry review checks (code-review, security-review, ...); see list_work_item_checks and claim/complete_work_item_check. ' +
839
869
  'IMAGES: Image references in the description (e.g. `![alt](/api/files/...)`) can be viewed using the download_image tool.',
840
870
  inputSchema: {
841
871
  type: 'object',
@@ -986,6 +1016,8 @@ class WolfpackMCPServer {
986
1016
  'agent and will return 403: ask a human to route it to your pool or assign it to you. ' +
987
1017
  'AGENTS: pulling puts the item straight into "doing" — you are taking it to start on it ' +
988
1018
  'now — so there is no separate "move it to doing" step. Move it to "review" when done. ' +
1019
+ 'AGENTS: with more than one item claimable, take them in the order list_work_items gives ' +
1020
+ 'you: bug fixes first, then higher priority, then oldest. ' +
989
1021
  'If no assignee is specified, assigns to the API key owner. ' +
990
1022
  'In personal projects, items are always assigned to the owner.',
991
1023
  inputSchema: {
@@ -1031,6 +1063,79 @@ class WolfpackMCPServer {
1031
1063
  required: ['work_item_id', 'form_values'],
1032
1064
  },
1033
1065
  },
1066
+ {
1067
+ name: 'list_work_item_checks',
1068
+ description: 'List review checks (key controls such as code-review, security-review, e2e-review) on work items. ' +
1069
+ 'With work_item_id: every check on that item. Without it: your REVIEWER INBOX — pending checks on ' +
1070
+ 'work items in the work pools you belong to that are unclaimed or held by you, each with workItemRefId and workItemTitle. ' +
1071
+ 'REVIEW WORKFLOW: claim a check with claim_work_item_check, get_work_item to read the work, review it, ' +
1072
+ 'then complete_work_item_check with "passed" or "failed" and a short summary. ' +
1073
+ 'A failed check sends the item back to its developer with your summary as feedback; do not change the item status yourself.',
1074
+ inputSchema: {
1075
+ type: 'object',
1076
+ properties: {
1077
+ work_item_id: {
1078
+ type: 'string',
1079
+ description: 'The refId of a work item; omit for your reviewer inbox',
1080
+ },
1081
+ status: {
1082
+ type: 'string',
1083
+ enum: ['pending', 'passed', 'failed'],
1084
+ description: 'Filter by check status',
1085
+ },
1086
+ project_slug: {
1087
+ type: 'string',
1088
+ description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
1089
+ },
1090
+ },
1091
+ },
1092
+ },
1093
+ {
1094
+ name: 'claim_work_item_check',
1095
+ description: 'Claim a pending, unclaimed review check on a work item so other reviewers know it is being handled. ' +
1096
+ 'Only one reviewer can hold a check; the claim is refused if someone else got there first.',
1097
+ inputSchema: {
1098
+ type: 'object',
1099
+ properties: {
1100
+ work_item_id: { type: 'string', description: 'The refId of the work item' },
1101
+ check_id: {
1102
+ type: 'string',
1103
+ description: 'The check ID (checkId from list_work_item_checks)',
1104
+ },
1105
+ project_slug: {
1106
+ type: 'string',
1107
+ description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
1108
+ },
1109
+ },
1110
+ required: ['work_item_id', 'check_id'],
1111
+ },
1112
+ },
1113
+ {
1114
+ name: 'complete_work_item_check',
1115
+ description: 'Record the verdict on a review check: "passed" or "failed", with a short summary of the findings. ' +
1116
+ 'A claimed check can only be completed by its claimant (or an admin). When every check on the item is ' +
1117
+ 'resolved the owning procedure continues — with a failed check it returns the item to the developer with the summaries as feedback.',
1118
+ inputSchema: {
1119
+ type: 'object',
1120
+ properties: {
1121
+ work_item_id: { type: 'string', description: 'The refId of the work item' },
1122
+ check_id: {
1123
+ type: 'string',
1124
+ description: 'The check ID (checkId from list_work_item_checks)',
1125
+ },
1126
+ status: { type: 'string', enum: ['passed', 'failed'], description: 'The verdict' },
1127
+ summary: {
1128
+ type: 'string',
1129
+ description: 'Short summary of the review findings (what was checked, what failed)',
1130
+ },
1131
+ project_slug: {
1132
+ type: 'string',
1133
+ description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
1134
+ },
1135
+ },
1136
+ required: ['work_item_id', 'check_id', 'status'],
1137
+ },
1138
+ },
1034
1139
  // Radar Item (Initiative/Roadmap) tools
1035
1140
  {
1036
1141
  name: 'list_radar_items',
@@ -2040,6 +2145,7 @@ class WolfpackMCPServer {
2040
2145
  },
2041
2146
  ...(this.capabilities.includes('procedures') ? PROCEDURE_TOOLS : []),
2042
2147
  ...(this.capabilities.includes('agent_self') ? AGENT_SELF_TOOLS : []),
2148
+ ...(this.capabilities.includes('agent_memory') ? AGENT_MEMORY_TOOLS : []),
2043
2149
  ...(this.capabilities.includes('agent_builder') ? AGENT_BUILDER_TOOLS : []),
2044
2150
  ],
2045
2151
  };
@@ -2309,6 +2415,43 @@ class WolfpackMCPServer {
2309
2415
  content: [{ type: 'text', text: 'Work item not found' }],
2310
2416
  };
2311
2417
  }
2418
+ case 'list_work_item_checks': {
2419
+ const parsed = ListWorkItemChecksSchema.parse(args);
2420
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
2421
+ const checks = await this.client.listWorkItemChecks({ workItemId: parsed.work_item_id, status: parsed.status }, teamSlug);
2422
+ const text = checks.length === 0
2423
+ ? parsed.work_item_id
2424
+ ? 'No review checks on this work item'
2425
+ : 'No review checks waiting for you'
2426
+ : JSON.stringify(checks.map(formatWorkItemCheck), null, 2);
2427
+ return { content: [{ type: 'text', text }] };
2428
+ }
2429
+ case 'claim_work_item_check': {
2430
+ const parsed = ClaimWorkItemCheckSchema.parse(args);
2431
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
2432
+ const check = await this.client.claimWorkItemCheck(parsed.work_item_id, parsed.check_id, teamSlug);
2433
+ return {
2434
+ content: [
2435
+ {
2436
+ type: 'text',
2437
+ text: `Claimed ${check.kind} check on #${check.workItemRefId} "${check.workItemTitle}"\n\n${JSON.stringify(formatWorkItemCheck(check), null, 2)}`,
2438
+ },
2439
+ ],
2440
+ };
2441
+ }
2442
+ case 'complete_work_item_check': {
2443
+ const parsed = CompleteWorkItemCheckSchema.parse(args);
2444
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
2445
+ const check = await this.client.completeWorkItemCheck(parsed.work_item_id, parsed.check_id, { status: parsed.status, summary: parsed.summary }, teamSlug);
2446
+ return {
2447
+ content: [
2448
+ {
2449
+ type: 'text',
2450
+ text: `Marked ${check.kind} check on #${check.workItemRefId} as ${check.status}\n\n${JSON.stringify(formatWorkItemCheck(check), null, 2)}`,
2451
+ },
2452
+ ],
2453
+ };
2454
+ }
2312
2455
  // Radar Item handlers
2313
2456
  case 'list_radar_items': {
2314
2457
  const parsed = ListRadarItemsSchema.parse(args);
@@ -2965,6 +3108,13 @@ class WolfpackMCPServer {
2965
3108
  return handleAgentSelfTool(name, args, this.client);
2966
3109
  }
2967
3110
  }
3111
+ // Check memory tools (separately gated — #1776)
3112
+ if (this.capabilities.includes('agent_memory')) {
3113
+ const memoryToolNames = AGENT_MEMORY_TOOLS.map((t) => t.name);
3114
+ if (memoryToolNames.includes(name)) {
3115
+ return handleAgentSelfTool(name, args, this.client);
3116
+ }
3117
+ }
2968
3118
  // Check agent builder tools
2969
3119
  if (this.capabilities.includes('agent_builder')) {
2970
3120
  return handleAgentBuilderTool(name, args, this.client);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolfpack-mcp",
3
- "version": "1.0.79",
3
+ "version": "1.0.81",
4
4
  "description": "MCP server for Wolfpack AI-enhanced software delivery tools",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",