@arii/boomtick-mcp 0.4.2 → 0.6.0

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.
Files changed (205) hide show
  1. package/.mcp/schemas/boomtick.health.json +5 -0
  2. package/.mcp/schemas/boomtick_health.json +5 -0
  3. package/.mcp/schemas/github.checkout_branch.json +5 -0
  4. package/.mcp/schemas/github.comment_triage_summary.json +5 -0
  5. package/.mcp/schemas/github.create_issue.json +5 -0
  6. package/.mcp/schemas/github.create_pull_request.json +5 -0
  7. package/.mcp/schemas/github.get_merge_conflict_files.json +5 -0
  8. package/.mcp/schemas/github.get_pr.json +5 -0
  9. package/.mcp/schemas/github.get_pr_commits.json +37 -0
  10. package/.mcp/schemas/github.get_pr_diff.json +5 -0
  11. package/.mcp/schemas/github.get_pr_reviews.json +37 -0
  12. package/.mcp/schemas/github.issue_comment.json +5 -0
  13. package/.mcp/schemas/github.issue_update.json +5 -0
  14. package/.mcp/schemas/github.issue_view.json +5 -0
  15. package/.mcp/schemas/github.open_replacement_pr.json +5 -0
  16. package/.mcp/schemas/github.search_open_prs.json +5 -0
  17. package/.mcp/schemas/github_checkout_branch.json +5 -0
  18. package/.mcp/schemas/github_comment_triage_summary.json +5 -0
  19. package/.mcp/schemas/github_create_issue.json +5 -0
  20. package/.mcp/schemas/github_create_pull_request.json +5 -0
  21. package/.mcp/schemas/github_get_merge_conflict_files.json +5 -0
  22. package/.mcp/schemas/github_get_pr.json +5 -0
  23. package/.mcp/schemas/github_get_pr_commits.json +37 -0
  24. package/.mcp/schemas/github_get_pr_diff.json +5 -0
  25. package/.mcp/schemas/github_get_pr_reviews.json +37 -0
  26. package/.mcp/schemas/github_issue_comment.json +5 -0
  27. package/.mcp/schemas/github_issue_update.json +5 -0
  28. package/.mcp/schemas/github_issue_view.json +5 -0
  29. package/.mcp/schemas/github_open_replacement_pr.json +5 -0
  30. package/.mcp/schemas/github_search_open_prs.json +5 -0
  31. package/.mcp/schemas/jules.cancel_session.json +5 -0
  32. package/.mcp/schemas/jules.create_session.json +5 -0
  33. package/.mcp/schemas/jules.get_messages.json +5 -0
  34. package/.mcp/schemas/jules.get_pr.json +5 -0
  35. package/.mcp/schemas/jules.get_session.json +5 -0
  36. package/.mcp/schemas/jules.list_sessions.json +5 -0
  37. package/.mcp/schemas/jules.send_message.json +5 -0
  38. package/.mcp/schemas/jules.trigger_feedback.json +5 -0
  39. package/.mcp/schemas/jules_cancel_session.json +5 -0
  40. package/.mcp/schemas/jules_create_session.json +5 -0
  41. package/.mcp/schemas/jules_get_messages.json +5 -0
  42. package/.mcp/schemas/jules_get_pr.json +5 -0
  43. package/.mcp/schemas/jules_get_session.json +5 -0
  44. package/.mcp/schemas/jules_list_sessions.json +5 -0
  45. package/.mcp/schemas/jules_send_message.json +5 -0
  46. package/.mcp/schemas/jules_trigger_feedback.json +5 -0
  47. package/.mcp/schemas/repo.commit_patch.json +5 -0
  48. package/.mcp/schemas/repo.create_branch.json +5 -0
  49. package/.mcp/schemas/repo.create_repair_branch.json +5 -0
  50. package/.mcp/schemas/repo.get_changed_files.json +5 -0
  51. package/.mcp/schemas/repo.get_command_schema.json +6 -1
  52. package/.mcp/schemas/repo.get_package_scripts.json +5 -0
  53. package/.mcp/schemas/repo.get_workflow_runs.json +55 -0
  54. package/.mcp/schemas/repo.logs.json +19 -0
  55. package/.mcp/schemas/repo.read_agent_context.json +5 -0
  56. package/.mcp/schemas/repo.read_ci_logs.json +19 -0
  57. package/.mcp/schemas/repo.run_tests.json +5 -0
  58. package/.mcp/schemas/repo_commit_patch.json +5 -0
  59. package/.mcp/schemas/repo_create_branch.json +5 -0
  60. package/.mcp/schemas/repo_create_repair_branch.json +5 -0
  61. package/.mcp/schemas/repo_get_changed_files.json +5 -0
  62. package/.mcp/schemas/repo_get_command_schema.json +6 -1
  63. package/.mcp/schemas/repo_get_package_scripts.json +5 -0
  64. package/.mcp/schemas/repo_get_workflow_runs.json +55 -0
  65. package/.mcp/schemas/repo_logs.json +19 -0
  66. package/.mcp/schemas/repo_read_agent_context.json +5 -0
  67. package/.mcp/schemas/repo_read_ci_logs.json +19 -0
  68. package/.mcp/schemas/repo_run_tests.json +5 -0
  69. package/CHANGELOG.md +14 -0
  70. package/README.md +0 -1
  71. package/actions/ai-review/action.yml +2 -2
  72. package/actions/audit/action.yml +1 -1
  73. package/actions/ci-validate/action.yml +2 -2
  74. package/actions/impact-analysis/action.yml +7 -19
  75. package/actions/run-project-gate/action.yml +7 -14
  76. package/actions/setup/action.yml +1 -1
  77. package/actions/test-build/action.yml +2 -20
  78. package/dist/config.js +1 -1
  79. package/dist/config.test.js +3 -3
  80. package/dist/lib/git.js +44 -0
  81. package/dist/lib/git.test.js +82 -0
  82. package/dist/lib/result.js +4 -0
  83. package/dist/lib/result.test.js +4 -2
  84. package/dist/lib/shell.js +6 -6
  85. package/dist/mcp/definitions.js +86 -38
  86. package/dist/mcp/http.js +91 -0
  87. package/dist/mcp/http.test.js +58 -0
  88. package/dist/mcp/server.js +51 -57
  89. package/dist/mcp/server.test.js +19 -32
  90. package/dist/tools/contract.js +244 -3
  91. package/dist/tools/github.checkout_branch.js +1 -1
  92. package/dist/tools/github.comment_triage_summary.js +1 -1
  93. package/dist/tools/github.create_issue.js +1 -1
  94. package/dist/tools/github.create_issue.test.js +6 -6
  95. package/dist/tools/github.create_pull_request.js +1 -1
  96. package/dist/tools/github.create_pull_request.test.js +4 -4
  97. package/dist/tools/github.get_merge_conflict_files.js +10 -18
  98. package/dist/tools/github.get_pr.js +1 -1
  99. package/dist/tools/github.get_pr_commits.js +21 -0
  100. package/dist/tools/github.get_pr_diff.js +1 -1
  101. package/dist/tools/github.get_pr_reviews.js +21 -0
  102. package/dist/tools/github.get_pr_reviews.test.js +99 -0
  103. package/dist/tools/github.issue_comment.js +1 -1
  104. package/dist/tools/github.issue_update.js +1 -1
  105. package/dist/tools/github.issue_view.js +1 -1
  106. package/dist/tools/github.search_open_prs.js +1 -1
  107. package/dist/tools/jules/cancel-session.js +1 -1
  108. package/dist/tools/jules/create-session.js +1 -2
  109. package/dist/tools/jules/create-session.test.js +11 -11
  110. package/dist/tools/jules/get-messages.js +1 -1
  111. package/dist/tools/jules/get-messages.test.js +3 -3
  112. package/dist/tools/jules/get-pr.js +1 -2
  113. package/dist/tools/jules/get-pr.test.js +3 -3
  114. package/dist/tools/jules/get-session.js +1 -2
  115. package/dist/tools/jules/list-sessions.js +1 -1
  116. package/dist/tools/jules/send-message.js +1 -1
  117. package/dist/tools/jules/send-message.test.js +5 -5
  118. package/dist/tools/jules/shared.js +24 -0
  119. package/dist/tools/jules/trigger-feedback.js +1 -1
  120. package/dist/tools/jules/trigger-feedback.test.js +5 -5
  121. package/dist/tools/repo.get_changed_files.js +2 -13
  122. package/dist/tools/repo.get_command_schema.js +2 -2
  123. package/dist/tools/repo.get_workflow_runs.js +29 -0
  124. package/dist/tools/repo.logs.js +5 -1
  125. package/dist/tools/repo.read_agent_context.js +27 -1
  126. package/dist/tools/repo.read_agent_context.test.js +1 -1
  127. package/dist/tools/repo.read_ci_logs.js +5 -1
  128. package/dist/tools/repo.run_tests.js +1 -1
  129. package/package.json +3 -6
  130. package/scripts/sync-mcp-schemas.ts +2 -0
  131. package/src/agents/verifier-agent.prompt.md +0 -4
  132. package/src/config.test.ts +3 -3
  133. package/src/config.ts +1 -1
  134. package/src/lib/git.test.ts +110 -0
  135. package/src/lib/git.ts +75 -0
  136. package/src/lib/result.test.ts +4 -2
  137. package/src/lib/result.ts +6 -0
  138. package/src/lib/shell.ts +6 -6
  139. package/src/mcp/definitions.ts +91 -42
  140. package/src/mcp/http.test.ts +72 -0
  141. package/src/mcp/http.ts +118 -0
  142. package/src/mcp/server.test.ts +20 -38
  143. package/src/mcp/server.ts +60 -54
  144. package/src/tools/contract.ts +256 -3
  145. package/src/tools/github.checkout_branch.ts +1 -1
  146. package/src/tools/github.comment_triage_summary.ts +1 -1
  147. package/src/tools/github.create_issue.test.ts +6 -6
  148. package/src/tools/github.create_issue.ts +1 -1
  149. package/src/tools/github.create_pull_request.test.ts +4 -4
  150. package/src/tools/github.create_pull_request.ts +1 -1
  151. package/src/tools/github.get_merge_conflict_files.ts +10 -20
  152. package/src/tools/github.get_pr.ts +1 -1
  153. package/src/tools/github.get_pr_commits.ts +27 -0
  154. package/src/tools/github.get_pr_diff.ts +1 -1
  155. package/src/tools/github.get_pr_reviews.test.ts +110 -0
  156. package/src/tools/github.get_pr_reviews.ts +27 -0
  157. package/src/tools/github.issue_comment.ts +1 -1
  158. package/src/tools/github.issue_update.ts +1 -1
  159. package/src/tools/github.issue_view.ts +1 -1
  160. package/src/tools/github.search_open_prs.ts +1 -1
  161. package/src/tools/jules/cancel-session.ts +1 -1
  162. package/src/tools/jules/create-session.test.ts +11 -11
  163. package/src/tools/jules/create-session.ts +1 -2
  164. package/src/tools/jules/get-messages.test.ts +3 -3
  165. package/src/tools/jules/get-messages.ts +1 -1
  166. package/src/tools/jules/get-pr.test.ts +3 -3
  167. package/src/tools/jules/get-pr.ts +1 -2
  168. package/src/tools/jules/get-session.ts +1 -2
  169. package/src/tools/jules/list-sessions.ts +1 -1
  170. package/src/tools/jules/send-message.test.ts +5 -5
  171. package/src/tools/jules/send-message.ts +1 -1
  172. package/src/tools/jules/shared.ts +35 -0
  173. package/src/tools/jules/trigger-feedback.test.ts +5 -5
  174. package/src/tools/jules/trigger-feedback.ts +1 -1
  175. package/src/tools/repo.get_changed_files.ts +2 -16
  176. package/src/tools/repo.get_command_schema.ts +2 -2
  177. package/src/tools/repo.get_workflow_runs.ts +36 -0
  178. package/src/tools/repo.logs.ts +5 -1
  179. package/src/tools/repo.read_agent_context.test.ts +1 -1
  180. package/src/tools/repo.read_agent_context.ts +35 -1
  181. package/src/tools/repo.read_ci_logs.ts +5 -1
  182. package/src/tools/repo.run_tests.ts +1 -1
  183. package/.mcp/schemas/agent.search_ddgs.json +0 -31
  184. package/.mcp/schemas/agent_search_ddgs.json +0 -31
  185. package/.mcp/schemas/repo.get_route_map.json +0 -23
  186. package/.mcp/schemas/repo.run_lighthouse.json +0 -29
  187. package/.mcp/schemas/repo.run_playwright.json +0 -36
  188. package/.mcp/schemas/repo_get_route_map.json +0 -23
  189. package/.mcp/schemas/repo_run_lighthouse.json +0 -29
  190. package/.mcp/schemas/repo_run_playwright.json +0 -36
  191. package/dist/lib/td-cli.js +0 -54
  192. package/dist/tools/ddgs.search.js +0 -50
  193. package/dist/tools/ddgs.search.test.js +0 -67
  194. package/dist/tools/ddgs_search.py +0 -23
  195. package/dist/tools/repo.get_route_map.js +0 -37
  196. package/dist/tools/repo.run_lighthouse.js +0 -37
  197. package/dist/tools/repo.run_playwright.js +0 -34
  198. package/scripts/export-mcp-schema.ts +0 -7
  199. package/src/lib/td-cli.ts +0 -73
  200. package/src/tools/ddgs.search.test.ts +0 -92
  201. package/src/tools/ddgs.search.ts +0 -58
  202. package/src/tools/ddgs_search.py +0 -23
  203. package/src/tools/repo.get_route_map.ts +0 -41
  204. package/src/tools/repo.run_lighthouse.ts +0 -40
  205. package/src/tools/repo.run_playwright.ts +0 -42
@@ -0,0 +1,27 @@
1
+ import { z } from "zod";
2
+ import { runCommand } from "../lib/shell.js";
3
+ import { resolveRepo } from "../lib/git.js";
4
+ import { sanitizeError } from "../lib/error_utils.js";
5
+
6
+ const GetPrReviewsInputSchema = z.object({
7
+ prNumber: z.number().describe("The number of the PR to view reviews for."),
8
+ repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
9
+ });
10
+
11
+ export async function getPrReviewsHandler(args: z.infer<typeof GetPrReviewsInputSchema>) {
12
+ const params = GetPrReviewsInputSchema.parse(args);
13
+ const targetRepo = resolveRepo(params.repo);
14
+
15
+ const result = await runCommand("td", ["gh", "read-pr-reviews", "--pr-number", params.prNumber.toString(), "--repo", targetRepo]);
16
+
17
+ if (result.exitCode !== 0) {
18
+ throw new Error(`Failed to read PR reviews: ${sanitizeError(result.stderr)}`);
19
+ }
20
+
21
+ const output = JSON.parse(result.stdout);
22
+ if (output.status === "error") {
23
+ throw new Error(`Failed to read PR reviews: ${output.message}`);
24
+ }
25
+
26
+ return { reviews: output.reviews, reviewCount: output.review_count };
27
+ }
@@ -19,7 +19,7 @@ export async function issueCommentHandler(args: z.infer<typeof IssueCommentInput
19
19
  const params = IssueCommentInputSchema.parse(args);
20
20
  const targetRepo = resolveRepo(params.repo);
21
21
 
22
- const result = await runCommand("td-cli", [
22
+ const result = await runCommand("td", [
23
23
  "gh", "issue-comment", params.issueNumber.toString(),
24
24
  "--body", params.body,
25
25
  "--repo", targetRepo
@@ -19,7 +19,7 @@ export async function issueUpdateHandler(args: z.infer<typeof IssueUpdateInputSc
19
19
  if (params.state) cmdArgs.push("--state", params.state);
20
20
  cmdArgs.push("--repo", targetRepo);
21
21
 
22
- const result = await runCommand("td-cli", cmdArgs);
22
+ const result = await runCommand("td", cmdArgs);
23
23
 
24
24
  if (result.exitCode !== 0) {
25
25
  throw new Error(`Failed to update issue: ${sanitizeError(result.stderr)}`);
@@ -23,7 +23,7 @@ export async function issueViewHandler(args: z.infer<typeof IssueViewInputSchema
23
23
  const params = IssueViewInputSchema.parse(args);
24
24
  const targetRepo = resolveRepo(params.repo);
25
25
 
26
- const result = await runCommand("td-cli", ["gh", "issue-view", params.issueNumber.toString(), "--repo", targetRepo]);
26
+ const result = await runCommand("td", ["gh", "issue-view", params.issueNumber.toString(), "--repo", targetRepo]);
27
27
 
28
28
  if (result.exitCode !== 0) {
29
29
  throw new Error(`Failed to view issue: ${sanitizeError(result.stderr)}`);
@@ -29,7 +29,7 @@ export async function searchOpenPrsHandler(args: z.infer<typeof SearchOpenPrsInp
29
29
  tdArgs.push("--labels", params.labels.join(","));
30
30
  }
31
31
 
32
- const result = await runCommand("td-cli", tdArgs);
32
+ const result = await runCommand("td", tdArgs);
33
33
 
34
34
  if (result.exitCode !== 0) {
35
35
  throw new Error(`Failed to list PRs: ${result.stderr}`);
@@ -7,7 +7,7 @@ export const CancelJulesSessionInputSchema = z.object({
7
7
  });
8
8
 
9
9
  export async function cancelJulesSessionHandler(input: z.infer<typeof CancelJulesSessionInputSchema>): Promise<JulesSession> {
10
- const result = await runCommand("td-cli", ["agent", "cancel", input.sessionId]);
10
+ const result = await runCommand("td", ["agent", "cancel", input.sessionId]);
11
11
 
12
12
  if (result.exitCode !== 0) {
13
13
  throw new Error(`Failed to cancel session: ${result.stderr}`);
@@ -20,7 +20,7 @@ describe("createJulesSessionHandler", () => {
20
20
  stderr: "",
21
21
  exitCode: 0,
22
22
  durationMs: 10,
23
- command: "td-cli agent dispatch"
23
+ command: "td agent dispatch"
24
24
  });
25
25
  });
26
26
 
@@ -35,7 +35,7 @@ describe("createJulesSessionHandler", () => {
35
35
  expect(result.status).toBe("IN_PROGRESS");
36
36
  expect(result.createdAt).toBeInstanceOf(Date);
37
37
 
38
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
38
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
39
39
  "agent", "dispatch", "main", "do work"
40
40
  ]);
41
41
  });
@@ -44,7 +44,7 @@ describe("createJulesSessionHandler", () => {
44
44
  const result = await createJulesSessionHandler({ task: "do work", branch: "feature-x" });
45
45
  expect(result.id).toBe("1234567890");
46
46
 
47
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
47
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
48
48
  "agent", "dispatch", "feature-x", "do work"
49
49
  ]);
50
50
  });
@@ -57,7 +57,7 @@ describe("createJulesSessionHandler", () => {
57
57
  stderr: "",
58
58
  exitCode: 0,
59
59
  durationMs: 10,
60
- command: "td-cli gh view"
60
+ command: "td gh view"
61
61
  };
62
62
  }
63
63
  return {
@@ -70,18 +70,18 @@ describe("createJulesSessionHandler", () => {
70
70
  stderr: "",
71
71
  exitCode: 0,
72
72
  durationMs: 10,
73
- command: "td-cli agent dispatch"
73
+ command: "td agent dispatch"
74
74
  };
75
75
  });
76
76
 
77
77
  const result = await createJulesSessionHandler({ task: "do work", pr: 42 });
78
78
  expect(result.id).toBe("1234567890");
79
79
 
80
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
80
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
81
81
  "gh", "view", "42"
82
82
  ]);
83
83
 
84
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
84
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
85
85
  "agent", "dispatch", "pr-branch", "do work"
86
86
  ]);
87
87
  });
@@ -92,11 +92,11 @@ describe("createJulesSessionHandler", () => {
92
92
  stderr: "Original error",
93
93
  exitCode: 1,
94
94
  durationMs: 10,
95
- command: "td-cli gh view"
95
+ command: "td gh view"
96
96
  });
97
97
 
98
98
  await expect(createJulesSessionHandler({ task: "do work", pr: 999 }))
99
- .rejects.toThrow("td-cli returned error: PR not found");
99
+ .rejects.toThrow("td returned error: PR not found");
100
100
  });
101
101
 
102
102
  it("should throw descriptive error if PR JSON is invalid", async () => {
@@ -105,10 +105,10 @@ describe("createJulesSessionHandler", () => {
105
105
  stderr: "",
106
106
  exitCode: 0,
107
107
  durationMs: 10,
108
- command: "td-cli gh view"
108
+ command: "td gh view"
109
109
  });
110
110
 
111
111
  await expect(createJulesSessionHandler({ task: "do work", pr: 42 }))
112
- .rejects.toThrow("td-cli returned non-JSON output with exit code 0: invalid json");
112
+ .rejects.toThrow("td returned non-JSON output with exit code 0: invalid json");
113
113
  });
114
114
  });
@@ -1,6 +1,5 @@
1
1
  import { z } from "zod";
2
- import { runTDCli } from "../../lib/td-cli.js";
3
- import { parseJulesSession } from "./shared.js";
2
+ import { runTDCli, parseJulesSession } from "./shared.js";
4
3
 
5
4
  export const CreateJulesSessionInputSchema = z.object({
6
5
  task: z.string(),
@@ -17,7 +17,7 @@ describe("getJulesMessagesHandler", () => {
17
17
  vi.clearAllMocks();
18
18
  });
19
19
 
20
- it("should return messages from td-cli", async () => {
20
+ it("should return messages from td", async () => {
21
21
  const mockMessages = [
22
22
  {
23
23
  role: "user",
@@ -36,7 +36,7 @@ describe("getJulesMessagesHandler", () => {
36
36
  stderr: "",
37
37
  exitCode: 0,
38
38
  durationMs: 0,
39
- command: "td-cli agent messages"
39
+ command: "td agent messages"
40
40
  });
41
41
 
42
42
  const result = await getJulesMessagesHandler({ sessionId: "123" });
@@ -45,7 +45,7 @@ describe("getJulesMessagesHandler", () => {
45
45
  expect(result.messages[0].role).toBe("user");
46
46
  expect(result.messages[0].content).toBe("Hello Jules");
47
47
 
48
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
48
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
49
49
  "agent", "messages", "123"
50
50
  ]);
51
51
  });
@@ -6,7 +6,7 @@ export const GetJulesMessagesInputSchema = z.object({
6
6
  });
7
7
 
8
8
  export async function getJulesMessagesHandler(input: z.infer<typeof GetJulesMessagesInputSchema>) {
9
- const result = await runCommand("td-cli", ["agent", "messages", input.sessionId]);
9
+ const result = await runCommand("td", ["agent", "messages", input.sessionId]);
10
10
 
11
11
  if (result.exitCode !== 0) {
12
12
  throw new Error(`Failed to get messages: ${result.stderr}`);
@@ -17,7 +17,7 @@ describe("getJulesPullRequestHandler", () => {
17
17
  vi.clearAllMocks();
18
18
  });
19
19
 
20
- it("should get PR from td-cli", async () => {
20
+ it("should get PR from td", async () => {
21
21
  vi.mocked(shell.runCommand).mockResolvedValue({
22
22
  stdout: JSON.stringify({
23
23
  status: "success",
@@ -29,14 +29,14 @@ describe("getJulesPullRequestHandler", () => {
29
29
  stderr: "",
30
30
  exitCode: 0,
31
31
  durationMs: 0,
32
- command: "td-cli agent get-session"
32
+ command: "td agent get-session"
33
33
  });
34
34
 
35
35
  const result = await getJulesPullRequestHandler({ sessionId: "123" });
36
36
  expect(result.id).toBe("123");
37
37
  expect(result.pullRequestUrl).toBe("https://github.com/pr/1");
38
38
 
39
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
39
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
40
40
  "agent", "get-session", "123"
41
41
  ]);
42
42
  });
@@ -1,6 +1,5 @@
1
1
  import { z } from "zod";
2
- import { runTDCli } from "../../lib/td-cli.js";
3
- import { parseJulesSession } from "./shared.js";
2
+ import { runTDCli, parseJulesSession } from "./shared.js";
4
3
 
5
4
  export const GetJulesPullRequestInputSchema = z.object({
6
5
  sessionId: z.string(),
@@ -1,6 +1,5 @@
1
1
  import { z } from "zod";
2
- import { runTDCli } from "../../lib/td-cli.js";
3
- import { parseJulesSession } from "./shared.js";
2
+ import { runTDCli, parseJulesSession } from "./shared.js";
4
3
 
5
4
  export const GetJulesSessionInputSchema = z.object({
6
5
  sessionId: z.string(),
@@ -8,7 +8,7 @@ export const ListJulesSessionsInputSchema = z.object({
8
8
  });
9
9
 
10
10
  export async function listJulesSessionsHandler(input: z.infer<typeof ListJulesSessionsInputSchema>): Promise<JulesSession[]> {
11
- const result = await runCommand("td-cli", ["agent", "sync"]);
11
+ const result = await runCommand("td", ["agent", "sync"]);
12
12
 
13
13
  if (result.exitCode !== 0) {
14
14
  throw new Error(`Failed to list sessions: ${result.stderr}`);
@@ -17,20 +17,20 @@ describe("sendJulesMessageHandler", () => {
17
17
  vi.clearAllMocks();
18
18
  });
19
19
 
20
- it("should send a message via td-cli", async () => {
20
+ it("should send a message via td", async () => {
21
21
  vi.mocked(shell.runCommand).mockResolvedValue({
22
22
  stdout: JSON.stringify({ status: "success", message: "Message sent successfully" }),
23
23
  stderr: "",
24
24
  exitCode: 0,
25
25
  durationMs: 0,
26
- command: "td-cli agent send"
26
+ command: "td agent send"
27
27
  });
28
28
 
29
29
  const result = await sendJulesMessageHandler({ sessionId: "123", message: "hi" });
30
30
  expect(result.id).toBe("123");
31
31
  expect(result.status).toBe("success");
32
32
 
33
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
33
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
34
34
  "agent", "send", "123", "hi"
35
35
  ]);
36
36
  });
@@ -48,7 +48,7 @@ describe("sendJulesMessageHandler", () => {
48
48
  stderr: "",
49
49
  exitCode: 0,
50
50
  durationMs: 0,
51
- command: "td-cli agent send"
51
+ command: "td agent send"
52
52
  });
53
53
 
54
54
  const result = await sendJulesMessageHandler({
@@ -59,7 +59,7 @@ describe("sendJulesMessageHandler", () => {
59
59
  expect(result.id).toEqual(["s1", "s2"]);
60
60
  expect(result.status).toBe("success");
61
61
 
62
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
62
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
63
63
  "agent", "send", "sessions/s1,sessions/s2", "hi batch"
64
64
  ]);
65
65
  });
@@ -8,7 +8,7 @@ export const SendJulesMessageInputSchema = z.object({
8
8
 
9
9
  export async function sendJulesMessageHandler(input: z.infer<typeof SendJulesMessageInputSchema>) {
10
10
  const sessionIds = Array.isArray(input.sessionId) ? input.sessionId.join(",") : input.sessionId;
11
- const result = await runCommand("td-cli", ["agent", "send", sessionIds, input.message]);
11
+ const result = await runCommand("td", ["agent", "send", sessionIds, input.message]);
12
12
 
13
13
  if (result.exitCode !== 0) {
14
14
  throw new Error(`Failed to send message: ${result.stderr}`);
@@ -1,4 +1,39 @@
1
1
  import { JulesSession, JulesStatus } from "../types.js";
2
+ import { runCommand } from "../../lib/shell.js";
3
+
4
+ export interface TDCliResponse {
5
+ status?: string;
6
+ message?: string;
7
+ [key: string]: any;
8
+ }
9
+
10
+ function tryParseJson(text: string): TDCliResponse | null {
11
+ try {
12
+ return JSON.parse(text) as TDCliResponse;
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+
18
+ export async function runTDCli(args: string[]): Promise<TDCliResponse> {
19
+ const result = await runCommand("td", args);
20
+ const stdout = result.stdout.trim();
21
+ const output = stdout.startsWith("{") ? tryParseJson(stdout) : null;
22
+
23
+ if (output?.status === "error") {
24
+ throw new Error(`td returned error: ${output.message ?? "Unknown error"}`);
25
+ }
26
+
27
+ if (result.exitCode !== 0) {
28
+ throw new Error(`td command failed (${args.join(" ")}): ${result.stderr || stdout}`);
29
+ }
30
+
31
+ if (!output) {
32
+ throw new Error(`td returned non-JSON output with exit code 0: ${stdout}`);
33
+ }
34
+
35
+ return output;
36
+ }
2
37
 
3
38
  export function parseJulesSession(data: any): JulesSession {
4
39
  const name = data.name || "";
@@ -17,31 +17,31 @@ describe("triggerJulesFeedbackHandler", () => {
17
17
  vi.clearAllMocks();
18
18
  });
19
19
 
20
- it("should return success output from td-cli", async () => {
20
+ it("should return success output from td", async () => {
21
21
  vi.mocked(shell.runCommand).mockResolvedValue({
22
22
  stdout: JSON.stringify({ status: "success", feedback: "All checks passed successfully. You may proceed." }),
23
23
  stderr: "",
24
24
  exitCode: 0,
25
25
  durationMs: 0,
26
- command: "td-cli agent trigger-feedback"
26
+ command: "td agent trigger-feedback"
27
27
  });
28
28
 
29
29
  const result = await triggerJulesFeedbackHandler({ sessionId: "123" });
30
30
  expect(result.status).toBe("success");
31
31
  expect(result.feedback).toBe("All checks passed successfully. You may proceed.");
32
32
 
33
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
33
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
34
34
  "agent", "trigger-feedback", "123"
35
35
  ]);
36
36
  });
37
37
 
38
- it("should throw error if td-cli returns error", async () => {
38
+ it("should throw error if td returns error", async () => {
39
39
  vi.mocked(shell.runCommand).mockResolvedValue({
40
40
  stdout: JSON.stringify({ status: "error", message: "Session not found" }),
41
41
  stderr: "",
42
42
  exitCode: 0,
43
43
  durationMs: 0,
44
- command: "td-cli agent trigger-feedback"
44
+ command: "td agent trigger-feedback"
45
45
  });
46
46
 
47
47
  await expect(triggerJulesFeedbackHandler({ sessionId: "123" }))
@@ -6,7 +6,7 @@ export const TriggerJulesFeedbackInputSchema = z.object({
6
6
  });
7
7
 
8
8
  export async function triggerJulesFeedbackHandler(input: z.infer<typeof TriggerJulesFeedbackInputSchema>) {
9
- const result = await runCommand("td-cli", ["agent", "trigger-feedback", input.sessionId]);
9
+ const result = await runCommand("td", ["agent", "trigger-feedback", input.sessionId]);
10
10
 
11
11
  if (result.exitCode !== 0) {
12
12
  throw new Error(`Failed to trigger feedback: ${result.stderr}`);
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { runCommand } from "../lib/shell.js";
2
+ import { getChangedFiles } from "../lib/git.js";
3
3
 
4
4
  export const GetChangedFilesInputSchema = z.object({
5
5
  base: z.string().optional().default("main"),
@@ -7,20 +7,6 @@ export const GetChangedFilesInputSchema = z.object({
7
7
  });
8
8
 
9
9
  export async function getChangedFilesHandler(args: z.infer<typeof GetChangedFilesInputSchema>) {
10
- const result = await runCommand("git", [
11
- "diff",
12
- "--name-status",
13
- `${args.base}...${args.head}`
14
- ]);
15
-
16
- if (result.exitCode !== 0) {
17
- throw new Error(`Failed to get changed files: ${result.stderr}`);
18
- }
19
-
20
- const files = result.stdout.trim().split("\n").filter(line => line.length > 0).map(line => {
21
- const [status, path] = line.split(/\s+/);
22
- return { status, path };
23
- });
24
-
10
+ const files = await getChangedFiles(args.base || "main", args.head || "HEAD");
25
11
  return { files };
26
12
  }
@@ -8,12 +8,12 @@ export const GetCommandSchemaInputSchema = z.object({
8
8
  export async function getCommandSchemaHandler(args: z.infer<typeof GetCommandSchemaInputSchema>) {
9
9
  // Sanitize input to prevent command injection (allow only alphanumeric, spaces, hyphens, and underscores)
10
10
  const sanitizedPath = args.commandPath.replace(/[^a-zA-Z0-9-_ ]/g, "");
11
- const result = await runCommand("td-cli", ["schema", sanitizedPath]);
11
+ const result = await runCommand("td", ["schema", sanitizedPath]);
12
12
 
13
13
  if (result.exitCode !== 0) {
14
14
  // Log stderr for debugging but don't expose it to the user
15
15
  // Using comma-separated arguments to satisfy semgrep unsafe-formatstring
16
- console.error("td-cli schema failed for", sanitizedPath, ":", result.stderr);
16
+ console.error("td schema failed for", sanitizedPath, ":", result.stderr);
17
17
  throw new Error(`Failed to get command schema for '${sanitizedPath}'`);
18
18
  }
19
19
 
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ import { runCommand } from "../lib/shell.js";
3
+ import { resolveRepo } from "../lib/git.js";
4
+ import { sanitizeError } from "../lib/error_utils.js";
5
+
6
+ const GetWorkflowRunsInputSchema = z.object({
7
+ branch: z.string().optional().describe("Filter workflow runs by branch name."),
8
+ event: z.string().optional().describe("Filter workflow runs by event (e.g. push, pull_request)."),
9
+ repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
10
+ });
11
+
12
+ export async function getWorkflowRunsHandler(args: z.infer<typeof GetWorkflowRunsInputSchema>) {
13
+ const params = GetWorkflowRunsInputSchema.parse(args);
14
+ const targetRepo = resolveRepo(params.repo);
15
+
16
+ const cliArgs = ["repo", "workflow-runs", "--repo", targetRepo];
17
+ if (params.branch) {
18
+ cliArgs.push("--branch", params.branch);
19
+ }
20
+ if (params.event) {
21
+ cliArgs.push("--event", params.event);
22
+ }
23
+
24
+ const result = await runCommand("td", cliArgs);
25
+
26
+ if (result.exitCode !== 0) {
27
+ throw new Error(`Failed to fetch workflow runs: ${sanitizeError(result.stderr)}`);
28
+ }
29
+
30
+ const output = JSON.parse(result.stdout);
31
+ if (output.status === "error") {
32
+ throw new Error(`Failed to fetch workflow runs: ${output.message}`);
33
+ }
34
+
35
+ return { workflowRuns: output.workflow_runs };
36
+ }
@@ -1,9 +1,10 @@
1
1
  import { z } from "zod";
2
- import { runTDCli } from "../lib/td-cli.js";
2
+ import { runTDCli } from "./jules/shared.js";
3
3
 
4
4
  export const RepoLogsInputSchema = z.object({
5
5
  prNumber: z.number(),
6
6
  grep: z.string().optional(),
7
+ repo: z.string().optional(),
7
8
  });
8
9
 
9
10
  export async function repoLogsHandler(args: z.infer<typeof RepoLogsInputSchema>) {
@@ -12,6 +13,9 @@ export async function repoLogsHandler(args: z.infer<typeof RepoLogsInputSchema>)
12
13
  if (args.grep) {
13
14
  params.push("--grep", args.grep);
14
15
  }
16
+ if (args.repo) {
17
+ params.push("--repo", args.repo);
18
+ }
15
19
 
16
20
  const output = await runTDCli(params);
17
21
 
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { loadStandaloneAgentContext } from "../lib/td-cli.js";
2
+ import { loadStandaloneAgentContext } from "./repo.read_agent_context.js";
3
3
 
4
4
  describe("Standalone Agent Context Loader", () => {
5
5
  it("should load agent context without submodule references", () => {
@@ -1,6 +1,40 @@
1
1
  import { z } from "zod";
2
2
  import { config } from "../config.js";
3
- import { loadStandaloneAgentContext } from "../lib/td-cli.js";
3
+ import { execSync } from "child_process";
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+
7
+ export interface AgentContext {
8
+ packageName: string;
9
+ gitCommit: string;
10
+ config: Record<string, unknown>;
11
+ }
12
+
13
+ export const loadStandaloneAgentContext = (repoRoot: string = process.cwd()): AgentContext => {
14
+ const configPath = path.join(repoRoot, "project_config.json");
15
+ let projectConfig: Record<string, unknown> = {};
16
+
17
+ if (fs.existsSync(configPath)) {
18
+ try {
19
+ projectConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
20
+ } catch (e) {
21
+ console.warn(`[MCP Warning] Failed to parse ${configPath}:`, e);
22
+ }
23
+ }
24
+
25
+ let gitCommit = "unknown";
26
+ try {
27
+ gitCommit = execSync("git rev-parse HEAD", { cwd: repoRoot, encoding: "utf-8" }).trim();
28
+ } catch {
29
+ // Fallback if git is unavailable
30
+ }
31
+
32
+ return {
33
+ packageName: (projectConfig.packageName as string) ?? "boomtick",
34
+ gitCommit,
35
+ config: projectConfig,
36
+ };
37
+ };
4
38
 
5
39
  export const ReadAgentContextInputSchema = z.object({});
6
40
 
@@ -1,9 +1,10 @@
1
1
  import { z } from "zod";
2
- import { runTDCli } from "../lib/td-cli.js";
2
+ import { runTDCli } from "./jules/shared.js";
3
3
 
4
4
  export const ReadCiLogsInputSchema = z.object({
5
5
  prNumber: z.number(),
6
6
  all: z.boolean().optional(),
7
+ repo: z.string().optional(),
7
8
  });
8
9
 
9
10
  export async function readCiLogsHandler(args: z.infer<typeof ReadCiLogsInputSchema>) {
@@ -11,6 +12,9 @@ export async function readCiLogsHandler(args: z.infer<typeof ReadCiLogsInputSche
11
12
  if (args.all) {
12
13
  params.push("--all");
13
14
  }
15
+ if (args.repo) {
16
+ params.push("--repo", args.repo);
17
+ }
14
18
  const output = await runTDCli(params);
15
19
 
16
20
  return {
@@ -9,7 +9,7 @@ export const RunTestsInputSchema = z.object({
9
9
 
10
10
  export type RunTestsInput = z.input<typeof RunTestsInputSchema>;
11
11
 
12
- export function parseCommandArguments(fullCmd: string): [string, string[]] {
12
+ function parseCommandArguments(fullCmd: string): [string, string[]] {
13
13
  const tokens: string[] = [];
14
14
  const regex = /"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|(\S+)/g;
15
15
  let match: RegExpExecArray | null;
@@ -1,31 +0,0 @@
1
- {
2
- "name": "agent.search_ddgs",
3
- "description": "Search the web using DuckDuckGo (via ddgs python library).",
4
- "parameters": {
5
- "properties": {
6
- "query": {
7
- "description": "The search query.",
8
- "title": "Query",
9
- "type": "string"
10
- },
11
- "maxResults": {
12
- "anyOf": [
13
- {
14
- "type": "integer"
15
- },
16
- {
17
- "type": "null"
18
- }
19
- ],
20
- "default": null,
21
- "description": "Maximum number of results to return.",
22
- "title": "Maxresults"
23
- }
24
- },
25
- "required": [
26
- "query"
27
- ],
28
- "title": "SearchDdgsInput",
29
- "type": "object"
30
- }
31
- }
@@ -1,31 +0,0 @@
1
- {
2
- "name": "agent_search_ddgs",
3
- "description": "Search the web using DuckDuckGo (via ddgs python library).",
4
- "parameters": {
5
- "properties": {
6
- "query": {
7
- "description": "The search query.",
8
- "title": "Query",
9
- "type": "string"
10
- },
11
- "maxResults": {
12
- "anyOf": [
13
- {
14
- "type": "integer"
15
- },
16
- {
17
- "type": "null"
18
- }
19
- ],
20
- "default": null,
21
- "description": "Maximum number of results to return.",
22
- "title": "Maxresults"
23
- }
24
- },
25
- "required": [
26
- "query"
27
- ],
28
- "title": "SearchDdgsInput",
29
- "type": "object"
30
- }
31
- }