overseer-mcp 0.1.1

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/.env.example ADDED
@@ -0,0 +1,40 @@
1
+ # Core
2
+ OVERSEER_PROVIDER=openai
3
+ # OVERSEER_REPO_ROOT=/absolute/path/to/your/repo
4
+ # OVERSEER_TEST_COMMAND=npm test
5
+
6
+ # Context and validation caps
7
+ OVERSEER_MAX_FILES=12
8
+ # get_plan sends full bodies for this many top-relevant files; the rest go as signature-only outlines.
9
+ OVERSEER_PLAN_FULL_FILES=3
10
+ OVERSEER_MAX_FILE_BYTES=65536
11
+ OVERSEER_MAX_DIFF_BYTES=262144
12
+ OVERSEER_TEST_TIMEOUT_MS=300000
13
+
14
+ # Shared API provider options
15
+ # Either set the key directly, or point to another env var that the MCP client forwards.
16
+ OVERSEER_API_KEY=replace-with-your-key
17
+ # OVERSEER_API_KEY_ENV=OPENAI_API_KEY
18
+ OVERSEER_MODEL=replace-with-model-name
19
+ # OVERSEER_MAX_OUTPUT_TOKENS=2500
20
+ OVERSEER_TEMPERATURE=0.2
21
+
22
+ # OpenAI-compatible provider
23
+ # OVERSEER_PROVIDER=openai
24
+ OVERSEER_BASE_URL=https://api.openai.com/v1
25
+ # Custom OpenAI-compatible gateways, including opencode-go style API-key plans:
26
+ # OVERSEER_BASE_URL=https://your-gateway.example/v1
27
+ # OVERSEER_API_KEY_ENV=OPENCODE_API_KEY
28
+ # OVERSEER_MODEL=your-model-name
29
+
30
+ # Anthropic provider
31
+ # OVERSEER_PROVIDER=anthropic
32
+ # OVERSEER_BASE_URL=https://api.anthropic.com
33
+
34
+ # CLI provider
35
+ # OVERSEER_PROVIDER=cli
36
+ OVERSEER_CLI_COMMAND=codex
37
+ # JSON array is safest for args with spaces.
38
+ OVERSEER_CLI_ARGS=["exec"]
39
+ OVERSEER_CLI_PROMPT_VIA=stdin
40
+ OVERSEER_CLI_TIMEOUT_MS=120000
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 digisdatadigisdata-coder
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,231 @@
1
+ # overseer-mcp
2
+
3
+ `overseer-mcp` is an MCP server for cheap executor agents that need a stronger expert only at the moments where they tend to derail: planning, mid-implementation decisions, and final review.
4
+
5
+ The expert is dormant between calls. When a tool is called, the server reads ground truth from git and disk, assembles the smallest useful context, asks the configured expert provider, and returns a compact contract.
6
+
7
+ ## Why It Exists
8
+
9
+ Executor agents can bias an expert if they summarize the code incorrectly. `overseer-mcp` avoids that failure mode: the executor chooses which tool to call and which file paths matter, but file content, diffs, status, and validation output are read by the server.
10
+
11
+ The design is deliberately token-frugal:
12
+
13
+ - `get_plan` sends git status, a capped tracked-file map, the executor's named files, and a server-selected set of relevant files — full bodies for the top few, signature-only outlines for the rest.
14
+ - `consult_expert` sends named files, the real current diff, and literal error output.
15
+ - `request_review` sends real unstaged/staged diffs and optional validation output.
16
+ - File count, file bytes, diff bytes, temperature, and output tokens are capped.
17
+ - System prompts are static and first in the message order for provider prefix caching.
18
+ - Anthropic requests mark the system prompt with prompt-cache metadata.
19
+ - The executor should call the expert at three gates only: plan, blocker, review.
20
+
21
+ ## Tools
22
+
23
+ `get_plan`
24
+
25
+ Call before writing code. Input: `task`, optional `focus_paths`, optional `mode` (`full` or `lite`). Returns a self-sufficient implementation contract.
26
+
27
+ `consult_expert`
28
+
29
+ Call before improvising on a non-trivial decision, unclear error, or ambiguity. Input: `question`, optional `file_paths`, `error_output`, `options_considered`. Returns `PROCEED`, `DECIDE`, `FIX`, `REDIRECT`, or `NEED_INFO`.
30
+
31
+ `request_review`
32
+
33
+ Call when implementation is done. Input: optional `task`, optional `run_tests` (default `true`). Returns `APPROVE` or `REQUEST_CHANGES`.
34
+
35
+ ## Install
36
+
37
+ Use it through any MCP client:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "overseer": {
43
+ "command": "npx",
44
+ "args": ["-y", "overseer-mcp"],
45
+ "env": {
46
+ "OVERSEER_PROVIDER": "openai",
47
+ "OVERSEER_API_KEY": "YOUR_KEY",
48
+ "OVERSEER_MODEL": "gpt-5.5",
49
+ "OVERSEER_REPO_ROOT": "/absolute/path/to/your/repo",
50
+ "OVERSEER_TEST_COMMAND": "npm test"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ For local development in this repo:
58
+
59
+ ```bash
60
+ npm install
61
+ npm run build
62
+ OVERSEER_PROVIDER=cli OVERSEER_CLI_COMMAND=codex OVERSEER_CLI_ARGS='["exec"]' node dist/index.js
63
+ ```
64
+
65
+ ## Init Wizard
66
+
67
+ Generate MCP configuration with:
68
+
69
+ ```bash
70
+ overseer-mcp init
71
+ ```
72
+
73
+ From this repo, use:
74
+
75
+ ```bash
76
+ node dist/index.js init
77
+ ```
78
+
79
+ The wizard supports:
80
+
81
+ - OpenAI API (`OVERSEER_PROVIDER=openai`).
82
+ - Anthropic API (`OVERSEER_PROVIDER=anthropic`).
83
+ - Custom OpenAI-compatible APIs (`OVERSEER_PROVIDER=openai` plus `OVERSEER_BASE_URL`), including opencode-go style API-key subscriptions and GLM/gateway providers.
84
+ - CLI experts (`OVERSEER_PROVIDER=cli`) for Codex, Claude, or local CLIs, with optional login.
85
+
86
+ On Windows, the helper script walks through the same setup and writes both MCP config formats to `generated/`:
87
+
88
+ ```bat
89
+ configure-overseer.bat
90
+ ```
91
+
92
+ It builds the package, asks for the expert profile that Overseer will call, runs `init --print`, then writes:
93
+
94
+ - `generated\overseer-codex.toml`
95
+ - `generated\overseer-mcp.json`
96
+ - `generated\OVERSEER_AGENT_INSTRUCTIONS.md`
97
+
98
+ `OVERSEER_AGENT_INSTRUCTIONS.md` is for the cheap/operator agent, not for the expert model. It is generic AGENTS.md-style guidance that tells whichever executor you use (Codex, Mimo, Qoder, Cline, Roo, Trae, Claude Code, etc.) to call `get_plan`, `consult_expert`, and `request_review` at the right gates.
99
+
100
+ If the operator agent is Codex, the script can append the generated MCP block to the target repo `.codex\config.toml` after creating a backup. For Qoder, Mimo, Cline, Roo, or similar clients, paste/import the generated `overseer-mcp.json` where that client keeps MCP servers. Separately, the script can append the operator instructions to the target repo `AGENTS.md` after creating a backup. It never asks for the API key value; it asks for the environment variable name, such as `OPENCODE_API_KEY`, `OPENAI_API_KEY`, or `ANTHROPIC_API_KEY`.
101
+
102
+ The Windows configurator also copies the JSON config into the target repo as `overseer-mcp.json` so the operator agent can find it from project context. Treat that file as local machine config because it contains absolute paths. Do not commit it to GitHub unless you intentionally convert it into a portable template such as `overseer-mcp.example.json`.
103
+
104
+ For non-interactive generation:
105
+
106
+ ```bash
107
+ node dist/index.js init --print \
108
+ --target codex \
109
+ --name overseer-opencode \
110
+ --expert openai-compatible \
111
+ --repo-root C:/Users/Usuario/automatizador-qoder- \
112
+ --api-key-env OPENCODE_API_KEY \
113
+ --base-url https://api.opencode.example/v1 \
114
+ --model opencode-go
115
+ ```
116
+
117
+ That prints a Codex `config.toml` block. The key is not embedded. Codex forwards `OPENCODE_API_KEY`, and `overseer-mcp` reads it through `OVERSEER_API_KEY_ENV`.
118
+
119
+ Generate only the operator instructions:
120
+
121
+ ```bash
122
+ node dist/index.js instructions --print --mcp-name overseer-opencode > generated/OVERSEER_AGENT_INSTRUCTIONS.md
123
+ ```
124
+
125
+ Put those instructions where the **operator agent** reads persistent project guidance. For most coding agents, that means appending them to the target repo `AGENTS.md`.
126
+
127
+ To manage several expert profiles, generate one block per profile with a different `--name`:
128
+
129
+ ```bash
130
+ node dist/index.js init --print --target codex --name overseer-gpt --expert openai --api-key-env OPENAI_API_KEY --model gpt-5.5
131
+ node dist/index.js init --print --target codex --name overseer-claude --expert anthropic --api-key-env ANTHROPIC_API_KEY --model claude-your-model
132
+ node dist/index.js init --print --target codex --name overseer-opencode --expert openai-compatible --api-key-env OPENCODE_API_KEY --base-url https://api.opencode.example/v1 --model opencode-go
133
+ ```
134
+
135
+ For JSON-style MCP clients such as Qoder/Mimo/Cline/Roo-style configs:
136
+
137
+ ```bash
138
+ node dist/index.js init --print --target json --name overseer-opencode --expert openai-compatible --api-key-env OPENCODE_API_KEY --base-url https://api.opencode.example/v1 --model opencode-go
139
+ ```
140
+
141
+ For CLI plan providers:
142
+
143
+ ```bash
144
+ node dist/index.js init --print --target codex --name overseer-codex-cli --expert cli --cli-command codex --cli-args '["exec"]'
145
+ node dist/index.js init --print --target codex --name overseer-claude-cli --expert cli --cli-command claude --cli-args '["-p"]' --run-login
146
+ ```
147
+
148
+ `--run-login` uses the current terminal and runs the known login command for `codex` or `claude`. For other CLIs, pass an explicit login command:
149
+
150
+ ```bash
151
+ node dist/index.js init --print --expert cli --cli-command mycli --login-command '["mycli","login"]' --run-login
152
+ ```
153
+
154
+ When the Windows configurator uses Codex CLI, it checks `~\.codex\config.toml` before login. If it finds an unsupported `service_tier` value such as `default`, it offers `flex`, `fast`, or removing the line, saves a backup, then continues.
155
+
156
+ CLI login is owned by the selected CLI, not by `overseer-mcp`. For example, `codex login` stores Codex auth in Codex's global files. Re-running `configure-overseer.bat` does not delete that login; answer `no` to the login prompt when the CLI is already authenticated.
157
+
158
+ ## Configuration
159
+
160
+ | Variable | Required | Provider | Default | Meaning |
161
+ | --- | --- | --- | --- | --- |
162
+ | `OVERSEER_PROVIDER` | yes | all | none | `openai`, `anthropic`, or `cli`. |
163
+ | `OVERSEER_REPO_ROOT` | no | all | `process.cwd()` | Repo the server reads. |
164
+ | `OVERSEER_TEST_COMMAND` | no | all | none | Validation command for `request_review`. |
165
+ | `OVERSEER_MAX_FILES` | no | all | `12` | Max files read per tool call. |
166
+ | `OVERSEER_MAX_FILE_BYTES` | no | all | `65536` | Per-file byte cap. |
167
+ | `OVERSEER_MAX_DIFF_BYTES` | no | all | `262144` | Review diff byte cap. |
168
+ | `OVERSEER_TEST_TIMEOUT_MS` | no | all | `300000` | Validation timeout. |
169
+ | `OVERSEER_API_KEY` | yes | `openai`, `anthropic` | none | API key. |
170
+ | `OVERSEER_API_KEY_ENV` | no | `openai`, `anthropic` | none | Name of an env var containing the API key. Useful for MCP clients that forward secrets. |
171
+ | `OVERSEER_BASE_URL` | no | `openai`, `anthropic` | OpenAI/Anthropic default | API base URL. |
172
+ | `OVERSEER_MODEL` | yes | `openai`, `anthropic` | none | Expert model name. |
173
+ | `OVERSEER_MAX_OUTPUT_TOKENS` | no | `openai`, `anthropic` | tool-specific cap | Overrides output cap. |
174
+ | `OVERSEER_TEMPERATURE` | no | `openai`, `anthropic` | `0.2` | Deterministic output. |
175
+ | `OVERSEER_CLI_COMMAND` | yes | `cli` | none | CLI executable. |
176
+ | `OVERSEER_CLI_ARGS` | no | `cli` | empty | JSON string array or whitespace list. |
177
+ | `OVERSEER_CLI_PROMPT_VIA` | no | `cli` | `stdin` | `stdin` or `arg`. |
178
+ | `OVERSEER_CLI_TIMEOUT_MS` | no | `cli` | `120000` | CLI completion timeout. |
179
+
180
+ OpenAI-compatible endpoints include OpenAI, GLM/Zhipu gateways, opencode-style gateways, and local servers that implement chat completions.
181
+
182
+ ## Executor System Instructions
183
+
184
+ Copy this block into the executor agent system prompt:
185
+
186
+ ```text
187
+ You have an `overseer` expert advisor available via MCP tools. Use it like this:
188
+ 1. Before writing any code, call get_plan with the user's request. Follow the plan.
189
+ 2. While implementing, the moment you face a non-trivial design decision, an error you
190
+ don't fully understand, or an ambiguity - call consult_expert BEFORE improvising.
191
+ Attach the relevant file_paths and literal error_output. Do not guess on your own.
192
+ 3. When done, call request_review. If it returns REQUEST_CHANGES, apply REQUIRED_FIXES
193
+ and review again. Only finish on APPROVE.
194
+ Always pass real file paths and real error text - the expert reads them from disk itself.
195
+ ```
196
+
197
+ ## Manual Smoke Test
198
+
199
+ Build first:
200
+
201
+ ```bash
202
+ npm install
203
+ npm run build
204
+ ```
205
+
206
+ Then inspect the server:
207
+
208
+ ```bash
209
+ npx @modelcontextprotocol/inspector node dist/index.js
210
+ ```
211
+
212
+ Use safe local env for listing tools, for example:
213
+
214
+ ```bash
215
+ OVERSEER_PROVIDER=cli OVERSEER_CLI_COMMAND=node OVERSEER_CLI_ARGS='["-e","process.stdin.resume()"]' npx @modelcontextprotocol/inspector node dist/index.js
216
+ ```
217
+
218
+ The tool list should contain exactly:
219
+
220
+ - `get_plan`
221
+ - `consult_expert`
222
+ - `request_review`
223
+
224
+ ## Development
225
+
226
+ ```bash
227
+ npm test
228
+ npm run build
229
+ ```
230
+
231
+ The tests cover config validation, path traversal refusal, prompt payload labels, tool context assembly, diff truncation, and stdio tool listing.
@@ -0,0 +1,239 @@
1
+ @echo off
2
+ setlocal EnableExtensions EnableDelayedExpansion
3
+
4
+ cd /d "%~dp0"
5
+
6
+ echo.
7
+ echo overseer-mcp configurator
8
+ echo =========================
9
+ echo.
10
+
11
+ where node >nul 2>nul
12
+ if errorlevel 1 (
13
+ echo ERROR: node was not found in PATH.
14
+ exit /b 1
15
+ )
16
+
17
+ where npm >nul 2>nul
18
+ if errorlevel 1 (
19
+ echo ERROR: npm was not found in PATH.
20
+ exit /b 1
21
+ )
22
+
23
+ if not exist "generated" mkdir "generated"
24
+ set "OUT_CODEX=generated\overseer-codex.toml"
25
+ set "OUT_JSON=generated\overseer-mcp.json"
26
+ set "REPO_JSON=overseer-mcp.json"
27
+
28
+ echo.
29
+ echo This wizard generates both MCP config formats:
30
+ echo - Codex operator: generated\overseer-codex.toml for project .codex\config.toml
31
+ echo - Generic JSON operator: generated\overseer-mcp.json for Qoder / Mimo / Cline / Roo / other MCP clients
32
+ echo The expert model is selected in the next step.
33
+
34
+ echo.
35
+ echo Expert profile:
36
+ echo 1. opencode-go or custom OpenAI-compatible API
37
+ echo 2. OpenAI API
38
+ echo 3. Anthropic API
39
+ echo 4. Codex CLI plan
40
+ echo 5. Claude CLI plan
41
+ set /p "EXPERT_CHOICE=Choose expert [1]: "
42
+ if "%EXPERT_CHOICE%"=="" set "EXPERT_CHOICE=1"
43
+ set "EXPERT_CHOICE=%EXPERT_CHOICE:~0,1%"
44
+
45
+ set "REPO_ROOT=%CD%\.."
46
+ for %%I in ("%REPO_ROOT%") do set "REPO_ROOT=%%~fI"
47
+ set /p "INPUT_REPO_ROOT=Repo root [%REPO_ROOT%]: "
48
+ if not "%INPUT_REPO_ROOT%"=="" set "REPO_ROOT=%INPUT_REPO_ROOT%"
49
+
50
+ set "TEST_COMMAND="
51
+ set /p "TEST_COMMAND=Validation command, empty to skip: "
52
+
53
+ if "%EXPERT_CHOICE%"=="1" goto custom_api
54
+ if "%EXPERT_CHOICE%"=="2" goto openai_api
55
+ if "%EXPERT_CHOICE%"=="3" goto anthropic_api
56
+ if "%EXPERT_CHOICE%"=="4" goto codex_cli
57
+ if "%EXPERT_CHOICE%"=="5" goto claude_cli
58
+
59
+ echo ERROR: invalid expert choice.
60
+ exit /b 1
61
+
62
+ :custom_api
63
+ set "PROFILE_NAME=overseer-opencode"
64
+ set "KEY_ENV_NAME=OPENCODE_API_KEY"
65
+ set "BASE_URL=https://api.opencode.example/v1"
66
+ set "MODEL_NAME=opencode-go"
67
+ set /p "INPUT_PROFILE=MCP profile name [%PROFILE_NAME%]: "
68
+ if not "%INPUT_PROFILE%"=="" set "PROFILE_NAME=%INPUT_PROFILE%"
69
+ set /p "INPUT_KEY_ENV=Secret env var name [%KEY_ENV_NAME%]: "
70
+ if not "%INPUT_KEY_ENV%"=="" set "KEY_ENV_NAME=%INPUT_KEY_ENV%"
71
+ set /p "INPUT_BASE_URL=OpenAI-compatible base URL [%BASE_URL%]: "
72
+ if not "%INPUT_BASE_URL%"=="" set "BASE_URL=%INPUT_BASE_URL%"
73
+ set /p "INPUT_MODEL=Model name [%MODEL_NAME%]: "
74
+ if not "%INPUT_MODEL%"=="" set "MODEL_NAME=%INPUT_MODEL%"
75
+ call :run_init_api openai-compatible "%PROFILE_NAME%" "%KEY_ENV_NAME%" "%BASE_URL%" "%MODEL_NAME%"
76
+ if errorlevel 1 goto fail
77
+ goto install
78
+
79
+ :openai_api
80
+ set "PROFILE_NAME=overseer-gpt"
81
+ set "KEY_ENV_NAME=OPENAI_API_KEY"
82
+ set "MODEL_NAME=gpt-5.5"
83
+ set /p "INPUT_PROFILE=MCP profile name [%PROFILE_NAME%]: "
84
+ if not "%INPUT_PROFILE%"=="" set "PROFILE_NAME=%INPUT_PROFILE%"
85
+ set /p "INPUT_KEY_ENV=Secret env var name [%KEY_ENV_NAME%]: "
86
+ if not "%INPUT_KEY_ENV%"=="" set "KEY_ENV_NAME=%INPUT_KEY_ENV%"
87
+ set /p "INPUT_MODEL=Model name [%MODEL_NAME%]: "
88
+ if not "%INPUT_MODEL%"=="" set "MODEL_NAME=%INPUT_MODEL%"
89
+ call :run_init_api openai "%PROFILE_NAME%" "%KEY_ENV_NAME%" "" "%MODEL_NAME%"
90
+ if errorlevel 1 goto fail
91
+ goto install
92
+
93
+ :anthropic_api
94
+ set "PROFILE_NAME=overseer-claude"
95
+ set "KEY_ENV_NAME=ANTHROPIC_API_KEY"
96
+ set "MODEL_NAME=claude-your-model"
97
+ set /p "INPUT_PROFILE=MCP profile name [%PROFILE_NAME%]: "
98
+ if not "%INPUT_PROFILE%"=="" set "PROFILE_NAME=%INPUT_PROFILE%"
99
+ set /p "INPUT_KEY_ENV=Secret env var name [%KEY_ENV_NAME%]: "
100
+ if not "%INPUT_KEY_ENV%"=="" set "KEY_ENV_NAME=%INPUT_KEY_ENV%"
101
+ set /p "INPUT_MODEL=Model name [%MODEL_NAME%]: "
102
+ if not "%INPUT_MODEL%"=="" set "MODEL_NAME=%INPUT_MODEL%"
103
+ call :run_init_api anthropic "%PROFILE_NAME%" "%KEY_ENV_NAME%" "" "%MODEL_NAME%"
104
+ if errorlevel 1 goto fail
105
+ goto install
106
+
107
+ :codex_cli
108
+ set "PROFILE_NAME=overseer-codex-cli"
109
+ set /p "INPUT_PROFILE=MCP profile name [%PROFILE_NAME%]: "
110
+ if not "%INPUT_PROFILE%"=="" set "PROFILE_NAME=%INPUT_PROFILE%"
111
+ call :run_init_cli "%PROFILE_NAME%" codex "[\"exec\"]"
112
+ if errorlevel 1 goto fail
113
+ goto install
114
+
115
+ :claude_cli
116
+ set "PROFILE_NAME=overseer-claude-cli"
117
+ set /p "INPUT_PROFILE=MCP profile name [%PROFILE_NAME%]: "
118
+ if not "%INPUT_PROFILE%"=="" set "PROFILE_NAME=%INPUT_PROFILE%"
119
+ call :run_init_cli "%PROFILE_NAME%" claude "[\"-p\"]"
120
+ if errorlevel 1 goto fail
121
+ goto install
122
+
123
+ :run_init_api
124
+ call :ensure_build
125
+ if errorlevel 1 goto fail
126
+ set "EXPERT=%~1"
127
+ set "PROFILE=%~2"
128
+ set "ENV_NAME=%~3"
129
+ set "URL=%~4"
130
+ set "MODEL=%~5"
131
+ set "BASE_ARGS=--print --name "%PROFILE%" --expert %EXPERT% --repo-root "%REPO_ROOT%" --api-key-env "%ENV_NAME%" --model "%MODEL%""
132
+ if not "%TEST_COMMAND%"=="" set "BASE_ARGS=%BASE_ARGS% --test-command "%TEST_COMMAND%""
133
+ if not "%URL%"=="" set "BASE_ARGS=%BASE_ARGS% --base-url "%URL%""
134
+ node dist\index.js init %BASE_ARGS% --target codex > "%OUT_CODEX%"
135
+ if errorlevel 1 goto fail
136
+ node dist\index.js init %BASE_ARGS% --target json > "%OUT_JSON%"
137
+ if errorlevel 1 goto fail
138
+ node dist\index.js instructions --print --mcp-name "%PROFILE%" > "generated\OVERSEER_AGENT_INSTRUCTIONS.md"
139
+ if errorlevel 1 goto fail
140
+ exit /b 0
141
+
142
+ :run_init_cli
143
+ call :ensure_build
144
+ if errorlevel 1 goto fail
145
+ set "PROFILE=%~1"
146
+ set "CLI_COMMAND=%~2"
147
+ set "CLI_ARGS=%~3"
148
+ set "LOGIN_FLAG="
149
+ if /I "%CLI_COMMAND%"=="codex" (
150
+ echo Checking Codex CLI config...
151
+ node dist\index.js codex-config
152
+ if errorlevel 1 exit /b 1
153
+ )
154
+ echo Login is stored by the CLI (%CLI_COMMAND%), not by overseer-mcp.
155
+ echo Re-running this configurator does not delete an existing CLI login.
156
+ echo If you are already logged in, answer no.
157
+ echo If login hangs, close this window and run "%CLI_COMMAND% login" manually in a terminal.
158
+ set /p "RUN_LOGIN=Run CLI login now? yes/no [no]: "
159
+ if /I "%RUN_LOGIN%"=="yes" set "LOGIN_FLAG=--run-login"
160
+ set "BASE_ARGS=--print --name "%PROFILE%" --expert cli --repo-root "%REPO_ROOT%" --cli-command "%CLI_COMMAND%" --cli-args "%CLI_ARGS%" %LOGIN_FLAG%"
161
+ if not "%TEST_COMMAND%"=="" set "BASE_ARGS=%BASE_ARGS% --test-command "%TEST_COMMAND%""
162
+ node dist\index.js init %BASE_ARGS% --target codex > "%OUT_CODEX%"
163
+ if errorlevel 1 goto fail
164
+ node dist\index.js init %BASE_ARGS% --target json > "%OUT_JSON%"
165
+ if errorlevel 1 goto fail
166
+ node dist\index.js instructions --print --mcp-name "%PROFILE%" > "generated\OVERSEER_AGENT_INSTRUCTIONS.md"
167
+ if errorlevel 1 goto fail
168
+ exit /b 0
169
+
170
+ :install
171
+ echo.
172
+ echo Generated MCP configs:
173
+ echo Codex operator: %CD%\%OUT_CODEX%
174
+ echo JSON operator: %CD%\%OUT_JSON%
175
+ echo Local MCP JSON: %REPO_ROOT%\%REPO_JSON%
176
+ echo Generated operator instructions:
177
+ echo %CD%\generated\OVERSEER_AGENT_INSTRUCTIONS.md
178
+ echo.
179
+ if exist "%REPO_ROOT%\%REPO_JSON%" (
180
+ copy "%REPO_ROOT%\%REPO_JSON%" "%REPO_ROOT%\%REPO_JSON%.backup-%RANDOM%" >nul
181
+ )
182
+ copy "%OUT_JSON%" "%REPO_ROOT%\%REPO_JSON%" >nul
183
+ echo Copied local MCP JSON to %REPO_ROOT%\%REPO_JSON%
184
+ echo.
185
+ echo JSON config preview:
186
+ type "%OUT_JSON%"
187
+ echo.
188
+
189
+ echo.
190
+ set /p "INSTALL_CODEX=If your cheap operator is Codex, append Codex MCP config to project .codex\config.toml with backup? yes/no [no]: "
191
+ if /I not "%INSTALL_CODEX%"=="yes" goto done
192
+
193
+ if not exist "%REPO_ROOT%\.codex" mkdir "%REPO_ROOT%\.codex"
194
+ if exist "%REPO_ROOT%\.codex\config.toml" (
195
+ copy "%REPO_ROOT%\.codex\config.toml" "%REPO_ROOT%\.codex\config.toml.backup-%RANDOM%" >nul
196
+ )
197
+ echo.>> "%REPO_ROOT%\.codex\config.toml"
198
+ type "%OUT_CODEX%" >> "%REPO_ROOT%\.codex\config.toml"
199
+ echo Installed in %REPO_ROOT%\.codex\config.toml
200
+ echo Restart Codex or run /mcp to verify the server appears.
201
+ goto done
202
+
203
+ :done
204
+ echo.
205
+ set /p "APPEND_AGENTS=Append operator instructions to repo AGENTS.md with backup? yes/no [no]: "
206
+ if /I "%APPEND_AGENTS%"=="yes" (
207
+ if exist "%REPO_ROOT%\AGENTS.md" (
208
+ copy "%REPO_ROOT%\AGENTS.md" "%REPO_ROOT%\AGENTS.md.backup-%RANDOM%" >nul
209
+ )
210
+ echo.>> "%REPO_ROOT%\AGENTS.md"
211
+ type "generated\OVERSEER_AGENT_INSTRUCTIONS.md" >> "%REPO_ROOT%\AGENTS.md"
212
+ echo Appended instructions to %REPO_ROOT%\AGENTS.md
213
+ )
214
+ echo.
215
+ echo Next checks:
216
+ echo 1. Ensure the secret env var exists in the environment that starts your agent.
217
+ echo 2. For Qoder / Mimo / Cline / Roo, import or paste %REPO_ROOT%\%REPO_JSON% into that client's MCP settings.
218
+ echo 3. Restart the agent or reload MCP servers.
219
+ echo 4. Ask the agent to list MCP tools and look for get_plan, consult_expert, request_review.
220
+ exit /b 0
221
+
222
+ :ensure_build
223
+ echo.
224
+ echo Installing dependencies and building overseer-mcp...
225
+ call npm install
226
+ if errorlevel 1 exit /b 1
227
+ call npm run build
228
+ if errorlevel 1 exit /b 1
229
+ exit /b 0
230
+
231
+ :fail
232
+ echo.
233
+ echo ERROR: configuration failed.
234
+ echo If this happened during CLI login, run the login command manually in a normal terminal to see the full error.
235
+ echo Example: codex login
236
+ echo.
237
+ echo Press any key to close this window.
238
+ pause >nul
239
+ exit /b 1
package/dist/config.js ADDED
@@ -0,0 +1,150 @@
1
+ import path from "node:path";
2
+ import { findGitRoot } from "./repo/findRoot.js";
3
+ import { AnthropicProvider } from "./providers/anthropic.js";
4
+ import { CliProvider } from "./providers/cli.js";
5
+ import { OpenAICompatibleProvider } from "./providers/openaiCompatible.js";
6
+ /** Returns a copy of `config` with `repoRoot` overridden to `newRoot`. */
7
+ export function withRepoRoot(config, newRoot) {
8
+ const resolved = findGitRoot(newRoot) ?? path.resolve(newRoot);
9
+ if (resolved === config.repoRoot)
10
+ return config;
11
+ return { ...config, repoRoot: resolved };
12
+ }
13
+ function required(env, name) {
14
+ const value = env[name];
15
+ if (!value) {
16
+ throw new Error(`Missing required environment variable: ${name}`);
17
+ }
18
+ return value;
19
+ }
20
+ function apiKey(env) {
21
+ if (env.OVERSEER_API_KEY) {
22
+ return env.OVERSEER_API_KEY;
23
+ }
24
+ const keyEnvName = env.OVERSEER_API_KEY_ENV;
25
+ if (!keyEnvName) {
26
+ throw new Error("Missing required environment variable: OVERSEER_API_KEY");
27
+ }
28
+ const value = env[keyEnvName];
29
+ if (!value) {
30
+ throw new Error(`Missing required environment variable: ${keyEnvName} (from OVERSEER_API_KEY_ENV)`);
31
+ }
32
+ return value;
33
+ }
34
+ function optionalNumber(env, name, fallback) {
35
+ const raw = env[name];
36
+ if (!raw)
37
+ return fallback;
38
+ const parsed = Number(raw);
39
+ if (!Number.isFinite(parsed) || parsed <= 0) {
40
+ throw new Error(`Invalid ${name}: expected a positive number`);
41
+ }
42
+ return parsed;
43
+ }
44
+ function optionalNumberAllowZero(env, name, fallback) {
45
+ const raw = env[name];
46
+ if (!raw)
47
+ return fallback;
48
+ const parsed = Number(raw);
49
+ if (!Number.isFinite(parsed) || parsed < 0) {
50
+ throw new Error(`Invalid ${name}: expected a non-negative number`);
51
+ }
52
+ return parsed;
53
+ }
54
+ function optionalPositiveNumber(env, name) {
55
+ const raw = env[name];
56
+ if (!raw)
57
+ return undefined;
58
+ const parsed = Number(raw);
59
+ if (!Number.isFinite(parsed) || parsed <= 0) {
60
+ throw new Error(`Invalid ${name}: expected a positive number`);
61
+ }
62
+ return parsed;
63
+ }
64
+ function optionalTemperature(env) {
65
+ const raw = env.OVERSEER_TEMPERATURE;
66
+ if (!raw)
67
+ return undefined;
68
+ const parsed = Number(raw);
69
+ if (!Number.isFinite(parsed) || parsed < 0 || parsed > 2) {
70
+ throw new Error("Invalid OVERSEER_TEMPERATURE: expected a number between 0 and 2");
71
+ }
72
+ return parsed;
73
+ }
74
+ function parseCliArgs(raw) {
75
+ if (!raw)
76
+ return [];
77
+ const trimmed = raw.trim();
78
+ if (!trimmed)
79
+ return [];
80
+ if (trimmed.startsWith("[")) {
81
+ const parsed = JSON.parse(trimmed);
82
+ if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
83
+ throw new Error("Invalid OVERSEER_CLI_ARGS: expected a JSON string array");
84
+ }
85
+ return parsed;
86
+ }
87
+ return trimmed.split(/\s+/);
88
+ }
89
+ function buildProvider(env, repoRoot) {
90
+ const provider = required(env, "OVERSEER_PROVIDER");
91
+ const maxTokens = optionalPositiveNumber(env, "OVERSEER_MAX_OUTPUT_TOKENS");
92
+ const temperature = optionalTemperature(env);
93
+ if (provider === "openai") {
94
+ return new OpenAICompatibleProvider({
95
+ apiKey: apiKey(env),
96
+ baseUrl: env.OVERSEER_BASE_URL ?? "https://api.openai.com/v1",
97
+ model: required(env, "OVERSEER_MODEL"),
98
+ maxTokens,
99
+ temperature,
100
+ });
101
+ }
102
+ if (provider === "anthropic") {
103
+ return new AnthropicProvider({
104
+ apiKey: apiKey(env),
105
+ baseUrl: env.OVERSEER_BASE_URL,
106
+ model: required(env, "OVERSEER_MODEL"),
107
+ maxTokens,
108
+ temperature,
109
+ });
110
+ }
111
+ if (provider === "cli") {
112
+ const promptVia = env.OVERSEER_CLI_PROMPT_VIA ?? "stdin";
113
+ if (promptVia !== "stdin" && promptVia !== "arg") {
114
+ throw new Error("Invalid OVERSEER_CLI_PROMPT_VIA: expected stdin or arg");
115
+ }
116
+ return new CliProvider({
117
+ command: required(env, "OVERSEER_CLI_COMMAND"),
118
+ args: parseCliArgs(env.OVERSEER_CLI_ARGS),
119
+ promptVia,
120
+ timeoutMs: optionalNumber(env, "OVERSEER_CLI_TIMEOUT_MS", 120000),
121
+ cwd: repoRoot,
122
+ });
123
+ }
124
+ throw new Error("Invalid OVERSEER_PROVIDER: expected openai, anthropic, or cli");
125
+ }
126
+ export function loadConfig(env = process.env, cwd = process.cwd()) {
127
+ // Prefer the first candidate that actually sits inside a git repo. VSCODE_CWD
128
+ // can point at the IDE install directory (e.g. ...\Programs\Trae) rather than
129
+ // the open project, which would root the expert at the wrong/empty repo.
130
+ const candidates = [env.OVERSEER_REPO_ROOT, env.VSCODE_CWD, cwd].filter((value) => Boolean(value));
131
+ let repoRoot;
132
+ for (const candidate of candidates) {
133
+ const root = findGitRoot(candidate);
134
+ if (root) {
135
+ repoRoot = root;
136
+ break;
137
+ }
138
+ }
139
+ repoRoot ??= path.resolve(env.OVERSEER_REPO_ROOT ?? cwd);
140
+ return {
141
+ provider: buildProvider(env, repoRoot),
142
+ repoRoot,
143
+ testCommand: env.OVERSEER_TEST_COMMAND,
144
+ maxFiles: optionalNumber(env, "OVERSEER_MAX_FILES", 12),
145
+ planFullFiles: optionalNumberAllowZero(env, "OVERSEER_PLAN_FULL_FILES", 0),
146
+ maxFileBytes: optionalNumber(env, "OVERSEER_MAX_FILE_BYTES", 65536),
147
+ maxDiffBytes: optionalNumber(env, "OVERSEER_MAX_DIFF_BYTES", 262144),
148
+ testTimeoutMs: optionalNumber(env, "OVERSEER_TEST_TIMEOUT_MS", 300000),
149
+ };
150
+ }