@freelancercom/phabricator-mcp 2.0.0 → 2.0.2

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.
@@ -83,7 +83,7 @@ export function registerDifferentialTools(server, client) {
83
83
  transactions.push({ type: 'subscribers.remove', value: params.removeSubscriberPHIDs });
84
84
  }
85
85
  if (params.repositoryPHID !== undefined) {
86
- transactions.push({ type: 'repositoryPHID', value: params.repositoryPHID });
86
+ transactions.push({ type: 'repository', value: params.repositoryPHID });
87
87
  }
88
88
  if (transactions.length === 0) {
89
89
  return { content: [{ type: 'text', text: 'No changes specified' }] };
@@ -154,7 +154,7 @@ export function registerDifferentialTools(server, client) {
154
154
  lineNumber: params.lineNumber,
155
155
  lineLength: params.lineLength ?? 0,
156
156
  content: params.content,
157
- isNewFile: params.isNewFile ?? true,
157
+ isNewFile: (params.isNewFile ?? true) ? 1 : 0,
158
158
  });
159
159
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
160
160
  });
@@ -62,7 +62,7 @@ export function registerDiffusionTools(server, client) {
62
62
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
63
63
  });
64
64
  // Read file content from repository
65
- server.tool('phabricator_repository_file_content', 'Read file contents from a Diffusion repository at a given path and commit/branch', {
65
+ server.tool('phabricator_repository_file_content', 'Read file contents from a Diffusion repository at a given path and commit/branch. Returns the file content as a base64-encoded blob. If the file is too large, returns tooHuge: true with no content.', {
66
66
  path: z.string().describe('File path in the repository (e.g., "src/index.ts")'),
67
67
  repository: z.string().optional().describe('Repository callsign, short name, or PHID'),
68
68
  commit: z.string().optional().describe('Commit hash or branch name (default: HEAD)'),
@@ -72,7 +72,14 @@ export function registerDiffusionTools(server, client) {
72
72
  repository: params.repository,
73
73
  commit: params.commit,
74
74
  });
75
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
75
+ if (result.tooHuge || result.tooSlow) {
76
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
77
+ }
78
+ // Fetch actual file content using the returned filePHID
79
+ const fileInfo = await client.call('file.info', {
80
+ phid: result.filePHID,
81
+ });
82
+ return { content: [{ type: 'text', text: JSON.stringify({ ...result, ...fileInfo }, null, 2) }] };
76
83
  });
77
84
  // List branches
78
85
  server.tool('phabricator_branch_search', 'List branches in a Diffusion repository', {
@@ -3,6 +3,7 @@ export function registerFeedTools(server, client) {
3
3
  // Query activity feed
4
4
  server.tool('phabricator_feed_query', 'Query the Phabricator activity feed. Returns recent activity (task updates, revision changes, commits, etc.) as an object keyed by story PHID. Uses feed.query (the only Conduit method for feed data).', {
5
5
  filterPHIDs: z.array(z.string()).optional().describe('Only show activity involving these PHIDs (user, project, task, etc.)'),
6
+ view: z.enum(['data', 'text', 'html']).optional().describe('Output format: "data" (structured, default), "text" (human-readable), "html" (rendered HTML)'),
6
7
  limit: z.coerce.number().max(100).optional().describe('Maximum results (max 100)'),
7
8
  after: z.string().optional().describe('Cursor for pagination (chronological key from previous results)'),
8
9
  before: z.string().optional().describe('Cursor for reverse pagination'),
@@ -78,11 +78,37 @@ export function registerHarbormasterTools(server, client) {
78
78
  server.tool('phabricator_build_command', 'Report build status to Harbormaster. Used by external build systems to notify Phabricator of build results. Provide the build target PHID (use phabricator_build_target_search to find it).', {
79
79
  buildTargetPHID: z.string().describe('Build target PHID to send the message to. Use phabricator_build_target_search to find this.'),
80
80
  type: z.enum(['pass', 'fail', 'work']).describe('Message type: "pass" (build succeeded), "fail" (build failed), "work" (build is still running)'),
81
+ unit: jsonCoerce(z.array(z.object({
82
+ name: z.string().describe('Test name'),
83
+ result: z.string().describe('Result: "pass", "fail", "skip", "broken", "unsound"'),
84
+ namespace: z.string().optional().describe('Test namespace/group'),
85
+ engine: z.string().optional().describe('Test engine name'),
86
+ duration: z.coerce.number().optional().describe('Duration in seconds'),
87
+ path: z.string().optional().describe('File path related to the test'),
88
+ coverage: z.record(z.string(), z.string()).optional().describe('Coverage data as {path: "NNCUUUC..."} where N=not executable, C=covered, U=uncovered'),
89
+ details: z.string().optional().describe('Additional details or failure message'),
90
+ }))).optional().describe('Unit test results to report'),
91
+ lint: jsonCoerce(z.array(z.object({
92
+ name: z.string().describe('Lint message name'),
93
+ code: z.string().describe('Lint rule code'),
94
+ severity: z.string().describe('Severity: "advice", "autofix", "warning", "error", "disabled"'),
95
+ path: z.string().optional().describe('File path'),
96
+ line: z.coerce.number().optional().describe('Line number'),
97
+ char: z.coerce.number().optional().describe('Character offset'),
98
+ description: z.string().optional().describe('Lint message description'),
99
+ }))).optional().describe('Lint results to report'),
81
100
  }, async (params) => {
82
- const result = await client.call('harbormaster.sendmessage', {
101
+ const apiParams = {
83
102
  buildTargetPHID: params.buildTargetPHID,
84
103
  type: params.type,
85
- });
104
+ };
105
+ if (params.unit !== undefined) {
106
+ apiParams.unit = params.unit;
107
+ }
108
+ if (params.lint !== undefined) {
109
+ apiParams.lint = params.lint;
110
+ }
111
+ const result = await client.call('harbormaster.sendmessage', apiParams);
86
112
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
87
113
  });
88
114
  // Search build plans
@@ -158,7 +158,7 @@ export function registerManiphestTools(server, client) {
158
158
  transactions.push({ type: 'subtasks.remove', value: params.removeSubtaskPHIDs });
159
159
  }
160
160
  if (params.columnPHID !== undefined) {
161
- transactions.push({ type: 'column', value: [params.columnPHID] });
161
+ transactions.push({ type: 'column', value: [{ columnPHID: params.columnPHID }] });
162
162
  }
163
163
  if (params.comment !== undefined) {
164
164
  transactions.push({ type: 'comment', value: params.comment });
@@ -27,6 +27,8 @@ export function registerPhrictionTools(server, client) {
27
27
  objectIdentifier: z.string().describe('Document slug, PHID, or ID (e.g., "projects/myproject/")'),
28
28
  title: z.string().optional().describe('Document title'),
29
29
  content: z.string().optional().describe('Document content (Remarkup)'),
30
+ delete: z.boolean().optional().describe('Set to true to delete/archive the document'),
31
+ move: z.string().optional().describe('New slug to move/rename the document to'),
30
32
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
31
33
  removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
32
34
  }, async (params) => {
@@ -37,6 +39,12 @@ export function registerPhrictionTools(server, client) {
37
39
  if (params.content !== undefined) {
38
40
  transactions.push({ type: 'content', value: params.content });
39
41
  }
42
+ if (params.delete === true) {
43
+ transactions.push({ type: 'delete', value: true });
44
+ }
45
+ if (params.move !== undefined) {
46
+ transactions.push({ type: 'move', value: params.move });
47
+ }
40
48
  if (params.addSubscriberPHIDs !== undefined) {
41
49
  transactions.push({ type: 'subscribers.add', value: params.addSubscriberPHIDs });
42
50
  }
@@ -8,7 +8,7 @@ export function registerProjectTools(server, client) {
8
8
  ids: z.array(z.coerce.number()).optional().describe('Project IDs'),
9
9
  phids: z.array(z.string()).optional().describe('Project PHIDs'),
10
10
  slugs: z.array(z.string()).optional().describe('Project slugs'),
11
- name: z.string().optional().describe('Exact name match'),
11
+ name: z.string().optional().describe('Name substring search'),
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'),
@@ -39,6 +39,8 @@ export function registerProjectTools(server, client) {
39
39
  removeMemberPHIDs: z.array(z.string()).optional().describe('Remove members'),
40
40
  addSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to add'),
41
41
  removeSubscriberPHIDs: z.array(z.string()).optional().describe('Subscriber PHIDs to remove'),
42
+ parent: z.string().optional().describe('Parent project PHID (to create as a subproject)'),
43
+ milestone: z.string().optional().describe('Parent project PHID (to create as a milestone of that project)'),
42
44
  slug: z.string().optional().describe('Project URL slug (replaces ALL existing slugs with this one)'),
43
45
  comment: z.string().optional().describe('Add a comment alongside the edit (supports Remarkup)'),
44
46
  }, async (params) => {
@@ -46,6 +48,12 @@ export function registerProjectTools(server, client) {
46
48
  if (params.name !== undefined) {
47
49
  transactions.push({ type: 'name', value: params.name });
48
50
  }
51
+ if (params.parent !== undefined) {
52
+ transactions.push({ type: 'parent', value: params.parent });
53
+ }
54
+ if (params.milestone !== undefined) {
55
+ transactions.push({ type: 'milestone', value: params.milestone });
56
+ }
49
57
  if (params.slug !== undefined) {
50
58
  transactions.push({ type: 'slugs', value: [params.slug] });
51
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freelancercom/phabricator-mcp",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
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",