886 lines
16 KiB
Markdown
886 lines
16 KiB
Markdown
# ARCHITECTURE.md
|
|
|
|
# ChatGPT MCP Server Architecture
|
|
|
|
## 1. Project Purpose
|
|
|
|
The ChatGPT MCP Server is a local MCP server that allows Claude Code to ask ChatGPT for focused second-opinion help.
|
|
|
|
Claude Code remains the primary coding agent.
|
|
|
|
ChatGPT acts only as:
|
|
|
|
- Reviewer
|
|
- Planner
|
|
- Debugging assistant
|
|
- Architecture advisor
|
|
- Risk checker
|
|
- Task decomposition helper
|
|
|
|
The server must not:
|
|
|
|
- Modify files
|
|
- Run shell commands
|
|
- Access Git automatically
|
|
- Deploy anything
|
|
- Send whole repositories by default
|
|
- Send secrets
|
|
- Make autonomous decisions
|
|
|
|
---
|
|
|
|
## 2. Local AI Workflow
|
|
|
|
This project uses a hybrid local/cloud assistant model.
|
|
|
|
```text
|
|
Claude Code
|
|
↓
|
|
Local Ollama model: Qwen3.6:35b-a3b
|
|
↓
|
|
Primary coding, editing, testing, and implementation
|
|
```
|
|
|
|
When Claude Code wants an external second opinion:
|
|
|
|
```text
|
|
Claude Code
|
|
↓
|
|
Local ChatGPT MCP Server
|
|
↓
|
|
OpenAI Responses API
|
|
↓
|
|
ChatGPT review response
|
|
↓
|
|
Claude Code
|
|
```
|
|
|
|
ChatGPT is advisory only.
|
|
|
|
Claude Code remains responsible for:
|
|
|
|
- Coding
|
|
- File edits
|
|
- Running tests
|
|
- Applying changes
|
|
- Git operations
|
|
- Final decisions
|
|
|
|
---
|
|
|
|
## 3. Technical Stack
|
|
|
|
Use a simple JavaScript MVP.
|
|
|
|
```text
|
|
Node.js 22+
|
|
JavaScript ESM
|
|
MCP SDK
|
|
OpenAI SDK
|
|
OpenAI Responses API
|
|
Zod
|
|
Vitest
|
|
stdio transport
|
|
Local macOS execution
|
|
Environment variables
|
|
```
|
|
|
|
Use JavaScript instead of TypeScript to keep the first version simple and reviewable.
|
|
|
|
TypeScript can be added later only if the project grows enough to justify it.
|
|
|
|
---
|
|
|
|
## 4. High-Level Architecture
|
|
|
|
```text
|
|
Claude Code
|
|
|
|
|
| MCP stdio
|
|
v
|
|
src/server.js
|
|
|
|
|
v
|
|
MCP tool router
|
|
|
|
|
v
|
|
Tool handler
|
|
|
|
|
v
|
|
Input validation with Zod
|
|
|
|
|
v
|
|
Secret redaction
|
|
|
|
|
v
|
|
Context size checks
|
|
|
|
|
v
|
|
Prompt builder
|
|
|
|
|
v
|
|
OpenAI Responses API
|
|
|
|
|
v
|
|
Structured advisory response
|
|
```
|
|
|
|
The MCP server is a bridge and prompt wrapper. It is not an autonomous agent.
|
|
|
|
---
|
|
|
|
## 5. Repository Structure
|
|
|
|
```text
|
|
chatgpt-mcp/
|
|
├── README.md
|
|
├── ARCHITECTURE.md
|
|
├── TASKS.md
|
|
├── PROJECT_STATE.md
|
|
├── AGENT_HANDOFF.md
|
|
├── package.json
|
|
├── .env.example
|
|
├── .gitignore
|
|
├── src/
|
|
│ ├── server.js
|
|
│ ├── tools/
|
|
│ │ ├── ask-chatgpt.js
|
|
│ │ ├── review-plan.js
|
|
│ │ ├── review-code.js
|
|
│ │ ├── debug-issue.js
|
|
│ │ ├── architecture-review.js
|
|
│ │ └── schemas.js
|
|
│ ├── openai/
|
|
│ │ ├── client.js
|
|
│ │ └── responses.js
|
|
│ ├── prompts/
|
|
│ │ ├── base.js
|
|
│ │ ├── ask-chatgpt.js
|
|
│ │ ├── review-plan.js
|
|
│ │ ├── review-code.js
|
|
│ │ ├── debug-issue.js
|
|
│ │ └── architecture-review.js
|
|
│ ├── config/
|
|
│ │ ├── env.js
|
|
│ │ └── defaults.js
|
|
│ └── utils/
|
|
│ ├── redact.js
|
|
│ ├── context-budget.js
|
|
│ ├── errors.js
|
|
│ └── logging.js
|
|
├── context/
|
|
│ ├── project-context.md
|
|
│ ├── mcp-context.md
|
|
│ ├── openai-context.md
|
|
│ ├── claude-context.md
|
|
│ ├── security-context.md
|
|
│ ├── user-context.md
|
|
│ ├── infrastructure-context.md
|
|
│ ├── development-context.md
|
|
│ ├── repository-context.md
|
|
│ ├── current-environment.md
|
|
│ └── company-context.md
|
|
└── test/
|
|
├── tools/
|
|
├── prompts/
|
|
├── utils/
|
|
└── fixtures/
|
|
```
|
|
|
|
---
|
|
|
|
## 6. MCP Tools
|
|
|
|
Start with five focused tools.
|
|
|
|
### 6.1 `ask_chatgpt`
|
|
|
|
General second-opinion question.
|
|
|
|
Use for:
|
|
|
|
- General advice
|
|
- Alternatives
|
|
- Risks
|
|
- Clarification
|
|
- Breaking down tasks
|
|
|
|
### 6.2 `review_plan`
|
|
|
|
Reviews a proposed implementation plan before Claude Code acts.
|
|
|
|
Use for:
|
|
|
|
- Missing steps
|
|
- Unsafe assumptions
|
|
- Scope creep
|
|
- Better sequencing
|
|
- Test gaps
|
|
|
|
### 6.3 `review_code`
|
|
|
|
Reviews focused snippets, patches, or diffs.
|
|
|
|
Use for:
|
|
|
|
- Correctness
|
|
- Bugs
|
|
- Maintainability
|
|
- Security issues
|
|
- Tests
|
|
- Simpler approaches
|
|
|
|
### 6.4 `debug_issue`
|
|
|
|
Reviews errors, logs, failed tests, or stack traces.
|
|
|
|
Use for:
|
|
|
|
- Likely root causes
|
|
- Debugging steps
|
|
- Minimal experiments
|
|
- What not to change yet
|
|
|
|
### 6.5 `architecture_review`
|
|
|
|
Reviews architecture decisions and trade-offs.
|
|
|
|
Use for:
|
|
|
|
- Local vs cloud trade-offs
|
|
- Simplicity
|
|
- Maintainability
|
|
- Operational risk
|
|
- Vendor lock-in
|
|
- Future extension paths
|
|
|
|
---
|
|
|
|
## 7. Tool Input Schema
|
|
|
|
All tools should share a common shape.
|
|
|
|
```js
|
|
{
|
|
question: string,
|
|
context?: string,
|
|
constraints?: string[],
|
|
expectedOutput?: string,
|
|
projectSummary?: string,
|
|
taskSummary?: string,
|
|
relevantFiles?: [
|
|
{
|
|
path: string,
|
|
content: string,
|
|
language?: string
|
|
}
|
|
],
|
|
logs?: string
|
|
}
|
|
```
|
|
|
|
Rules:
|
|
|
|
- `question` is required.
|
|
- Context must be focused.
|
|
- Do not send whole repositories.
|
|
- Do not send secrets.
|
|
- Do not send `.env` files.
|
|
- Do not send unrelated large files.
|
|
|
|
---
|
|
|
|
## 8. Tool Output Format
|
|
|
|
Default output should be structured and concise.
|
|
|
|
```text
|
|
Summary:
|
|
...
|
|
|
|
Recommendation:
|
|
...
|
|
|
|
Key Concerns:
|
|
1. ...
|
|
2. ...
|
|
|
|
Suggested Next Steps:
|
|
1. ...
|
|
2. ...
|
|
|
|
Confidence:
|
|
Low | Medium | High
|
|
|
|
Notes:
|
|
...
|
|
```
|
|
|
|
For code review, include:
|
|
|
|
```text
|
|
Issues by Severity:
|
|
...
|
|
|
|
Suggested Fixes:
|
|
...
|
|
|
|
Test Suggestions:
|
|
...
|
|
```
|
|
|
|
For debugging, include:
|
|
|
|
```text
|
|
Likely Causes:
|
|
...
|
|
|
|
Fast Checks:
|
|
...
|
|
|
|
Minimal Safe Experiments:
|
|
...
|
|
|
|
What Not To Do Yet:
|
|
...
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Context Model
|
|
|
|
Use layered context.
|
|
|
|
```text
|
|
1. Company/development preferences
|
|
2. Project context
|
|
3. Claude Code role context
|
|
4. Current task context
|
|
5. Specific question
|
|
6. Relevant snippets/logs
|
|
```
|
|
|
|
For MVP, do not automatically load every context file.
|
|
|
|
Recommended MVP behaviour:
|
|
|
|
- Use built-in base prompt rules.
|
|
- Accept focused context from Claude Code tool calls.
|
|
- Keep automatic context loading disabled by default.
|
|
|
|
Later enhancement:
|
|
|
|
- Optional loading of selected files from `/context`.
|
|
- Never load secrets or environment files.
|
|
|
|
---
|
|
|
|
## 10. Prompt Rules
|
|
|
|
All prompts must reinforce:
|
|
|
|
- Claude Code is the primary coding agent.
|
|
- ChatGPT is advisory only.
|
|
- ChatGPT must not claim to have run commands or tests.
|
|
- ChatGPT must not ask for secrets.
|
|
- ChatGPT must not request the whole repo.
|
|
- ChatGPT should prefer small, reviewable changes.
|
|
- ChatGPT should call out uncertainty.
|
|
|
|
---
|
|
|
|
## 11. Base Prompt
|
|
|
|
```text
|
|
You are ChatGPT acting as a second-opinion assistant for Claude Code.
|
|
|
|
Claude Code is the primary coding agent and is currently backed by a local Ollama coding model.
|
|
|
|
You are not responsible for editing files, running commands, deploying, committing code, or making autonomous decisions.
|
|
|
|
Your role:
|
|
- Review plans
|
|
- Review code snippets
|
|
- Analyse architecture
|
|
- Debug issues
|
|
- Identify risks
|
|
- Suggest safer implementation approaches
|
|
- Break work into smaller steps
|
|
|
|
Rules:
|
|
- Be concise and actionable.
|
|
- Use only the context provided.
|
|
- Do not assume access to the full repository.
|
|
- Do not request secrets.
|
|
- Do not recommend sending entire repositories.
|
|
- Prefer small reviewable changes.
|
|
- Prefer simple architecture.
|
|
- Prefer local/self-hosted options where practical.
|
|
- Call out uncertainty clearly.
|
|
- Avoid over-engineering.
|
|
- Do not pretend to have executed code or tests.
|
|
```
|
|
|
|
---
|
|
|
|
## 12. OpenAI Integration
|
|
|
|
Use OpenAI as a second-opinion provider only. The integration lives behind the provider abstraction layer:
|
|
|
|
```text
|
|
src/providers/factory.js — createChatProvider(config) validates and returns configured provider
|
|
src/providers/openai.js — openaiProvider.send(input, config) thin adapter
|
|
src/openai/client.js — createOpenAIClient(config) low-level client
|
|
src/openai/responses.js — sendOpenAIResponse(client, params) API call wrapper
|
|
```
|
|
|
|
### Provider Selection
|
|
|
|
Configured via `CHATGPT_MCP_PROVIDER` env var (defaults to `"openai"`):
|
|
|
|
```env
|
|
CHATGPT_MCP_PROVIDER=openai # or "manual" for copy-paste workflow
|
|
```
|
|
|
|
Supported provider values:
|
|
|
|
| Value | Description | Requires API key? |
|
|
| -------- | -------------------------------------------------------------- | ----------------- |
|
|
| `openai` | Default — calls ChatGPT via OpenAI API | Yes |
|
|
| `manual` | Copy-paste — wraps prompts in a ready-to-copy format | No |
|
|
| `ollama` | Local AI — uses Ollama `/api/chat` endpoint with Qwen3 | No |
|
|
|
|
The factory whitelists `"openai"`, `"manual"`, and `"ollama"`. Any unrecognized value throws at provider creation time (not config load time). Null/NaN/falsy values default to `"openai"` for safe fallback.
|
|
|
|
### OpenAI-specific Environment Variables
|
|
|
|
```env
|
|
OPENAI_API_KEY= # required — no default, throws if missing
|
|
OPENAI_MODEL=gpt-5.1
|
|
OPENAI_TEMPERATURE=0.2
|
|
OPENAI_MAX_OUTPUT_TOKENS=2000
|
|
```
|
|
|
|
### Ollama-specific Environment Variables
|
|
|
|
```env
|
|
OLLAMA_BASE_URL=http://localhost:11434 # Ollama API endpoint
|
|
OLLAMA_MODEL=qwen3:latest # default model for chat requests
|
|
OLLAMA_TEMPERATURE=0.2 # sampling temperature
|
|
OLLAMA_TIMEOUT=60 # request timeout in seconds
|
|
```
|
|
|
|
The provider pattern makes it straightforward to add other providers (Anthropic, custom) — implement the `send(request, config)` interface and register it in the factory's whitelist. Ollama is already implemented.
|
|
|
|
---
|
|
|
|
## 13. Configuration
|
|
|
|
Use `.env.example`:
|
|
|
|
```env
|
|
OPENAI_API_KEY=
|
|
OPENAI_MODEL=gpt-5.1
|
|
OPENAI_TEMPERATURE=0.2
|
|
OPENAI_MAX_OUTPUT_TOKENS=2000
|
|
|
|
CHATGPT_MCP_LOG_LEVEL=info
|
|
CHATGPT_MCP_ENABLE_FILE_CONTEXT=false
|
|
CHATGPT_MCP_CONTEXT_DIR=./context
|
|
CHATGPT_MCP_MAX_INPUT_CHARS=30000
|
|
CHATGPT_MCP_MAX_FILE_CHARS=12000
|
|
CHATGPT_MCP_MAX_FILES=5
|
|
CHATGPT_MCP_MAX_LOG_CHARS=10000
|
|
CHATGPT_MCP_REDACT_SECRETS=true
|
|
```
|
|
|
|
Rules:
|
|
|
|
- Fail fast if `OPENAI_API_KEY` is missing and provider is `openai`.
|
|
- OPENAI_API_KEY is optional for `manual` and `ollama` providers.
|
|
- Do not hardcode secrets.
|
|
- Do not read `.env` content into prompts.
|
|
- Keep context loading disabled by default.
|
|
|
|
---
|
|
|
|
## 14. Security Rules
|
|
|
|
The server must never automatically include:
|
|
|
|
```text
|
|
.env
|
|
.env.*
|
|
*.pem
|
|
*.key
|
|
id_rsa
|
|
id_ed25519
|
|
.ssh/*
|
|
node_modules/*
|
|
dist/*
|
|
build/*
|
|
coverage/*
|
|
.git/*
|
|
```
|
|
|
|
Redact likely secrets before API calls.
|
|
|
|
Patterns to redact:
|
|
|
|
- API keys
|
|
- Tokens
|
|
- Passwords
|
|
- Bearer tokens
|
|
- Private keys
|
|
- SSH keys
|
|
- PEM blocks
|
|
- Database URLs with credentials
|
|
- Git credentials
|
|
|
|
Replacement:
|
|
|
|
```text
|
|
[REDACTED]
|
|
```
|
|
|
|
Logging must not include:
|
|
|
|
- Full prompts
|
|
- Source code
|
|
- Secrets
|
|
- Environment variables
|
|
- Full OpenAI responses by default
|
|
|
|
---
|
|
|
|
## 15. Context Size Management
|
|
|
|
MVP should use character limits.
|
|
|
|
Recommended defaults:
|
|
|
|
```text
|
|
Max total input: 30000 chars
|
|
Max single file: 12000 chars
|
|
Max files: 5
|
|
Max logs: 10000 chars
|
|
```
|
|
|
|
Priority when trimming:
|
|
|
|
1. Repeated logs
|
|
2. Long file snippets
|
|
3. General context
|
|
4. Project summary
|
|
|
|
Never silently drop the main question.
|
|
|
|
If context is still too large, reject with:
|
|
|
|
```text
|
|
Input is too large for a focused review. Please retry with only the specific files, diff, or error section relevant to the question.
|
|
```
|
|
|
|
---
|
|
|
|
## 16. Logging
|
|
|
|
Log safe metadata only:
|
|
|
|
- Tool name
|
|
- Timestamp
|
|
- Model
|
|
- Input size
|
|
- Output size
|
|
- Duration
|
|
- Success/failure
|
|
- Error type
|
|
|
|
Use stderr for MVP.
|
|
|
|
No database.
|
|
|
|
No telemetry.
|
|
|
|
No external logging service.
|
|
|
|
---
|
|
|
|
## 17. Error Handling
|
|
|
|
### Configuration errors
|
|
|
|
Example (when using `openai` provider):
|
|
|
|
```text
|
|
Configuration error: OPENAI_API_KEY is required for the openai provider.
|
|
```
|
|
|
|
### Validation errors
|
|
|
|
Example:
|
|
|
|
```text
|
|
Validation error: question is required.
|
|
```
|
|
|
|
### Context errors
|
|
|
|
Example:
|
|
|
|
```text
|
|
Input is too large. Provide a smaller focused snippet.
|
|
```
|
|
|
|
### OpenAI errors
|
|
|
|
Handle:
|
|
|
|
- Authentication failure
|
|
- Rate limits
|
|
- Timeout
|
|
- Model unavailable
|
|
- Network failure
|
|
|
|
Return safe messages only.
|
|
|
|
Do not expose stack traces unless debug mode is explicitly enabled.
|
|
|
|
---
|
|
|
|
## 18. Claude Code MCP Configuration
|
|
|
|
Production-style local config:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"chatgpt-mcp": {
|
|
"command": "node",
|
|
"args": ["/absolute/path/to/chatgpt-mcp/src/server.js"],
|
|
"env": {
|
|
"OPENAI_API_KEY": "your-openai-api-key",
|
|
"OPENAI_MODEL": "gpt-5.1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Development config:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"chatgpt-mcp": {
|
|
"command": "npm",
|
|
"args": ["run", "dev:mcp"],
|
|
"cwd": "/absolute/path/to/chatgpt-mcp",
|
|
"env": {
|
|
"OPENAI_API_KEY": "your-openai-api-key"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
The server runs locally on macOS using stdio.
|
|
|
|
It does not need to be deployed for the MVP.
|
|
|
|
---
|
|
|
|
## 19. Development Workflow
|
|
|
|
Use the normal Gitea workflow.
|
|
|
|
```text
|
|
Feature branch
|
|
→ Commit
|
|
→ Pull request
|
|
→ Merge
|
|
```
|
|
|
|
Branch examples:
|
|
|
|
```text
|
|
feature/TASK-001
|
|
fix/TASK-002
|
|
docs/TASK-003
|
|
```
|
|
|
|
Commit examples:
|
|
|
|
```text
|
|
feat: add ask_chatgpt tool
|
|
fix: redact bearer tokens
|
|
docs: update MCP setup instructions
|
|
test: add prompt builder tests
|
|
chore: initialise project
|
|
```
|
|
|
|
Rules:
|
|
|
|
- One task per change.
|
|
- Keep changes small.
|
|
- Update docs when behaviour changes.
|
|
- Do not add hidden behaviour.
|
|
- Do not add automatic repository scanning in MVP.
|
|
- Do not add deployment automation until the local MVP works.
|
|
|
|
---
|
|
|
|
## 20. Testing Strategy
|
|
|
|
Use Vitest.
|
|
|
|
Test areas:
|
|
|
|
- Config loading
|
|
- Secret redaction
|
|
- Context budget checks
|
|
- Prompt construction
|
|
- Tool schema validation
|
|
- OpenAI wrapper with mocked responses
|
|
- Error formatting
|
|
|
|
Manual smoke tests:
|
|
|
|
1. Start MCP server locally.
|
|
2. Confirm Claude Code can discover tools.
|
|
3. Call `ask_chatgpt`.
|
|
4. Call `review_plan`.
|
|
5. Call `review_code`.
|
|
6. Call `debug_issue`.
|
|
7. Confirm no files were modified by the MCP server.
|
|
8. Confirm fake secrets are redacted.
|
|
|
|
---
|
|
|
|
## 21. MVP Scope
|
|
|
|
Smallest useful MVP:
|
|
|
|
```text
|
|
Node.js JavaScript project
|
|
MCP stdio server
|
|
OpenAI Responses API wrapper
|
|
Config loader
|
|
Secret redaction
|
|
Context size checks
|
|
ask_chatgpt tool
|
|
README setup instructions
|
|
```
|
|
|
|
Do not build all advanced features first.
|
|
|
|
After the MVP works, add the other tools one at a time.
|
|
|
|
---
|
|
|
|
## 22. Recommended Implementation Order
|
|
|
|
1. Create repository skeleton.
|
|
2. Add package.json.
|
|
3. Add `.env.example`.
|
|
4. Add config loader.
|
|
5. Add redaction utility.
|
|
6. Add context budget utility.
|
|
7. Add OpenAI client wrapper.
|
|
8. Add base prompt.
|
|
9. Add `ask_chatgpt`.
|
|
10. Add MCP stdio server.
|
|
11. Test with Claude Code.
|
|
12. Add `review_plan`.
|
|
13. Add `review_code`.
|
|
14. Add `debug_issue`.
|
|
15. Add `architecture_review`.
|
|
16. Add README examples.
|
|
17. Add tests.
|
|
18. Update PROJECT_STATE.md.
|
|
|
|
---
|
|
|
|
## 23. Future Roadmap
|
|
|
|
The following items remain from the original planning scope:
|
|
|
|
### Near term (post-v1)
|
|
|
|
- Add context file opt-in loading from `/context` directory
|
|
- Add structured response formatting enhancements
|
|
|
|
### Medium term
|
|
|
|
- Add Anthropic provider adapter (abstraction layer ready; implement `send(request, config)` interface)
|
|
- Add model-per-tool configuration
|
|
- Add timeout/retry tuning per provider
|
|
|
|
### Later
|
|
|
|
- Add Dockerfile
|
|
- Add CI/CD pipeline (Jenkins validation, Gitea PR workflow)
|
|
- Add safe project summary generation
|
|
- Add optional OpenHands integration
|
|
- Add streaming responses support
|
|
- Add cost tracking per tool call
|
|
|
|
---
|
|
|
|
## 24. Key Risks
|
|
|
|
### Risk: Secret leakage
|
|
|
|
Mitigation:
|
|
|
|
- Explicit context only.
|
|
- Redaction.
|
|
- No automatic `.env` loading.
|
|
- Safe logging.
|
|
|
|
### Risk: Too much context
|
|
|
|
Mitigation:
|
|
|
|
- Character limits.
|
|
- File count limits.
|
|
- Focused tool inputs.
|
|
- Reject oversized requests.
|
|
|
|
### Risk: ChatGPT overrules Claude Code
|
|
|
|
Mitigation:
|
|
|
|
- Prompt says advisory only.
|
|
- Claude Code remains executor.
|
|
- Responses include assumptions and confidence.
|
|
|
|
### Risk: Over-engineering
|
|
|
|
Mitigation:
|
|
|
|
- JavaScript MVP.
|
|
- One tool first.
|
|
- No automatic repo scanning.
|
|
- No deployment work until local MVP works.
|
|
|
|
### Risk: Conflicting advice between Qwen and ChatGPT
|
|
|
|
Mitigation:
|
|
|
|
- Treat ChatGPT as second opinion only.
|
|
- Use it for risk checks and alternatives.
|
|
- Claude Code decides what to implement.
|
|
|
|
---
|
|
|
|
## 25. Decision Summary
|
|
|
|
Use JavaScript, not TypeScript, for the MVP.
|
|
|
|
Use Claude Code with local Ollama/Qwen as the main coding assistant.
|
|
|
|
Use ChatGPT through MCP only as a focused external reviewer.
|
|
|
|
Keep the system local-first, simple, explicit, and non-mutating.
|