# 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. - 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: ```text Configuration error: OPENAI_API_KEY is missing. ``` ### 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 Near term: - Add all five MCP tools. - Add structured response formatting. - Add better tests. - Add context file opt-in loading. Medium term: - Add Anthropic provider. - Add model-per-tool config. - Add cost tracking. - Add timeout/retry tuning. - Add local-only mode for sensitive reviews. Later: - Add Dockerfile. - Add Jenkins validation pipeline. - Add Gitea pull request workflow. - Add safe project summary generation. - Add optional OpenHands integration. - Implement Anthropic provider. - 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.