Files

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.