@arii/boomtick-mcp 0.6.1 → 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_issue.json +72 -3
- package/.mcp/schemas/github.create_pull_request.json +16 -3
- package/.mcp/schemas/github.get_merge_conflict_files.json +40 -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_diff.json +30 -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_update.json +72 -3
- package/.mcp/schemas/github.issue_view.json +17 -3
- package/.mcp/schemas/github.open_replacement_pr.json +16 -3
- package/.mcp/schemas/github.search_open_prs.json +130 -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_issue.json +72 -3
- package/.mcp/schemas/github_create_pull_request.json +16 -3
- package/.mcp/schemas/github_get_merge_conflict_files.json +40 -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_diff.json +30 -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_update.json +72 -3
- package/.mcp/schemas/github_issue_view.json +17 -3
- package/.mcp/schemas/github_open_replacement_pr.json +16 -3
- package/.mcp/schemas/github_search_open_prs.json +130 -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 +128 -0
- 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.run_tests.json +31 -3
- package/.mcp/schemas/repo_check_jules_status.json +128 -0
- 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_run_tests.json +31 -3
- package/CHANGELOG.md +22 -0
- package/README.md +29 -6
- package/actions/run-project-gate/action.yml +1 -1
- package/dist/config/dynamic.js +34 -0
- package/dist/config/github.js +16 -0
- package/dist/config/repo.js +28 -0
- package/dist/config.js +16 -81
- package/dist/config.test.js +10 -3
- package/dist/http.js +10 -0
- package/dist/mcp/definitions.js +76 -41
- package/dist/mcp/http.js +32 -9
- package/dist/mcp/http.test.js +62 -4
- package/dist/mcp/server.js +69 -10
- package/dist/mcp/server.test.js +59 -1
- package/dist/tools/contract.js +1079 -45
- package/dist/tools/github.comment_triage_summary.js +3 -10
- package/dist/tools/github.get_merge_conflict_files.js +4 -2
- package/dist/tools/github.get_pr_diff.js +3 -11
- package/dist/tools/jules/cancel-session.js +2 -9
- package/dist/tools/jules/cli.js +31 -0
- package/dist/tools/jules/create-session.js +12 -2
- package/dist/tools/jules/create-session.test.js +7 -0
- package/dist/tools/jules/get-messages.js +2 -9
- package/dist/tools/jules/list-sessions.js +4 -35
- package/dist/tools/jules/send-message.js +2 -9
- package/dist/tools/jules/session.js +26 -0
- package/dist/tools/jules/shared.js +2 -50
- package/dist/tools/jules/trigger-feedback.js +2 -10
- package/dist/tools/repo.check_jules_status.js +148 -0
- package/dist/tools/repo.check_jules_status.test.js +47 -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/dist/tools/repo.run_tests.js +13 -1
- package/package.json +3 -2
- package/scripts/sync-contracts.ts +11 -2
- package/src/config/dynamic.ts +37 -0
- package/src/config/github.ts +16 -0
- package/src/config/repo.ts +36 -0
- package/src/config.test.ts +11 -3
- package/src/config.ts +16 -89
- package/src/http.ts +13 -0
- package/src/mcp/definitions.ts +110 -41
- package/src/mcp/http.test.ts +75 -5
- package/src/mcp/http.ts +40 -14
- package/src/mcp/server.test.ts +72 -1
- package/src/mcp/server.ts +72 -11
- package/src/tools/contract.ts +1194 -36
- package/src/tools/github.comment_triage_summary.ts +3 -12
- package/src/tools/github.get_merge_conflict_files.ts +5 -2
- package/src/tools/github.get_pr_diff.ts +3 -13
- package/src/tools/jules/cancel-session.ts +2 -11
- package/src/tools/jules/cli.ts +42 -0
- package/src/tools/jules/create-session.test.ts +9 -0
- package/src/tools/jules/create-session.ts +13 -2
- package/src/tools/jules/get-messages.ts +2 -11
- package/src/tools/jules/list-sessions.ts +5 -39
- package/src/tools/jules/send-message.ts +2 -11
- package/src/tools/jules/session.ts +28 -0
- package/src/tools/jules/shared.ts +2 -63
- package/src/tools/jules/trigger-feedback.ts +2 -13
- package/src/tools/repo.check_jules_status.test.ts +55 -0
- package/src/tools/repo.check_jules_status.ts +176 -0
- 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/tools/repo.run_tests.ts +14 -1
package/src/mcp/definitions.ts
CHANGED
|
@@ -1,35 +1,70 @@
|
|
|
1
1
|
import { Tool, Prompt, Resource, ResourceTemplate } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import {
|
|
3
3
|
HealthCheckInputJsonSchema,
|
|
4
|
+
HealthCheckResponseJsonSchema,
|
|
4
5
|
SearchPRsInputJsonSchema,
|
|
6
|
+
SearchPRsResponseJsonSchema,
|
|
5
7
|
GetPrDiffInputJsonSchema,
|
|
8
|
+
PrDiffResponseJsonSchema,
|
|
6
9
|
CheckoutBranchInputJsonSchema,
|
|
10
|
+
CheckoutBranchResponseJsonSchema,
|
|
7
11
|
GetMergeConflictFilesInputJsonSchema,
|
|
12
|
+
GetMergeConflictFilesResponseJsonSchema,
|
|
8
13
|
GetChangedFilesInputJsonSchema,
|
|
14
|
+
GetChangedFilesResponseJsonSchema,
|
|
9
15
|
GetPackageScriptsInputJsonSchema,
|
|
16
|
+
GetPackageScriptsResponseJsonSchema,
|
|
10
17
|
ReadCiLogsInputJsonSchema,
|
|
18
|
+
ReadCiLogsResponseJsonSchema,
|
|
11
19
|
RepoLogsInputJsonSchema,
|
|
20
|
+
RepoLogsResponseJsonSchema,
|
|
12
21
|
CreateBranchInputJsonSchema,
|
|
22
|
+
CreateBranchResponseJsonSchema,
|
|
13
23
|
CreateRepairBranchInputJsonSchema,
|
|
24
|
+
CreateRepairBranchResponseJsonSchema,
|
|
25
|
+
CheckJulesStatusResponseJsonSchema,
|
|
14
26
|
RunTestsInputJsonSchema,
|
|
27
|
+
RunTestsResponseJsonSchema,
|
|
15
28
|
CommitPatchInputJsonSchema,
|
|
29
|
+
CommitPatchResponseJsonSchema,
|
|
16
30
|
OpenReplacementPrInputJsonSchema,
|
|
31
|
+
OpenReplacementPrResponseJsonSchema,
|
|
17
32
|
CreatePullRequestInputJsonSchema,
|
|
33
|
+
CreatePullRequestResponseJsonSchema,
|
|
18
34
|
CommentTriageSummaryInputJsonSchema,
|
|
35
|
+
CommentTriageSummaryResponseJsonSchema,
|
|
19
36
|
GetPrInputJsonSchema,
|
|
37
|
+
GetPrResponseJsonSchema,
|
|
20
38
|
IssueViewInputJsonSchema,
|
|
39
|
+
IssueViewResponseJsonSchema,
|
|
21
40
|
IssueUpdateInputJsonSchema,
|
|
41
|
+
IssueUpdateResponseJsonSchema,
|
|
22
42
|
IssueCommentInputJsonSchema,
|
|
43
|
+
IssueCommentResponseJsonSchema,
|
|
23
44
|
CreateIssueInputJsonSchema,
|
|
45
|
+
CreateIssueResponseJsonSchema,
|
|
24
46
|
GetCommandSchemaInputJsonSchema,
|
|
47
|
+
GetCommandSchemaResponseJsonSchema,
|
|
25
48
|
ReadAgentContextInputJsonSchema as ReadAgentContextSchema,
|
|
49
|
+
ReadAgentContextResponseJsonSchema,
|
|
50
|
+
MultiExecInputJsonSchema,
|
|
51
|
+
MultiExecResponseJsonSchema,
|
|
26
52
|
CreateJulesSessionInputJsonSchema,
|
|
27
53
|
JulesSessionIdInputJsonSchema,
|
|
28
54
|
JulesSendMessageInputJsonSchema,
|
|
55
|
+
JulesSendMessageResponseJsonSchema,
|
|
56
|
+
JulesGetMessagesResponseJsonSchema,
|
|
29
57
|
JulesListSessionsInputJsonSchema,
|
|
58
|
+
JulesListSessionsResponseJsonSchema,
|
|
59
|
+
JulesSessionResponseJsonSchema,
|
|
60
|
+
JulesGetPrResponseJsonSchema,
|
|
61
|
+
JulesTriggerFeedbackResponseJsonSchema,
|
|
30
62
|
GetPrReviewsInputJsonSchema,
|
|
63
|
+
GetPrReviewsResponseJsonSchema,
|
|
31
64
|
GetPrCommitsInputJsonSchema,
|
|
65
|
+
GetPrCommitsResponseJsonSchema,
|
|
32
66
|
GetWorkflowRunsInputJsonSchema,
|
|
67
|
+
GetWorkflowRunsResponseJsonSchema,
|
|
33
68
|
} from "../tools/contract.js";
|
|
34
69
|
|
|
35
70
|
export const MCP_PROMPTS: Prompt[] = [
|
|
@@ -72,12 +107,30 @@ export const MCP_RESOURCES: Resource[] = [
|
|
|
72
107
|
mimeType: "text/markdown",
|
|
73
108
|
description: "The agent contract specification file (.agents/AGENT_CONTRACT.md).",
|
|
74
109
|
},
|
|
110
|
+
{
|
|
111
|
+
uri: "mcp://workspace/project-config",
|
|
112
|
+
name: "Project Configuration",
|
|
113
|
+
mimeType: "application/json",
|
|
114
|
+
description: "The project configuration (project_config.json).",
|
|
115
|
+
},
|
|
75
116
|
{
|
|
76
117
|
uri: "mcp://git/changed-files",
|
|
77
118
|
name: "Git Changed Files",
|
|
78
119
|
mimeType: "application/json",
|
|
79
120
|
description: "List of changed files in the repository.",
|
|
80
121
|
},
|
|
122
|
+
{
|
|
123
|
+
uri: "mcp://git/status",
|
|
124
|
+
name: "Git Status",
|
|
125
|
+
mimeType: "application/json",
|
|
126
|
+
description: "Current working directory git status.",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
uri: "mcp://ci/latest-run",
|
|
130
|
+
name: "Latest CI Run",
|
|
131
|
+
mimeType: "application/json",
|
|
132
|
+
description: "Recent CI exit statuses, workflow runs, and annotations.",
|
|
133
|
+
},
|
|
81
134
|
{
|
|
82
135
|
uri: "repo://package-json",
|
|
83
136
|
name: "package.json",
|
|
@@ -113,216 +166,232 @@ export const MCP_RESOURCE_TEMPLATES: ResourceTemplate[] = [
|
|
|
113
166
|
},
|
|
114
167
|
];
|
|
115
168
|
|
|
116
|
-
const DEFAULT_OUTPUT_SCHEMA = {
|
|
117
|
-
type: "object",
|
|
118
|
-
properties: {},
|
|
119
|
-
additionalProperties: true,
|
|
120
|
-
} as const;
|
|
121
|
-
|
|
122
169
|
const BASE_MCP_TOOLS: Tool[] = [
|
|
123
170
|
{
|
|
124
171
|
name: "boomtick.health",
|
|
125
172
|
description: "Check the health and configuration of the MCP server.",
|
|
126
173
|
inputSchema: HealthCheckInputJsonSchema as any,
|
|
127
|
-
outputSchema:
|
|
174
|
+
outputSchema: HealthCheckResponseJsonSchema as any,
|
|
128
175
|
},
|
|
129
176
|
{
|
|
130
177
|
name: "github.search_open_prs",
|
|
131
178
|
description: "Search for open pull requests in the repository.",
|
|
132
179
|
inputSchema: SearchPRsInputJsonSchema as any,
|
|
133
|
-
outputSchema:
|
|
180
|
+
outputSchema: SearchPRsResponseJsonSchema as any,
|
|
134
181
|
},
|
|
135
182
|
{
|
|
136
183
|
name: "repo.read_agent_context",
|
|
137
|
-
description: "Read the
|
|
184
|
+
description: "Read the repository index including metadata, model review chains, or multi-repo ecosystem status.",
|
|
138
185
|
inputSchema: ReadAgentContextSchema as any,
|
|
139
|
-
outputSchema:
|
|
186
|
+
outputSchema: ReadAgentContextResponseJsonSchema as any,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: "repo.multi_exec",
|
|
190
|
+
description: "Execute a shell command sequentially across ecosystem repositories (or a filtered subset).",
|
|
191
|
+
inputSchema: MultiExecInputJsonSchema as any,
|
|
192
|
+
outputSchema: MultiExecResponseJsonSchema as any,
|
|
140
193
|
},
|
|
141
194
|
{
|
|
142
195
|
name: "github.get_pr_diff",
|
|
143
196
|
description: "Get the diff and changed files for a pull request.",
|
|
144
197
|
inputSchema: GetPrDiffInputJsonSchema as any,
|
|
145
|
-
outputSchema:
|
|
198
|
+
outputSchema: PrDiffResponseJsonSchema as any,
|
|
146
199
|
},
|
|
147
200
|
{
|
|
148
201
|
name: "github.checkout_branch",
|
|
149
202
|
description: "Checkout a specific branch in the repository or worktree.",
|
|
150
203
|
inputSchema: CheckoutBranchInputJsonSchema as any,
|
|
151
|
-
outputSchema:
|
|
204
|
+
outputSchema: CheckoutBranchResponseJsonSchema as any,
|
|
152
205
|
},
|
|
153
206
|
{
|
|
154
207
|
name: "github.get_merge_conflict_files",
|
|
155
208
|
description: "Detect files that conflict when a PR is merged with the base branch.",
|
|
156
209
|
inputSchema: GetMergeConflictFilesInputJsonSchema as any,
|
|
157
|
-
outputSchema:
|
|
210
|
+
outputSchema: GetMergeConflictFilesResponseJsonSchema as any,
|
|
158
211
|
},
|
|
159
212
|
{
|
|
160
213
|
name: "repo.get_changed_files",
|
|
161
214
|
description: "Get the list of changed files between two refs.",
|
|
162
215
|
inputSchema: GetChangedFilesInputJsonSchema as any,
|
|
163
|
-
outputSchema:
|
|
216
|
+
outputSchema: GetChangedFilesResponseJsonSchema as any,
|
|
164
217
|
},
|
|
165
218
|
{
|
|
166
219
|
name: "repo.get_command_schema",
|
|
167
220
|
description: "Retrieve a lightweight, targeted schema for a specific td subcommand. Use this instead of reading the entire cli-schema.json to save tokens.",
|
|
168
221
|
inputSchema: GetCommandSchemaInputJsonSchema as any,
|
|
169
|
-
outputSchema:
|
|
222
|
+
outputSchema: GetCommandSchemaResponseJsonSchema as any,
|
|
170
223
|
},
|
|
171
224
|
{
|
|
172
225
|
name: "repo.get_package_scripts",
|
|
173
226
|
description: "Get the scripts defined in package.json.",
|
|
174
227
|
inputSchema: GetPackageScriptsInputJsonSchema as any,
|
|
175
|
-
outputSchema:
|
|
228
|
+
outputSchema: GetPackageScriptsResponseJsonSchema as any,
|
|
176
229
|
},
|
|
177
230
|
{
|
|
178
231
|
name: "repo.read_ci_logs",
|
|
179
232
|
description: "Read CI logs for a given pull request.",
|
|
180
233
|
inputSchema: ReadCiLogsInputJsonSchema as any,
|
|
181
|
-
outputSchema:
|
|
234
|
+
outputSchema: ReadCiLogsResponseJsonSchema as any,
|
|
182
235
|
},
|
|
183
236
|
{
|
|
184
237
|
name: "repo.logs",
|
|
185
238
|
description: "Stream or grep combined CI logs for all jobs in a pull request.",
|
|
186
239
|
inputSchema: RepoLogsInputJsonSchema as any,
|
|
187
|
-
outputSchema:
|
|
240
|
+
outputSchema: RepoLogsResponseJsonSchema as any,
|
|
188
241
|
},
|
|
189
242
|
{
|
|
190
243
|
name: "repo.create_branch",
|
|
191
244
|
description: "Creates a new clean git branch from a target base branch.",
|
|
192
245
|
inputSchema: CreateBranchInputJsonSchema as any,
|
|
193
|
-
outputSchema:
|
|
246
|
+
outputSchema: CreateBranchResponseJsonSchema as any,
|
|
194
247
|
},
|
|
195
248
|
{
|
|
196
249
|
name: "repo.create_repair_branch",
|
|
197
250
|
description: "Creates a fresh worktree and a new repair branch for an existing PR. This isolates the repair work from the main codebase.",
|
|
198
251
|
inputSchema: CreateRepairBranchInputJsonSchema as any,
|
|
199
|
-
outputSchema:
|
|
252
|
+
outputSchema: CreateRepairBranchResponseJsonSchema as any,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: "repo.check_jules_status",
|
|
256
|
+
description: "Check or poll the status of a Jules remediation session and verify its branch or PR status.",
|
|
257
|
+
inputSchema: {
|
|
258
|
+
type: "object",
|
|
259
|
+
properties: {
|
|
260
|
+
sessionId: { type: "string", description: "The unique ID or task ID of the Jules session." },
|
|
261
|
+
commitSha: { type: "string", description: "Commit SHA for idempotency key verification." },
|
|
262
|
+
failureLog: { type: "string", description: "Failure log content for idempotency key calculation." },
|
|
263
|
+
poll: { type: "boolean", description: "Whether to poll until session completion or timeout." },
|
|
264
|
+
timeoutMs: { type: "integer", description: "Timeout in milliseconds when polling." },
|
|
265
|
+
intervalMs: { type: "integer", description: "Polling interval in milliseconds." },
|
|
266
|
+
},
|
|
267
|
+
} as any,
|
|
268
|
+
outputSchema: CheckJulesStatusResponseJsonSchema as any,
|
|
200
269
|
},
|
|
201
270
|
{
|
|
202
271
|
name: "repo.run_tests",
|
|
203
272
|
description: "Run repository tests and checks.",
|
|
204
273
|
inputSchema: RunTestsInputJsonSchema as any,
|
|
205
|
-
outputSchema:
|
|
274
|
+
outputSchema: RunTestsResponseJsonSchema as any,
|
|
206
275
|
},
|
|
207
276
|
{
|
|
208
277
|
name: "repo.commit_patch",
|
|
209
278
|
description: "Commit verified repair changes in a worktree.",
|
|
210
279
|
inputSchema: CommitPatchInputJsonSchema as any,
|
|
211
|
-
outputSchema:
|
|
280
|
+
outputSchema: CommitPatchResponseJsonSchema as any,
|
|
212
281
|
},
|
|
213
282
|
{
|
|
214
283
|
name: "github.open_replacement_pr",
|
|
215
284
|
description: "Open a new PR that replaces or repairs the original PR.",
|
|
216
285
|
inputSchema: OpenReplacementPrInputJsonSchema as any,
|
|
217
|
-
outputSchema:
|
|
286
|
+
outputSchema: OpenReplacementPrResponseJsonSchema as any,
|
|
218
287
|
},
|
|
219
288
|
{
|
|
220
289
|
name: "github.create_pull_request",
|
|
221
290
|
description: "Creates a pull request on GitHub using the MCP server's integrated credentials. Bypasses terminal CLI constraints.",
|
|
222
291
|
inputSchema: CreatePullRequestInputJsonSchema as any,
|
|
223
|
-
outputSchema:
|
|
292
|
+
outputSchema: CreatePullRequestResponseJsonSchema as any,
|
|
224
293
|
},
|
|
225
294
|
{
|
|
226
295
|
name: "github.comment_triage_summary",
|
|
227
296
|
description: "Comment on the original PR with a diagnosis and replacement link.",
|
|
228
297
|
inputSchema: CommentTriageSummaryInputJsonSchema as any,
|
|
229
|
-
outputSchema:
|
|
298
|
+
outputSchema: CommentTriageSummaryResponseJsonSchema as any,
|
|
230
299
|
},
|
|
231
300
|
{
|
|
232
301
|
name: "github.get_pr",
|
|
233
302
|
description: "Get details of a GitHub PR including title, state, and URLs.",
|
|
234
303
|
inputSchema: GetPrInputJsonSchema as any,
|
|
235
|
-
outputSchema:
|
|
304
|
+
outputSchema: GetPrResponseJsonSchema as any,
|
|
236
305
|
},
|
|
237
306
|
{
|
|
238
307
|
name: "github.get_pr_reviews",
|
|
239
308
|
description: "Get top-level reviews, verdicts, states, and bodies for a GitHub PR.",
|
|
240
309
|
inputSchema: GetPrReviewsInputJsonSchema as any,
|
|
241
|
-
outputSchema:
|
|
310
|
+
outputSchema: GetPrReviewsResponseJsonSchema as any,
|
|
242
311
|
},
|
|
243
312
|
{
|
|
244
313
|
name: "github.get_pr_commits",
|
|
245
314
|
description: "List commits and commit metadata (SHAs, authors, messages) for a GitHub PR.",
|
|
246
315
|
inputSchema: GetPrCommitsInputJsonSchema as any,
|
|
247
|
-
outputSchema:
|
|
316
|
+
outputSchema: GetPrCommitsResponseJsonSchema as any,
|
|
248
317
|
},
|
|
249
318
|
{
|
|
250
319
|
name: "repo.get_workflow_runs",
|
|
251
320
|
description: "List recent GitHub Actions workflow runs for the repository.",
|
|
252
321
|
inputSchema: GetWorkflowRunsInputJsonSchema as any,
|
|
253
|
-
outputSchema:
|
|
322
|
+
outputSchema: GetWorkflowRunsResponseJsonSchema as any,
|
|
254
323
|
},
|
|
255
324
|
{
|
|
256
325
|
name: "github.issue_view",
|
|
257
326
|
description: "View details of a GitHub issue including title, body, and state.",
|
|
258
327
|
inputSchema: IssueViewInputJsonSchema as any,
|
|
259
|
-
outputSchema:
|
|
328
|
+
outputSchema: IssueViewResponseJsonSchema as any,
|
|
260
329
|
},
|
|
261
330
|
{
|
|
262
331
|
name: "github.issue_update",
|
|
263
332
|
description: "Update a GitHub issue's body, labels, and/or state.",
|
|
264
333
|
inputSchema: IssueUpdateInputJsonSchema as any,
|
|
265
|
-
outputSchema:
|
|
334
|
+
outputSchema: IssueUpdateResponseJsonSchema as any,
|
|
266
335
|
},
|
|
267
336
|
{
|
|
268
337
|
name: "github.issue_comment",
|
|
269
338
|
description: "Add a new comment to a GitHub issue.",
|
|
270
339
|
inputSchema: IssueCommentInputJsonSchema as any,
|
|
271
|
-
outputSchema:
|
|
340
|
+
outputSchema: IssueCommentResponseJsonSchema as any,
|
|
272
341
|
},
|
|
273
342
|
{
|
|
274
343
|
name: "github.create_issue",
|
|
275
344
|
description: "Create a new GitHub issue.",
|
|
276
345
|
inputSchema: CreateIssueInputJsonSchema as any,
|
|
277
|
-
outputSchema:
|
|
346
|
+
outputSchema: CreateIssueResponseJsonSchema as any,
|
|
278
347
|
},
|
|
279
348
|
{
|
|
280
349
|
name: "jules.create_session",
|
|
281
350
|
description: "Create a Jules session that performs work externally and may generate a GitHub pull request.",
|
|
282
351
|
inputSchema: CreateJulesSessionInputJsonSchema as any,
|
|
283
|
-
outputSchema:
|
|
352
|
+
outputSchema: JulesSessionResponseJsonSchema as any,
|
|
284
353
|
},
|
|
285
354
|
{
|
|
286
355
|
name: "jules.get_session",
|
|
287
356
|
description: "Get the status and details of a Jules session.",
|
|
288
357
|
inputSchema: JulesSessionIdInputJsonSchema as any,
|
|
289
|
-
outputSchema:
|
|
358
|
+
outputSchema: JulesSessionResponseJsonSchema as any,
|
|
290
359
|
},
|
|
291
360
|
{
|
|
292
361
|
name: "jules.send_message",
|
|
293
362
|
description: "Send a message to an active Jules session.",
|
|
294
363
|
inputSchema: JulesSendMessageInputJsonSchema as any,
|
|
295
|
-
outputSchema:
|
|
364
|
+
outputSchema: JulesSendMessageResponseJsonSchema as any,
|
|
296
365
|
},
|
|
297
366
|
{
|
|
298
367
|
name: "jules.get_messages",
|
|
299
368
|
description: "Get the message history of a Jules session.",
|
|
300
369
|
inputSchema: JulesSessionIdInputJsonSchema as any,
|
|
301
|
-
outputSchema:
|
|
370
|
+
outputSchema: JulesGetMessagesResponseJsonSchema as any,
|
|
302
371
|
},
|
|
303
372
|
{
|
|
304
373
|
name: "jules.list_sessions",
|
|
305
374
|
description: "List all Jules sessions.",
|
|
306
375
|
inputSchema: JulesListSessionsInputJsonSchema as any,
|
|
307
|
-
outputSchema:
|
|
376
|
+
outputSchema: JulesListSessionsResponseJsonSchema as any,
|
|
308
377
|
},
|
|
309
378
|
{
|
|
310
379
|
name: "jules.cancel_session",
|
|
311
380
|
description: "Cancel an ongoing Jules session.",
|
|
312
381
|
inputSchema: JulesSessionIdInputJsonSchema as any,
|
|
313
|
-
outputSchema:
|
|
382
|
+
outputSchema: JulesSessionResponseJsonSchema as any,
|
|
314
383
|
},
|
|
315
384
|
{
|
|
316
385
|
name: "jules.get_pr",
|
|
317
386
|
description: "Get the generated pull request url associated with an active Jules agent session.",
|
|
318
387
|
inputSchema: JulesSessionIdInputJsonSchema as any,
|
|
319
|
-
outputSchema:
|
|
388
|
+
outputSchema: JulesGetPrResponseJsonSchema as any,
|
|
320
389
|
},
|
|
321
390
|
{
|
|
322
391
|
name: "jules.trigger_feedback",
|
|
323
392
|
description: "Automatically collect CI status/logs for the PR associated with a Jules session and send them back as feedback.",
|
|
324
393
|
inputSchema: JulesSessionIdInputJsonSchema as any,
|
|
325
|
-
outputSchema:
|
|
394
|
+
outputSchema: JulesTriggerFeedbackResponseJsonSchema as any,
|
|
326
395
|
},
|
|
327
396
|
];
|
|
328
397
|
|
package/src/mcp/http.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import http from "node:http";
|
|
3
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
3
|
import { createMcpHttpServer } from "./http.js";
|
|
4
|
+
import { BoomtickMCPServer } from "./server.js";
|
|
5
5
|
|
|
6
6
|
describe("createMcpHttpServer", () => {
|
|
7
7
|
let mcpServer: Server;
|
|
@@ -18,19 +18,58 @@ describe("createMcpHttpServer", () => {
|
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
it("should respond with
|
|
21
|
+
it("should respond with 200 on GET /health endpoint", async () => {
|
|
22
|
+
httpServerObj = createMcpHttpServer({ port: 0, mcpServer });
|
|
23
|
+
port = await httpServerObj.listen(0);
|
|
24
|
+
|
|
25
|
+
const res = await fetch(`http://localhost:${port}/health`);
|
|
26
|
+
expect(res.status).toBe(200);
|
|
27
|
+
const body = await res.json();
|
|
28
|
+
expect(body).toEqual({ status: "ok", transport: "http" });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should respond with RFC 9728 OAuth protected resource metadata on /.well-known/oauth-protected-resource", async () => {
|
|
22
32
|
httpServerObj = createMcpHttpServer({ port: 0, mcpServer });
|
|
23
33
|
port = await httpServerObj.listen(0);
|
|
24
34
|
|
|
25
35
|
const res = await fetch(`http://localhost:${port}/.well-known/oauth-protected-resource`);
|
|
26
36
|
expect(res.status).toBe(200);
|
|
37
|
+
expect(res.headers.get("content-type")).toContain("application/json");
|
|
38
|
+
|
|
27
39
|
const body = await res.json();
|
|
28
40
|
expect(body.resource).toBe("mcp://boomtick-mcp");
|
|
29
|
-
expect(body.authorization_servers).
|
|
41
|
+
expect(body.authorization_servers).toEqual(["https://auth.boomtick.dev"]);
|
|
30
42
|
expect(body.scopes_supported).toEqual(["mcp:read", "mcp:write"]);
|
|
43
|
+
expect(body.bearer_methods_supported).toEqual(["header"]);
|
|
44
|
+
expect(body.resource_documentation).toBe("https://github.com/arii/boomtick");
|
|
31
45
|
});
|
|
32
46
|
|
|
33
|
-
it("should
|
|
47
|
+
it("should handle HEAD requests for /.well-known/oauth-protected-resource", async () => {
|
|
48
|
+
httpServerObj = createMcpHttpServer({ port: 0, mcpServer });
|
|
49
|
+
port = await httpServerObj.listen(0);
|
|
50
|
+
|
|
51
|
+
const res = await fetch(`http://localhost:${port}/.well-known/oauth-protected-resource`, {
|
|
52
|
+
method: "HEAD",
|
|
53
|
+
});
|
|
54
|
+
expect(res.status).toBe(200);
|
|
55
|
+
const text = await res.text();
|
|
56
|
+
expect(text).toBe("");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should handle OPTIONS preflight CORS requests", async () => {
|
|
60
|
+
httpServerObj = createMcpHttpServer({ port: 0, mcpServer });
|
|
61
|
+
port = await httpServerObj.listen(0);
|
|
62
|
+
|
|
63
|
+
const res = await fetch(`http://localhost:${port}/sse`, {
|
|
64
|
+
method: "OPTIONS",
|
|
65
|
+
});
|
|
66
|
+
expect(res.status).toBe(204);
|
|
67
|
+
expect(res.headers.get("access-control-allow-origin")).toBe("*");
|
|
68
|
+
expect(res.headers.get("access-control-allow-methods")).toContain("GET");
|
|
69
|
+
expect(res.headers.get("access-control-allow-headers")).toContain("Authorization");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should reject protected requests when Bearer token is missing or invalid", async () => {
|
|
34
73
|
httpServerObj = createMcpHttpServer({ port: 0, bearerToken: "secret123", mcpServer });
|
|
35
74
|
port = await httpServerObj.listen(0);
|
|
36
75
|
|
|
@@ -38,6 +77,7 @@ describe("createMcpHttpServer", () => {
|
|
|
38
77
|
const res1 = await fetch(`http://localhost:${port}/sse`);
|
|
39
78
|
expect(res1.status).toBe(401);
|
|
40
79
|
expect(res1.headers.get("www-authenticate")).toContain('Bearer realm="boomtick-mcp"');
|
|
80
|
+
expect(res1.headers.get("www-authenticate")).toContain('error="invalid_token"');
|
|
41
81
|
|
|
42
82
|
// Request with wrong token
|
|
43
83
|
const res2 = await fetch(`http://localhost:${port}/sse`, {
|
|
@@ -45,7 +85,7 @@ describe("createMcpHttpServer", () => {
|
|
|
45
85
|
});
|
|
46
86
|
expect(res2.status).toBe(401);
|
|
47
87
|
|
|
48
|
-
//
|
|
88
|
+
// Public resource metadata accessible with or without token
|
|
49
89
|
const res3 = await fetch(`http://localhost:${port}/.well-known/oauth-protected-resource`, {
|
|
50
90
|
headers: { Authorization: "Bearer secret123" },
|
|
51
91
|
});
|
|
@@ -69,4 +109,34 @@ describe("createMcpHttpServer", () => {
|
|
|
69
109
|
const body = await res.json();
|
|
70
110
|
expect(body.error).toContain("Server misconfiguration");
|
|
71
111
|
});
|
|
112
|
+
|
|
113
|
+
it("should return 400 for message requests without session or invalid session", async () => {
|
|
114
|
+
httpServerObj = createMcpHttpServer({ port: 0, bearerToken: "secret123", mcpServer });
|
|
115
|
+
port = await httpServerObj.listen(0);
|
|
116
|
+
|
|
117
|
+
const res = await fetch(`http://localhost:${port}/messages?sessionId=invalid_session`, {
|
|
118
|
+
method: "POST",
|
|
119
|
+
headers: {
|
|
120
|
+
Authorization: "Bearer secret123",
|
|
121
|
+
"Content-Type": "application/json",
|
|
122
|
+
},
|
|
123
|
+
body: JSON.stringify({ jsonrpc: "2.0", method: "ping", id: 1 }),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(res.status).toBe(400);
|
|
127
|
+
const body = await res.json();
|
|
128
|
+
expect(body.error).toContain("Session not found or expired");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("should allow BoomtickMCPServer to start HTTP server via run() when transport is http", async () => {
|
|
132
|
+
process.env.MCP_TRANSPORT = "http";
|
|
133
|
+
process.env.PORT = "0";
|
|
134
|
+
process.env.BOOMTICK_MCP_BEARER_TOKEN = "test-token";
|
|
135
|
+
|
|
136
|
+
const boomtickServer = new BoomtickMCPServer();
|
|
137
|
+
await boomtickServer.run();
|
|
138
|
+
|
|
139
|
+
// Verify instance initialized properly
|
|
140
|
+
expect(boomtickServer).toBeInstanceOf(BoomtickMCPServer);
|
|
141
|
+
});
|
|
72
142
|
});
|
package/src/mcp/http.ts
CHANGED
|
@@ -21,7 +21,7 @@ export function createMcpHttpServer(options: HttpServerOptions) {
|
|
|
21
21
|
const server = http.createServer(async (req, res) => {
|
|
22
22
|
// CORS Headers
|
|
23
23
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
24
|
-
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
24
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, HEAD");
|
|
25
25
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
26
26
|
|
|
27
27
|
if (req.method === "OPTIONS") {
|
|
@@ -32,22 +32,35 @@ export function createMcpHttpServer(options: HttpServerOptions) {
|
|
|
32
32
|
|
|
33
33
|
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
34
34
|
|
|
35
|
-
// Endpoint
|
|
36
|
-
if (url.pathname === "
|
|
35
|
+
// Endpoint 0: Health check endpoint for readiness probes / load balancers
|
|
36
|
+
if (url.pathname === "/health" && req.method === "GET") {
|
|
37
37
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
38
|
-
res.end(
|
|
39
|
-
JSON.stringify({
|
|
40
|
-
resource: "mcp://boomtick-mcp",
|
|
41
|
-
"authorization_servers": [
|
|
42
|
-
process.env.MCP_OAUTH_AUTH_SERVER || "https://auth.boomtick.dev",
|
|
43
|
-
],
|
|
44
|
-
scopes_supported: ["mcp:read", "mcp:write"],
|
|
45
|
-
})
|
|
46
|
-
);
|
|
38
|
+
res.end(JSON.stringify({ status: "ok", transport: "http" }));
|
|
47
39
|
return;
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
//
|
|
42
|
+
// Endpoint 1: RFC 9728 OAuth Protected Resource Metadata Discovery
|
|
43
|
+
if (url.pathname === "/.well-known/oauth-protected-resource" && (req.method === "GET" || req.method === "HEAD")) {
|
|
44
|
+
const metadata = {
|
|
45
|
+
resource: process.env.MCP_RESOURCE_URI || process.env.BOOMTICK_RESOURCE_URI || "mcp://boomtick-mcp",
|
|
46
|
+
authorization_servers: [
|
|
47
|
+
process.env.MCP_OAUTH_AUTH_SERVER || "https://auth.boomtick.dev",
|
|
48
|
+
],
|
|
49
|
+
scopes_supported: ["mcp:read", "mcp:write"],
|
|
50
|
+
bearer_methods_supported: ["header"],
|
|
51
|
+
resource_documentation: process.env.MCP_RESOURCE_DOCS || "https://github.com/arii/boomtick",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
55
|
+
if (req.method === "HEAD") {
|
|
56
|
+
res.end();
|
|
57
|
+
} else {
|
|
58
|
+
res.end(JSON.stringify(metadata, null, 2));
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Bearer Token / OAuth 2.1 Validation for Protected Routes (/sse & /messages)
|
|
51
64
|
if (url.pathname === "/sse" || url.pathname === "/messages") {
|
|
52
65
|
if (!bearerToken) {
|
|
53
66
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
@@ -67,7 +80,7 @@ export function createMcpHttpServer(options: HttpServerOptions) {
|
|
|
67
80
|
if (!isMatch) {
|
|
68
81
|
res.writeHead(401, {
|
|
69
82
|
"Content-Type": "application/json",
|
|
70
|
-
"WWW-Authenticate": 'Bearer realm="boomtick-mcp", error="invalid_token"',
|
|
83
|
+
"WWW-Authenticate": 'Bearer realm="boomtick-mcp", error="invalid_token", error_description="Invalid or missing Bearer token"',
|
|
71
84
|
});
|
|
72
85
|
res.end(JSON.stringify({ error: "unauthorized", message: "Invalid or missing Bearer token" }));
|
|
73
86
|
return;
|
|
@@ -76,11 +89,24 @@ export function createMcpHttpServer(options: HttpServerOptions) {
|
|
|
76
89
|
|
|
77
90
|
// Endpoint 2: SSE stream setup
|
|
78
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
|
+
|
|
79
96
|
const transport = new SSEServerTransport("/messages", res);
|
|
80
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
|
+
|
|
81
105
|
transport.onclose = () => {
|
|
106
|
+
clearInterval(keepAliveInterval);
|
|
82
107
|
transports.delete(transport.sessionId);
|
|
83
108
|
};
|
|
109
|
+
|
|
84
110
|
await mcpServer.connect(transport);
|
|
85
111
|
return;
|
|
86
112
|
}
|