@freelancercom/phabricator-mcp 2.0.12 → 2.0.13

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.
@@ -20,12 +20,14 @@ export function registerConpherenceTools(server, client) {
20
20
  });
21
21
  // Read messages in a thread
22
22
  server.tool('phabricator_conpherence_read', 'Read messages from a Conpherence chat room/thread (returned in reverse chronological order). Uses conpherence.querytransaction (the only Conduit method that returns message content).', {
23
- roomID: z.coerce.number().describe('Numeric room ID (use phabricator_conpherence_search to find it)'),
23
+ roomID: z.coerce.number().optional().describe('Numeric room ID (provide this or roomPHID)'),
24
+ roomPHID: z.string().optional().describe('Room PHID (provide this or roomID)'),
24
25
  limit: z.coerce.number().max(100).optional().describe('Maximum messages to return'),
25
26
  offset: z.coerce.number().optional().describe('Result offset for pagination'),
26
27
  }, async (params) => {
27
28
  const result = await client.call('conpherence.querytransaction', {
28
29
  roomID: params.roomID,
30
+ roomPHID: params.roomPHID,
29
31
  limit: params.limit,
30
32
  offset: params.offset,
31
33
  });
@@ -46,10 +46,17 @@ export function registerDifferentialTools(server, client) {
46
46
  addProjectPHIDs: z.array(z.string()).optional().describe('Add projects'),
47
47
  removeProjectPHIDs: z.array(z.string()).optional().describe('Remove projects'),
48
48
  comment: z.string().optional().describe('Add a comment'),
49
- action: z.enum(['accept', 'reject', 'abandon', 'reclaim', 'reopen', 'request-review', 'resign', 'commandeer', 'plan-changes', 'close', 'draft']).optional().describe('Revision action to take'),
49
+ action: z.enum(['accept', 'reject', 'abandon', 'reclaim', 'reopen', 'request-review', 'resign', 'commandeer', 'plan-changes', 'close']).optional().describe('Revision action to take. Each action is sent as its own transaction type with value true.'),
50
+ draft: z.boolean().optional().describe('Hold revision as draft (true) or release from draft (false)'),
50
51
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
51
52
  removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
52
53
  repositoryPHID: z.string().optional().describe('Repository PHID to associate with the revision'),
54
+ addTaskPHIDs: z.array(z.string()).optional().describe('Maniphest task PHIDs to associate'),
55
+ removeTaskPHIDs: z.array(z.string()).optional().describe('Maniphest task PHIDs to remove'),
56
+ addParentPHIDs: z.array(z.string()).optional().describe('Parent revision PHIDs to add (dependencies)'),
57
+ removeParentPHIDs: z.array(z.string()).optional().describe('Parent revision PHIDs to remove'),
58
+ addChildPHIDs: z.array(z.string()).optional().describe('Child revision PHIDs to add (dependents)'),
59
+ removeChildPHIDs: z.array(z.string()).optional().describe('Child revision PHIDs to remove'),
53
60
  }, async (params) => {
54
61
  const transactions = [];
55
62
  if (params.title !== undefined) {
@@ -80,7 +87,10 @@ export function registerDifferentialTools(server, client) {
80
87
  transactions.push({ type: 'comment', value: params.comment });
81
88
  }
82
89
  if (params.action !== undefined) {
83
- transactions.push({ type: 'action', value: params.action });
90
+ transactions.push({ type: params.action, value: true });
91
+ }
92
+ if (params.draft !== undefined) {
93
+ transactions.push({ type: 'draft', value: params.draft });
84
94
  }
85
95
  if (params.addSubscriberPHIDs !== undefined) {
86
96
  transactions.push({ type: 'subscribers.add', value: params.addSubscriberPHIDs });
@@ -89,7 +99,25 @@ export function registerDifferentialTools(server, client) {
89
99
  transactions.push({ type: 'subscribers.remove', value: params.removeSubscriberPHIDs });
90
100
  }
91
101
  if (params.repositoryPHID !== undefined) {
92
- transactions.push({ type: 'repository', value: params.repositoryPHID });
102
+ transactions.push({ type: 'repositoryPHID', value: params.repositoryPHID });
103
+ }
104
+ if (params.addTaskPHIDs !== undefined) {
105
+ transactions.push({ type: 'tasks.add', value: params.addTaskPHIDs });
106
+ }
107
+ if (params.removeTaskPHIDs !== undefined) {
108
+ transactions.push({ type: 'tasks.remove', value: params.removeTaskPHIDs });
109
+ }
110
+ if (params.addParentPHIDs !== undefined) {
111
+ transactions.push({ type: 'parents.add', value: params.addParentPHIDs });
112
+ }
113
+ if (params.removeParentPHIDs !== undefined) {
114
+ transactions.push({ type: 'parents.remove', value: params.removeParentPHIDs });
115
+ }
116
+ if (params.addChildPHIDs !== undefined) {
117
+ transactions.push({ type: 'children.add', value: params.addChildPHIDs });
118
+ }
119
+ if (params.removeChildPHIDs !== undefined) {
120
+ transactions.push({ type: 'children.remove', value: params.removeChildPHIDs });
93
121
  }
94
122
  if (transactions.length === 0) {
95
123
  return { content: [{ type: 'text', text: 'No changes specified' }] };
@@ -11,6 +11,8 @@ export function registerDiffusionTools(server, client) {
11
11
  shortNames: z.array(z.string()).optional().describe('Repository short names'),
12
12
  types: z.array(z.string()).optional().describe('VCS types: git, hg, svn'),
13
13
  uris: z.array(z.string()).optional().describe('Repository URIs'),
14
+ status: z.string().optional().describe('Repository status: "open" (active) or "closed" (inactive)'),
15
+ hosted: z.string().optional().describe('Hosting: "phabricator" (hosted) or "remote"'),
14
16
  projects: z.array(z.string()).optional().describe('Project PHIDs'),
15
17
  spaces: z.array(z.string()).optional().describe('Space PHIDs (for multi-space installations)'),
16
18
  query: z.string().optional().describe('Full-text search query'),
@@ -178,8 +180,6 @@ export function registerDiffusionTools(server, client) {
178
180
  status: z.enum(['active', 'inactive']).optional().describe('Repository status'),
179
181
  addProjectPHIDs: z.array(z.string()).optional().describe('Project PHIDs to add'),
180
182
  removeProjectPHIDs: z.array(z.string()).optional().describe('Project PHIDs to remove'),
181
- addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
182
- removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
183
183
  space: z.string().optional().describe('Space PHID (for multi-space installations)'),
184
184
  }, async (params) => {
185
185
  const transactions = [];
@@ -210,12 +210,6 @@ export function registerDiffusionTools(server, client) {
210
210
  if (params.removeProjectPHIDs !== undefined) {
211
211
  transactions.push({ type: 'projects.remove', value: params.removeProjectPHIDs });
212
212
  }
213
- if (params.addSubscriberPHIDs !== undefined) {
214
- transactions.push({ type: 'subscribers.add', value: params.addSubscriberPHIDs });
215
- }
216
- if (params.removeSubscriberPHIDs !== undefined) {
217
- transactions.push({ type: 'subscribers.remove', value: params.removeSubscriberPHIDs });
218
- }
219
213
  if (params.space !== undefined) {
220
214
  transactions.push({ type: 'space', value: params.space });
221
215
  }
@@ -3,15 +3,17 @@ import { jsonCoerce } from './coerce.js';
3
3
  export function registerFileTools(server, client) {
4
4
  // Upload a file
5
5
  server.tool('phabricator_file_upload', 'Upload a file to Phabricator. Returns a file PHID that can be used with phabricator_file_info to get the file ID for embedding in Remarkup via {F<id>}.', {
6
- name: z.string().describe('Filename with extension (e.g. "screenshot.png")'),
6
+ name: z.string().optional().describe('Filename with extension (e.g. "screenshot.png")'),
7
7
  data_base64: z.string().describe('Base64-encoded file content'),
8
8
  viewPolicy: z.string().optional().describe('File visibility policy (e.g., "public", "users", or a custom policy PHID)'),
9
9
  canCDN: z.boolean().optional().describe('Whether the file can be served over CDN (for public assets)'),
10
10
  }, async (params) => {
11
11
  const apiParams = {
12
- name: params.name,
13
12
  data_base64: params.data_base64,
14
13
  };
14
+ if (params.name !== undefined) {
15
+ apiParams.name = params.name;
16
+ }
15
17
  if (params.viewPolicy !== undefined) {
16
18
  apiParams.viewPolicy = params.viewPolicy;
17
19
  }
@@ -31,6 +31,9 @@ export function registerHarbormasterTools(server, client) {
31
31
  statuses: z.array(z.string()).optional().describe('Build statuses: building, passed, failed, aborted, error, paused'),
32
32
  initiators: z.array(z.string()).optional().describe('PHIDs of users/objects that initiated the build'),
33
33
  })).optional().describe('Search constraints'),
34
+ attachments: jsonCoerce(z.object({
35
+ querybuilds: z.boolean().optional().describe('Include build query data'),
36
+ })).optional().describe('Data attachments'),
34
37
  order: z.string().optional().describe('Result order'),
35
38
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
36
39
  after: z.string().optional().describe('Cursor for next-page pagination'),
@@ -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('true: only tasks with open parent tasks. false: only tasks without. Omit to show all.'),
25
25
  hasSubtasks: z.boolean().optional().describe('true: only tasks with open subtasks. false: only tasks without. Omit to show all.'),
26
+ subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
26
27
  spaces: z.array(z.string()).optional().describe('Filter by Space PHIDs (for multi-space installations)'),
27
28
  closedStart: z.coerce.number().optional().describe('Closed after (epoch timestamp)'),
28
29
  closedEnd: z.coerce.number().optional().describe('Closed before (epoch timestamp)'),
@@ -53,6 +54,7 @@ export function registerManiphestTools(server, client) {
53
54
  subtype: z.string().optional().describe('Task subtype (e.g. "default", "incident")'),
54
55
  parentPHIDs: z.array(z.string()).optional().describe('Parent task PHIDs'),
55
56
  subtaskPHIDs: z.array(z.string()).optional().describe('Subtask PHIDs'),
57
+ points: z.coerce.number().nullable().optional().describe('Story points value (if points are enabled on this instance)'),
56
58
  space: z.string().optional().describe('Space PHID to place the task in (for multi-space installations)'),
57
59
  comment: z.string().optional().describe('Initial comment on the task (supports Remarkup)'),
58
60
  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.'),
@@ -87,6 +89,9 @@ export function registerManiphestTools(server, client) {
87
89
  if (params.subtaskPHIDs !== undefined) {
88
90
  transactions.push({ type: 'subtasks.set', value: params.subtaskPHIDs });
89
91
  }
92
+ if (params.points !== undefined) {
93
+ transactions.push({ type: 'points', value: params.points });
94
+ }
90
95
  if (params.space !== undefined) {
91
96
  transactions.push({ type: 'space', value: params.space });
92
97
  }
@@ -118,6 +123,7 @@ export function registerManiphestTools(server, client) {
118
123
  removeParentPHIDs: z.array(z.string()).optional().describe('Parent task PHIDs to remove'),
119
124
  addSubtaskPHIDs: z.array(z.string()).optional().describe('Subtask PHIDs to add'),
120
125
  removeSubtaskPHIDs: z.array(z.string()).optional().describe('Subtask PHIDs to remove'),
126
+ points: z.coerce.number().nullable().optional().describe('Story points value (null to clear)'),
121
127
  columnPHID: z.string().optional().describe('Move to workboard column'),
122
128
  space: z.string().optional().describe('Space PHID to move the task to (for multi-space installations)'),
123
129
  comment: z.string().optional().describe('Add a comment alongside the edit (supports Remarkup)'),
@@ -166,6 +172,9 @@ export function registerManiphestTools(server, client) {
166
172
  if (params.removeSubtaskPHIDs !== undefined) {
167
173
  transactions.push({ type: 'subtasks.remove', value: params.removeSubtaskPHIDs });
168
174
  }
175
+ if (params.points !== undefined) {
176
+ transactions.push({ type: 'points', value: params.points });
177
+ }
169
178
  if (params.columnPHID !== undefined) {
170
179
  transactions.push({ type: 'column', value: [{ columnPHID: params.columnPHID }] });
171
180
  }
@@ -37,6 +37,7 @@ export function registerPasteTools(server, client) {
37
37
  language: z.string().optional().describe('Syntax highlighting language'),
38
38
  status: z.string().optional().describe('Status: active or archived'),
39
39
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
40
+ addProjectPHIDs: z.array(z.string()).optional().describe('Project PHIDs to tag'),
40
41
  }, async (params) => {
41
42
  const transactions = [
42
43
  { type: 'text', value: params.content },
@@ -53,6 +54,9 @@ export function registerPasteTools(server, client) {
53
54
  if (params.addSubscriberPHIDs !== undefined) {
54
55
  transactions.push({ type: 'subscribers.add', value: params.addSubscriberPHIDs });
55
56
  }
57
+ if (params.addProjectPHIDs !== undefined) {
58
+ transactions.push({ type: 'projects.add', value: params.addProjectPHIDs });
59
+ }
56
60
  const result = await client.call('paste.edit', { transactions });
57
61
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
58
62
  });
@@ -65,6 +69,8 @@ export function registerPasteTools(server, client) {
65
69
  status: z.string().optional().describe('Status: active or archived'),
66
70
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
67
71
  removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
72
+ addProjectPHIDs: z.array(z.string()).optional().describe('Project PHIDs to add'),
73
+ removeProjectPHIDs: z.array(z.string()).optional().describe('Project PHIDs to remove'),
68
74
  comment: z.string().optional().describe('Add a comment alongside the edit (supports Remarkup)'),
69
75
  }, async (params) => {
70
76
  const transactions = [];
@@ -86,6 +92,12 @@ export function registerPasteTools(server, client) {
86
92
  if (params.removeSubscriberPHIDs !== undefined) {
87
93
  transactions.push({ type: 'subscribers.remove', value: params.removeSubscriberPHIDs });
88
94
  }
95
+ if (params.addProjectPHIDs !== undefined) {
96
+ transactions.push({ type: 'projects.add', value: params.addProjectPHIDs });
97
+ }
98
+ if (params.removeProjectPHIDs !== undefined) {
99
+ transactions.push({ type: 'projects.remove', value: params.removeProjectPHIDs });
100
+ }
89
101
  if (params.comment !== undefined) {
90
102
  transactions.push({ type: 'comment', value: params.comment });
91
103
  }
@@ -7,7 +7,6 @@ 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 (may not be supported on all instances)'),
11
10
  subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
12
11
  projects: z.array(z.string()).optional().describe('Project PHIDs'),
13
12
  query: z.string().optional().describe('Full-text search query'),
@@ -30,7 +29,7 @@ export function registerPhameTools(server, client) {
30
29
  name: z.string().optional().describe('Blog name'),
31
30
  subtitle: z.string().optional().describe('Blog subtitle'),
32
31
  description: z.string().optional().describe('Blog description (Remarkup)'),
33
- fullDomain: z.string().optional().describe('Custom full domain for the blog'),
32
+ domainFullURI: z.string().optional().describe('Custom full domain URI for the blog'),
34
33
  parentSite: z.string().optional().describe('Parent site name'),
35
34
  parentDomain: z.string().optional().describe('Parent domain URL'),
36
35
  status: z.string().optional().describe('Blog status'),
@@ -48,8 +47,8 @@ export function registerPhameTools(server, client) {
48
47
  if (params.description !== undefined) {
49
48
  transactions.push({ type: 'description', value: params.description });
50
49
  }
51
- if (params.fullDomain !== undefined) {
52
- transactions.push({ type: 'fullDomain', value: params.fullDomain });
50
+ if (params.domainFullURI !== undefined) {
51
+ transactions.push({ type: 'domainFullURI', value: params.domainFullURI });
53
52
  }
54
53
  if (params.parentSite !== undefined) {
55
54
  transactions.push({ type: 'parentSite', value: params.parentSite });
@@ -13,6 +13,7 @@ export function registerProjectTools(server, client) {
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
15
  parents: z.array(z.string()).optional().describe('Parent project PHIDs (find subprojects)'),
16
+ status: z.string().optional().describe('Project status: "active" (default), "archived"'),
16
17
  icons: z.array(z.string()).optional().describe('Filter by project icon'),
17
18
  isMilestone: z.boolean().optional().describe('Filter milestones'),
18
19
  isRoot: z.boolean().optional().describe('Filter root projects'),
@@ -40,13 +41,10 @@ export function registerProjectTools(server, client) {
40
41
  server.tool('phabricator_project_edit', 'Create or edit a Phabricator project. Omit objectIdentifier to create a new project (name is required for creation).', {
41
42
  objectIdentifier: z.string().optional().describe('Project PHID or ID. Omit to create a new project.'),
42
43
  name: z.string().optional().describe('New name'),
43
- description: z.string().optional().describe('New description'),
44
44
  icon: z.string().optional().describe('New icon'),
45
45
  color: z.string().optional().describe('New color'),
46
46
  addMemberPHIDs: z.array(z.string()).optional().describe('Add members'),
47
47
  removeMemberPHIDs: z.array(z.string()).optional().describe('Remove members'),
48
- addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
49
- removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
50
48
  space: z.string().optional().describe('Space PHID (for multi-space installations)'),
51
49
  parent: z.string().optional().describe('Parent project PHID (to create as a subproject)'),
52
50
  milestone: z.string().optional().describe('Parent project PHID (to create as a milestone of that project)'),
@@ -69,9 +67,6 @@ export function registerProjectTools(server, client) {
69
67
  if (params.slug !== undefined) {
70
68
  transactions.push({ type: 'slugs', value: [params.slug] });
71
69
  }
72
- if (params.description !== undefined) {
73
- transactions.push({ type: 'description', value: params.description });
74
- }
75
70
  if (params.icon !== undefined) {
76
71
  transactions.push({ type: 'icon', value: params.icon });
77
72
  }
@@ -84,12 +79,6 @@ export function registerProjectTools(server, client) {
84
79
  if (params.removeMemberPHIDs !== undefined) {
85
80
  transactions.push({ type: 'members.remove', value: params.removeMemberPHIDs });
86
81
  }
87
- if (params.addSubscriberPHIDs !== undefined) {
88
- transactions.push({ type: 'subscribers.add', value: params.addSubscriberPHIDs });
89
- }
90
- if (params.removeSubscriberPHIDs !== undefined) {
91
- transactions.push({ type: 'subscribers.remove', value: params.removeSubscriberPHIDs });
92
- }
93
82
  if (params.comment !== undefined) {
94
83
  transactions.push({ type: 'comment', value: params.comment });
95
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freelancercom/phabricator-mcp",
3
- "version": "2.0.12",
3
+ "version": "2.0.13",
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",