@freelancercom/phabricator-mcp 2.0.7 → 2.0.9

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/README.md CHANGED
@@ -290,6 +290,7 @@ To allowlist all tools including write operations, use `"mcp__phabricator__*"` i
290
290
  | Tool | Description |
291
291
  |------|-------------|
292
292
  | `phabricator_blog_search` | Search Phame blogs |
293
+ | `phabricator_blog_edit` | Create or edit a Phame blog |
293
294
  | `phabricator_blog_post_search` | Search blog posts |
294
295
  | `phabricator_blog_post_create` | Create a new blog post |
295
296
  | `phabricator_blog_post_edit` | Edit an existing blog post |
@@ -8,7 +8,7 @@ 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
+ fulltext: z.string().optional().describe('Search for rooms containing these words'),
12
12
  })).optional().describe('Search constraints'),
13
13
  order: z.string().optional().describe('Result order'),
14
14
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
@@ -17,13 +17,14 @@ export function registerDifferentialTools(server, client) {
17
17
  createdEnd: z.coerce.number().optional().describe('Created before (epoch timestamp)'),
18
18
  modifiedStart: z.coerce.number().optional().describe('Modified after (epoch timestamp)'),
19
19
  modifiedEnd: z.coerce.number().optional().describe('Modified before (epoch timestamp)'),
20
+ subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
21
+ projects: z.array(z.string()).optional().describe('Project PHIDs'),
20
22
  query: z.string().optional().describe('Full-text search query'),
21
23
  })).optional().describe('Search constraints'),
22
24
  attachments: jsonCoerce(z.object({
23
25
  reviewers: z.boolean().optional().describe('Include reviewers'),
24
26
  subscribers: z.boolean().optional().describe('Include subscribers'),
25
27
  projects: z.boolean().optional().describe('Include projects'),
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
28
  })).optional().describe('Data attachments'),
28
29
  order: z.string().optional().describe('Result order: "newest", "oldest", "updated", "relevance"'),
29
30
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
@@ -44,6 +44,8 @@ export function registerDiffusionTools(server, client) {
44
44
  unreachable: z.boolean().optional().describe('Include unreachable commits'),
45
45
  permanent: z.boolean().optional().describe('Filter by permanent (reachable from any permanent ref) status'),
46
46
  ancestorsOf: z.array(z.string()).optional().describe('Find ancestors of these commit identifiers'),
47
+ subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
48
+ projects: z.array(z.string()).optional().describe('Project PHIDs'),
47
49
  query: z.string().optional().describe('Full-text search query'),
48
50
  })).optional().describe('Search constraints'),
49
51
  attachments: jsonCoerce(z.object({
@@ -25,6 +25,9 @@ export function registerFileTools(server, client) {
25
25
  explicit: z.boolean().optional().describe('Filter to explicitly uploaded files only'),
26
26
  subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
27
27
  })).optional().describe('Search constraints'),
28
+ attachments: jsonCoerce(z.object({
29
+ subscribers: z.boolean().optional().describe('Include subscriber details'),
30
+ })).optional().describe('Data attachments'),
28
31
  order: z.string().optional().describe('Result order'),
29
32
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
30
33
  after: z.string().optional().describe('Cursor for next-page pagination'),
@@ -10,6 +10,7 @@ export function registerHarbormasterTools(server, client) {
10
10
  objectPHIDs: z.array(z.string()).optional().describe('Object PHIDs (revision or commit PHIDs)'),
11
11
  containerPHIDs: z.array(z.string()).optional().describe('Container PHIDs'),
12
12
  statuses: z.array(z.string()).optional().describe('Buildable statuses'),
13
+ manual: z.boolean().optional().describe('Filter to manual buildables only (true) or automated only (false)'),
13
14
  })).optional().describe('Search constraints'),
14
15
  order: z.string().optional().describe('Result order'),
15
16
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
@@ -26,9 +27,9 @@ export function registerHarbormasterTools(server, client) {
26
27
  ids: z.array(z.coerce.number()).optional().describe('Build IDs'),
27
28
  phids: z.array(z.string()).optional().describe('Build PHIDs'),
28
29
  buildables: z.array(z.string()).optional().describe('Buildable PHIDs'),
29
- plans: z.array(z.string()).optional().describe('Build plan PHIDs'),
30
+ plans: z.array(z.string()).optional().describe('Build plan PHIDs (use phabricator_build_plan_search to find these)'),
30
31
  statuses: z.array(z.string()).optional().describe('Build statuses: building, passed, failed, aborted, error, paused'),
31
- initiatorPHIDs: z.array(z.string()).optional().describe('PHIDs of users/objects that initiated the build'),
32
+ initiators: z.array(z.string()).optional().describe('PHIDs of users/objects that initiated the build'),
32
33
  })).optional().describe('Search constraints'),
33
34
  order: z.string().optional().describe('Result order'),
34
35
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
@@ -46,10 +47,12 @@ export function registerHarbormasterTools(server, client) {
46
47
  phids: z.array(z.string()).optional().describe('Target PHIDs'),
47
48
  buildPHIDs: z.array(z.string()).optional().describe('Build PHIDs'),
48
49
  statuses: z.array(z.string()).optional().describe('Target statuses'),
49
- dateCreatedStart: z.coerce.number().optional().describe('Created after (epoch timestamp)'),
50
- dateCreatedEnd: z.coerce.number().optional().describe('Created before (epoch timestamp)'),
51
- dateModifiedStart: z.coerce.number().optional().describe('Modified after (epoch timestamp)'),
52
- dateModifiedEnd: z.coerce.number().optional().describe('Modified before (epoch timestamp)'),
50
+ createdStart: z.coerce.number().optional().describe('Created after (epoch timestamp)'),
51
+ createdEnd: z.coerce.number().optional().describe('Created before (epoch timestamp)'),
52
+ startedStart: z.coerce.number().optional().describe('Started executing after (epoch timestamp)'),
53
+ startedEnd: z.coerce.number().optional().describe('Started executing before (epoch timestamp)'),
54
+ completedStart: z.coerce.number().optional().describe('Completed after (epoch timestamp)'),
55
+ completedEnd: z.coerce.number().optional().describe('Completed before (epoch timestamp)'),
53
56
  })).optional().describe('Search constraints'),
54
57
  order: z.string().optional().describe('Result order'),
55
58
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
@@ -7,7 +7,7 @@ export function registerManiphestTools(server, client) {
7
7
  constraints: jsonCoerce(z.object({
8
8
  ids: z.array(z.coerce.number()).optional().describe('Task IDs to search for'),
9
9
  phids: z.array(z.string()).optional().describe('Task PHIDs to search for'),
10
- assignedPHIDs: z.array(z.string()).optional().describe('Assigned user PHIDs'),
10
+ assigned: z.array(z.string()).optional().describe('Assigned user PHIDs'),
11
11
  authorPHIDs: z.array(z.string()).optional().describe('Author PHIDs'),
12
12
  statuses: z.array(z.string()).optional().describe('Task statuses: open, resolved, wontfix, invalid, spite, duplicate'),
13
13
  priorities: z.array(z.coerce.number()).optional().describe('Priority levels'),
@@ -23,7 +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 open parent tasks'),
25
25
  hasSubtasks: z.boolean().optional().describe('Filter to tasks that have open subtasks'),
26
- spacePHIDs: z.array(z.string()).optional().describe('Filter by Space PHIDs (for multi-space installations)'),
26
+ spaces: z.array(z.string()).optional().describe('Filter by Space PHIDs (for multi-space installations)'),
27
27
  closedStart: z.coerce.number().optional().describe('Closed after (epoch timestamp)'),
28
28
  closedEnd: z.coerce.number().optional().describe('Closed before (epoch timestamp)'),
29
29
  closerPHIDs: z.array(z.string()).optional().describe('PHIDs of users who closed the task'),
@@ -32,7 +32,6 @@ export function registerManiphestTools(server, client) {
32
32
  columns: z.boolean().optional().describe('Include workboard column info'),
33
33
  projects: z.boolean().optional().describe('Include project info'),
34
34
  subscribers: z.boolean().optional().describe('Include subscriber info'),
35
- 'custom-fields': z.boolean().optional().describe('Include custom field values in results'),
36
35
  })).optional().describe('Data attachments to include'),
37
36
  order: z.string().optional().describe('Result order: "priority", "updated", "newest", "oldest", "title", "relevance"'),
38
37
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
@@ -10,9 +10,8 @@ export function registerOwnersTools(server, client) {
10
10
  owners: z.array(z.string()).optional().describe('Owner user or project PHIDs'),
11
11
  repositories: z.array(z.string()).optional().describe('Repository PHIDs'),
12
12
  paths: z.array(z.string()).optional().describe('Code paths to search for (e.g. "/src/foo.ts")'),
13
+ name: z.string().optional().describe('Search for packages by name substring'),
13
14
  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"'),
16
15
  query: z.string().optional().describe('Full-text search query'),
17
16
  })).optional().describe('Search constraints'),
18
17
  attachments: jsonCoerce(z.object({
@@ -10,12 +10,17 @@ export function registerPasteTools(server, client) {
10
10
  authors: z.array(z.string()).optional().describe('Author PHIDs'),
11
11
  languages: z.array(z.string()).optional().describe('Languages'),
12
12
  statuses: z.array(z.string()).optional().describe('Statuses: active, archived'),
13
+ subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
14
+ projects: z.array(z.string()).optional().describe('Project PHIDs'),
15
+ spaces: z.array(z.string()).optional().describe('Space PHIDs (for multi-space installations)'),
13
16
  createdStart: z.coerce.number().optional().describe('Created after (epoch timestamp)'),
14
17
  createdEnd: z.coerce.number().optional().describe('Created before (epoch timestamp)'),
15
18
  query: z.string().optional().describe('Full-text search query'),
16
19
  })).optional().describe('Search constraints'),
17
20
  attachments: jsonCoerce(z.object({
18
21
  content: z.boolean().optional().describe('Include paste content'),
22
+ subscribers: z.boolean().optional().describe('Include subscriber details'),
23
+ projects: z.boolean().optional().describe('Include tagged projects'),
19
24
  })).optional().describe('Data attachments'),
20
25
  order: z.string().optional().describe('Result order'),
21
26
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
@@ -7,7 +7,9 @@ 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
+ statuses: z.array(z.string()).optional().describe('Blog statuses (may not be supported on all instances)'),
11
+ subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
12
+ projects: z.array(z.string()).optional().describe('Project PHIDs'),
11
13
  query: z.string().optional().describe('Full-text search query'),
12
14
  })).optional().describe('Search constraints'),
13
15
  attachments: jsonCoerce(z.object({
@@ -22,6 +24,61 @@ export function registerPhameTools(server, client) {
22
24
  const result = await client.call('phame.blog.search', params);
23
25
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
24
26
  });
27
+ // Edit a blog
28
+ server.tool('phabricator_blog_edit', 'Create or edit a Phame blog. Omit objectIdentifier to create a new blog (name is required for creation).', {
29
+ objectIdentifier: z.string().optional().describe('Blog PHID or ID. Omit to create a new blog.'),
30
+ name: z.string().optional().describe('Blog name'),
31
+ subtitle: z.string().optional().describe('Blog subtitle'),
32
+ description: z.string().optional().describe('Blog description (Remarkup)'),
33
+ fullDomain: z.string().optional().describe('Custom full domain for the blog'),
34
+ parentSite: z.string().optional().describe('Parent site name'),
35
+ parentDomain: z.string().optional().describe('Parent domain URL'),
36
+ status: z.string().optional().describe('Blog status'),
37
+ addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
38
+ removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
39
+ comment: z.string().optional().describe('Add a comment alongside the edit (supports Remarkup)'),
40
+ }, async (params) => {
41
+ const transactions = [];
42
+ if (params.name !== undefined) {
43
+ transactions.push({ type: 'name', value: params.name });
44
+ }
45
+ if (params.subtitle !== undefined) {
46
+ transactions.push({ type: 'subtitle', value: params.subtitle });
47
+ }
48
+ if (params.description !== undefined) {
49
+ transactions.push({ type: 'description', value: params.description });
50
+ }
51
+ if (params.fullDomain !== undefined) {
52
+ transactions.push({ type: 'fullDomain', value: params.fullDomain });
53
+ }
54
+ if (params.parentSite !== undefined) {
55
+ transactions.push({ type: 'parentSite', value: params.parentSite });
56
+ }
57
+ if (params.parentDomain !== undefined) {
58
+ transactions.push({ type: 'parentDomain', value: params.parentDomain });
59
+ }
60
+ if (params.status !== undefined) {
61
+ transactions.push({ type: 'status', value: params.status });
62
+ }
63
+ if (params.addSubscriberPHIDs !== undefined) {
64
+ transactions.push({ type: 'subscribers.add', value: params.addSubscriberPHIDs });
65
+ }
66
+ if (params.removeSubscriberPHIDs !== undefined) {
67
+ transactions.push({ type: 'subscribers.remove', value: params.removeSubscriberPHIDs });
68
+ }
69
+ if (params.comment !== undefined) {
70
+ transactions.push({ type: 'comment', value: params.comment });
71
+ }
72
+ if (transactions.length === 0) {
73
+ return { content: [{ type: 'text', text: 'No changes specified' }] };
74
+ }
75
+ const apiParams = { transactions };
76
+ if (params.objectIdentifier !== undefined) {
77
+ apiParams.objectIdentifier = params.objectIdentifier;
78
+ }
79
+ const result = await client.call('phame.blog.edit', apiParams);
80
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
81
+ });
25
82
  // Search blog posts
26
83
  server.tool('phabricator_blog_post_search', 'Search Phame blog posts', {
27
84
  queryKey: z.string().optional().describe('Built-in query: "all", "live"'),
@@ -29,8 +86,9 @@ export function registerPhameTools(server, client) {
29
86
  ids: z.array(z.coerce.number()).optional().describe('Post IDs'),
30
87
  phids: z.array(z.string()).optional().describe('Post PHIDs'),
31
88
  blogPHIDs: z.array(z.string()).optional().describe('Filter by blog PHIDs'),
32
- authorPHIDs: z.array(z.string()).optional().describe('Filter by author PHIDs'),
33
89
  visibility: z.array(z.string()).optional().describe('Visibility: "published", "draft", "archived" (or numeric: "1", "0", "2")'),
90
+ subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
91
+ projects: z.array(z.string()).optional().describe('Project PHIDs'),
34
92
  query: z.string().optional().describe('Full-text search query'),
35
93
  })).optional().describe('Search constraints'),
36
94
  attachments: jsonCoerce(z.object({
@@ -11,6 +11,9 @@ export function registerPhrictionTools(server, client) {
11
11
  parentPaths: z.array(z.string()).optional().describe('Parent paths (direct children only)'),
12
12
  ancestorPaths: z.array(z.string()).optional().describe('Ancestor paths to search under (any depth)'),
13
13
  statuses: z.array(z.string()).optional().describe('Document statuses'),
14
+ subscribers: z.array(z.string()).optional().describe('Subscriber user/project PHIDs'),
15
+ projects: z.array(z.string()).optional().describe('Project PHIDs'),
16
+ spaces: z.array(z.string()).optional().describe('Space PHIDs (for multi-space installations)'),
14
17
  query: z.string().optional().describe('Full-text search query'),
15
18
  })).optional().describe('Search constraints'),
16
19
  attachments: jsonCoerce(z.object({
@@ -20,6 +20,7 @@ export function registerProjectTools(server, client) {
20
20
  maxDepth: z.coerce.number().optional().describe('Maximum project depth'),
21
21
  subtypes: z.array(z.string()).optional().describe('Project subtypes'),
22
22
  colors: z.array(z.string()).optional().describe('Project colors'),
23
+ spaces: z.array(z.string()).optional().describe('Space PHIDs (for multi-space installations)'),
23
24
  query: z.string().optional().describe('Full-text search query'),
24
25
  })).optional().describe('Search constraints'),
25
26
  attachments: jsonCoerce(z.object({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freelancercom/phabricator-mcp",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
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",