@arii/boomtick-mcp 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mcp/schemas/github.create_issue.json +72 -3
- package/.mcp/schemas/github.get_merge_conflict_files.json +40 -3
- package/.mcp/schemas/github.get_pr_diff.json +30 -3
- package/.mcp/schemas/github.issue_update.json +72 -3
- package/.mcp/schemas/github.search_open_prs.json +130 -3
- package/.mcp/schemas/github_create_issue.json +72 -3
- package/.mcp/schemas/github_get_merge_conflict_files.json +40 -3
- package/.mcp/schemas/github_get_pr_diff.json +30 -3
- package/.mcp/schemas/github_issue_update.json +72 -3
- package/.mcp/schemas/github_search_open_prs.json +130 -3
- package/.mcp/schemas/repo.check_jules_status.json +38 -0
- package/.mcp/schemas/repo.run_tests.json +31 -3
- package/.mcp/schemas/repo_check_jules_status.json +38 -0
- package/.mcp/schemas/repo_run_tests.json +31 -3
- package/CHANGELOG.md +15 -0
- package/README.md +22 -1
- package/actions/run-project-gate/action.yml +1 -1
- package/dist/config/dynamic.js +33 -0
- package/dist/config/github.js +16 -0
- package/dist/config/repo.js +28 -0
- package/dist/config.js +16 -81
- package/dist/http.js +10 -0
- package/dist/mcp/definitions.js +29 -7
- package/dist/mcp/http.js +18 -10
- package/dist/mcp/http.test.js +54 -4
- package/dist/mcp/server.js +47 -10
- package/dist/mcp/server.test.js +52 -1
- package/dist/tools/contract.js +77 -0
- 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_commits.js +1 -1
- package/dist/tools/github.get_pr_diff.js +3 -11
- package/dist/tools/github.get_pr_reviews.js +1 -1
- package/dist/tools/jules/cancel-session.js +2 -9
- package/dist/tools/jules/cli.js +31 -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.get_workflow_runs.js +1 -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 +36 -0
- package/src/config/github.ts +16 -0
- package/src/config/repo.ts +36 -0
- package/src/config.ts +16 -89
- package/src/http.ts +13 -0
- package/src/mcp/definitions.ts +34 -6
- package/src/mcp/http.test.ts +65 -5
- package/src/mcp/http.ts +20 -14
- package/src/mcp/server.test.ts +62 -1
- package/src/mcp/server.ts +48 -11
- package/src/tools/contract.ts +85 -0
- 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_commits.ts +1 -1
- package/src/tools/github.get_pr_diff.ts +3 -13
- package/src/tools/github.get_pr_reviews.ts +1 -1
- package/src/tools/jules/cancel-session.ts +2 -11
- package/src/tools/jules/cli.ts +42 -0
- 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.get_workflow_runs.ts +1 -1
- package/src/tools/repo.run_tests.ts +14 -1
|
@@ -63,8 +63,135 @@
|
|
|
63
63
|
"type": "object"
|
|
64
64
|
},
|
|
65
65
|
"outputSchema": {
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
"$defs": {
|
|
67
|
+
"PRSummary": {
|
|
68
|
+
"properties": {
|
|
69
|
+
"number": {
|
|
70
|
+
"title": "Number",
|
|
71
|
+
"type": "integer"
|
|
72
|
+
},
|
|
73
|
+
"title": {
|
|
74
|
+
"title": "Title",
|
|
75
|
+
"type": "string"
|
|
76
|
+
},
|
|
77
|
+
"author": {
|
|
78
|
+
"additionalProperties": {
|
|
79
|
+
"type": "string"
|
|
80
|
+
},
|
|
81
|
+
"title": "Author",
|
|
82
|
+
"type": "object"
|
|
83
|
+
},
|
|
84
|
+
"headRefName": {
|
|
85
|
+
"anyOf": [
|
|
86
|
+
{
|
|
87
|
+
"type": "string"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"type": "null"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"default": null,
|
|
94
|
+
"title": "Headrefname"
|
|
95
|
+
},
|
|
96
|
+
"baseRefName": {
|
|
97
|
+
"anyOf": [
|
|
98
|
+
{
|
|
99
|
+
"type": "string"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"type": "null"
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"default": null,
|
|
106
|
+
"title": "Baserefname"
|
|
107
|
+
},
|
|
108
|
+
"isDraft": {
|
|
109
|
+
"default": false,
|
|
110
|
+
"title": "Isdraft",
|
|
111
|
+
"type": "boolean"
|
|
112
|
+
},
|
|
113
|
+
"mergeStateStatus": {
|
|
114
|
+
"anyOf": [
|
|
115
|
+
{
|
|
116
|
+
"type": "string"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"type": "null"
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"default": null,
|
|
123
|
+
"title": "Mergestatestatus"
|
|
124
|
+
},
|
|
125
|
+
"updatedAt": {
|
|
126
|
+
"anyOf": [
|
|
127
|
+
{
|
|
128
|
+
"type": "string"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"type": "null"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"default": null,
|
|
135
|
+
"title": "Updatedat"
|
|
136
|
+
},
|
|
137
|
+
"url": {
|
|
138
|
+
"anyOf": [
|
|
139
|
+
{
|
|
140
|
+
"type": "string"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"type": "null"
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
"default": null,
|
|
147
|
+
"title": "Url"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"required": [
|
|
151
|
+
"number",
|
|
152
|
+
"title"
|
|
153
|
+
],
|
|
154
|
+
"title": "PRSummary",
|
|
155
|
+
"type": "object"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"properties": {
|
|
159
|
+
"status": {
|
|
160
|
+
"default": "success",
|
|
161
|
+
"title": "Status",
|
|
162
|
+
"type": "string"
|
|
163
|
+
},
|
|
164
|
+
"message": {
|
|
165
|
+
"anyOf": [
|
|
166
|
+
{
|
|
167
|
+
"type": "string"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"type": "null"
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"default": null,
|
|
174
|
+
"title": "Message"
|
|
175
|
+
},
|
|
176
|
+
"data": {
|
|
177
|
+
"anyOf": [
|
|
178
|
+
{},
|
|
179
|
+
{
|
|
180
|
+
"type": "null"
|
|
181
|
+
}
|
|
182
|
+
],
|
|
183
|
+
"default": null,
|
|
184
|
+
"title": "Data"
|
|
185
|
+
},
|
|
186
|
+
"prs": {
|
|
187
|
+
"items": {
|
|
188
|
+
"$ref": "#/$defs/PRSummary"
|
|
189
|
+
},
|
|
190
|
+
"title": "Prs",
|
|
191
|
+
"type": "array"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
"title": "SearchPRsResponse",
|
|
195
|
+
"type": "object"
|
|
69
196
|
}
|
|
70
197
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "repo.check_jules_status",
|
|
3
|
+
"description": "Check or poll the status of a Jules remediation session and verify its branch or PR status.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"sessionId": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The unique ID or task ID of the Jules session."
|
|
10
|
+
},
|
|
11
|
+
"commitSha": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Commit SHA for idempotency key verification."
|
|
14
|
+
},
|
|
15
|
+
"failureLog": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Failure log content for idempotency key calculation."
|
|
18
|
+
},
|
|
19
|
+
"poll": {
|
|
20
|
+
"type": "boolean",
|
|
21
|
+
"description": "Whether to poll until session completion or timeout."
|
|
22
|
+
},
|
|
23
|
+
"timeoutMs": {
|
|
24
|
+
"type": "integer",
|
|
25
|
+
"description": "Timeout in milliseconds when polling."
|
|
26
|
+
},
|
|
27
|
+
"intervalMs": {
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"description": "Polling interval in milliseconds."
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"outputSchema": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {},
|
|
36
|
+
"additionalProperties": true
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -43,8 +43,36 @@
|
|
|
43
43
|
"type": "object"
|
|
44
44
|
},
|
|
45
45
|
"outputSchema": {
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
"properties": {
|
|
47
|
+
"passed": {
|
|
48
|
+
"title": "Passed",
|
|
49
|
+
"type": "boolean"
|
|
50
|
+
},
|
|
51
|
+
"exitCode": {
|
|
52
|
+
"title": "Exitcode",
|
|
53
|
+
"type": "integer"
|
|
54
|
+
},
|
|
55
|
+
"failedTests": {
|
|
56
|
+
"items": {
|
|
57
|
+
"type": "string"
|
|
58
|
+
},
|
|
59
|
+
"title": "Failedtests",
|
|
60
|
+
"type": "array"
|
|
61
|
+
},
|
|
62
|
+
"results": {
|
|
63
|
+
"items": {
|
|
64
|
+
"additionalProperties": true,
|
|
65
|
+
"type": "object"
|
|
66
|
+
},
|
|
67
|
+
"title": "Results",
|
|
68
|
+
"type": "array"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"required": [
|
|
72
|
+
"passed",
|
|
73
|
+
"exitCode"
|
|
74
|
+
],
|
|
75
|
+
"title": "RunTestsResponse",
|
|
76
|
+
"type": "object"
|
|
49
77
|
}
|
|
50
78
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "repo_check_jules_status",
|
|
3
|
+
"description": "Check or poll the status of a Jules remediation session and verify its branch or PR status.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"sessionId": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The unique ID or task ID of the Jules session."
|
|
10
|
+
},
|
|
11
|
+
"commitSha": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Commit SHA for idempotency key verification."
|
|
14
|
+
},
|
|
15
|
+
"failureLog": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Failure log content for idempotency key calculation."
|
|
18
|
+
},
|
|
19
|
+
"poll": {
|
|
20
|
+
"type": "boolean",
|
|
21
|
+
"description": "Whether to poll until session completion or timeout."
|
|
22
|
+
},
|
|
23
|
+
"timeoutMs": {
|
|
24
|
+
"type": "integer",
|
|
25
|
+
"description": "Timeout in milliseconds when polling."
|
|
26
|
+
},
|
|
27
|
+
"intervalMs": {
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"description": "Polling interval in milliseconds."
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"outputSchema": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {},
|
|
36
|
+
"additionalProperties": true
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -43,8 +43,36 @@
|
|
|
43
43
|
"type": "object"
|
|
44
44
|
},
|
|
45
45
|
"outputSchema": {
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
"properties": {
|
|
47
|
+
"passed": {
|
|
48
|
+
"title": "Passed",
|
|
49
|
+
"type": "boolean"
|
|
50
|
+
},
|
|
51
|
+
"exitCode": {
|
|
52
|
+
"title": "Exitcode",
|
|
53
|
+
"type": "integer"
|
|
54
|
+
},
|
|
55
|
+
"failedTests": {
|
|
56
|
+
"items": {
|
|
57
|
+
"type": "string"
|
|
58
|
+
},
|
|
59
|
+
"title": "Failedtests",
|
|
60
|
+
"type": "array"
|
|
61
|
+
},
|
|
62
|
+
"results": {
|
|
63
|
+
"items": {
|
|
64
|
+
"additionalProperties": true,
|
|
65
|
+
"type": "object"
|
|
66
|
+
},
|
|
67
|
+
"title": "Results",
|
|
68
|
+
"type": "array"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"required": [
|
|
72
|
+
"passed",
|
|
73
|
+
"exitCode"
|
|
74
|
+
],
|
|
75
|
+
"title": "RunTestsResponse",
|
|
76
|
+
"type": "object"
|
|
49
77
|
}
|
|
50
78
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.2](https://github.com/arii/boomtick/compare/mcp-v0.6.1...mcp-v0.6.2) (2026-10-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **ci:** fix release pipeline schema generation and issue quality check on automated alerts [skip-scope-check] ([#956](https://github.com/arii/boomtick/issues/956)) ([a0e6114](https://github.com/arii/boomtick/commit/a0e6114e33dac799313f36f363de6008477cebfe))
|
|
9
|
+
* **cli:** Eliminate runtime sys.path mutations in schema_gen.py ([#967](https://github.com/arii/boomtick/issues/967)) ([e1654de](https://github.com/arii/boomtick/commit/e1654dec8cf4af0da08d0808ee815e39cb9ab634))
|
|
10
|
+
|
|
11
|
+
## [0.6.1](https://github.com/arii/boomtick/compare/mcp-v0.6.0...mcp-v0.6.1) (2026-10-23)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* **mcp:** mount missing handlers for github_get_pr_reviews, github_get_pr_commits, and repo_get_workflow_runs [skip-scope-check] ([#916](https://github.com/arii/boomtick/issues/916)) ([60a2851](https://github.com/arii/boomtick/commit/60a2851a2f2d5ac8010422796573b7ea20bb6767))
|
|
17
|
+
|
|
3
18
|
## [0.6.0](https://github.com/arii/boomtick/compare/mcp-v0.5.0...mcp-v0.6.0) (2026-10-22)
|
|
4
19
|
|
|
5
20
|
|
package/README.md
CHANGED
|
@@ -75,11 +75,32 @@ BOOMTICK_REPO_PATH=/path/to/repo
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
## Usage
|
|
78
|
-
|
|
78
|
+
|
|
79
|
+
### Stdio Transport
|
|
80
|
+
Run the server via stdio (ideal for local CLI workflows and Docker container actions):
|
|
79
81
|
```bash
|
|
80
82
|
node dist/index.js
|
|
81
83
|
```
|
|
82
84
|
|
|
85
|
+
### Streamable HTTP Transport & Remote Networked Access
|
|
86
|
+
For hosted agent harnesses (e.g. Google Gemini Agent endpoints, remote DevAI dashboards) requiring network transport with Bearer token / OAuth 2.1 authentication and RFC 9728 metadata discovery:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Run HTTP entrypoint directly
|
|
90
|
+
node dist/http.js --port 3000 --bearer-token secret123
|
|
91
|
+
|
|
92
|
+
# Or via CLI binary entrypoint
|
|
93
|
+
boomtick-mcp-http --port 3000 --bearer-token secret123
|
|
94
|
+
|
|
95
|
+
# Or using environment variables
|
|
96
|
+
MCP_TRANSPORT=http PORT=3000 BOOMTICK_MCP_BEARER_TOKEN=secret123 node dist/index.js
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Network Endpoints & RFC 9728 Discovery
|
|
100
|
+
- `GET /.well-known/oauth-protected-resource`: OAuth 2.0 / 2.1 Protected Resource Metadata discovery endpoint (RFC 9728).
|
|
101
|
+
- `GET /sse`: Server-Sent Events (SSE) stream endpoint for MCP connections (Protected via Bearer token).
|
|
102
|
+
- `POST /messages?sessionId=...`: MCP client JSON-RPC message posting endpoint (Protected via Bearer token).
|
|
103
|
+
|
|
83
104
|
## Release Process
|
|
84
105
|
1. Run tests: `pnpm test`
|
|
85
106
|
2. Run evals: `pnpm run run-evals`
|
|
@@ -94,7 +94,7 @@ runs:
|
|
|
94
94
|
if command -v td >/dev/null 2>&1; then
|
|
95
95
|
PYTHONPATH="$CLI_PATH" td schema --generate
|
|
96
96
|
else
|
|
97
|
-
PYTHONPATH="$CLI_PATH" python3
|
|
97
|
+
PYTHONPATH="$CLI_PATH" python3 -m dev_tools.schema_gen
|
|
98
98
|
fi
|
|
99
99
|
npx tsx "$FILTER_PATH/scripts/sync-contracts.ts"
|
|
100
100
|
pnpm --filter "$FILTER_PATH" run sync:mcp-schemas
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
let cachedDynamicConfig = null;
|
|
3
|
+
export function initializeConfig() {
|
|
4
|
+
if (cachedDynamicConfig !== null) {
|
|
5
|
+
return cachedDynamicConfig;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
const cwd = process.env.BOOMTICK_REPO_PATH || process.cwd();
|
|
9
|
+
const cmd = `td config view`;
|
|
10
|
+
const output = execSync(cmd, {
|
|
11
|
+
cwd,
|
|
12
|
+
encoding: "utf-8",
|
|
13
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
14
|
+
});
|
|
15
|
+
cachedDynamicConfig = JSON.parse(output);
|
|
16
|
+
return cachedDynamicConfig;
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
20
|
+
const errorPrefix = `CRITICAL: Failed to load dynamic config from Python CLI. Ensure Python 3 is installed and cli is in your PYTHONPATH. Details: ${message}`;
|
|
21
|
+
if (process.env.NODE_ENV === "development" || process.env.CI === "true") {
|
|
22
|
+
throw new Error(errorPrefix);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.warn(errorPrefix);
|
|
26
|
+
}
|
|
27
|
+
cachedDynamicConfig = {};
|
|
28
|
+
}
|
|
29
|
+
return cachedDynamicConfig;
|
|
30
|
+
}
|
|
31
|
+
export function getCachedDynamicConfig() {
|
|
32
|
+
return cachedDynamicConfig;
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
export function getGithubToken() {
|
|
3
|
+
if (process.env.GITHUB_TOKEN) {
|
|
4
|
+
return process.env.GITHUB_TOKEN;
|
|
5
|
+
}
|
|
6
|
+
try {
|
|
7
|
+
const token = execSync("gh auth token", { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
8
|
+
if (token) {
|
|
9
|
+
return token;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
/* ignore to allow fallback */
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
export function findRepoRoot() {
|
|
6
|
+
if (process.env.BOOMTICK_REPO_PATH) {
|
|
7
|
+
return process.env.BOOMTICK_REPO_PATH;
|
|
8
|
+
}
|
|
9
|
+
let current = process.cwd();
|
|
10
|
+
while (current !== path.parse(current).root) {
|
|
11
|
+
if (fs.existsSync(path.join(current, "project_config.json")) ||
|
|
12
|
+
fs.existsSync(path.join(current, "workspace.json")) ||
|
|
13
|
+
fs.existsSync(path.join(current, ".git"))) {
|
|
14
|
+
return current;
|
|
15
|
+
}
|
|
16
|
+
current = path.dirname(current);
|
|
17
|
+
}
|
|
18
|
+
current = __dirname;
|
|
19
|
+
while (current !== path.parse(current).root) {
|
|
20
|
+
if (fs.existsSync(path.join(current, "project_config.json")) ||
|
|
21
|
+
fs.existsSync(path.join(current, "workspace.json")) ||
|
|
22
|
+
fs.existsSync(path.join(current, ".git"))) {
|
|
23
|
+
return current;
|
|
24
|
+
}
|
|
25
|
+
current = path.dirname(current);
|
|
26
|
+
}
|
|
27
|
+
return path.resolve(__dirname, "../../../../");
|
|
28
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
|
-
import {
|
|
4
|
+
import { findRepoRoot } from "./config/repo.js";
|
|
5
|
+
import { getGithubToken } from "./config/github.js";
|
|
6
|
+
import { initializeConfig, getCachedDynamicConfig } from "./config/dynamic.js";
|
|
5
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
8
|
const envPath = path.resolve(__dirname, "../.env");
|
|
7
9
|
if (fs.existsSync(envPath) && typeof process.loadEnvFile === "function") {
|
|
@@ -12,84 +14,13 @@ if (fs.existsSync(envPath) && typeof process.loadEnvFile === "function") {
|
|
|
12
14
|
// Ignore if already loaded or invalid
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
|
-
|
|
16
|
-
if (process.env.GITHUB_TOKEN) {
|
|
17
|
-
return process.env.GITHUB_TOKEN;
|
|
18
|
-
}
|
|
19
|
-
try {
|
|
20
|
-
const token = execSync("gh auth token", { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
21
|
-
if (token) {
|
|
22
|
-
return token;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
catch (e) { /* ignore to allow fallback */ }
|
|
26
|
-
return undefined;
|
|
27
|
-
}
|
|
28
|
-
let cachedDynamicConfig = null;
|
|
29
|
-
/**
|
|
30
|
-
* Explicitly initializes dynamic configuration from the Python CLI.
|
|
31
|
-
* Should be called once during server startup.
|
|
32
|
-
*/
|
|
33
|
-
export function initializeConfig() {
|
|
34
|
-
if (cachedDynamicConfig !== null) {
|
|
35
|
-
return cachedDynamicConfig;
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
// Attempt to load core properties from the Python CLI in the active workspace
|
|
39
|
-
const cwd = process.env.BOOMTICK_REPO_PATH || process.cwd();
|
|
40
|
-
const cmd = `td config view`;
|
|
41
|
-
const output = execSync(cmd, {
|
|
42
|
-
cwd,
|
|
43
|
-
encoding: "utf-8",
|
|
44
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
45
|
-
});
|
|
46
|
-
cachedDynamicConfig = JSON.parse(output);
|
|
47
|
-
return cachedDynamicConfig;
|
|
48
|
-
}
|
|
49
|
-
catch (e) {
|
|
50
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
51
|
-
const errorPrefix = `CRITICAL: Failed to load dynamic config from Python CLI. Ensure Python 3 is installed and cli is in your PYTHONPATH. Details: ${message}`;
|
|
52
|
-
if (process.env.NODE_ENV === "development" || process.env.CI === "true") {
|
|
53
|
-
throw new Error(errorPrefix);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
console.warn(errorPrefix);
|
|
57
|
-
}
|
|
58
|
-
// Set an empty object to prevent repeated attempts if initialization fails in non-blocking mode
|
|
59
|
-
cachedDynamicConfig = {};
|
|
60
|
-
}
|
|
61
|
-
return cachedDynamicConfig;
|
|
62
|
-
}
|
|
63
|
-
function findRepoRoot() {
|
|
64
|
-
if (process.env.BOOMTICK_REPO_PATH) {
|
|
65
|
-
return process.env.BOOMTICK_REPO_PATH;
|
|
66
|
-
}
|
|
67
|
-
// Traverse up from process.cwd() to find project_config.json, workspace.json, or .git
|
|
68
|
-
let current = process.cwd();
|
|
69
|
-
while (current !== path.parse(current).root) {
|
|
70
|
-
if (fs.existsSync(path.join(current, "project_config.json")) ||
|
|
71
|
-
fs.existsSync(path.join(current, "workspace.json")) ||
|
|
72
|
-
fs.existsSync(path.join(current, ".git"))) {
|
|
73
|
-
return current;
|
|
74
|
-
}
|
|
75
|
-
current = path.dirname(current);
|
|
76
|
-
}
|
|
77
|
-
// Fallback to __dirname search if discovery from cwd fails
|
|
78
|
-
current = __dirname;
|
|
79
|
-
while (current !== path.parse(current).root) {
|
|
80
|
-
if (fs.existsSync(path.join(current, "project_config.json")) ||
|
|
81
|
-
fs.existsSync(path.join(current, "workspace.json")) ||
|
|
82
|
-
fs.existsSync(path.join(current, ".git"))) {
|
|
83
|
-
return current;
|
|
84
|
-
}
|
|
85
|
-
current = path.dirname(current);
|
|
86
|
-
}
|
|
87
|
-
// Fallback to the monolithic relative path if discovery fails
|
|
88
|
-
return path.resolve(__dirname, "../../../");
|
|
89
|
-
}
|
|
17
|
+
export { initializeConfig };
|
|
90
18
|
export const config = {
|
|
91
|
-
get githubToken() {
|
|
19
|
+
get githubToken() {
|
|
20
|
+
return getGithubToken();
|
|
21
|
+
},
|
|
92
22
|
get githubOwner() {
|
|
23
|
+
const cachedDynamicConfig = getCachedDynamicConfig();
|
|
93
24
|
const repoString = cachedDynamicConfig?.github_repo;
|
|
94
25
|
if (typeof repoString === "string" && repoString.includes("/")) {
|
|
95
26
|
return repoString.split("/")[0];
|
|
@@ -103,6 +34,7 @@ export const config = {
|
|
|
103
34
|
throw new Error("GITHUB_OWNER must be set via environment variable or project_config.json");
|
|
104
35
|
},
|
|
105
36
|
get githubRepo() {
|
|
37
|
+
const cachedDynamicConfig = getCachedDynamicConfig();
|
|
106
38
|
const repoString = cachedDynamicConfig?.github_repo;
|
|
107
39
|
if (typeof repoString === "string" && repoString.includes("/")) {
|
|
108
40
|
return repoString.split("/")[1];
|
|
@@ -119,16 +51,19 @@ export const config = {
|
|
|
119
51
|
return findRepoRoot();
|
|
120
52
|
},
|
|
121
53
|
get defaultBaseBranch() {
|
|
54
|
+
const cachedDynamicConfig = getCachedDynamicConfig();
|
|
122
55
|
return process.env.DEFAULT_BASE_BRANCH || cachedDynamicConfig?.base_branch?.split("/").pop() || "main";
|
|
123
56
|
},
|
|
124
57
|
get viteBasePath() {
|
|
125
|
-
const
|
|
126
|
-
|
|
58
|
+
const cachedDynamicConfig = getCachedDynamicConfig();
|
|
59
|
+
const pathValue = process.env.VITE_BASE_PATH || cachedDynamicConfig?.vite_base_path;
|
|
60
|
+
if (!pathValue) {
|
|
127
61
|
throw new Error("VITE_BASE_PATH must be set via environment variable or project_config.json");
|
|
128
62
|
}
|
|
129
|
-
return
|
|
63
|
+
return pathValue;
|
|
130
64
|
},
|
|
131
65
|
get ghPath() {
|
|
66
|
+
const cachedDynamicConfig = getCachedDynamicConfig();
|
|
132
67
|
return process.env.GH_PATH || cachedDynamicConfig?.gh_path || "gh";
|
|
133
|
-
}
|
|
68
|
+
},
|
|
134
69
|
};
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { BoomtickMCPServer } from "./mcp/server.js";
|
|
3
|
+
import { initializeConfig } from "./config.js";
|
|
4
|
+
initializeConfig();
|
|
5
|
+
process.env.MCP_TRANSPORT = "http";
|
|
6
|
+
const server = new BoomtickMCPServer();
|
|
7
|
+
server.run().catch((error) => {
|
|
8
|
+
console.error("Fatal error running HTTP server:", error);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
});
|