@freelancercom/phabricator-mcp 2.0.2 → 2.0.3

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.
@@ -8,13 +8,15 @@ export function registerConpherenceTools(server, client) {
8
8
  ids: z.array(z.coerce.number()).optional().describe('Room IDs'),
9
9
  phids: z.array(z.string()).optional().describe('Room PHIDs'),
10
10
  participants: z.array(z.string()).optional().describe('Participant user PHIDs'),
11
+ query: z.string().optional().describe('Full-text search query'),
11
12
  })).optional().describe('Search constraints'),
12
13
  attachments: jsonCoerce(z.object({
13
14
  participants: z.boolean().optional().describe('Include participant details'),
14
15
  })).optional().describe('Data attachments'),
15
16
  order: z.string().optional().describe('Result order'),
16
17
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
17
- after: z.string().optional().describe('Pagination cursor'),
18
+ after: z.string().optional().describe('Cursor for next-page pagination'),
19
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
18
20
  }, async (params) => {
19
21
  const result = await client.call('conpherence.search', params);
20
22
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -56,6 +58,7 @@ export function registerConpherenceTools(server, client) {
56
58
  title: z.string().optional().describe('New room title'),
57
59
  addParticipantPHIDs: z.array(z.string()).optional().describe('Participant PHIDs to add'),
58
60
  removeParticipantPHIDs: z.array(z.string()).optional().describe('Participant PHIDs to remove'),
61
+ comment: z.string().optional().describe('Send a message alongside the edit (supports Remarkup)'),
59
62
  }, async (params) => {
60
63
  const transactions = [];
61
64
  if (params.title !== undefined) {
@@ -67,6 +70,9 @@ export function registerConpherenceTools(server, client) {
67
70
  if (params.removeParticipantPHIDs !== undefined) {
68
71
  transactions.push({ type: 'participants.remove', value: params.removeParticipantPHIDs });
69
72
  }
73
+ if (params.comment !== undefined) {
74
+ transactions.push({ type: 'comment', value: params.comment });
75
+ }
70
76
  if (transactions.length === 0) {
71
77
  return { content: [{ type: 'text', text: 'No changes specified' }] };
72
78
  }
@@ -3,7 +3,7 @@ import { jsonCoerce } from './coerce.js';
3
3
  export function registerDifferentialTools(server, client) {
4
4
  // Search revisions
5
5
  server.tool('phabricator_revision_search', 'Search Differential revisions (code reviews)', {
6
- queryKey: z.string().optional().describe('Built-in query: "all", "active", "authored", "waiting", "reviewable"'),
6
+ queryKey: z.string().optional().describe('Built-in query: "all", "active", "authored"'),
7
7
  constraints: jsonCoerce(z.object({
8
8
  ids: z.array(z.coerce.number()).optional().describe('Revision IDs'),
9
9
  phids: z.array(z.string()).optional().describe('Revision PHIDs'),
@@ -23,11 +23,12 @@ export function registerDifferentialTools(server, client) {
23
23
  reviewers: z.boolean().optional().describe('Include reviewers'),
24
24
  subscribers: z.boolean().optional().describe('Include subscribers'),
25
25
  projects: z.boolean().optional().describe('Include projects'),
26
- 'reviewers-extra': z.boolean().optional().describe('Include detailed reviewer info with status (accepted, rejected, etc.)'),
26
+ 'reviewers-extra': z.boolean().optional().describe('Include detailed reviewer info with voids and diff context (may not be available on all Phabricator versions)'),
27
27
  })).optional().describe('Data attachments'),
28
28
  order: z.string().optional().describe('Result order: "newest", "oldest", "updated", "relevance"'),
29
29
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
30
- after: z.string().optional().describe('Pagination cursor'),
30
+ after: z.string().optional().describe('Cursor for next-page pagination'),
31
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
31
32
  }, async (params) => {
32
33
  const result = await client.call('differential.revision.search', params);
33
34
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -38,12 +39,13 @@ export function registerDifferentialTools(server, client) {
38
39
  title: z.string().optional().describe('New title'),
39
40
  summary: z.string().optional().describe('New summary'),
40
41
  testPlan: z.string().optional().describe('New test plan'),
41
- addReviewerPHIDs: z.array(z.string()).optional().describe('Add reviewers'),
42
+ addReviewerPHIDs: z.array(z.string()).optional().describe('Add reviewers. Prefix with "blocking(PHID)" to add as blocking reviewer'),
42
43
  removeReviewerPHIDs: z.array(z.string()).optional().describe('Remove reviewers'),
44
+ setReviewerPHIDs: z.array(z.string()).optional().describe('Replace all reviewers with this list. Prefix with "blocking(PHID)" for blocking'),
43
45
  addProjectPHIDs: z.array(z.string()).optional().describe('Add projects'),
44
46
  removeProjectPHIDs: z.array(z.string()).optional().describe('Remove projects'),
45
47
  comment: z.string().optional().describe('Add a comment'),
46
- action: z.enum(['accept', 'reject', 'abandon', 'reclaim', 'request-review', 'resign', 'commandeer', 'plan-changes']).optional().describe('Revision action to take'),
48
+ action: z.enum(['accept', 'reject', 'abandon', 'reclaim', 'request-review', 'resign', 'commandeer', 'plan-changes', 'close']).optional().describe('Revision action to take'),
47
49
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
48
50
  removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
49
51
  repositoryPHID: z.string().optional().describe('Repository PHID to associate with the revision'),
@@ -64,6 +66,9 @@ export function registerDifferentialTools(server, client) {
64
66
  if (params.removeReviewerPHIDs !== undefined) {
65
67
  transactions.push({ type: 'reviewers.remove', value: params.removeReviewerPHIDs });
66
68
  }
69
+ if (params.setReviewerPHIDs !== undefined) {
70
+ transactions.push({ type: 'reviewers.set', value: params.setReviewerPHIDs });
71
+ }
67
72
  if (params.addProjectPHIDs !== undefined) {
68
73
  transactions.push({ type: 'projects.add', value: params.addProjectPHIDs });
69
74
  }
@@ -116,7 +121,8 @@ export function registerDifferentialTools(server, client) {
116
121
  })).optional().describe('Data attachments'),
117
122
  order: z.string().optional().describe('Result order: "newest", "oldest"'),
118
123
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
119
- after: z.string().optional().describe('Pagination cursor'),
124
+ after: z.string().optional().describe('Cursor for next-page pagination'),
125
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
120
126
  }, async (params) => {
121
127
  const result = await client.call('differential.diff.search', params);
122
128
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -132,7 +138,8 @@ export function registerDifferentialTools(server, client) {
132
138
  })).optional().describe('Data attachments'),
133
139
  order: z.string().optional().describe('Result order'),
134
140
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
135
- after: z.string().optional().describe('Pagination cursor'),
141
+ after: z.string().optional().describe('Cursor for next-page pagination'),
142
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
136
143
  }, async (params) => {
137
144
  const result = await client.call('differential.changeset.search', params);
138
145
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -20,7 +20,8 @@ export function registerDiffusionTools(server, client) {
20
20
  })).optional().describe('Data attachments'),
21
21
  order: z.string().optional().describe('Result order'),
22
22
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
23
- after: z.string().optional().describe('Pagination cursor'),
23
+ after: z.string().optional().describe('Cursor for next-page pagination'),
24
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
24
25
  }, async (params) => {
25
26
  const result = await client.call('diffusion.repository.search', params);
26
27
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -34,6 +35,8 @@ export function registerDiffusionTools(server, client) {
34
35
  repositoryPHIDs: z.array(z.string()).optional().describe('Repository PHIDs'),
35
36
  identifiers: z.array(z.string()).optional().describe('Commit identifiers (hashes)'),
36
37
  authorPHIDs: z.array(z.string()).optional().describe('Author PHIDs'),
38
+ responsiblePHIDs: z.array(z.string()).optional().describe('User PHIDs responsible (as author or auditor)'),
39
+ statuses: z.array(z.string()).optional().describe('Audit statuses: audited, needs-audit, concern-raised, partially-audited'),
37
40
  query: z.string().optional().describe('Full-text search query'),
38
41
  })).optional().describe('Search constraints'),
39
42
  attachments: jsonCoerce(z.object({
@@ -43,7 +46,8 @@ export function registerDiffusionTools(server, client) {
43
46
  })).optional().describe('Data attachments'),
44
47
  order: z.string().optional().describe('Result order'),
45
48
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
46
- after: z.string().optional().describe('Pagination cursor'),
49
+ after: z.string().optional().describe('Cursor for next-page pagination'),
50
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
47
51
  }, async (params) => {
48
52
  const result = await client.call('diffusion.commit.search', params);
49
53
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -20,10 +20,13 @@ export function registerFileTools(server, client) {
20
20
  phids: z.array(z.string()).optional().describe('File PHIDs'),
21
21
  authorPHIDs: z.array(z.string()).optional().describe('Author PHIDs'),
22
22
  names: z.array(z.string()).optional().describe('File names'),
23
+ dateCreatedStart: z.coerce.number().optional().describe('Created after (epoch timestamp)'),
24
+ dateCreatedEnd: z.coerce.number().optional().describe('Created before (epoch timestamp)'),
23
25
  })).optional().describe('Search constraints'),
24
26
  order: z.string().optional().describe('Result order'),
25
27
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
26
- after: z.string().optional().describe('Pagination cursor'),
28
+ after: z.string().optional().describe('Cursor for next-page pagination'),
29
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
27
30
  }, async (params) => {
28
31
  const result = await client.call('file.search', params);
29
32
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -16,7 +16,8 @@ export function registerHarbormasterTools(server, client) {
16
16
  })).optional().describe('Data attachments'),
17
17
  order: z.string().optional().describe('Result order'),
18
18
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
19
- after: z.string().optional().describe('Pagination cursor'),
19
+ after: z.string().optional().describe('Cursor for next-page pagination'),
20
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
20
21
  }, async (params) => {
21
22
  const result = await client.call('harbormaster.buildable.search', params);
22
23
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -30,13 +31,15 @@ export function registerHarbormasterTools(server, client) {
30
31
  buildablePHIDs: z.array(z.string()).optional().describe('Buildable PHIDs'),
31
32
  buildPlanPHIDs: z.array(z.string()).optional().describe('Build plan PHIDs'),
32
33
  statuses: z.array(z.string()).optional().describe('Build statuses: building, passed, failed, aborted, error, paused, deadlocked'),
34
+ initiatorPHIDs: z.array(z.string()).optional().describe('PHIDs of users/objects that initiated the build'),
33
35
  })).optional().describe('Search constraints'),
34
36
  attachments: jsonCoerce(z.object({
35
37
  targets: z.boolean().optional().describe('Include build targets for each build'),
36
38
  })).optional().describe('Data attachments'),
37
39
  order: z.string().optional().describe('Result order'),
38
40
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
39
- after: z.string().optional().describe('Pagination cursor'),
41
+ after: z.string().optional().describe('Cursor for next-page pagination'),
42
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
40
43
  }, async (params) => {
41
44
  const result = await client.call('harbormaster.build.search', params);
42
45
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -51,7 +54,8 @@ export function registerHarbormasterTools(server, client) {
51
54
  })).optional().describe('Search constraints'),
52
55
  order: z.string().optional().describe('Result order'),
53
56
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
54
- after: z.string().optional().describe('Pagination cursor'),
57
+ after: z.string().optional().describe('Cursor for next-page pagination'),
58
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
55
59
  }, async (params) => {
56
60
  const result = await client.call('harbormaster.target.search', params);
57
61
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -69,7 +73,8 @@ export function registerHarbormasterTools(server, client) {
69
73
  })).optional().describe('Data attachments'),
70
74
  order: z.string().optional().describe('Result order'),
71
75
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
72
- after: z.string().optional().describe('Pagination cursor'),
76
+ after: z.string().optional().describe('Cursor for next-page pagination'),
77
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
73
78
  }, async (params) => {
74
79
  const result = await client.call('harbormaster.log.search', params);
75
80
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -122,7 +127,8 @@ export function registerHarbormasterTools(server, client) {
122
127
  })).optional().describe('Search constraints'),
123
128
  order: z.string().optional().describe('Result order'),
124
129
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
125
- after: z.string().optional().describe('Pagination cursor'),
130
+ after: z.string().optional().describe('Cursor for next-page pagination'),
131
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
126
132
  }, async (params) => {
127
133
  const result = await client.call('harbormaster.buildplan.search', params);
128
134
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -23,6 +23,7 @@ export function registerManiphestTools(server, client) {
23
23
  subtaskIDs: z.array(z.coerce.number()).optional().describe('Subtask IDs'),
24
24
  hasParents: z.boolean().optional().describe('Filter to tasks that have parent tasks'),
25
25
  hasSubtasks: z.boolean().optional().describe('Filter to tasks that have subtasks'),
26
+ spacePHIDs: z.array(z.string()).optional().describe('Filter by Space PHIDs (for multi-space installations)'),
26
27
  })).optional().describe('Search constraints'),
27
28
  attachments: jsonCoerce(z.object({
28
29
  columns: z.boolean().optional().describe('Include workboard column info'),
@@ -30,9 +31,10 @@ export function registerManiphestTools(server, client) {
30
31
  subscribers: z.boolean().optional().describe('Include subscriber info'),
31
32
  'custom-fields': z.boolean().optional().describe('Include custom field values in results'),
32
33
  })).optional().describe('Data attachments to include'),
33
- order: z.string().optional().describe('Result order: "priority", "updated", "newest", "oldest"'),
34
+ order: z.string().optional().describe('Result order: "priority", "updated", "newest", "oldest", "title", "relevance"'),
34
35
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
35
- after: z.string().optional().describe('Cursor for pagination'),
36
+ after: z.string().optional().describe('Cursor for next-page pagination'),
37
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
36
38
  }, async (params) => {
37
39
  const result = await client.call('maniphest.search', params);
38
40
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -42,13 +44,14 @@ export function registerManiphestTools(server, client) {
42
44
  title: z.string().describe('Task title'),
43
45
  description: z.string().optional().describe('Task description (supports Remarkup)'),
44
46
  ownerPHID: z.string().optional().describe('Assigned owner PHID'),
45
- priority: z.string().optional().describe('Priority: unbreak, triage, high, normal, low, wish'),
47
+ priority: z.string().optional().describe('Priority keyword (unbreak, triage, high, normal, low, wish) or numeric value'),
46
48
  projectPHIDs: z.array(z.string()).optional().describe('Project PHIDs to tag'),
47
49
  subscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs'),
48
50
  status: z.string().optional().describe('Initial status'),
49
51
  subtype: z.string().optional().describe('Task subtype (e.g. "default", "incident")'),
50
52
  parentPHIDs: z.array(z.string()).optional().describe('Parent task PHIDs'),
51
53
  subtaskPHIDs: z.array(z.string()).optional().describe('Subtask PHIDs'),
54
+ space: z.string().optional().describe('Space PHID to place the task in (for multi-space installations)'),
52
55
  comment: z.string().optional().describe('Initial comment on the task (supports Remarkup)'),
53
56
  customFields: jsonCoerce(z.record(z.string(), z.unknown())).optional().describe('Custom field transactions. Keys are transaction types (e.g. "custom.my-field"), values are the field values. Check your Phabricator Conduit console (conduit/method/maniphest.edit/) for available fields.'),
54
57
  }, async (params) => {
@@ -82,6 +85,9 @@ export function registerManiphestTools(server, client) {
82
85
  if (params.subtaskPHIDs !== undefined) {
83
86
  transactions.push({ type: 'subtasks.set', value: params.subtaskPHIDs });
84
87
  }
88
+ if (params.space !== undefined) {
89
+ transactions.push({ type: 'space', value: params.space });
90
+ }
85
91
  if (params.comment !== undefined) {
86
92
  transactions.push({ type: 'comment', value: params.comment });
87
93
  }
@@ -111,6 +117,7 @@ export function registerManiphestTools(server, client) {
111
117
  addSubtaskPHIDs: z.array(z.string()).optional().describe('Subtask PHIDs to add'),
112
118
  removeSubtaskPHIDs: z.array(z.string()).optional().describe('Subtask PHIDs to remove'),
113
119
  columnPHID: z.string().optional().describe('Move to workboard column'),
120
+ space: z.string().optional().describe('Space PHID to move the task to (for multi-space installations)'),
114
121
  comment: z.string().optional().describe('Add a comment alongside the edit (supports Remarkup)'),
115
122
  customFields: jsonCoerce(z.record(z.string(), z.unknown())).optional().describe('Custom field transactions. Keys are transaction types (e.g. "custom.my-field"), values are the field values. Check your Phabricator Conduit console (conduit/method/maniphest.edit/) for available fields.'),
116
123
  }, async (params) => {
@@ -160,6 +167,9 @@ export function registerManiphestTools(server, client) {
160
167
  if (params.columnPHID !== undefined) {
161
168
  transactions.push({ type: 'column', value: [{ columnPHID: params.columnPHID }] });
162
169
  }
170
+ if (params.space !== undefined) {
171
+ transactions.push({ type: 'space', value: params.space });
172
+ }
163
173
  if (params.comment !== undefined) {
164
174
  transactions.push({ type: 'comment', value: params.comment });
165
175
  }
@@ -11,6 +11,8 @@ export function registerOwnersTools(server, client) {
11
11
  repositoryPHIDs: z.array(z.string()).optional().describe('Repository PHIDs'),
12
12
  paths: z.array(z.array(z.string())).optional().describe('Code paths as [repositoryPHID, path] pairs (e.g. [["PHID-REPO-xxx", "/src/foo.ts"]])'),
13
13
  statuses: z.array(z.string()).optional().describe('Package statuses'),
14
+ dominion: z.array(z.string()).optional().describe('Ownership strength: "strong" (default) or "weak"'),
15
+ autoReview: z.array(z.string()).optional().describe('Auto-review setting: "none", "subscribe", "review", "block"'),
14
16
  query: z.string().optional().describe('Full-text search query'),
15
17
  })).optional().describe('Search constraints'),
16
18
  attachments: jsonCoerce(z.object({
@@ -19,7 +21,8 @@ export function registerOwnersTools(server, client) {
19
21
  })).optional().describe('Data attachments'),
20
22
  order: z.string().optional().describe('Result order'),
21
23
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
22
- after: z.string().optional().describe('Pagination cursor'),
24
+ after: z.string().optional().describe('Cursor for next-page pagination'),
25
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
23
26
  }, async (params) => {
24
27
  const result = await client.call('owners.search', params);
25
28
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -9,6 +9,7 @@ export function registerPasteTools(server, client) {
9
9
  phids: z.array(z.string()).optional().describe('Paste PHIDs'),
10
10
  authorPHIDs: z.array(z.string()).optional().describe('Author PHIDs'),
11
11
  languages: z.array(z.string()).optional().describe('Languages'),
12
+ statuses: z.array(z.string()).optional().describe('Statuses: active, archived'),
12
13
  query: z.string().optional().describe('Full-text search query'),
13
14
  })).optional().describe('Search constraints'),
14
15
  attachments: jsonCoerce(z.object({
@@ -16,7 +17,8 @@ export function registerPasteTools(server, client) {
16
17
  })).optional().describe('Data attachments'),
17
18
  order: z.string().optional().describe('Result order'),
18
19
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
19
- after: z.string().optional().describe('Pagination cursor'),
20
+ after: z.string().optional().describe('Cursor for next-page pagination'),
21
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
20
22
  }, async (params) => {
21
23
  const result = await client.call('paste.search', params);
22
24
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -56,6 +58,7 @@ export function registerPasteTools(server, client) {
56
58
  status: z.string().optional().describe('Status: active or archived'),
57
59
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
58
60
  removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
61
+ comment: z.string().optional().describe('Add a comment alongside the edit (supports Remarkup)'),
59
62
  }, async (params) => {
60
63
  const transactions = [];
61
64
  if (params.title !== undefined) {
@@ -76,6 +79,9 @@ export function registerPasteTools(server, client) {
76
79
  if (params.removeSubscriberPHIDs !== undefined) {
77
80
  transactions.push({ type: 'subscribers.remove', value: params.removeSubscriberPHIDs });
78
81
  }
82
+ if (params.comment !== undefined) {
83
+ transactions.push({ type: 'comment', value: params.comment });
84
+ }
79
85
  if (transactions.length === 0) {
80
86
  return { content: [{ type: 'text', text: 'No changes specified' }] };
81
87
  }
@@ -7,6 +7,7 @@ export function registerPhameTools(server, client) {
7
7
  constraints: jsonCoerce(z.object({
8
8
  ids: z.array(z.coerce.number()).optional().describe('Blog IDs'),
9
9
  phids: z.array(z.string()).optional().describe('Blog PHIDs'),
10
+ statuses: z.array(z.string()).optional().describe('Blog statuses'),
10
11
  query: z.string().optional().describe('Full-text search query'),
11
12
  })).optional().describe('Search constraints'),
12
13
  attachments: jsonCoerce(z.object({
@@ -14,7 +15,8 @@ export function registerPhameTools(server, client) {
14
15
  })).optional().describe('Data attachments'),
15
16
  order: z.string().optional().describe('Result order'),
16
17
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
17
- after: z.string().optional().describe('Cursor for pagination'),
18
+ after: z.string().optional().describe('Cursor for next-page pagination'),
19
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
18
20
  }, async (params) => {
19
21
  const result = await client.call('phame.blog.search', params);
20
22
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -26,6 +28,7 @@ export function registerPhameTools(server, client) {
26
28
  ids: z.array(z.coerce.number()).optional().describe('Post IDs'),
27
29
  phids: z.array(z.string()).optional().describe('Post PHIDs'),
28
30
  blogPHIDs: z.array(z.string()).optional().describe('Filter by blog PHIDs'),
31
+ authorPHIDs: z.array(z.string()).optional().describe('Filter by author PHIDs'),
29
32
  visibility: z.array(z.coerce.number()).optional().describe('Visibility: 1 (published), 0 (draft), 2 (archived). Note: use these numeric codes in search; use string names like "published" in create/edit.'),
30
33
  query: z.string().optional().describe('Full-text search query'),
31
34
  })).optional().describe('Search constraints'),
@@ -34,7 +37,8 @@ export function registerPhameTools(server, client) {
34
37
  })).optional().describe('Data attachments'),
35
38
  order: z.string().optional().describe('Result order'),
36
39
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
37
- after: z.string().optional().describe('Cursor for pagination'),
40
+ after: z.string().optional().describe('Cursor for next-page pagination'),
41
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
38
42
  }, async (params) => {
39
43
  const result = await client.call('phame.post.search', params);
40
44
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -14,10 +14,13 @@ export function registerPhrictionTools(server, client) {
14
14
  })).optional().describe('Search constraints'),
15
15
  attachments: jsonCoerce(z.object({
16
16
  content: z.boolean().optional().describe('Include document content'),
17
+ subscribers: z.boolean().optional().describe('Include subscriber details'),
18
+ projects: z.boolean().optional().describe('Include tagged projects'),
17
19
  })).optional().describe('Data attachments'),
18
20
  order: z.string().optional().describe('Result order'),
19
21
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
20
- after: z.string().optional().describe('Pagination cursor'),
22
+ after: z.string().optional().describe('Cursor for next-page pagination'),
23
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
21
24
  }, async (params) => {
22
25
  const result = await client.call('phriction.document.search', params);
23
26
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -12,6 +12,8 @@ export function registerProjectTools(server, client) {
12
12
  members: z.array(z.string()).optional().describe('Member user PHIDs'),
13
13
  watchers: z.array(z.string()).optional().describe('Watcher user PHIDs'),
14
14
  ancestors: z.array(z.string()).optional().describe('Ancestor project PHIDs'),
15
+ parentPHIDs: z.array(z.string()).optional().describe('Parent project PHIDs (find subprojects)'),
16
+ icons: z.array(z.string()).optional().describe('Filter by project icon'),
15
17
  isMilestone: z.boolean().optional().describe('Filter milestones'),
16
18
  isRoot: z.boolean().optional().describe('Filter root projects'),
17
19
  query: z.string().optional().describe('Full-text search query'),
@@ -23,7 +25,8 @@ export function registerProjectTools(server, client) {
23
25
  })).optional().describe('Data attachments'),
24
26
  order: z.string().optional().describe('Result order'),
25
27
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
26
- after: z.string().optional().describe('Pagination cursor'),
28
+ after: z.string().optional().describe('Cursor for next-page pagination'),
29
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
27
30
  }, async (params) => {
28
31
  const result = await client.call('project.search', params);
29
32
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -39,6 +42,7 @@ export function registerProjectTools(server, client) {
39
42
  removeMemberPHIDs: z.array(z.string()).optional().describe('Remove members'),
40
43
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
41
44
  removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
45
+ space: z.string().optional().describe('Space PHID (for multi-space installations)'),
42
46
  parent: z.string().optional().describe('Parent project PHID (to create as a subproject)'),
43
47
  milestone: z.string().optional().describe('Parent project PHID (to create as a milestone of that project)'),
44
48
  slug: z.string().optional().describe('Project URL slug (replaces ALL existing slugs with this one)'),
@@ -48,6 +52,9 @@ export function registerProjectTools(server, client) {
48
52
  if (params.name !== undefined) {
49
53
  transactions.push({ type: 'name', value: params.name });
50
54
  }
55
+ if (params.space !== undefined) {
56
+ transactions.push({ type: 'space', value: params.space });
57
+ }
51
58
  if (params.parent !== undefined) {
52
59
  transactions.push({ type: 'parent', value: params.parent });
53
60
  }
@@ -104,7 +111,8 @@ export function registerProjectTools(server, client) {
104
111
  })).optional().describe('Data attachments'),
105
112
  order: z.string().optional().describe('Result order'),
106
113
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
107
- after: z.string().optional().describe('Pagination cursor'),
114
+ after: z.string().optional().describe('Cursor for next-page pagination'),
115
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
108
116
  }, async (params) => {
109
117
  const result = await client.call('project.column.search', params);
110
118
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
@@ -18,6 +18,8 @@ export function registerUserTools(server, client) {
18
18
  isDisabled: z.boolean().optional().describe('Filter by disabled status'),
19
19
  isBot: z.boolean().optional().describe('Filter by bot status'),
20
20
  isMailingList: z.boolean().optional().describe('Filter by mailing list status'),
21
+ createdStart: z.coerce.number().optional().describe('Created after (epoch timestamp)'),
22
+ createdEnd: z.coerce.number().optional().describe('Created before (epoch timestamp)'),
21
23
  query: z.string().optional().describe('Full-text search query'),
22
24
  })).optional().describe('Search constraints'),
23
25
  attachments: jsonCoerce(z.object({
@@ -25,7 +27,8 @@ export function registerUserTools(server, client) {
25
27
  })).optional().describe('Data attachments'),
26
28
  order: z.string().optional().describe('Result order'),
27
29
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
28
- after: z.string().optional().describe('Pagination cursor'),
30
+ after: z.string().optional().describe('Cursor for next-page pagination'),
31
+ before: z.string().optional().describe('Cursor for previous-page pagination'),
29
32
  }, async (params) => {
30
33
  const result = await client.call('user.search', params);
31
34
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freelancercom/phabricator-mcp",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "MCP server for Phabricator Conduit API - manage tasks, code reviews, repositories, and more",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",