MCP OpenAI Server
by Akira-AA83
README.md
# MCP OpenAI — Astra second opinion
An MCP server that gives Claude Code a second, independent opinion from OpenAI models.
It exposes two tools:
- **`openai_chat`**: ask an OpenAI model a question and get a text answer.
- **`astra_investigate`**: hand a task to an autonomous OpenAI agent that inspects the project on its own through the same MCP servers Claude uses (Unreal Editor, Perplexity, ...) and reports back a verdict with evidence.
The point of `astra_investigate` is independence: the agent is not fed Claude's summary of the situation, it looks at the real state of the project with its own criteria.
> Fork of [mzxrai/mcp-openai](https://github.com/mzxrai/mcp-openai), extended with the autonomous agent, model tiers and a cross-agent semaphore.
## How it works
```
Claude Code
│ astra_investigate(prompt, tier)
▼
this server (stdio MCP)
│ reads the project .mcp.json, connects to every MCP server except itself
├──[http]──▶ unreal-mcp
├──[stdio]─▶ perplexity
│
│ loop: OpenAI Responses API ──function_call──▶ forward to the owning MCP server
│ ◀──function_call_output──
▼
final verdict + trace (tool calls, tokens) back to Claude
```
Child MCP servers are connected lazily on the first `astra_investigate` call, so `openai_chat` keeps working even when, say, the Unreal Editor is closed. Servers that fail to connect are skipped and listed as `unavailable` in the trace.
Every investigation re-checks the servers, so you can open or close the Unreal Editor at any time without restarting anything:
- a server that was unavailable is retried, and picked up as soon as it is running;
- an already connected server is pinged first; if it stopped answering (e.g. the editor was closed and reopened, which invalidates the old session), the stale connection is dropped and a new one is opened.
A server that goes down *during* an investigation makes the remaining calls fail; the agent sees the errors and reports them.
## Tools
### `openai_chat`
| Argument | Required | Description |
|---|---|---|
| `messages` | yes | Array of `{ role: "system" \| "user" \| "assistant", content }` |
| `tier` | no | `fast`, `reason` (default) or `deep`, see [Model tiers](#model-tiers) |
| `model` | no | Exact model, overrides `tier` |
### `astra_investigate`
| Argument | Required | Description |
|---|---|---|
| `prompt` | yes | The task. Be specific: the agent decides which tools to call |
| `tier` | no | `fast`, `reason` (default) or `deep` |
| `model` | no | Exact model, overrides `tier` |
| `allowedServers` | no | Restrict the agent to some MCP servers, e.g. `["unreal-mcp"]` |
Example prompts, as you would type them to Claude:
```text
Use astra_investigate with tier deep: verify that PCG_CliffRockScatter has slope
filters that really catch vertical walls. Verdict plus suggested fixes.
```
```text
Ask astra_investigate to test whether the maxThreshold of FilterCliffSlopes can be
changed via MCP, then restore it.
```
The answer ends with a trace like:
```text
Astra trace: model=gpt-6-astra, servers=unreal-mcp, perplexity
Tokens: 73430 in (59664 cached) / 890 out
Tool calls (7):
- unreal-mcp__list_toolsets {}
- unreal-mcp__call_tool {"toolset_name":"PCGToolset.PCGToolset","tool_name":"UpdateNode",...}
...
```
## Model tiers
The default is **never** the expensive model: ask for `deep` explicitly.
| Tier | Model | Use for |
|---|---|---|
| `fast` | `gpt-5-mini` | Trivial lookups. Noticeably less reliable on facts |
| `reason` (default) | `gpt-5` | Most checks and reviews |
| `deep` | `gpt-6-astra` | Critical audits. Much slower and more expensive than the other tiers |
`model` accepts any of these, all verified on both the Chat Completions and the Responses API with function calling:
`gpt-6-astra`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5`, `gpt-5-mini`, `o3`, `o4-mini`, `gpt-4.1`, `gpt-4.1-mini`, `gpt-4o`, `gpt-4o-mini`
Tiers and the model list live in [`src/models.ts`](src/models.ts). Verify a model before adding it.
## What the agent may do
The agent has **write access** to the MCP servers, because some questions can only be answered by trying something. Its instructions require it to:
1. read and note original values before changing anything;
2. restore every original value and verify the restore by reading it back;
3. never save assets, levels or packages, and never delete assets;
4. end its answer with a **Modifications** table (object, property, original, test value, restored?).
Changes therefore stay in memory in the editor: if something goes wrong, close without saving or use Undo.
Two unreal-mcp toolsets are always blocked for the agent: `ProgrammaticToolset` (runs Python in the editor) and `SlateInspectorToolset` (simulates UI input).
## Semaphore between Claude and the agent
Claude and the agent must not drive the same MCP server at the same time, especially while the agent is in the middle of a "change, test, restore" sequence.
- During an investigation the agent holds a lock on each server it uses, until the investigation ends.
- A Claude Code hook takes a short lock around each of Claude's own MCP calls and **denies** the call if the agent holds the server:
`MCP server "unreal-mcp" is locked by Astra (pid 18616, since 13:05:48) running astra_investigate.`
- If Claude has a call in flight, the agent waits (up to 90 s) before touching that server.
- Locks of dead processes are ignored, so a crash never leaves a server blocked.
Locks are files in `~/.astra-mcp-locks/`. Install the hook in every project whose Claude sessions use the same MCP servers, in `.claude/settings.local.json`:
```json
{
"hooks": {
"PreToolUse": [
{ "matcher": "mcp__.*", "hooks": [{ "type": "command", "command": "node", "args": ["<repo>/hooks/mcp-lock-hook.mjs"], "timeout": 15 }] }
],
"PostToolUse": [
{ "matcher": "mcp__.*", "hooks": [{ "type": "command", "command": "node", "args": ["<repo>/hooks/mcp-lock-hook.mjs"], "timeout": 15 }] }
],
"PostToolUseFailure": [
{ "matcher": "mcp__.*", "hooks": [{ "type": "command", "command": "node", "args": ["<repo>/hooks/mcp-lock-hook.mjs"], "timeout": 15 }] }
]
}
}
```
The hook imports `dist/lock.js`, so the project must be built. If the hook itself fails, it lets the call through.
## Installation
Requirements: Node.js 18+, an [OpenAI API key](https://platform.openai.com/api-keys), Claude Code.
```bash
git clone https://github.com/Akira-AA83/MCP-OPENAI.git
cd MCP-OPENAI
npm install # also builds dist/ through the prepare script
```
Register it in the project that holds the MCP servers the agent should use:
```bash
cd <your-project>
claude mcp add openai --scope project \
--env OPENAI_API_KEY=<your-key> \
--env ASTRA_MCP_CONFIG=<your-project>/.mcp.json \
-- node <repo>/dist/index.js
```
Keep the server name `openai`, or set `ASTRA_SELF_NAME` to the name you use: the server skips that entry to avoid launching itself. Then restart Claude Code (or `claude --continue`) and add the hook above.
`--scope project` writes the key into `.mcp.json`: don't commit that file, or use `--scope local`.
## Configuration
| Variable | Default | Description |
|---|---|---|
| `OPENAI_API_KEY` | (required) | OpenAI key |
| `ASTRA_MCP_CONFIG` | `C:/Users/angel/Desktop/EDGELAB/THE_VALLEY/.mcp.json` | `.mcp.json` listing the servers the agent may use |
| `ASTRA_SELF_NAME` | `openai` | Name of this server in that file, excluded to avoid recursion |
| `ASTRA_MAX_ITERATIONS` | `30` | Max model round trips per investigation |
| `ASTRA_MAX_OUTPUT_TOKENS` | `8000` | Max output tokens per round trip |
| `ASTRA_MAX_RESULT_CHARS` | `20000` | Tool results longer than this are truncated; images are always omitted |
| `ASTRA_TOOL_TIMEOUT_MS` | `300000` | Timeout of a single child tool call |
| `ASTRA_LOCK_WAIT_MS` | `90000` | How long the agent waits for a server Claude is using |
| `ASTRA_CLAUDE_LOCK_TTL_MS` | `120000` | Expiry of Claude's per-call lock, in case PostToolUse never fires |
| `ASTRA_LOCK_DIR` | `~/.astra-mcp-locks` | Lock directory, shared by server and hook |
## Limitations
- Servers that authenticate through Claude Code's own OAuth (e.g. Atlassian) can't be reused by the agent and are skipped.
- Tool calls within one iteration run sequentially; no streaming.
- Only verified on Windows.
## Development
```bash
npm run build # tsc into dist/
npm run watch # rebuild on change
```
| File | Role |
|---|---|
| `src/index.ts` | MCP server, `openai_chat` and `astra_investigate` |
| `src/astraLoop.ts` | Agent loop over the Responses API, instructions, trace |
| `src/toolBridge.ts` | Aggregates child tools, naming, policy, result truncation |
| `src/childManager.ts` | Connects to child MCP servers (stdio / HTTP) |
| `src/mcpConfig.ts` | Reads `.mcp.json`, excludes this server |
| `src/models.ts` | Verified models and tiers |
| `src/lock.ts` | Semaphore shared by the server and the hook |
| `hooks/mcp-lock-hook.mjs` | Claude Code hook enforcing the semaphore |
## License
MIT. Original `openai_chat` server by [mzxrai](https://github.com/mzxrai/mcp-openai).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues