@almightygpt/core 0.8.1 → 0.9.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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +42 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +317 -0
- package/dist/mcp/server.js.map +1 -0
- package/package.json +2 -1
- package/src/index.ts +4 -1
- package/src/mcp/server.ts +361 -0
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
* - review/ ✅ task #11 diff review pipeline (with #12/#13/#14 wiring)
|
|
13
13
|
* - budget/ ✅ task #14 BudgetTracker + BudgetExceededError
|
|
14
14
|
*/
|
|
15
|
-
export declare const VERSION = "0.
|
|
15
|
+
export declare const VERSION = "0.9.0";
|
|
16
|
+
export { startMcpServer } from "./mcp/server.js";
|
|
16
17
|
export { checkGitStatus, assertSafeToWrite, GitStatusDirtyError, type GitStatusCheck, } from "./git/status.js";
|
|
17
18
|
export { installTemplate, hasExistingConfig, type InstallOptions, type InstallResult, } from "./templates/install.js";
|
|
18
19
|
export { loadConfig, ConfigError } from "./config/load.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,aAAa,EACb,aAAa,EACb,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,aAAa,EACb,aAAa,EACb,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* - review/ ✅ task #11 diff review pipeline (with #12/#13/#14 wiring)
|
|
13
13
|
* - budget/ ✅ task #14 BudgetTracker + BudgetExceededError
|
|
14
14
|
*/
|
|
15
|
-
export const VERSION = "0.
|
|
15
|
+
export const VERSION = "0.9.0";
|
|
16
|
+
// MCP server (v0.9.0+) — exposes AlmightyGPT's review surface as MCP tools.
|
|
17
|
+
export { startMcpServer } from "./mcp/server.js";
|
|
16
18
|
// Git safety primitives
|
|
17
19
|
export { checkGitStatus, assertSafeToWrite, GitStatusDirtyError, } from "./git/status.js";
|
|
18
20
|
// Template installer
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,wBAAwB;AACxB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,eAAe,EACf,iBAAiB,GAGlB,MAAM,wBAAwB,CAAC;AAEhC,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAGhB,MAAM,oBAAoB,CAAC;AAE5B,WAAW;AACX,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GAQd,MAAM,qBAAqB,CAAC;AAE7B,sBAAsB;AACtB,OAAO,EAAE,aAAa,EAA6C,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GAGrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO;AACP,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,GAIf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,GAGf,MAAM,kBAAkB,CAAC;AAE1B,kBAAkB;AAClB,OAAO,EACL,aAAa,GAGd,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,GAGxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAqC,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAE7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC;AAO5B,2DAA2D;AAC3D,OAAO,EACL,aAAa,EACb,aAAa,GAEd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAIlB,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,4EAA4E;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,wBAAwB;AACxB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,eAAe,EACf,iBAAiB,GAGlB,MAAM,wBAAwB,CAAC;AAEhC,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAGhB,MAAM,oBAAoB,CAAC;AAE5B,WAAW;AACX,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GAQd,MAAM,qBAAqB,CAAC;AAE7B,sBAAsB;AACtB,OAAO,EAAE,aAAa,EAA6C,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GAGrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO;AACP,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,GAIf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,GAGf,MAAM,kBAAkB,CAAC;AAE1B,kBAAkB;AAClB,OAAO,EACL,aAAa,GAGd,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,GAGxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAqC,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAE7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC;AAO5B,2DAA2D;AAC3D,OAAO,EACL,aAAa,EACb,aAAa,GAEd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAIlB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlmightyGPT MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the AlmightyGPT CLI's review/precommit/auth/runs surface as
|
|
5
|
+
* Model Context Protocol tools, so MCP-aware clients (Claude Desktop,
|
|
6
|
+
* Cursor, Continue, etc.) can invoke them directly.
|
|
7
|
+
*
|
|
8
|
+
* Transport: stdio (the default for local MCP servers). Spawned from
|
|
9
|
+
* the user's MCP client config — typically something like:
|
|
10
|
+
*
|
|
11
|
+
* {
|
|
12
|
+
* "mcpServers": {
|
|
13
|
+
* "almightygpt": {
|
|
14
|
+
* "command": "almightygpt",
|
|
15
|
+
* "args": ["mcp", "serve"]
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* Tool surface (v0.9.0):
|
|
21
|
+
* - review_diff: run a Worker/Reviewer or Reviewer-only review on a diff
|
|
22
|
+
* - precommit: quick last-mile review of uncommitted changes
|
|
23
|
+
* - auth_status: see which providers are configured
|
|
24
|
+
* - runs_list: list recent runs
|
|
25
|
+
* - runs_latest: show the most recent run
|
|
26
|
+
*
|
|
27
|
+
* Each tool is a thin wrapper around the existing core functions —
|
|
28
|
+
* no orchestration logic lives here. The CLI and MCP server are
|
|
29
|
+
* peer transports for the same underlying capabilities.
|
|
30
|
+
*/
|
|
31
|
+
interface ServeOptions {
|
|
32
|
+
/** Override the cwd the MCP server treats as the repo root. */
|
|
33
|
+
cwd?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Start the AlmightyGPT MCP server on stdio. Blocks for the lifetime
|
|
37
|
+
* of the process (returns the connect() promise — caller should await
|
|
38
|
+
* it inside the CLI command handler).
|
|
39
|
+
*/
|
|
40
|
+
export declare function startMcpServer(options?: ServeOptions): Promise<void>;
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAkBH,UAAU,YAAY;IACpB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+Q9E"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlmightyGPT MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the AlmightyGPT CLI's review/precommit/auth/runs surface as
|
|
5
|
+
* Model Context Protocol tools, so MCP-aware clients (Claude Desktop,
|
|
6
|
+
* Cursor, Continue, etc.) can invoke them directly.
|
|
7
|
+
*
|
|
8
|
+
* Transport: stdio (the default for local MCP servers). Spawned from
|
|
9
|
+
* the user's MCP client config — typically something like:
|
|
10
|
+
*
|
|
11
|
+
* {
|
|
12
|
+
* "mcpServers": {
|
|
13
|
+
* "almightygpt": {
|
|
14
|
+
* "command": "almightygpt",
|
|
15
|
+
* "args": ["mcp", "serve"]
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* Tool surface (v0.9.0):
|
|
21
|
+
* - review_diff: run a Worker/Reviewer or Reviewer-only review on a diff
|
|
22
|
+
* - precommit: quick last-mile review of uncommitted changes
|
|
23
|
+
* - auth_status: see which providers are configured
|
|
24
|
+
* - runs_list: list recent runs
|
|
25
|
+
* - runs_latest: show the most recent run
|
|
26
|
+
*
|
|
27
|
+
* Each tool is a thin wrapper around the existing core functions —
|
|
28
|
+
* no orchestration logic lives here. The CLI and MCP server are
|
|
29
|
+
* peer transports for the same underlying capabilities.
|
|
30
|
+
*/
|
|
31
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
32
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
33
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
34
|
+
import { runDiffReview } from "../review/run-diff-review.js";
|
|
35
|
+
import { runWorkerReviewerReview } from "../review/run-worker-reviewer.js";
|
|
36
|
+
import { listRuns, findLatestRun } from "../runs/list.js";
|
|
37
|
+
import { resolveApiKey } from "../auth/resolver.js";
|
|
38
|
+
import { PROVIDER_ENV_VARS } from "../auth/types.js";
|
|
39
|
+
import { loadConfig } from "../config/load.js";
|
|
40
|
+
const SERVER_NAME = "almightygpt";
|
|
41
|
+
/**
|
|
42
|
+
* Start the AlmightyGPT MCP server on stdio. Blocks for the lifetime
|
|
43
|
+
* of the process (returns the connect() promise — caller should await
|
|
44
|
+
* it inside the CLI command handler).
|
|
45
|
+
*/
|
|
46
|
+
export async function startMcpServer(options = {}) {
|
|
47
|
+
const repoRoot = options.cwd ?? process.cwd();
|
|
48
|
+
const server = new Server({
|
|
49
|
+
name: SERVER_NAME,
|
|
50
|
+
version: "0.9.0",
|
|
51
|
+
}, {
|
|
52
|
+
capabilities: {
|
|
53
|
+
tools: {},
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
// Tool list — what clients see when they introspect the server.
|
|
57
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
58
|
+
tools: [
|
|
59
|
+
{
|
|
60
|
+
name: "review_diff",
|
|
61
|
+
description: "Run a cross-AI review on a git diff. Use `worker` to enable the " +
|
|
62
|
+
"Worker/Reviewer two-role flow, or omit for reviewer-only. Returns " +
|
|
63
|
+
"the review markdown plus cost/latency metrics.",
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: "object",
|
|
66
|
+
properties: {
|
|
67
|
+
topic: {
|
|
68
|
+
type: "string",
|
|
69
|
+
description: "Topic slug for the review file path (e.g. 'auth-refactor').",
|
|
70
|
+
},
|
|
71
|
+
reviewer: {
|
|
72
|
+
type: "string",
|
|
73
|
+
description: "Reviewer agent name. Falls back to config.defaults.reviewer.",
|
|
74
|
+
},
|
|
75
|
+
worker: {
|
|
76
|
+
type: "string",
|
|
77
|
+
description: "Worker agent name. If set, runs the two-role flow.",
|
|
78
|
+
},
|
|
79
|
+
range: {
|
|
80
|
+
type: "string",
|
|
81
|
+
description: "Git range like 'HEAD~3..HEAD'. Omit for uncommitted.",
|
|
82
|
+
},
|
|
83
|
+
force: {
|
|
84
|
+
type: "boolean",
|
|
85
|
+
description: "Overwrite existing review file. Default false.",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
required: ["topic"],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "precommit",
|
|
93
|
+
description: "Quick last-mile review of uncommitted changes using the configured " +
|
|
94
|
+
"quick reviewer (Gemini Flash by default). Cheap (~$0.003) and fast. " +
|
|
95
|
+
"Returns review markdown + shallow-flag for CI gating.",
|
|
96
|
+
inputSchema: {
|
|
97
|
+
type: "object",
|
|
98
|
+
properties: {
|
|
99
|
+
topic: {
|
|
100
|
+
type: "string",
|
|
101
|
+
description: "Topic slug. Defaults to `precommit-<unix-timestamp>` if omitted.",
|
|
102
|
+
},
|
|
103
|
+
reviewer: {
|
|
104
|
+
type: "string",
|
|
105
|
+
description: "Override the quick reviewer. Defaults to config.defaults.quickReviewer.",
|
|
106
|
+
},
|
|
107
|
+
range: {
|
|
108
|
+
type: "string",
|
|
109
|
+
description: "Git range. Omit for uncommitted changes.",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "auth_status",
|
|
116
|
+
description: "Report which providers (OpenAI, Anthropic, Google) have API keys " +
|
|
117
|
+
"configured, and from where (env var vs keychain vs missing).",
|
|
118
|
+
inputSchema: {
|
|
119
|
+
type: "object",
|
|
120
|
+
properties: {},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: "runs_list",
|
|
125
|
+
description: "List recent AlmightyGPT runs with cost, status, and timestamps.",
|
|
126
|
+
inputSchema: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
limit: {
|
|
130
|
+
type: "number",
|
|
131
|
+
description: "Max runs to return. Default 10.",
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "runs_latest",
|
|
138
|
+
description: "Show the most recent run (path to review file + metrics).",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: {},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
}));
|
|
146
|
+
// Tool dispatcher — routes to the right core function.
|
|
147
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
148
|
+
const { name, arguments: args = {} } = request.params;
|
|
149
|
+
const a = args;
|
|
150
|
+
try {
|
|
151
|
+
switch (name) {
|
|
152
|
+
case "review_diff": {
|
|
153
|
+
const topic = String(a["topic"]);
|
|
154
|
+
if (!topic)
|
|
155
|
+
throw new Error("`topic` is required");
|
|
156
|
+
const useWorker = typeof a["worker"] === "string";
|
|
157
|
+
if (useWorker) {
|
|
158
|
+
const opts = {
|
|
159
|
+
repoRoot,
|
|
160
|
+
topic,
|
|
161
|
+
force: a["force"] === true,
|
|
162
|
+
};
|
|
163
|
+
if (typeof a["range"] === "string")
|
|
164
|
+
opts.range = a["range"];
|
|
165
|
+
if (typeof a["worker"] === "string")
|
|
166
|
+
opts.worker = a["worker"];
|
|
167
|
+
if (typeof a["reviewer"] === "string")
|
|
168
|
+
opts.reviewer = a["reviewer"];
|
|
169
|
+
const result = await runWorkerReviewerReview(opts);
|
|
170
|
+
return formatReviewResult({
|
|
171
|
+
reviewPath: result.reviewPath,
|
|
172
|
+
tokensIn: result.totals.tokensIn,
|
|
173
|
+
tokensOut: result.totals.tokensOut,
|
|
174
|
+
costUsd: result.totals.costUsd,
|
|
175
|
+
latencyMs: result.totals.latencyMs,
|
|
176
|
+
filesReviewed: result.filesReviewed.length,
|
|
177
|
+
runFolder: result.runFolder,
|
|
178
|
+
worker: result.worker.name,
|
|
179
|
+
reviewer: result.reviewer.name,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const opts = {
|
|
183
|
+
repoRoot,
|
|
184
|
+
topic,
|
|
185
|
+
force: a["force"] === true,
|
|
186
|
+
};
|
|
187
|
+
if (typeof a["range"] === "string")
|
|
188
|
+
opts.range = a["range"];
|
|
189
|
+
if (typeof a["reviewer"] === "string")
|
|
190
|
+
opts.reviewer = a["reviewer"];
|
|
191
|
+
const result = await runDiffReview(opts);
|
|
192
|
+
return formatReviewResult({
|
|
193
|
+
reviewPath: result.reviewPath,
|
|
194
|
+
tokensIn: result.tokensIn,
|
|
195
|
+
tokensOut: result.tokensOut,
|
|
196
|
+
costUsd: result.costUsd,
|
|
197
|
+
latencyMs: result.latencyMs,
|
|
198
|
+
filesReviewed: result.filesReviewed.length,
|
|
199
|
+
runFolder: result.runFolder,
|
|
200
|
+
reviewer: result.reviewer,
|
|
201
|
+
shallowWarning: result.shallowWarning,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
case "precommit": {
|
|
205
|
+
const config = await loadConfig(repoRoot);
|
|
206
|
+
const reviewer = (typeof a["reviewer"] === "string" && a["reviewer"]) ||
|
|
207
|
+
config.defaults.quickReviewer ||
|
|
208
|
+
config.defaults.reviewer;
|
|
209
|
+
if (!reviewer) {
|
|
210
|
+
throw new Error("No quick reviewer configured. Set defaults.quickReviewer in " +
|
|
211
|
+
".almightygpt/config.yaml or pass `reviewer`.");
|
|
212
|
+
}
|
|
213
|
+
const topic = (typeof a["topic"] === "string" && a["topic"]) ||
|
|
214
|
+
`precommit-${Math.floor(Date.now() / 1000)}`;
|
|
215
|
+
const opts = {
|
|
216
|
+
repoRoot,
|
|
217
|
+
topic,
|
|
218
|
+
reviewer,
|
|
219
|
+
force: true,
|
|
220
|
+
};
|
|
221
|
+
if (typeof a["range"] === "string")
|
|
222
|
+
opts.range = a["range"];
|
|
223
|
+
const precommitDir = config.precommitDir;
|
|
224
|
+
if (precommitDir)
|
|
225
|
+
opts.reviewsDirOverride = precommitDir;
|
|
226
|
+
const result = await runDiffReview(opts);
|
|
227
|
+
return formatReviewResult({
|
|
228
|
+
reviewPath: result.reviewPath,
|
|
229
|
+
tokensIn: result.tokensIn,
|
|
230
|
+
tokensOut: result.tokensOut,
|
|
231
|
+
costUsd: result.costUsd,
|
|
232
|
+
latencyMs: result.latencyMs,
|
|
233
|
+
filesReviewed: result.filesReviewed.length,
|
|
234
|
+
runFolder: result.runFolder,
|
|
235
|
+
reviewer,
|
|
236
|
+
shallowWarning: result.shallowWarning,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
case "auth_status": {
|
|
240
|
+
const providers = ["openai", "anthropic", "google"];
|
|
241
|
+
const rows = await Promise.all(providers.map(async (p) => {
|
|
242
|
+
const r = await resolveApiKey(p);
|
|
243
|
+
return {
|
|
244
|
+
provider: p,
|
|
245
|
+
source: r.source,
|
|
246
|
+
envVar: r.envVar ?? PROVIDER_ENV_VARS[p][0],
|
|
247
|
+
configured: r.source !== "missing",
|
|
248
|
+
};
|
|
249
|
+
}));
|
|
250
|
+
return {
|
|
251
|
+
content: [
|
|
252
|
+
{
|
|
253
|
+
type: "text",
|
|
254
|
+
text: JSON.stringify({ providers: rows }, null, 2),
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
case "runs_list": {
|
|
260
|
+
const config = await loadConfig(repoRoot);
|
|
261
|
+
const limit = typeof a["limit"] === "number" ? a["limit"] : 10;
|
|
262
|
+
const result = await listRuns({
|
|
263
|
+
repoRoot,
|
|
264
|
+
runsDir: config.runsDir,
|
|
265
|
+
limit,
|
|
266
|
+
});
|
|
267
|
+
return {
|
|
268
|
+
content: [
|
|
269
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
270
|
+
],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
case "runs_latest": {
|
|
274
|
+
const config = await loadConfig(repoRoot);
|
|
275
|
+
const result = await findLatestRun(repoRoot, config.runsDir);
|
|
276
|
+
return {
|
|
277
|
+
content: [
|
|
278
|
+
{ type: "text", text: JSON.stringify(result ?? null, null, 2) },
|
|
279
|
+
],
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
default:
|
|
283
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
288
|
+
return {
|
|
289
|
+
isError: true,
|
|
290
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
const transport = new StdioServerTransport();
|
|
295
|
+
await server.connect(transport);
|
|
296
|
+
}
|
|
297
|
+
/** Compact summary of a review result for MCP clients. */
|
|
298
|
+
function formatReviewResult(r) {
|
|
299
|
+
const summary = {
|
|
300
|
+
reviewPath: r.reviewPath,
|
|
301
|
+
reviewer: r.reviewer,
|
|
302
|
+
...(r.worker ? { worker: r.worker } : {}),
|
|
303
|
+
metrics: {
|
|
304
|
+
tokensIn: r.tokensIn,
|
|
305
|
+
tokensOut: r.tokensOut,
|
|
306
|
+
costUsd: r.costUsd,
|
|
307
|
+
latencyMs: r.latencyMs,
|
|
308
|
+
filesReviewed: r.filesReviewed,
|
|
309
|
+
},
|
|
310
|
+
runFolder: r.runFolder,
|
|
311
|
+
...(r.shallowWarning ? { shallowWarning: r.shallowWarning } : {}),
|
|
312
|
+
};
|
|
313
|
+
return {
|
|
314
|
+
content: [{ type: "text", text: JSON.stringify(summary, null, 2) }],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almightygpt/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Core orchestrator, adapters, config, runs, and review logic for AlmightyGPT",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sdk": "^0.30.0",
|
|
27
27
|
"@google/generative-ai": "^0.21.0",
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
29
|
"execa": "^9.3.0",
|
|
29
30
|
"ignore": "^6.0.2",
|
|
30
31
|
"openai": "^4.52.0",
|
package/src/index.ts
CHANGED
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
* - budget/ ✅ task #14 BudgetTracker + BudgetExceededError
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
export const VERSION = "0.
|
|
16
|
+
export const VERSION = "0.9.0";
|
|
17
|
+
|
|
18
|
+
// MCP server (v0.9.0+) — exposes AlmightyGPT's review surface as MCP tools.
|
|
19
|
+
export { startMcpServer } from "./mcp/server.js";
|
|
17
20
|
|
|
18
21
|
// Git safety primitives
|
|
19
22
|
export {
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlmightyGPT MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the AlmightyGPT CLI's review/precommit/auth/runs surface as
|
|
5
|
+
* Model Context Protocol tools, so MCP-aware clients (Claude Desktop,
|
|
6
|
+
* Cursor, Continue, etc.) can invoke them directly.
|
|
7
|
+
*
|
|
8
|
+
* Transport: stdio (the default for local MCP servers). Spawned from
|
|
9
|
+
* the user's MCP client config — typically something like:
|
|
10
|
+
*
|
|
11
|
+
* {
|
|
12
|
+
* "mcpServers": {
|
|
13
|
+
* "almightygpt": {
|
|
14
|
+
* "command": "almightygpt",
|
|
15
|
+
* "args": ["mcp", "serve"]
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* Tool surface (v0.9.0):
|
|
21
|
+
* - review_diff: run a Worker/Reviewer or Reviewer-only review on a diff
|
|
22
|
+
* - precommit: quick last-mile review of uncommitted changes
|
|
23
|
+
* - auth_status: see which providers are configured
|
|
24
|
+
* - runs_list: list recent runs
|
|
25
|
+
* - runs_latest: show the most recent run
|
|
26
|
+
*
|
|
27
|
+
* Each tool is a thin wrapper around the existing core functions —
|
|
28
|
+
* no orchestration logic lives here. The CLI and MCP server are
|
|
29
|
+
* peer transports for the same underlying capabilities.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
33
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
34
|
+
import {
|
|
35
|
+
CallToolRequestSchema,
|
|
36
|
+
ListToolsRequestSchema,
|
|
37
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
38
|
+
|
|
39
|
+
import { runDiffReview } from "../review/run-diff-review.js";
|
|
40
|
+
import { runWorkerReviewerReview } from "../review/run-worker-reviewer.js";
|
|
41
|
+
import { listRuns, findLatestRun } from "../runs/list.js";
|
|
42
|
+
import { resolveApiKey } from "../auth/resolver.js";
|
|
43
|
+
import { PROVIDER_ENV_VARS, type ProviderId } from "../auth/types.js";
|
|
44
|
+
import { loadConfig } from "../config/load.js";
|
|
45
|
+
|
|
46
|
+
const SERVER_NAME = "almightygpt";
|
|
47
|
+
|
|
48
|
+
interface ServeOptions {
|
|
49
|
+
/** Override the cwd the MCP server treats as the repo root. */
|
|
50
|
+
cwd?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Start the AlmightyGPT MCP server on stdio. Blocks for the lifetime
|
|
55
|
+
* of the process (returns the connect() promise — caller should await
|
|
56
|
+
* it inside the CLI command handler).
|
|
57
|
+
*/
|
|
58
|
+
export async function startMcpServer(options: ServeOptions = {}): Promise<void> {
|
|
59
|
+
const repoRoot = options.cwd ?? process.cwd();
|
|
60
|
+
const server = new Server(
|
|
61
|
+
{
|
|
62
|
+
name: SERVER_NAME,
|
|
63
|
+
version: "0.9.0",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
capabilities: {
|
|
67
|
+
tools: {},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// Tool list — what clients see when they introspect the server.
|
|
73
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
74
|
+
tools: [
|
|
75
|
+
{
|
|
76
|
+
name: "review_diff",
|
|
77
|
+
description:
|
|
78
|
+
"Run a cross-AI review on a git diff. Use `worker` to enable the " +
|
|
79
|
+
"Worker/Reviewer two-role flow, or omit for reviewer-only. Returns " +
|
|
80
|
+
"the review markdown plus cost/latency metrics.",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: "object",
|
|
83
|
+
properties: {
|
|
84
|
+
topic: {
|
|
85
|
+
type: "string",
|
|
86
|
+
description:
|
|
87
|
+
"Topic slug for the review file path (e.g. 'auth-refactor').",
|
|
88
|
+
},
|
|
89
|
+
reviewer: {
|
|
90
|
+
type: "string",
|
|
91
|
+
description:
|
|
92
|
+
"Reviewer agent name. Falls back to config.defaults.reviewer.",
|
|
93
|
+
},
|
|
94
|
+
worker: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description:
|
|
97
|
+
"Worker agent name. If set, runs the two-role flow.",
|
|
98
|
+
},
|
|
99
|
+
range: {
|
|
100
|
+
type: "string",
|
|
101
|
+
description: "Git range like 'HEAD~3..HEAD'. Omit for uncommitted.",
|
|
102
|
+
},
|
|
103
|
+
force: {
|
|
104
|
+
type: "boolean",
|
|
105
|
+
description: "Overwrite existing review file. Default false.",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
required: ["topic"],
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "precommit",
|
|
113
|
+
description:
|
|
114
|
+
"Quick last-mile review of uncommitted changes using the configured " +
|
|
115
|
+
"quick reviewer (Gemini Flash by default). Cheap (~$0.003) and fast. " +
|
|
116
|
+
"Returns review markdown + shallow-flag for CI gating.",
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: "object",
|
|
119
|
+
properties: {
|
|
120
|
+
topic: {
|
|
121
|
+
type: "string",
|
|
122
|
+
description:
|
|
123
|
+
"Topic slug. Defaults to `precommit-<unix-timestamp>` if omitted.",
|
|
124
|
+
},
|
|
125
|
+
reviewer: {
|
|
126
|
+
type: "string",
|
|
127
|
+
description:
|
|
128
|
+
"Override the quick reviewer. Defaults to config.defaults.quickReviewer.",
|
|
129
|
+
},
|
|
130
|
+
range: {
|
|
131
|
+
type: "string",
|
|
132
|
+
description: "Git range. Omit for uncommitted changes.",
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "auth_status",
|
|
139
|
+
description:
|
|
140
|
+
"Report which providers (OpenAI, Anthropic, Google) have API keys " +
|
|
141
|
+
"configured, and from where (env var vs keychain vs missing).",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
properties: {},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "runs_list",
|
|
149
|
+
description:
|
|
150
|
+
"List recent AlmightyGPT runs with cost, status, and timestamps.",
|
|
151
|
+
inputSchema: {
|
|
152
|
+
type: "object",
|
|
153
|
+
properties: {
|
|
154
|
+
limit: {
|
|
155
|
+
type: "number",
|
|
156
|
+
description: "Max runs to return. Default 10.",
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "runs_latest",
|
|
163
|
+
description: "Show the most recent run (path to review file + metrics).",
|
|
164
|
+
inputSchema: {
|
|
165
|
+
type: "object",
|
|
166
|
+
properties: {},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
}));
|
|
171
|
+
|
|
172
|
+
// Tool dispatcher — routes to the right core function.
|
|
173
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
174
|
+
const { name, arguments: args = {} } = request.params;
|
|
175
|
+
const a = args as Record<string, unknown>;
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
switch (name) {
|
|
179
|
+
case "review_diff": {
|
|
180
|
+
const topic = String(a["topic"]);
|
|
181
|
+
if (!topic) throw new Error("`topic` is required");
|
|
182
|
+
const useWorker = typeof a["worker"] === "string";
|
|
183
|
+
|
|
184
|
+
if (useWorker) {
|
|
185
|
+
const opts: Parameters<typeof runWorkerReviewerReview>[0] = {
|
|
186
|
+
repoRoot,
|
|
187
|
+
topic,
|
|
188
|
+
force: a["force"] === true,
|
|
189
|
+
};
|
|
190
|
+
if (typeof a["range"] === "string") opts.range = a["range"];
|
|
191
|
+
if (typeof a["worker"] === "string") opts.worker = a["worker"];
|
|
192
|
+
if (typeof a["reviewer"] === "string") opts.reviewer = a["reviewer"];
|
|
193
|
+
const result = await runWorkerReviewerReview(opts);
|
|
194
|
+
return formatReviewResult({
|
|
195
|
+
reviewPath: result.reviewPath,
|
|
196
|
+
tokensIn: result.totals.tokensIn,
|
|
197
|
+
tokensOut: result.totals.tokensOut,
|
|
198
|
+
costUsd: result.totals.costUsd,
|
|
199
|
+
latencyMs: result.totals.latencyMs,
|
|
200
|
+
filesReviewed: result.filesReviewed.length,
|
|
201
|
+
runFolder: result.runFolder,
|
|
202
|
+
worker: result.worker.name,
|
|
203
|
+
reviewer: result.reviewer.name,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const opts: Parameters<typeof runDiffReview>[0] = {
|
|
208
|
+
repoRoot,
|
|
209
|
+
topic,
|
|
210
|
+
force: a["force"] === true,
|
|
211
|
+
};
|
|
212
|
+
if (typeof a["range"] === "string") opts.range = a["range"];
|
|
213
|
+
if (typeof a["reviewer"] === "string") opts.reviewer = a["reviewer"];
|
|
214
|
+
const result = await runDiffReview(opts);
|
|
215
|
+
return formatReviewResult({
|
|
216
|
+
reviewPath: result.reviewPath,
|
|
217
|
+
tokensIn: result.tokensIn,
|
|
218
|
+
tokensOut: result.tokensOut,
|
|
219
|
+
costUsd: result.costUsd,
|
|
220
|
+
latencyMs: result.latencyMs,
|
|
221
|
+
filesReviewed: result.filesReviewed.length,
|
|
222
|
+
runFolder: result.runFolder,
|
|
223
|
+
reviewer: result.reviewer,
|
|
224
|
+
shallowWarning: result.shallowWarning,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
case "precommit": {
|
|
229
|
+
const config = await loadConfig(repoRoot);
|
|
230
|
+
const reviewer =
|
|
231
|
+
(typeof a["reviewer"] === "string" && a["reviewer"]) ||
|
|
232
|
+
config.defaults.quickReviewer ||
|
|
233
|
+
config.defaults.reviewer;
|
|
234
|
+
if (!reviewer) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
"No quick reviewer configured. Set defaults.quickReviewer in " +
|
|
237
|
+
".almightygpt/config.yaml or pass `reviewer`.",
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
const topic =
|
|
241
|
+
(typeof a["topic"] === "string" && a["topic"]) ||
|
|
242
|
+
`precommit-${Math.floor(Date.now() / 1000)}`;
|
|
243
|
+
const opts: Parameters<typeof runDiffReview>[0] = {
|
|
244
|
+
repoRoot,
|
|
245
|
+
topic,
|
|
246
|
+
reviewer,
|
|
247
|
+
force: true,
|
|
248
|
+
};
|
|
249
|
+
if (typeof a["range"] === "string") opts.range = a["range"];
|
|
250
|
+
const precommitDir = (config as { precommitDir?: string }).precommitDir;
|
|
251
|
+
if (precommitDir) opts.reviewsDirOverride = precommitDir;
|
|
252
|
+
|
|
253
|
+
const result = await runDiffReview(opts);
|
|
254
|
+
return formatReviewResult({
|
|
255
|
+
reviewPath: result.reviewPath,
|
|
256
|
+
tokensIn: result.tokensIn,
|
|
257
|
+
tokensOut: result.tokensOut,
|
|
258
|
+
costUsd: result.costUsd,
|
|
259
|
+
latencyMs: result.latencyMs,
|
|
260
|
+
filesReviewed: result.filesReviewed.length,
|
|
261
|
+
runFolder: result.runFolder,
|
|
262
|
+
reviewer,
|
|
263
|
+
shallowWarning: result.shallowWarning,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
case "auth_status": {
|
|
268
|
+
const providers: ProviderId[] = ["openai", "anthropic", "google"];
|
|
269
|
+
const rows = await Promise.all(
|
|
270
|
+
providers.map(async (p) => {
|
|
271
|
+
const r = await resolveApiKey(p);
|
|
272
|
+
return {
|
|
273
|
+
provider: p,
|
|
274
|
+
source: r.source,
|
|
275
|
+
envVar: r.envVar ?? PROVIDER_ENV_VARS[p][0],
|
|
276
|
+
configured: r.source !== "missing",
|
|
277
|
+
};
|
|
278
|
+
}),
|
|
279
|
+
);
|
|
280
|
+
return {
|
|
281
|
+
content: [
|
|
282
|
+
{
|
|
283
|
+
type: "text",
|
|
284
|
+
text: JSON.stringify({ providers: rows }, null, 2),
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
case "runs_list": {
|
|
291
|
+
const config = await loadConfig(repoRoot);
|
|
292
|
+
const limit = typeof a["limit"] === "number" ? a["limit"] : 10;
|
|
293
|
+
const result = await listRuns({
|
|
294
|
+
repoRoot,
|
|
295
|
+
runsDir: config.runsDir,
|
|
296
|
+
limit,
|
|
297
|
+
});
|
|
298
|
+
return {
|
|
299
|
+
content: [
|
|
300
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
301
|
+
],
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
case "runs_latest": {
|
|
306
|
+
const config = await loadConfig(repoRoot);
|
|
307
|
+
const result = await findLatestRun(repoRoot, config.runsDir);
|
|
308
|
+
return {
|
|
309
|
+
content: [
|
|
310
|
+
{ type: "text", text: JSON.stringify(result ?? null, null, 2) },
|
|
311
|
+
],
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
default:
|
|
316
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
317
|
+
}
|
|
318
|
+
} catch (err) {
|
|
319
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
320
|
+
return {
|
|
321
|
+
isError: true,
|
|
322
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const transport = new StdioServerTransport();
|
|
328
|
+
await server.connect(transport);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** Compact summary of a review result for MCP clients. */
|
|
332
|
+
function formatReviewResult(r: {
|
|
333
|
+
reviewPath: string;
|
|
334
|
+
tokensIn: number;
|
|
335
|
+
tokensOut: number;
|
|
336
|
+
costUsd: number;
|
|
337
|
+
latencyMs: number;
|
|
338
|
+
filesReviewed: number;
|
|
339
|
+
runFolder: string;
|
|
340
|
+
worker?: string;
|
|
341
|
+
reviewer: string;
|
|
342
|
+
shallowWarning?: string | undefined;
|
|
343
|
+
}) {
|
|
344
|
+
const summary = {
|
|
345
|
+
reviewPath: r.reviewPath,
|
|
346
|
+
reviewer: r.reviewer,
|
|
347
|
+
...(r.worker ? { worker: r.worker } : {}),
|
|
348
|
+
metrics: {
|
|
349
|
+
tokensIn: r.tokensIn,
|
|
350
|
+
tokensOut: r.tokensOut,
|
|
351
|
+
costUsd: r.costUsd,
|
|
352
|
+
latencyMs: r.latencyMs,
|
|
353
|
+
filesReviewed: r.filesReviewed,
|
|
354
|
+
},
|
|
355
|
+
runFolder: r.runFolder,
|
|
356
|
+
...(r.shallowWarning ? { shallowWarning: r.shallowWarning } : {}),
|
|
357
|
+
};
|
|
358
|
+
return {
|
|
359
|
+
content: [{ type: "text", text: JSON.stringify(summary, null, 2) }],
|
|
360
|
+
};
|
|
361
|
+
}
|