@arii/boomtick-mcp 0.6.2 → 0.7.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.
- package/.mcp/schemas/boomtick.health.json +22 -3
- package/.mcp/schemas/boomtick_health.json +22 -3
- package/.mcp/schemas/github.checkout_branch.json +16 -3
- package/.mcp/schemas/github.comment_triage_summary.json +16 -3
- package/.mcp/schemas/github.create_pull_request.json +16 -3
- package/.mcp/schemas/github.get_pr.json +12 -3
- package/.mcp/schemas/github.get_pr_commits.json +12 -3
- package/.mcp/schemas/github.get_pr_reviews.json +24 -3
- package/.mcp/schemas/github.issue_comment.json +19 -3
- package/.mcp/schemas/github.issue_view.json +17 -3
- package/.mcp/schemas/github.open_replacement_pr.json +16 -3
- package/.mcp/schemas/github_checkout_branch.json +16 -3
- package/.mcp/schemas/github_comment_triage_summary.json +16 -3
- package/.mcp/schemas/github_create_pull_request.json +16 -3
- package/.mcp/schemas/github_get_pr.json +12 -3
- package/.mcp/schemas/github_get_pr_commits.json +12 -3
- package/.mcp/schemas/github_get_pr_reviews.json +24 -3
- package/.mcp/schemas/github_issue_comment.json +19 -3
- package/.mcp/schemas/github_issue_view.json +17 -3
- package/.mcp/schemas/github_open_replacement_pr.json +16 -3
- package/.mcp/schemas/jules.cancel_session.json +38 -3
- package/.mcp/schemas/jules.create_session.json +52 -3
- package/.mcp/schemas/jules.get_messages.json +19 -3
- package/.mcp/schemas/jules.get_pr.json +23 -3
- package/.mcp/schemas/jules.get_session.json +38 -3
- package/.mcp/schemas/jules.list_sessions.json +53 -3
- package/.mcp/schemas/jules.send_message.json +31 -3
- package/.mcp/schemas/jules.trigger_feedback.json +28 -3
- package/.mcp/schemas/jules_cancel_session.json +38 -3
- package/.mcp/schemas/jules_create_session.json +52 -3
- package/.mcp/schemas/jules_get_messages.json +19 -3
- package/.mcp/schemas/jules_get_pr.json +23 -3
- package/.mcp/schemas/jules_get_session.json +38 -3
- package/.mcp/schemas/jules_list_sessions.json +53 -3
- package/.mcp/schemas/jules_send_message.json +31 -3
- package/.mcp/schemas/jules_trigger_feedback.json +28 -3
- package/.mcp/schemas/repo.check_jules_status.json +93 -3
- package/.mcp/schemas/repo.commit_patch.json +23 -3
- package/.mcp/schemas/repo.create_branch.json +28 -3
- package/.mcp/schemas/repo.create_repair_branch.json +31 -3
- package/.mcp/schemas/repo.get_changed_files.json +11 -3
- package/.mcp/schemas/repo.get_command_schema.json +29 -3
- package/.mcp/schemas/repo.get_package_scripts.json +11 -3
- package/.mcp/schemas/repo.get_workflow_runs.json +12 -3
- package/.mcp/schemas/repo.logs.json +14 -3
- package/.mcp/schemas/repo.multi_exec.json +89 -0
- package/.mcp/schemas/repo.read_agent_context.json +117 -5
- package/.mcp/schemas/repo.read_ci_logs.json +46 -3
- package/.mcp/schemas/repo_check_jules_status.json +93 -3
- package/.mcp/schemas/repo_commit_patch.json +23 -3
- package/.mcp/schemas/repo_create_branch.json +28 -3
- package/.mcp/schemas/repo_create_repair_branch.json +31 -3
- package/.mcp/schemas/repo_get_changed_files.json +11 -3
- package/.mcp/schemas/repo_get_command_schema.json +29 -3
- package/.mcp/schemas/repo_get_package_scripts.json +11 -3
- package/.mcp/schemas/repo_get_workflow_runs.json +12 -3
- package/.mcp/schemas/repo_logs.json +14 -3
- package/.mcp/schemas/repo_multi_exec.json +89 -0
- package/.mcp/schemas/repo_read_agent_context.json +117 -5
- package/.mcp/schemas/repo_read_ci_logs.json +46 -3
- package/CHANGELOG.md +14 -0
- package/README.md +7 -5
- package/dist/config/dynamic.js +3 -2
- package/dist/config/repo.js +5 -5
- package/dist/config.test.js +10 -3
- package/dist/mcp/definitions.js +49 -36
- package/dist/mcp/http.js +15 -0
- package/dist/mcp/http.test.js +8 -0
- package/dist/mcp/server.js +34 -0
- package/dist/mcp/server.test.js +31 -0
- package/dist/tools/contract.js +960 -3
- package/dist/tools/jules/create-session.js +12 -2
- package/dist/tools/jules/create-session.test.js +7 -0
- package/dist/tools/repo.multi_exec.js +21 -0
- package/dist/tools/repo.multi_exec.test.js +13 -0
- package/dist/tools/repo.read_agent_context.js +65 -3
- package/dist/tools/repo.read_agent_context.test.js +30 -1
- package/package.json +1 -1
- package/src/config/dynamic.ts +3 -2
- package/src/config/repo.ts +6 -6
- package/src/config.test.ts +11 -3
- package/src/mcp/definitions.ts +77 -36
- package/src/mcp/http.test.ts +10 -0
- package/src/mcp/http.ts +20 -0
- package/src/mcp/server.test.ts +38 -0
- package/src/mcp/server.ts +36 -0
- package/src/tools/contract.ts +1089 -16
- package/src/tools/jules/create-session.test.ts +9 -0
- package/src/tools/jules/create-session.ts +13 -2
- package/src/tools/repo.multi_exec.test.ts +15 -0
- package/src/tools/repo.multi_exec.ts +23 -0
- package/src/tools/repo.read_agent_context.test.ts +35 -1
- package/src/tools/repo.read_agent_context.ts +68 -3
package/src/mcp/http.ts
CHANGED
|
@@ -32,6 +32,13 @@ export function createMcpHttpServer(options: HttpServerOptions) {
|
|
|
32
32
|
|
|
33
33
|
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
34
34
|
|
|
35
|
+
// Endpoint 0: Health check endpoint for readiness probes / load balancers
|
|
36
|
+
if (url.pathname === "/health" && req.method === "GET") {
|
|
37
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
38
|
+
res.end(JSON.stringify({ status: "ok", transport: "http" }));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
35
42
|
// Endpoint 1: RFC 9728 OAuth Protected Resource Metadata Discovery
|
|
36
43
|
if (url.pathname === "/.well-known/oauth-protected-resource" && (req.method === "GET" || req.method === "HEAD")) {
|
|
37
44
|
const metadata = {
|
|
@@ -82,11 +89,24 @@ export function createMcpHttpServer(options: HttpServerOptions) {
|
|
|
82
89
|
|
|
83
90
|
// Endpoint 2: SSE stream setup
|
|
84
91
|
if (url.pathname === "/sse" && req.method === "GET") {
|
|
92
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
93
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
94
|
+
res.setHeader("Connection", "keep-alive");
|
|
95
|
+
|
|
85
96
|
const transport = new SSEServerTransport("/messages", res);
|
|
86
97
|
transports.set(transport.sessionId, transport);
|
|
98
|
+
|
|
99
|
+
const keepAliveInterval = setInterval(() => {
|
|
100
|
+
if (!res.writableEnded) {
|
|
101
|
+
res.write(": keep-alive\n\n");
|
|
102
|
+
}
|
|
103
|
+
}, 15000);
|
|
104
|
+
|
|
87
105
|
transport.onclose = () => {
|
|
106
|
+
clearInterval(keepAliveInterval);
|
|
88
107
|
transports.delete(transport.sessionId);
|
|
89
108
|
};
|
|
109
|
+
|
|
90
110
|
await mcpServer.connect(transport);
|
|
91
111
|
return;
|
|
92
112
|
}
|
package/src/mcp/server.test.ts
CHANGED
|
@@ -207,6 +207,33 @@ describe("BoomtickMCPServer", () => {
|
|
|
207
207
|
expect(JSON.parse(result.contents[0].text)).toEqual({ files: ["src/index.ts"] });
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
+
it("should handle mcp://workspace/project-config", async () => {
|
|
211
|
+
const handler = requestHandlers.get("resources/read");
|
|
212
|
+
vi.mocked(fs.readFile).mockResolvedValue('{"packageName": "boomtick"}');
|
|
213
|
+
|
|
214
|
+
const result = await handler!({
|
|
215
|
+
method: "resources/read",
|
|
216
|
+
params: { uri: "mcp://workspace/project-config" },
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
expect(result.contents[0].uri).toBe("mcp://workspace/project-config");
|
|
220
|
+
expect(result.contents[0].mimeType).toBe("application/json");
|
|
221
|
+
expect(JSON.parse(result.contents[0].text)).toEqual({ packageName: "boomtick" });
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("should handle mcp://git/status", async () => {
|
|
225
|
+
const handler = requestHandlers.get("resources/read");
|
|
226
|
+
|
|
227
|
+
const result = await handler!({
|
|
228
|
+
method: "resources/read",
|
|
229
|
+
params: { uri: "mcp://git/status" },
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
expect(result.contents[0].uri).toBe("mcp://git/status");
|
|
233
|
+
expect(result.contents[0].mimeType).toBe("application/json");
|
|
234
|
+
expect(JSON.parse(result.contents[0].text)).toHaveProperty("status");
|
|
235
|
+
});
|
|
236
|
+
|
|
210
237
|
it("should handle mcp://ci/latest-run", async () => {
|
|
211
238
|
const handler = requestHandlers.get("resources/read");
|
|
212
239
|
vi.spyOn(workflowRunsModule, "getWorkflowRunsHandler").mockResolvedValue({ workflowRuns: [{ id: 1, status: "completed", conclusion: "success" }] } as any);
|
|
@@ -241,6 +268,17 @@ describe("BoomtickMCPServer", () => {
|
|
|
241
268
|
expect(result.tools).toBeDefined();
|
|
242
269
|
expect(Array.isArray(result.tools)).toBe(true);
|
|
243
270
|
});
|
|
271
|
+
|
|
272
|
+
it("should ensure all tools have typed outputSchema and none are empty or untyped DEFAULT_OUTPUT_SCHEMA", async () => {
|
|
273
|
+
const handler = requestHandlers.get("tools/list");
|
|
274
|
+
const result = await handler!({ method: "tools/list" });
|
|
275
|
+
for (const tool of result.tools) {
|
|
276
|
+
expect(tool.outputSchema).toBeDefined();
|
|
277
|
+
expect(tool.outputSchema.type).toBe("object");
|
|
278
|
+
expect(tool.outputSchema.properties).toBeDefined();
|
|
279
|
+
expect(Object.keys(tool.outputSchema.properties).length).toBeGreaterThan(0);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
244
282
|
});
|
|
245
283
|
|
|
246
284
|
describe("CallTool", () => {
|
package/src/mcp/server.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { getMergeConflictFilesHandler, GetMergeConflictFilesInputSchema } from "
|
|
|
20
20
|
import { checkoutBranchHandler, CheckoutBranchInputSchema } from "../tools/github.checkout_branch.js";
|
|
21
21
|
import { getChangedFilesHandler, GetChangedFilesInputSchema } from "../tools/repo.get_changed_files.js";
|
|
22
22
|
import { readAgentContextHandler, ReadAgentContextInputSchema } from "../tools/repo.read_agent_context.js";
|
|
23
|
+
import { multiExecHandler, MultiExecInputSchema } from "../tools/repo.multi_exec.js";
|
|
23
24
|
import { getCommandSchemaHandler, GetCommandSchemaInputSchema } from "../tools/repo.get_command_schema.js";
|
|
24
25
|
import { getPackageScriptsHandler, GetPackageScriptsInputSchema } from "../tools/repo.get_package_scripts.js";
|
|
25
26
|
import { readCiLogsHandler, ReadCiLogsInputSchema } from "../tools/repo.read_ci_logs.js";
|
|
@@ -142,6 +143,22 @@ export class BoomtickMCPServer {
|
|
|
142
143
|
contents: [{ uri, mimeType: "text/markdown", text: content }],
|
|
143
144
|
};
|
|
144
145
|
}
|
|
146
|
+
if (
|
|
147
|
+
uri === "mcp://workspace/project-config" ||
|
|
148
|
+
uri === "mcp://workspace/project_config" ||
|
|
149
|
+
uri === "repo://project-config"
|
|
150
|
+
) {
|
|
151
|
+
const configPath = path.join(config.repoPath, "project_config.json");
|
|
152
|
+
let content = "{}";
|
|
153
|
+
try {
|
|
154
|
+
content = await fs.readFile(configPath, "utf-8");
|
|
155
|
+
} catch {
|
|
156
|
+
// Fallback if file doesn't exist
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
contents: [{ uri, mimeType: "application/json", text: content }],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
145
162
|
if (
|
|
146
163
|
uri === "mcp://git/changed-files" ||
|
|
147
164
|
uri === "repo://changed-files"
|
|
@@ -151,6 +168,22 @@ export class BoomtickMCPServer {
|
|
|
151
168
|
contents: [{ uri, mimeType: "application/json", text: JSON.stringify(changedFiles, null, 2) }],
|
|
152
169
|
};
|
|
153
170
|
}
|
|
171
|
+
if (
|
|
172
|
+
uri === "mcp://git/status" ||
|
|
173
|
+
uri === "repo://git-status" ||
|
|
174
|
+
uri === "repo://status"
|
|
175
|
+
) {
|
|
176
|
+
let statusText = "";
|
|
177
|
+
try {
|
|
178
|
+
const res = spawnSync("git", ["status", "--porcelain"], { cwd: config.repoPath, encoding: "utf-8" });
|
|
179
|
+
statusText = res.stdout || "";
|
|
180
|
+
} catch {
|
|
181
|
+
// Fallback if git fails
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
contents: [{ uri, mimeType: "application/json", text: JSON.stringify({ status: statusText.trim() }, null, 2) }],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
154
187
|
if (
|
|
155
188
|
uri === "mcp://ci/latest-run" ||
|
|
156
189
|
uri === "repo://ci/latest-run" ||
|
|
@@ -213,6 +246,9 @@ export class BoomtickMCPServer {
|
|
|
213
246
|
case "repo.read.agent.context":
|
|
214
247
|
case "repo.read_agent_context":
|
|
215
248
|
return createSuccessResult(await readAgentContextHandler(ReadAgentContextInputSchema.parse(normArgs)));
|
|
249
|
+
case "repo.multi.exec":
|
|
250
|
+
case "repo.multi_exec":
|
|
251
|
+
return createSuccessResult(await multiExecHandler(MultiExecInputSchema.parse(normArgs)));
|
|
216
252
|
case "github.get.pr.diff":
|
|
217
253
|
case "github.get_pr_diff":
|
|
218
254
|
return createSuccessResult(await getPrDiffHandler(GetPrDiffInputSchema.parse(normArgs)));
|