763 lines
32 KiB
Markdown
763 lines
32 KiB
Markdown
# TASKS.md
|
|
|
|
## Phase 0 - Repository Setup
|
|
|
|
### Task 0.1 - Create repository skeleton
|
|
|
|
Create:
|
|
|
|
- README.md
|
|
- ARCHITECTURE.md
|
|
- TASKS.md
|
|
- PROJECT_STATE.md
|
|
- AGENT_HANDOFF.md
|
|
- src/
|
|
- test/
|
|
- context/
|
|
|
|
Do not implement functionality yet.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 0.2 - Add package.json and dependencies
|
|
|
|
Add `package.json` with MCP SDK, OpenAI SDK, Zod, Vitest.
|
|
|
|
Status: ✅ Complete
|
|
|
|
---
|
|
|
|
## Phase 1 - Core Utilities
|
|
|
|
### Task 1.1 - Configuration loader
|
|
|
|
Create `src/config/env.js`.
|
|
|
|
Requirements:
|
|
- Read environment variables and validate OPENAI_API_KEY exists.
|
|
- Apply defaults from ARCHITECTURE.md section 13.
|
|
- Return a structured config object.
|
|
- Throw clear configuration errors for missing or invalid values.
|
|
- Use plain JavaScript validation (no Zod yet).
|
|
- Single exported `loadConfig()` function.
|
|
|
|
Create `test/config/env.test.js`.
|
|
|
|
Requirements:
|
|
- Test all default values.
|
|
- Test all custom overrides (strings, numbers, booleans).
|
|
- Test error cases: missing API key, invalid numbers, invalid booleans.
|
|
- No external dependencies in the loader.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 1.2 - Secret redaction utility
|
|
|
|
Create `src/utils/redact.js`.
|
|
|
|
Requirements:
|
|
- Detect likely secrets (API keys, tokens, passwords, Bearer tokens, private keys, SSH keys, PEM blocks, DB URLs with credentials).
|
|
- Replace detected secrets with `[REDACTED]`.
|
|
- Return the redacted string.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 1.3 - Context budget utility
|
|
|
|
Create `src/utils/context-budget.js`.
|
|
|
|
Requirements:
|
|
- Character limit checks (max total, per file, max files).
|
|
- Priority-based trimming when limits exceeded.
|
|
- Reject oversized input with safe message.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 1.4 - Safe logging helper
|
|
|
|
Create `src/utils/logging.js`.
|
|
|
|
Requirements:
|
|
- Minimal logging to stderr only.
|
|
- Log safe metadata (tool name, timestamp, model, input/output size, duration, success/failure, error type).
|
|
- No stack traces in logs.
|
|
- No sensitive data in logs.
|
|
- Defensive redaction of secret field names and Bearer tokens in metadata values.
|
|
- Support levels: info, warn, error, silent (invalid levels throw).
|
|
|
|
Status: ✅ Complete
|
|
|
|
---
|
|
|
|
## Phase 2 - OpenAI Integration
|
|
|
|
### Task 2.1 - OpenAI client wrapper
|
|
|
|
Create `src/openai/client.js`.
|
|
|
|
Requirements:
|
|
- Create a minimal OpenAI API client using the OpenAI SDK.
|
|
- Accept API key from configuration (never hardcoded).
|
|
- Support configurable model and temperature.
|
|
- Implement streaming via the Responses API.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 2.2 - Response builder
|
|
|
|
Create `src/openai/responses.js`.
|
|
|
|
Requirements:
|
|
- Build structured OpenAI Responses API payloads from tool inputs.
|
|
- Apply character budget checks before sending.
|
|
- Redact secrets using `redact()` before constructing the request.
|
|
- Never include openaiApiKey in request logs or error messages.
|
|
- Handle OpenAI API errors gracefully (authentication, rate limits, timeouts).
|
|
- Return safe advisory-formatted text responses.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 2.3 - Error handling and edge cases for OpenAI integration
|
|
|
|
Update `src/openai/responses.js` test coverage.
|
|
|
|
Requirements:
|
|
- Add tests for additional error kinds (timeout, unknown API status, empty response body).
|
|
- Test boundary conditions for maxOutputTokens validation (non-positive floats, non-integers, zero).
|
|
- Mock OpenAI SDK network timeout errors separately from rate-limit errors.
|
|
- Verify that no API keys or secrets are ever leaked in error messages across all tested paths.
|
|
|
|
Status: ✅ Complete
|
|
|
|
---
|
|
|
|
## Phase 3 — Tool Inputs and Prompts
|
|
|
|
### Task 3.1 - Zod input validation schemas
|
|
|
|
Create `src/tools/schemas.js`.
|
|
|
|
Requirements:
|
|
- Export `baseInputSchema` — a single `z.object({...}).strict()` for the common tool input shape (ARCHITECTURE.md §7).
|
|
- Export `validateToolInput(raw)` — returns `{ ok: true, data }` or `{ ok: false, errors }`. Never throws.
|
|
- Export `assertValidToolInput(raw)` — returns validated data or throws a `ValidationError`.
|
|
- No per-tool schemas. No toolName parameters. Unknown keys must fail via `.strict()`.
|
|
|
|
Create `test/tools/schemas.test.js`.
|
|
|
|
Requirements:
|
|
- ~26 tests covering schema, validate, and assert paths.
|
|
- Test all fields: question (required, min(1)), context, constraints, expectedOutput, projectSummary, taskSummary, relevantFiles (nested object), logs.
|
|
- Test strict mode rejects unknown keys.
|
|
- Test type rejections for each field.
|
|
- Test assert throws `ValidationError` with `.kind` and message content.
|
|
- No MCP code. No OpenAI calls. Pure Zod validation only.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 3.2 - Base prompt template (NEXT)
|
|
|
|
Create `src/prompts/base.js`.
|
|
|
|
Requirements:
|
|
- Export a `buildBasePrompt()` function that returns the base system prompt (ARCHITECTURE.md §11).
|
|
- The base prompt must be injected as the first message in all tool payloads.
|
|
- Must include all rules from ARCHITECTURE.md §10 and §11.
|
|
- No per-tool variations yet — that belongs to Task 3.3.
|
|
|
|
Create `test/prompts/base.test.js`.
|
|
|
|
Requirements:
|
|
- Test that the returned prompt includes all key rules from ARCHITECTURE.md §11.
|
|
- Test that the prompt is a non-empty string.
|
|
- Test that the prompt does not include tool-specific content (review/code/debug/architecture).
|
|
|
|
### Task 3.3 - ask_chatgpt prompt builder
|
|
|
|
Create `src/prompts/ask-chatgpt.js`.
|
|
|
|
Requirements:
|
|
- Export a `buildAskChatGptPrompt(input)` function that returns a tool-specific prompt for the ask_chatgpt MCP tool.
|
|
- Compose with `buildBasePrompt()` — call it internally and append the result with `---` separator.
|
|
- The final prompt has two parts: [base system prompt] + [ask_chatgpt user instructions].
|
|
- Instruct ChatGPT to answer the question directly, act as a second-opinion advisor, identify assumptions, identify risks, suggest safer approaches, state uncertainty clearly.
|
|
- Support `expectedOutput` — if provided, append "Expected output: <value>" to the task section.
|
|
- Question is required; throw TypeError when missing or empty.
|
|
- No review_plan, review_code, debug_issue, or architecture_review content yet.
|
|
|
|
Create `test/prompts/ask-chatgpt.test.js`.
|
|
|
|
Requirements:
|
|
- ~27 tests covering base composition, ask_chatgpt instructions, optional field append/omit, expectedOutput present/absent, tool-specific guard, input validation, and full integration.
|
|
- No MCP code. No OpenAI calls. Pure prompt string assertions only.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 3.4 - review_plan prompt builder (completed)
|
|
|
|
Create `src/prompts/review-plan.js`.
|
|
|
|
Requirements:
|
|
- Export a `buildReviewPlanPrompt(input)` function that returns a tool-specific prompt for the review_plan MCP tool.
|
|
- Compose with `buildBasePrompt()` — call it internally and append the result with `---` separator.
|
|
- Instruct ChatGPT to review a proposed implementation plan before Claude Code acts.
|
|
- Look for: missing steps, unsafe assumptions, scope creep, better sequencing, test gaps.
|
|
- No other tool prompts yet (debug_issue, architecture_review, etc.).
|
|
|
|
Create `test/prompts/review-plan.test.js`.
|
|
|
|
Requirements:
|
|
- Mirror structure of ask-chatgpt tests: base composition, review_plan-specific instructions, optional fields, expectedOutput, input validation, tool guard, full integration.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 3.5 - review_code prompt builder (NEXT)
|
|
|
|
Create `src/prompts/review-code.js`.
|
|
|
|
Requirements:
|
|
- Export a `buildReviewCodePrompt(input)` function that returns a tool-specific prompt for the review_code MCP tool.
|
|
- Compose with `buildBasePrompt()` — call it internally and append the result with `---` separator.
|
|
- Instruct ChatGPT to review focused code snippets, patches, or diffs.
|
|
- Look for: correctness issues, bugs, maintainability concerns, security issues, test gaps, simpler approaches.
|
|
- Request response in structured format: Issues by Severity, Suggested Fixes, Test Suggestions.
|
|
- No other tool prompts yet (debug_issue, architecture_review, etc.).
|
|
|
|
Create `test/prompts/review-code.test.js`.
|
|
|
|
Requirements:
|
|
- Mirror structure of ask-chatgpt and review-plan tests: base composition, review_code-specific instructions, optional fields, expectedOutput, input validation, tool guard, full integration.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 3.6 - debug_issue prompt builder (NEXT)
|
|
|
|
Create `src/prompts/debug-issue.js`.
|
|
|
|
Requirements:
|
|
- Export a `buildDebugIssuePrompt(input)` function that returns a tool-specific prompt for the debug_issue MCP tool.
|
|
- Compose with `buildBasePrompt()` — call it internally and append the result with `---` separator.
|
|
- Instruct ChatGPT to analyse errors, logs, failed tests, or stack traces.
|
|
- Look for: likely root causes, fast checks, minimal safe experiments, what not to change yet.
|
|
- Request response in structured format: Likely Causes, Fast Checks, Minimal Safe Experiments, What Not To Do Yet.
|
|
- Support `relevantFiles` and `logs` input fields.
|
|
- No other tool prompts yet (architecture_review, etc.).
|
|
|
|
Create `test/prompts/debug-issue.test.js`.
|
|
|
|
Requirements:
|
|
- Mirror structure of ask_chatgpt, review-plan, and review-code tests: base composition, debug_issue-specific instructions, optional fields, expectedOutput, input validation, tool guard, full integration.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 3.7 - architecture_review prompt builder (NEXT)
|
|
|
|
Create `src/prompts/architecture-review.js`.
|
|
|
|
Requirements:
|
|
- Export a `buildArchitectureReviewPrompt(input)` function that returns a tool-specific prompt for the architecture_review MCP tool.
|
|
- Compose with `buildBasePrompt()` — call it internally and append the result with `---` separator.
|
|
- Instruct ChatGPT to review architecture decisions and trade-offs.
|
|
- Look for: local vs cloud trade-offs, simplicity, maintainability, operational risk, vendor lock-in, future extension paths.
|
|
- Support `relevantFiles` and `context` input fields.
|
|
- No other tool prompts yet.
|
|
|
|
Create `test/prompts/architecture-review.test.js`.
|
|
|
|
Requirements:
|
|
- Mirror structure of ask_chatgpt, review-plan, review-code, and debug-issue tests: base composition, architecture_review-specific instructions, optional fields, expectedOutput, input validation, tool guard, full integration.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 3.8 - Phase 3 completion summary (NEXT)
|
|
|
|
**Phase 3 — Tool Inputs and Prompts** is now complete.
|
|
|
|
All six prompt builders are implemented and tested:
|
|
|
|
| # | Prompt Builder | File | Tests |
|
|
|---|---|---|---|
|
|
| 0 | `buildBasePrompt` | `src/prompts/base.js` | ✅ |
|
|
| 1 | `buildAskChatGptPrompt` | `src/prompts/ask-chatgpt.js` | ✅ |
|
|
| 2 | `buildReviewPlanPrompt` | `src/prompts/review-plan.js` | ✅ |
|
|
| 3 | `buildReviewCodePrompt` | `src/prompts/review-code.js` | ✅ |
|
|
| 4 | `buildDebugIssuePrompt` | `src/prompts/debug-issue.js` | ✅ |
|
|
| 5 | `buildArchitectureReviewPrompt` | `src/prompts/architecture-review.js` | ✅ |
|
|
|
|
**What Phase 3 established:**
|
|
|
|
- Prompt composition pattern: `buildBasePrompt()` → explicit `\n\n---\n\n` separator → tool-specific section.
|
|
- All builders share the same input shape, validation rules, and optional field handling.
|
|
- Guard rails in every builder: Claude Code remains executor; ChatGPT is advisory only.
|
|
- `relevantFiles` inclusion with path, language (when present), and content — omitted when absent/empty.
|
|
- Each builder passes full integration tests covering all dimensions, response structure, optional fields, and negative guards.
|
|
|
|
**What Phase 3 did NOT do:**
|
|
|
|
- No MCP tool registration yet.
|
|
- No tool handlers yet.
|
|
- No OpenAI API calls from the builders.
|
|
- No file loading, logging, or context budget within the builders.
|
|
|
|
### Task 4.1 - ask_chatgpt MCP tool handler
|
|
|
|
Create `src/tools/ask-chatgpt.js` and `test/tools/ask-chatgpt.test.js`.
|
|
|
|
**Requirements:**
|
|
- Export `handleAskChatGpt(input, deps)` as standalone dependency-injected function.
|
|
- Execution order: validateToolInput → loadConfig → checkContextBudget → buildAskChatGptPrompt → createOpenAIClient → sendOpenAIResponse.
|
|
- Inject only 3 external deps: `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`. Internal utilities imported directly.
|
|
- If budget check fails (`ok: false`), immediately return that result — do not call buildAskChatGptPrompt or create client.
|
|
- All paths return structured `{ ok, answer|error, warnings }` — never throws to caller.
|
|
- OpenAI errors pass through `String(err)` unchanged (no wrapping/reformatting).
|
|
- 27 orchestration-only tests covering: success path, validation failure, config failure, budget failure, client creation failure, OpenAI failure, dependency call order, error handling for null/string throws, warning propagation, result shape, and short-circuit behavior.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 4.2 - review_plan MCP tool handler
|
|
|
|
Create `src/tools/review-plan.js` and `test/tools/review-plan.test.js`.
|
|
|
|
**Requirements:**
|
|
- Export `handleReviewPlan(input, deps)` as standalone dependency-injected function.
|
|
- Execution order: validateToolInput → loadConfig → checkContextBudget → buildReviewPlanPrompt → createOpenAIClient → sendOpenAIResponse.
|
|
- Inject only 3 external deps: `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`. Internal utilities imported directly.
|
|
- If budget check fails (`ok: false`), immediately return that result — do not call buildReviewPlanPrompt or create client.
|
|
- All paths return structured `{ ok, answer|error, warnings }` — never throws to caller.
|
|
- OpenAI errors pass through `String(err)` unchanged (no wrapping/reformatting).
|
|
- Mirror 4.1 structure: ~28 orchestration-only tests covering the same test categories (success path, validation failure, config failure, budget failure, client creation failure, OpenAI failure, dependency call order, buildReviewPlanPrompt integration, no throws escaping, warning propagation, result shape, short-circuit behavior).
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 4.3 - review_code tool handler ✅
|
|
|
|
Create `src/tools/review-code.js` and `test/tools/review-code.test.js`.
|
|
|
|
**Requirements:**
|
|
- Export `handleReviewCode(input, deps)` as standalone dependency-injected function.
|
|
- Execution order: validateToolInput → loadConfig → checkContextBudget → buildReviewCodePrompt → createOpenAIClient → sendOpenAIResponse.
|
|
- Inject only 3 external deps: `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`. Internal utilities imported directly.
|
|
- If budget check fails (`ok: false`), immediately return that result — do not call buildReviewCodePrompt or create client.
|
|
- All paths return structured `{ ok, answer|error, warnings }` — never throws to caller.
|
|
- OpenAI errors pass through `String(err)` unchanged (no wrapping/reformatting).
|
|
- Mirror 4.1 and 4.2 structure: ~28 orchestration-only tests covering the same test categories.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 4.4 - debug_issue tool handler (NEXT)
|
|
|
|
Create `src/tools/debug-issue.js` and `test/tools/debug-issue.test.js`.
|
|
|
|
**Requirements:**
|
|
- Export `handleDebugIssue(input, deps)` as standalone dependency-injected function.
|
|
- Execution order: validateToolInput → loadConfig → checkContextBudget → buildDebugIssuePrompt → createOpenAIClient → sendOpenAIResponse.
|
|
- Inject only 3 external deps: `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`. Internal utilities imported directly.
|
|
- If budget check fails (`ok: false`), immediately return that result — do not call buildDebugIssuePrompt or create client.
|
|
- All paths return structured `{ ok, answer|error, warnings }` — never throws to caller.
|
|
- OpenAI errors pass through `String(err)` unchanged (no wrapping/reformatting).
|
|
- Mirror 4.1/4.2/4.3 structure: ~28 orchestration-only tests covering the same test categories.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 4.5 - architecture_review tool handler
|
|
|
|
Create `src/tools/architecture-review.js` and `test/tools/architecture-review.test.js`.
|
|
|
|
**Requirements:**
|
|
- Export `handleArchitectureReview(input, deps)` as standalone dependency-injected function.
|
|
- Execution order: validateToolInput → loadConfig → checkContextBudget → buildArchitectureReviewPrompt → createOpenAIClient → sendOpenAIResponse.
|
|
- Inject only 3 external deps: `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`. Internal utilities imported directly.
|
|
- If budget check fails (`ok: false`), immediately return that result — do not call buildArchitectureReviewPrompt or create client.
|
|
- All paths return structured `{ ok, answer|error, warnings }` — never throws to caller.
|
|
- OpenAI errors pass through `String(err)` unchanged (no wrapping/reformatting).
|
|
- Mirror 4.1/4.2/4.3/4.4 structure: ~28 orchestration-only tests covering the same test categories.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 4.6 — Phase 4 completion summary
|
|
|
|
**Phase 4 — Tool Handlers** is now complete.
|
|
|
|
All five tool handlers are implemented and tested:
|
|
|
|
| # | Handler | File | Tests |
|
|
|---|---------|------|-------|
|
|
| 1 | `handleAskChatGpt` | `src/tools/ask-chatgpt.js` | ✅ 27 |
|
|
| 2 | `handleReviewPlan` | `src/tools/review-plan.js` | ✅ 28 |
|
|
| 3 | `handleReviewCode` | `src/tools/review-code.js` | ✅ 28 |
|
|
| 4 | `handleDebugIssue` | `src/tools/debug-issue.js` | ✅ 28 |
|
|
| 5 | `handleArchitectureReview` | `src/tools/architecture-review.js` | ✅ 28 |
|
|
|
|
**What Phase 4 established:**
|
|
|
|
- Five standalone, dependency-injected handlers following the same orchestration pattern: validate → config → budget → prompt → client → response.
|
|
- All external deps injected (loadConfig, createOpenAIClient, sendOpenAIResponse); internal utilities imported directly.
|
|
- Every handler returns structured `{ ok, answer|error, warnings }` — never throws to caller.
|
|
- Budget check short-circuits before prompt building or client creation.
|
|
- OpenAI errors pass through `String(err)` unchanged — no wrapping or reformatting.
|
|
- 139 orchestration-only tests covering success, validation failure, config failure, budget failure, client failure, OpenAI failure, call order, prompt integration, throws escaping, warnings, result shape, and short-circuit behavior.
|
|
|
|
**What Phase 4 did NOT do:**
|
|
|
|
- No MCP tool registration yet.
|
|
- No server or router code yet.
|
|
- That belongs to Phase 5.
|
|
|
|
---
|
|
|
|
Phase 2 complete. Phase 3 complete. Phase 4 complete. Phase 5 next: MCP Server and Tool Registration.
|
|
|
|
---
|
|
|
|
## Phase 5 - MCP Server and Tool Registration
|
|
|
|
### Task 5.1 - MCP server skeleton
|
|
|
|
Create the minimal runnable MCP server in `src/server.js`.
|
|
|
|
**Requirements:**
|
|
- Use `McpServer` from `@modelcontextprotocol/sdk/server/mcp.js`.
|
|
- Use `StdioServerTransport` from `@modelcontextprotocol/sdk/server/stdio.js`.
|
|
- Create server with name `"chatgpt-mcp"` and version `"0.1.0"`.
|
|
- Connect over stdio transport.
|
|
- Register no tools yet.
|
|
- Import no tool handlers yet.
|
|
- Do not load config.
|
|
- Do not call OpenAI.
|
|
- Keep it minimal (~15 lines).
|
|
|
|
**Smoke test:**
|
|
```bash
|
|
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke-test","version":"0.0.1"}}}' | npm start
|
|
```
|
|
|
|
Expected: process starts, no import/runtime crash, MCP initialize response returned with correct `serverInfo.name` and `serverInfo.version`.
|
|
|
|
Status: ✅ Complete
|
|
|
|
**What Task 5.1 established:**
|
|
- MCP stdio server skeleton is operational.
|
|
- MCP initialize handshake succeeds.
|
|
- No tools registered yet — that belongs to Task 5.2.
|
|
|
|
### Task 5.2 - Register ask_chatgpt MCP tool
|
|
|
|
Register `ask_chatgpt` as an MCP tool on the server in `src/server.js`.
|
|
|
|
**Requirements:**
|
|
- Import `baseInputSchema` from `./tools/schemas.js`.
|
|
- Import `handleAskChatGpt` from `./tools/ask-chatgpt.js`.
|
|
- Import `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse` from config/OpenAI modules.
|
|
- Register `ask_chatgpt` with `registerTool()` using the shared input schema and description from ARCHITECTURE.md §7.
|
|
- Pass all three deps into `handleAskChatGpt`.
|
|
- Return structured MCP tool result: `{ content: [{ type: "text", text }], isError, warnings }`.
|
|
|
|
**Smoke test results (all passing):**
|
|
|
|
| Test | Result |
|
|
|------|--------|
|
|
| initialize handshake | ✅ Server returns `chatgpt-mcp` v0.1.0 |
|
|
| tools/list | ✅ Exposes `ask_chatgpt` with correct schema (`question` required + 7 optional fields) |
|
|
| tools/call (happy path, mocked OpenAI) | ✅ Structured `{ content, isError: false }` with answer |
|
|
| tools/call (minimal input) | ✅ Works with `{ question: "hi" }` |
|
|
| tools/call (full input, all optional fields) | ✅ All 10 schema fields handled correctly |
|
|
| tools/call (missing OPENAI_API_KEY) | ✅ Structured MCP error: `"Error: Configuration error: OPENAI_API_KEY is missing."` |
|
|
| tools/call (invalid API key) | ✅ Structured MCP error: `"OpenAI API error (OpenAIAuthError): 401"` |
|
|
|
|
- All 523 unit tests pass across 18 test files.
|
|
- Production stdio transport verified end-to-end with real `npm start`.
|
|
|
|
**Production code (`src/server.js`):**
|
|
|
|
```js
|
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
import { baseInputSchema } from "./tools/schemas.js";
|
|
import { handleAskChatGpt } from "./tools/ask-chatgpt.js";
|
|
import { loadConfig } from "./config/env.js";
|
|
import { createOpenAIClient } from "./openai/client.js";
|
|
import { sendOpenAIResponse } from "./openai/responses.js";
|
|
|
|
const server = new McpServer({ name: "chatgpt-mcp", version: "0.1.0" });
|
|
|
|
server.registerTool(
|
|
"ask_chatgpt",
|
|
{ description: "General second-opinion question...", inputSchema: baseInputSchema },
|
|
async (input) => { ... }
|
|
);
|
|
|
|
await server.connect(new StdioServerTransport());
|
|
```
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 5.3 - Register remaining MCP tools
|
|
|
|
Register `review_plan`, `review_code`, `debug_issue`, and `architecture_review` as MCP tools on the server in `src/server.js`.
|
|
|
|
**Requirements:**
|
|
- Import four existing handlers: `handleReviewPlan`, `handleReviewCode`, `handleDebugIssue`, `handleArchitectureReview`.
|
|
- Use `baseInputSchema` for all tool input schemas.
|
|
- Explicitly register each tool with its own `registerTool()` call — no registry abstraction, no dynamic loop.
|
|
- Pass all three deps (`loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`) into each handler.
|
|
- Return structured MCP tool result: `{ content: [{ type: "text", text }], isError, warnings }`.
|
|
|
|
**Smoke test results (all passing):**
|
|
|
|
| Test | Result |
|
|
|------|--------|
|
|
| initialize handshake | ✅ Server returns `chatgpt-mcp` v0.1.0 |
|
|
| tools/list count | ✅ Returns 5 tools total |
|
|
| all tool names present | ✅ ask_chatgpt, review_plan, review_code, debug_issue, architecture_review |
|
|
| tools/call each tool (no API key) | ✅ Structured MCP error for all 5: `"Error: Configuration error: OPENAI_API_KEY is missing."` |
|
|
| npm test | ✅ 523 tests pass across 18 test files — no regressions |
|
|
|
|
**Production code (`src/server.js`) changes:**
|
|
|
|
- Added imports: `handleReviewPlan`, `handleReviewCode`, `handleDebugIssue`, `handleArchitectureReview`
|
|
- Added four `registerTool()` calls: `review_plan`, `review_code`, `debug_issue`, `architecture_review`
|
|
- Existing `ask_chatgpt` registration unchanged
|
|
- No new files created
|
|
|
|
**SDK quirks noted:**
|
|
|
|
1. `notifications/initialized` is not handled by the SDK — produces `-32601 Method not found`. Harmless.
|
|
2. When `isError: true`, the SDK wraps results in a JSON-RPC error envelope (`{"error":{"code":-32603,...}}`) rather than a success result.
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 5.4 - Normalize MCP tool error formatting ✅
|
|
|
|
Ensure all MCP tool error messages have a single, consistent "Error:" prefix.
|
|
|
|
Before this change, handlers returned errors prefixed with `"Error: "` and server.js prepended another `"Error: "`, producing duplicates like:
|
|
|
|
```
|
|
Error: Error: Configuration error: OPENAI_API_KEY is missing.
|
|
```
|
|
|
|
**Changes made (`src/server.js`):**
|
|
|
|
Each of the 5 tool registration callbacks now normalizes error text:
|
|
|
|
```js
|
|
const text = result.ok
|
|
? result.answer
|
|
: String(result.error || "Unknown error").startsWith("Error:")
|
|
? result.error
|
|
: `Error: ${result.error}`;
|
|
```
|
|
|
|
After fix:
|
|
|
|
- `"Error: Configuration error: OPENAI_API_KEY is missing."` — single prefix ✅
|
|
- Non-"Error:"-prefixed errors receive one prefix added by the server ✅
|
|
- Success responses unchanged ✅
|
|
|
|
Smoke tests:
|
|
|
|
| Test | Result |
|
|
|------|--------|
|
|
| npm test | ✅ 523 passed, no regressions |
|
|
| tools/list | ✅ 5 tools, unchanged |
|
|
| ask_chatgpt (no API key) | ✅ Single "Error:" prefix |
|
|
| review_plan (no API key) | ✅ Single "Error:" prefix |
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 5.5 - Claude Code MCP configuration and local end-to-end setup ✅
|
|
|
|
Configure project-local Claude Code discovery via `.claude/settings.local.json` and document local setup steps in README.
|
|
|
|
**Requirements:**
|
|
- Add `.claude/` to `.gitignore` so machine-specific MCP config is not committed.
|
|
- Document `npm install`, `export OPENAI_API_KEY=...`, `npm test`, `npm start` in README.
|
|
- Provide Claude Code MCP config snippet using `"command": "npm"`, `"args": ["start"]` (no absolute paths).
|
|
- List all 5 available MCP tools with descriptions in README.
|
|
|
|
**Changes made:**
|
|
- Added `.claude/` to `.gitignore` ✅
|
|
- Updated `README.md` with Setup, MCP Tools, and Running sections ✅
|
|
|
|
**What was NOT done:**
|
|
- No `.claude/settings.local.json` committed — machine-specific config remains local only ✅
|
|
- No secrets or absolute paths in any tracked file ✅
|
|
|
|
Status: ✅ Complete
|
|
|
|
---
|
|
|
|
## Phase 6 — Provider Abstraction
|
|
|
|
### Task 6.1 — Provider factory (`src/providers/factory.js`, `test/providers/factory.test.js`)
|
|
|
|
Create `createChatProvider(config)` factory that validates and returns configured chat provider.
|
|
|
|
**Requirements:**
|
|
- Whitelist validates against `"openai"` only (currently)
|
|
- Defaults to `"openai"` for any falsy/unknown value (null, NaN, empty string, numeric)
|
|
- Throws descriptive error on unrecognized provider names containing both the invalid name and supported providers
|
|
- No global state — all logic in pure function
|
|
|
|
**Tests:** ~30 tests covering default provider, CHATGPT_MCP_PROVIDER env var, whitelist enforcement, case sensitivity, edge cases (null, NaN, whitespace, JSON strings, mutation checks).
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 6.2 — OpenAI provider adapter (`src/providers/openai.js`, `test/providers/openai.test.js`)
|
|
|
|
Create `openaiProvider.send(input, config)` thin interface that wraps existing OpenAI modules.
|
|
|
|
**Interface:**
|
|
```js
|
|
provider.send(input, config) → Promise<{ content: string }>
|
|
```
|
|
|
|
Internally calls:
|
|
1. `createOpenAIClient(config)` — returns client with API key
|
|
2. `sendOpenAIResponse(client, { input: [{ role: "system", content }], model, temperature, maxOutputTokens })`
|
|
|
|
**Tests:** 27 tests covering parameter passing, call ordering, error propagation, idempotency, edge cases (empty input, unicode, long input, object input).
|
|
|
|
Status: ✅ Complete
|
|
|
|
---
|
|
|
|
## Phase 7 — Integration and Test Updates
|
|
|
|
### Task 7.1 — Update all tool handlers to use provider abstraction
|
|
|
|
All five handler files updated to use `{ loadConfig, createProvider }` dependency injection instead of `{ loadConfig, createOpenAIClient, sendOpenAIResponse }`.
|
|
|
|
| Handler | File | Change |
|
|
|---------|------|--------|
|
|
| handleAskChatGpt | `src/tools/ask-chatgpt.js` | deps.createProvider(config) + provider.send() |
|
|
| handleReviewPlan | `src/tools/review-plan.js` | same |
|
|
| handleReviewCode | `src/tools/review-code.js` | same |
|
|
| handleDebugIssue | `src/tools/debug-issue.js` | same |
|
|
| handleArchitectureReview | `src/tools/architecture-review.js` | same |
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 7.2 — Update handler tests to use provider mock pattern
|
|
|
|
All five handler test files rewritten with `{ loadConfig, createProvider }` mock pattern instead of `{ createOpenAIClient, sendOpenAIResponse }`.
|
|
|
|
**Key changes in tests:**
|
|
- `createProvider` mock returns `{ send: sendMock }` instead of direct client mocks
|
|
- All inputs use baseInputSchema `{ question, context, ... }` fields consistently
|
|
- 28 tests per handler (success path, validation failure, config failure, budget failure, provider creation/send failure, dependency order, warnings propagation, result shape, short-circuit behavior)
|
|
|
|
| File | Tests | Status |
|
|
|------|-------|--------|
|
|
| test/tools/ask-chatgpt.test.js | 27 | ✅ |
|
|
| test/tools/review-plan.test.js | 28 | ✅ |
|
|
| test/tools/review-code.test.js | 28 | ✅ |
|
|
| test/tools/debug-issue.test.js | 28 | ✅ |
|
|
| test/tools/architecture-review.test.js | 28 | ✅ |
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 7.3 — Config and provider test coverage
|
|
|
|
Added tests for `CHATGPT_MCP_PROVIDER` env var in `test/config/env.test.js` and new provider-specific tests.
|
|
|
|
- **env.test.js**: Added section testing chatgptMcpProvider defaults to `"openai"` and accepts any string value
|
|
- **factory.test.js**: ~30 tests covering factory behavior
|
|
- **openai.test.js**: 27 tests covering send delegation
|
|
|
|
Status: ✅ Complete
|
|
|
|
### Task 7.4 — Final integration verification
|
|
|
|
- All 579 tests pass across 20 test files
|
|
- No regressions in existing coverage
|
|
- `npm start` → tools/list shows same 5 tools with unchanged schemas
|
|
|
|
Status: ✅ Complete
|
|
|
|
---
|
|
|
|
## Phase 9 — Ollama Provider Support
|
|
|
|
### Task 9.1 — Ollama provider implementation ✅
|
|
|
|
Create `src/providers/ollama.js` and integrate into the provider factory.
|
|
|
|
**Implementation:**
|
|
- Uses Ollama `/api/chat` endpoint (OpenAI-compatible format) via native `fetch()` — zero new dependencies
|
|
- Implements `{ send(reviewRequest, config) => Promise<{ content: string }> }` provider interface
|
|
- Error categories: `OllamaTimeoutError`, `OllamaModelNotFoundError`, `OllamaValidationError`, `OllamaApiNotAvailableError`, `OllamaRequestError`
|
|
|
|
**Defaults:**
|
|
| Setting | Default Value |
|
|
|---------|---------------|
|
|
| Base URL | `http://localhost:11434` |
|
|
| Model | `qwen3:latest` |
|
|
| Temperature | `0.2` |
|
|
| Timeout | `60` seconds |
|
|
|
|
**Environment variables:**
|
|
```env
|
|
OLLAMA_BASE_URL=http://localhost:11434 # or custom Ollama endpoint
|
|
OLLAMA_MODEL=qwen3:latest # default model for chat
|
|
OLLAMA_TEMPERATURE=0.2 # sampling temperature
|
|
OLLAMA_TIMEOUT=60 # request timeout in seconds
|
|
```
|
|
|
|
**Factory integration:**
|
|
- `"ollama"` added to SUPPORTED_PROVIDERS whitelist: `Set(["openai", "manual", "ollama"])`
|
|
- `CHATGPT_MCP_PROVIDER=ollama` switches all tool handlers to local Ollama mode
|
|
- Defaults to `"openai"` when not set — OpenAI behaviour unchanged
|
|
- Same provider interface as openai and manual providers
|
|
|
|
**Status:** ✅ Complete
|
|
|
|
---
|
|
|
|
### Task 8.0 — Implement ReviewRequest and Manual Export Provider
|
|
|
|
Add a zero-API-cost Manual Export provider that generates copy/paste-ready prompts for ChatGPT Web (https://chatgpt.com).
|
|
|
|
**Files created:**
|
|
- `src/providers/manual-export.js` — Manual export provider implementing `{ send(request, config) => Promise<{ content: string }> }`
|
|
- `test/providers/manual-export.test.js` — 56 tests covering structure, tool detection, unicode, long prompts, edge cases, repeatability
|
|
|
|
**Files modified:**
|
|
- `src/providers/factory.js` — Added `"manual"` to SUPPORTED_PROVIDERS whitelist
|
|
- `.env.example` — Documents `CHATGPT_MCP_PROVIDER=manual` option
|
|
- `README.md` — Documents manual provider in Architecture table
|
|
- `ARCHITECTURE.md` §12 — Already lists `"manual"` as supported provider
|
|
|
|
**What it provides:**
|
|
- Provider receives `{ prompt, input }` from the ReviewRequest pattern
|
|
- Wraps the pre-built prompt in a box-delimited copy/paste format for ChatGPT Web
|
|
- Uses `https://chatgpt.com` (not `https://chat.openai.com`)
|
|
- Detects tool name from input fields (debug_issue, review_code, architecture_review, review_plan, ask_chatgpt)
|
|
- Adds prompt length metadata and advisory footer
|
|
- Warns on prompts over 30k characters
|
|
- Zero API calls — purely cosmetic wrapping
|
|
|
|
**Tests added:** 56 new tests in manual-export.test.js + 9 in factory.test.js for manual provider
|
|
**Total test count:** 644 passing across 21 test files, zero regressions
|
|
|
|
Status: ✅ Complete
|
|
|
|
---
|
|
|
|
## Completion Summary
|
|
|
|
| Phase | Description | Status |
|
|
|-------|-------------|--------|
|
|
| 0 | Repository Setup | ✅ Complete |
|
|
| 1 | Core Utilities | ✅ Complete |
|
|
| 2 | OpenAI Integration | ✅ Complete |
|
|
| 3 | Tool Inputs and Prompts | ✅ Complete |
|
|
| 4 | Tool Handlers | ✅ Complete (5 handlers, 139 tests) |
|
|
| 5 | MCP Server and Registration | ✅ Complete (5 tools registered) |
|
|
| 6 | Provider Abstraction | ✅ Complete (factory + adapter) |
|
|
| 7 | Integration and Tests | ✅ Complete (579 tests across 20 files) |
|
|
| 8 | Manual Export Provider | ✅ Complete (Task 8.0, 644 tests across 21 files) |
|
|
| 9 | Ollama Provider Support | ✅ Complete (Task 9.1, 644 tests across 21 files) |
|
|
|
|
**Total:** All planned MVP tasks complete. 644 passing tests, zero regressions, all docs updated. **3 supported providers: openai, manual, ollama.**
|