@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
@@ -15,7 +15,7 @@ const IssueCommentOutputSchema = z.object({
15
15
  export async function issueCommentHandler(args) {
16
16
  const params = IssueCommentInputSchema.parse(args);
17
17
  const targetRepo = resolveRepo(params.repo);
18
- const result = await runCommand("td-cli", [
18
+ const result = await runCommand("td", [
19
19
  "gh", "issue-comment", params.issueNumber.toString(),
20
20
  "--body", params.body,
21
21
  "--repo", targetRepo
@@ -20,7 +20,7 @@ export async function issueUpdateHandler(args) {
20
20
  if (params.state)
21
21
  cmdArgs.push("--state", params.state);
22
22
  cmdArgs.push("--repo", targetRepo);
23
- const result = await runCommand("td-cli", cmdArgs);
23
+ const result = await runCommand("td", cmdArgs);
24
24
  if (result.exitCode !== 0) {
25
25
  throw new Error(`Failed to update issue: ${sanitizeError(result.stderr)}`);
26
26
  }
@@ -19,7 +19,7 @@ const IssueViewOutputSchema = z.object({
19
19
  export async function issueViewHandler(args) {
20
20
  const params = IssueViewInputSchema.parse(args);
21
21
  const targetRepo = resolveRepo(params.repo);
22
- const result = await runCommand("td-cli", ["gh", "issue-view", params.issueNumber.toString(), "--repo", targetRepo]);
22
+ const result = await runCommand("td", ["gh", "issue-view", params.issueNumber.toString(), "--repo", targetRepo]);
23
23
  if (result.exitCode !== 0) {
24
24
  throw new Error(`Failed to view issue: ${sanitizeError(result.stderr)}`);
25
25
  }
@@ -23,7 +23,7 @@ export async function searchOpenPrsHandler(args) {
23
23
  if (params.labels && params.labels.length > 0) {
24
24
  tdArgs.push("--labels", params.labels.join(","));
25
25
  }
26
- const result = await runCommand("td-cli", tdArgs);
26
+ const result = await runCommand("td", tdArgs);
27
27
  if (result.exitCode !== 0) {
28
28
  throw new Error(`Failed to list PRs: ${result.stderr}`);
29
29
  }
@@ -4,7 +4,7 @@ export const CancelJulesSessionInputSchema = z.object({
4
4
  sessionId: z.string(),
5
5
  });
6
6
  export async function cancelJulesSessionHandler(input) {
7
- const result = await runCommand("td-cli", ["agent", "cancel", input.sessionId]);
7
+ const result = await runCommand("td", ["agent", "cancel", input.sessionId]);
8
8
  if (result.exitCode !== 0) {
9
9
  throw new Error(`Failed to cancel session: ${result.stderr}`);
10
10
  }
@@ -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
  export const CreateJulesSessionInputSchema = z.object({
5
4
  task: z.string(),
6
5
  branch: z.string().optional(),
@@ -18,7 +18,7 @@ describe("createJulesSessionHandler", () => {
18
18
  stderr: "",
19
19
  exitCode: 0,
20
20
  durationMs: 10,
21
- command: "td-cli agent dispatch"
21
+ command: "td agent dispatch"
22
22
  });
23
23
  });
24
24
  afterEach(() => {
@@ -30,14 +30,14 @@ describe("createJulesSessionHandler", () => {
30
30
  expect(result.id).toBe("1234567890");
31
31
  expect(result.status).toBe("IN_PROGRESS");
32
32
  expect(result.createdAt).toBeInstanceOf(Date);
33
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
33
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
34
34
  "agent", "dispatch", "main", "do work"
35
35
  ]);
36
36
  });
37
37
  it("should create a session with specific branch", async () => {
38
38
  const result = await createJulesSessionHandler({ task: "do work", branch: "feature-x" });
39
39
  expect(result.id).toBe("1234567890");
40
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
40
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
41
41
  "agent", "dispatch", "feature-x", "do work"
42
42
  ]);
43
43
  });
@@ -49,7 +49,7 @@ describe("createJulesSessionHandler", () => {
49
49
  stderr: "",
50
50
  exitCode: 0,
51
51
  durationMs: 10,
52
- command: "td-cli gh view"
52
+ command: "td gh view"
53
53
  };
54
54
  }
55
55
  return {
@@ -62,15 +62,15 @@ describe("createJulesSessionHandler", () => {
62
62
  stderr: "",
63
63
  exitCode: 0,
64
64
  durationMs: 10,
65
- command: "td-cli agent dispatch"
65
+ command: "td agent dispatch"
66
66
  };
67
67
  });
68
68
  const result = await createJulesSessionHandler({ task: "do work", pr: 42 });
69
69
  expect(result.id).toBe("1234567890");
70
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
70
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
71
71
  "gh", "view", "42"
72
72
  ]);
73
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
73
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
74
74
  "agent", "dispatch", "pr-branch", "do work"
75
75
  ]);
76
76
  });
@@ -80,10 +80,10 @@ describe("createJulesSessionHandler", () => {
80
80
  stderr: "Original error",
81
81
  exitCode: 1,
82
82
  durationMs: 10,
83
- command: "td-cli gh view"
83
+ command: "td gh view"
84
84
  });
85
85
  await expect(createJulesSessionHandler({ task: "do work", pr: 999 }))
86
- .rejects.toThrow("td-cli returned error: PR not found");
86
+ .rejects.toThrow("td returned error: PR not found");
87
87
  });
88
88
  it("should throw descriptive error if PR JSON is invalid", async () => {
89
89
  vi.mocked(shell.runCommand).mockResolvedValue({
@@ -91,9 +91,9 @@ describe("createJulesSessionHandler", () => {
91
91
  stderr: "",
92
92
  exitCode: 0,
93
93
  durationMs: 10,
94
- command: "td-cli gh view"
94
+ command: "td gh view"
95
95
  });
96
96
  await expect(createJulesSessionHandler({ task: "do work", pr: 42 }))
97
- .rejects.toThrow("td-cli returned non-JSON output with exit code 0: invalid json");
97
+ .rejects.toThrow("td returned non-JSON output with exit code 0: invalid json");
98
98
  });
99
99
  });
@@ -4,7 +4,7 @@ export const GetJulesMessagesInputSchema = z.object({
4
4
  sessionId: z.string(),
5
5
  });
6
6
  export async function getJulesMessagesHandler(input) {
7
- const result = await runCommand("td-cli", ["agent", "messages", input.sessionId]);
7
+ const result = await runCommand("td", ["agent", "messages", input.sessionId]);
8
8
  if (result.exitCode !== 0) {
9
9
  throw new Error(`Failed to get messages: ${result.stderr}`);
10
10
  }
@@ -13,7 +13,7 @@ describe("getJulesMessagesHandler", () => {
13
13
  teardownTestEnv();
14
14
  vi.clearAllMocks();
15
15
  });
16
- it("should return messages from td-cli", async () => {
16
+ it("should return messages from td", async () => {
17
17
  const mockMessages = [
18
18
  {
19
19
  role: "user",
@@ -31,14 +31,14 @@ describe("getJulesMessagesHandler", () => {
31
31
  stderr: "",
32
32
  exitCode: 0,
33
33
  durationMs: 0,
34
- command: "td-cli agent messages"
34
+ command: "td agent messages"
35
35
  });
36
36
  const result = await getJulesMessagesHandler({ sessionId: "123" });
37
37
  expect(result.id).toBe("123");
38
38
  expect(result.messages.length).toBe(2);
39
39
  expect(result.messages[0].role).toBe("user");
40
40
  expect(result.messages[0].content).toBe("Hello Jules");
41
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
41
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
42
42
  "agent", "messages", "123"
43
43
  ]);
44
44
  });
@@ -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
  export const GetJulesPullRequestInputSchema = z.object({
5
4
  sessionId: z.string(),
6
5
  });
@@ -13,7 +13,7 @@ describe("getJulesPullRequestHandler", () => {
13
13
  teardownTestEnv();
14
14
  vi.clearAllMocks();
15
15
  });
16
- it("should get PR from td-cli", async () => {
16
+ it("should get PR from td", async () => {
17
17
  vi.mocked(shell.runCommand).mockResolvedValue({
18
18
  stdout: JSON.stringify({
19
19
  status: "success",
@@ -25,12 +25,12 @@ describe("getJulesPullRequestHandler", () => {
25
25
  stderr: "",
26
26
  exitCode: 0,
27
27
  durationMs: 0,
28
- command: "td-cli agent get-session"
28
+ command: "td agent get-session"
29
29
  });
30
30
  const result = await getJulesPullRequestHandler({ sessionId: "123" });
31
31
  expect(result.id).toBe("123");
32
32
  expect(result.pullRequestUrl).toBe("https://github.com/pr/1");
33
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
33
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
34
34
  "agent", "get-session", "123"
35
35
  ]);
36
36
  });
@@ -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
  export const GetJulesSessionInputSchema = z.object({
5
4
  sessionId: z.string(),
6
5
  });
@@ -5,7 +5,7 @@ export const ListJulesSessionsInputSchema = z.object({
5
5
  pageToken: z.string().optional(),
6
6
  });
7
7
  export async function listJulesSessionsHandler(input) {
8
- const result = await runCommand("td-cli", ["agent", "sync"]);
8
+ const result = await runCommand("td", ["agent", "sync"]);
9
9
  if (result.exitCode !== 0) {
10
10
  throw new Error(`Failed to list sessions: ${result.stderr}`);
11
11
  }
@@ -6,7 +6,7 @@ export const SendJulesMessageInputSchema = z.object({
6
6
  });
7
7
  export async function sendJulesMessageHandler(input) {
8
8
  const sessionIds = Array.isArray(input.sessionId) ? input.sessionId.join(",") : input.sessionId;
9
- const result = await runCommand("td-cli", ["agent", "send", sessionIds, input.message]);
9
+ const result = await runCommand("td", ["agent", "send", sessionIds, input.message]);
10
10
  if (result.exitCode !== 0) {
11
11
  throw new Error(`Failed to send message: ${result.stderr}`);
12
12
  }
@@ -13,18 +13,18 @@ describe("sendJulesMessageHandler", () => {
13
13
  teardownTestEnv();
14
14
  vi.clearAllMocks();
15
15
  });
16
- it("should send a message via td-cli", async () => {
16
+ it("should send a message via td", async () => {
17
17
  vi.mocked(shell.runCommand).mockResolvedValue({
18
18
  stdout: JSON.stringify({ status: "success", message: "Message sent successfully" }),
19
19
  stderr: "",
20
20
  exitCode: 0,
21
21
  durationMs: 0,
22
- command: "td-cli agent send"
22
+ command: "td agent send"
23
23
  });
24
24
  const result = await sendJulesMessageHandler({ sessionId: "123", message: "hi" });
25
25
  expect(result.id).toBe("123");
26
26
  expect(result.status).toBe("success");
27
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
27
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
28
28
  "agent", "send", "123", "hi"
29
29
  ]);
30
30
  });
@@ -41,7 +41,7 @@ describe("sendJulesMessageHandler", () => {
41
41
  stderr: "",
42
42
  exitCode: 0,
43
43
  durationMs: 0,
44
- command: "td-cli agent send"
44
+ command: "td agent send"
45
45
  });
46
46
  const result = await sendJulesMessageHandler({
47
47
  sessionId: ["sessions/s1", "sessions/s2"],
@@ -49,7 +49,7 @@ describe("sendJulesMessageHandler", () => {
49
49
  });
50
50
  expect(result.id).toEqual(["s1", "s2"]);
51
51
  expect(result.status).toBe("success");
52
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
52
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
53
53
  "agent", "send", "sessions/s1,sessions/s2", "hi batch"
54
54
  ]);
55
55
  });
@@ -1,3 +1,27 @@
1
+ import { runCommand } from "../../lib/shell.js";
2
+ function tryParseJson(text) {
3
+ try {
4
+ return JSON.parse(text);
5
+ }
6
+ catch {
7
+ return null;
8
+ }
9
+ }
10
+ export async function runTDCli(args) {
11
+ const result = await runCommand("td", args);
12
+ const stdout = result.stdout.trim();
13
+ const output = stdout.startsWith("{") ? tryParseJson(stdout) : null;
14
+ if (output?.status === "error") {
15
+ throw new Error(`td returned error: ${output.message ?? "Unknown error"}`);
16
+ }
17
+ if (result.exitCode !== 0) {
18
+ throw new Error(`td command failed (${args.join(" ")}): ${result.stderr || stdout}`);
19
+ }
20
+ if (!output) {
21
+ throw new Error(`td returned non-JSON output with exit code 0: ${stdout}`);
22
+ }
23
+ return output;
24
+ }
1
25
  export function parseJulesSession(data) {
2
26
  const name = data.name || "";
3
27
  const id = name.startsWith("sessions/") ? name.substring(9) : name;
@@ -4,7 +4,7 @@ export const TriggerJulesFeedbackInputSchema = z.object({
4
4
  sessionId: z.string(),
5
5
  });
6
6
  export async function triggerJulesFeedbackHandler(input) {
7
- const result = await runCommand("td-cli", ["agent", "trigger-feedback", input.sessionId]);
7
+ const result = await runCommand("td", ["agent", "trigger-feedback", input.sessionId]);
8
8
  if (result.exitCode !== 0) {
9
9
  throw new Error(`Failed to trigger feedback: ${result.stderr}`);
10
10
  }
@@ -13,28 +13,28 @@ describe("triggerJulesFeedbackHandler", () => {
13
13
  teardownTestEnv();
14
14
  vi.clearAllMocks();
15
15
  });
16
- it("should return success output from td-cli", async () => {
16
+ it("should return success output from td", async () => {
17
17
  vi.mocked(shell.runCommand).mockResolvedValue({
18
18
  stdout: JSON.stringify({ status: "success", feedback: "All checks passed successfully. You may proceed." }),
19
19
  stderr: "",
20
20
  exitCode: 0,
21
21
  durationMs: 0,
22
- command: "td-cli agent trigger-feedback"
22
+ command: "td agent trigger-feedback"
23
23
  });
24
24
  const result = await triggerJulesFeedbackHandler({ sessionId: "123" });
25
25
  expect(result.status).toBe("success");
26
26
  expect(result.feedback).toBe("All checks passed successfully. You may proceed.");
27
- expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
27
+ expect(shell.runCommand).toHaveBeenCalledWith("td", [
28
28
  "agent", "trigger-feedback", "123"
29
29
  ]);
30
30
  });
31
- it("should throw error if td-cli returns error", async () => {
31
+ it("should throw error if td returns error", async () => {
32
32
  vi.mocked(shell.runCommand).mockResolvedValue({
33
33
  stdout: JSON.stringify({ status: "error", message: "Session not found" }),
34
34
  stderr: "",
35
35
  exitCode: 0,
36
36
  durationMs: 0,
37
- command: "td-cli agent trigger-feedback"
37
+ command: "td agent trigger-feedback"
38
38
  });
39
39
  await expect(triggerJulesFeedbackHandler({ sessionId: "123" }))
40
40
  .rejects.toThrow("Failed to trigger feedback: Session not found");
@@ -1,21 +1,10 @@
1
1
  import { z } from "zod";
2
- import { runCommand } from "../lib/shell.js";
2
+ import { getChangedFiles } from "../lib/git.js";
3
3
  export const GetChangedFilesInputSchema = z.object({
4
4
  base: z.string().optional().default("main"),
5
5
  head: z.string().optional().default("HEAD"),
6
6
  });
7
7
  export async function getChangedFilesHandler(args) {
8
- const result = await runCommand("git", [
9
- "diff",
10
- "--name-status",
11
- `${args.base}...${args.head}`
12
- ]);
13
- if (result.exitCode !== 0) {
14
- throw new Error(`Failed to get changed files: ${result.stderr}`);
15
- }
16
- const files = result.stdout.trim().split("\n").filter(line => line.length > 0).map(line => {
17
- const [status, path] = line.split(/\s+/);
18
- return { status, path };
19
- });
8
+ const files = await getChangedFiles(args.base || "main", args.head || "HEAD");
20
9
  return { files };
21
10
  }
@@ -6,11 +6,11 @@ export const GetCommandSchemaInputSchema = z.object({
6
6
  export async function getCommandSchemaHandler(args) {
7
7
  // Sanitize input to prevent command injection (allow only alphanumeric, spaces, hyphens, and underscores)
8
8
  const sanitizedPath = args.commandPath.replace(/[^a-zA-Z0-9-_ ]/g, "");
9
- const result = await runCommand("td-cli", ["schema", sanitizedPath]);
9
+ const result = await runCommand("td", ["schema", sanitizedPath]);
10
10
  if (result.exitCode !== 0) {
11
11
  // Log stderr for debugging but don't expose it to the user
12
12
  // Using comma-separated arguments to satisfy semgrep unsafe-formatstring
13
- console.error("td-cli schema failed for", sanitizedPath, ":", result.stderr);
13
+ console.error("td schema failed for", sanitizedPath, ":", result.stderr);
14
14
  throw new Error(`Failed to get command schema for '${sanitizedPath}'`);
15
15
  }
16
16
  try {
@@ -0,0 +1,29 @@
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
+ const GetWorkflowRunsInputSchema = z.object({
6
+ branch: z.string().optional().describe("Filter workflow runs by branch name."),
7
+ event: z.string().optional().describe("Filter workflow runs by event (e.g. push, pull_request)."),
8
+ repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
9
+ });
10
+ export async function getWorkflowRunsHandler(args) {
11
+ const params = GetWorkflowRunsInputSchema.parse(args);
12
+ const targetRepo = resolveRepo(params.repo);
13
+ const cliArgs = ["repo", "workflow-runs", "--repo", targetRepo];
14
+ if (params.branch) {
15
+ cliArgs.push("--branch", params.branch);
16
+ }
17
+ if (params.event) {
18
+ cliArgs.push("--event", params.event);
19
+ }
20
+ const result = await runCommand("td", cliArgs);
21
+ if (result.exitCode !== 0) {
22
+ throw new Error(`Failed to fetch workflow runs: ${sanitizeError(result.stderr)}`);
23
+ }
24
+ const output = JSON.parse(result.stdout);
25
+ if (output.status === "error") {
26
+ throw new Error(`Failed to fetch workflow runs: ${output.message}`);
27
+ }
28
+ return { workflowRuns: output.workflow_runs };
29
+ }
@@ -1,14 +1,18 @@
1
1
  import { z } from "zod";
2
- import { runTDCli } from "../lib/td-cli.js";
2
+ import { runTDCli } from "./jules/shared.js";
3
3
  export const RepoLogsInputSchema = z.object({
4
4
  prNumber: z.number(),
5
5
  grep: z.string().optional(),
6
+ repo: z.string().optional(),
6
7
  });
7
8
  export async function repoLogsHandler(args) {
8
9
  const params = ["repo", "logs", args.prNumber.toString()];
9
10
  if (args.grep) {
10
11
  params.push("--grep", args.grep);
11
12
  }
13
+ if (args.repo) {
14
+ params.push("--repo", args.repo);
15
+ }
12
16
  const output = await runTDCli(params);
13
17
  return {
14
18
  logs: output.logs || (output.data ? output.data.logs : undefined)
@@ -1,6 +1,32 @@
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
+ export const loadStandaloneAgentContext = (repoRoot = process.cwd()) => {
7
+ const configPath = path.join(repoRoot, "project_config.json");
8
+ let projectConfig = {};
9
+ if (fs.existsSync(configPath)) {
10
+ try {
11
+ projectConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
12
+ }
13
+ catch (e) {
14
+ console.warn(`[MCP Warning] Failed to parse ${configPath}:`, e);
15
+ }
16
+ }
17
+ let gitCommit = "unknown";
18
+ try {
19
+ gitCommit = execSync("git rev-parse HEAD", { cwd: repoRoot, encoding: "utf-8" }).trim();
20
+ }
21
+ catch {
22
+ // Fallback if git is unavailable
23
+ }
24
+ return {
25
+ packageName: projectConfig.packageName ?? "boomtick",
26
+ gitCommit,
27
+ config: projectConfig,
28
+ };
29
+ };
4
30
  export const ReadAgentContextInputSchema = z.object({});
5
31
  export async function readAgentContextHandler(_args) {
6
32
  const context = loadStandaloneAgentContext(config.repoPath);
@@ -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
  describe("Standalone Agent Context Loader", () => {
4
4
  it("should load agent context without submodule references", () => {
5
5
  const context = loadStandaloneAgentContext(process.cwd());
@@ -1,14 +1,18 @@
1
1
  import { z } from "zod";
2
- import { runTDCli } from "../lib/td-cli.js";
2
+ import { runTDCli } from "./jules/shared.js";
3
3
  export const ReadCiLogsInputSchema = z.object({
4
4
  prNumber: z.number(),
5
5
  all: z.boolean().optional(),
6
+ repo: z.string().optional(),
6
7
  });
7
8
  export async function readCiLogsHandler(args) {
8
9
  const params = ["repo", "ci-logs", args.prNumber.toString()];
9
10
  if (args.all) {
10
11
  params.push("--all");
11
12
  }
13
+ if (args.repo) {
14
+ params.push("--repo", args.repo);
15
+ }
12
16
  const output = await runTDCli(params);
13
17
  return {
14
18
  checks: output.checks,
@@ -5,7 +5,7 @@ export const RunTestsInputSchema = z.object({
5
5
  timeoutSeconds: z.number().optional().default(300),
6
6
  worktreePath: z.string().optional(),
7
7
  });
8
- export function parseCommandArguments(fullCmd) {
8
+ function parseCommandArguments(fullCmd) {
9
9
  const tokens = [];
10
10
  const regex = /"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|(\S+)/g;
11
11
  let match;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arii/boomtick-mcp",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "Boomtick MCP Guide: PR Rescue + Merge Conflict Agent",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,6 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/sdk": "^1.6.0",
20
- "dotenv": "^17.4.2",
21
20
  "zod": "^4.4.3"
22
21
  },
23
22
  "engines": {
@@ -27,14 +26,12 @@
27
26
  "devDependencies": {
28
27
  "@types/node": "^20.17.15",
29
28
  "json-schema-to-zod": "^2.8.1",
30
- "shx": "^0.4.0",
31
29
  "tsx": "^4.22.4",
32
30
  "typescript": "^5.7.3",
33
- "vitest": "^4.1.9",
34
- "yaml": "^2.9.0"
31
+ "vitest": "^4.1.9"
35
32
  },
36
33
  "scripts": {
37
- "build": "tsx scripts/sync-contracts.ts && tsc && shx cp src/tools/ddgs_search.py dist/tools/ && tsx scripts/sync-mcp-schemas.ts",
34
+ "build": "tsx scripts/sync-contracts.ts && tsc && tsx scripts/sync-mcp-schemas.ts",
38
35
  "watch": "tsc -w",
39
36
  "start": "node dist/index.js",
40
37
  "test": "tsx scripts/sync-contracts.ts && tsx scripts/sync-mcp-schemas.ts && vitest run",
@@ -19,6 +19,7 @@ function isWritable(dir: string): boolean {
19
19
  interface ToolDefinition {
20
20
  name: string;
21
21
  inputSchema: Record<string, unknown>;
22
+ outputSchema?: Record<string, unknown>;
22
23
  }
23
24
 
24
25
  /**
@@ -73,6 +74,7 @@ async function syncSchemas() {
73
74
  name: tool.name,
74
75
  description: tool.description,
75
76
  parameters: tool.inputSchema,
77
+ outputSchema: tool.outputSchema,
76
78
  };
77
79
  const schemaContent = JSON.stringify(exportedSchema, null, 2);
78
80
  const fileName = `${tool.name}.json`;
@@ -10,10 +10,6 @@ Required:
10
10
  - test
11
11
  - build
12
12
 
13
- Conditional:
14
- - Playwright for UI/routes/browser behavior
15
- - Lighthouse for performance/accessibility/SEO-sensitive changes
16
-
17
13
  Output:
18
14
  - commands run
19
15
  - pass/fail status
@@ -20,14 +20,14 @@ describe("config", () => {
20
20
  });
21
21
 
22
22
  describe("initializeConfig", () => {
23
- it("should load dynamic config from td-cli config view using active cwd", async () => {
23
+ it("should load dynamic config from td config view using active cwd", async () => {
24
24
  const mockConfig = { github_repo: "owner/repo", base_branch: "origin/main", vite_base_path: "/app/" };
25
25
  vi.mocked(execSync).mockReturnValue(JSON.stringify(mockConfig));
26
26
 
27
27
  const { initializeConfig } = await import("./config.js");
28
28
  const result = initializeConfig();
29
29
 
30
- expect(execSync).toHaveBeenCalledWith("td-cli config view", expect.objectContaining({
30
+ expect(execSync).toHaveBeenCalledWith("td config view", expect.objectContaining({
31
31
  cwd: process.cwd()
32
32
  }));
33
33
  expect(result).toEqual(mockConfig);
@@ -119,7 +119,7 @@ describe("config", () => {
119
119
  delete process.env.GITHUB_REPOSITORY;
120
120
  delete process.env.GH_REPO;
121
121
  vi.mocked(execSync).mockImplementation(() => {
122
- throw new Error("td-cli failed");
122
+ throw new Error("td failed");
123
123
  });
124
124
 
125
125
  process.env.NODE_ENV = "production";
package/src/config.ts CHANGED
@@ -41,7 +41,7 @@ export function initializeConfig() {
41
41
  try {
42
42
  // Attempt to load core properties from the Python CLI in the active workspace
43
43
  const cwd = process.env.BOOMTICK_REPO_PATH || process.cwd();
44
- const cmd = `td-cli config view`;
44
+ const cmd = `td config view`;
45
45
  const output = execSync(cmd, {
46
46
  cwd,
47
47
  encoding: "utf-8",