From d3aefa5bb8dbd70f2610d3b51a14df514ba8c9c0 Mon Sep 17 00:00:00 2001 From: robbond Date: Fri, 12 Jun 2026 12:09:08 +0100 Subject: [PATCH] feat: register ask_chatgpt MCP tool --- AGENT_HANDOFF.md | 23 ++++++++++++++++++++- PROJECT_STATE.md | 22 ++++++++++++++++++-- TASKS.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++- src/server.js | 29 ++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 4 deletions(-) diff --git a/AGENT_HANDOFF.md b/AGENT_HANDOFF.md index b14c10c..a33c7d2 100644 --- a/AGENT_HANDOFF.md +++ b/AGENT_HANDOFF.md @@ -57,9 +57,30 @@ Total: 139 orchestration-only tests, all passing. Minimal MCP stdio server in `src/server.js`. MCP initialize handshake succeeds. No tools registered yet. +### Task 5.2 - Register ask_chatgpt MCP tool ✅ + +`ask_chatgpt` is now registered as an MCP tool on the server (`src/server.js`). + +**Registration details:** +- Uses shared `baseInputSchema` (question required + context, constraints, expectedOutput, projectSummary, taskSummary, relevantFiles, logs optional). +- All 3 external deps injected: `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`. +- Returns structured MCP tool result: `{ content: [{ type: "text", text }], isError, warnings }`. + +**Smoke test results (all passing):** +- initialize → server returns `chatgpt-mcp` v0.1.0 ✅ +- tools/list → exposes `ask_chatgpt` with correct schema ✅ +- tools/call (happy path, mocked OpenAI) → `{ content: [...], isError: false }` with answer ✅ +- tools/call (minimal input `{ question: "hi" }`) → works ✅ +- tools/call (full input, 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 code (`src/server.js`):** ~39 lines, single `ask_chatgpt` tool registered with MCP via Stdio transport. + ## Next Pending -### Task 5.2 - Register ask_chatgpt MCP tool +### Task 5.3 - Register remaining MCP tools (review_plan, review_code, debug_issue, architecture_review) ## General Rules diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index d9bff1c..7cac035 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -7,7 +7,7 @@ ChatGPT MCP Server ## Status Planning complete. -Phase 0 complete. Phase 1 complete. Phase 2 complete. Phase 3 complete. Task 4.1 complete. Task 4.2 complete. Task 4.3 complete. Task 4.4 complete. Task 4.5 complete. Phase 4 complete. Task 5.1 complete. +Phase 0 complete. Phase 1 complete. Phase 2 complete. Phase 3 complete. Task 4.1 complete. Task 4.2 complete. Task 4.3 complete. Task 4.4 complete. Task 4.5 complete. Phase 4 complete. Task 5.1 complete. Task 5.2 complete. ## Current Phase @@ -37,6 +37,24 @@ Phase 5 - MCP Server and Tool Registration - Task 4.4 — debug_issue tool handler (`src/tools/debug-issue.js`, `test/tools/debug-issue.test.js`) ✅ - Task 4.5 — architecture_review tool handler (`src/tools/architecture-review.js`, `test/tools/architecture-review.test.js`) ✅ - Task 5.1 — MCP server skeleton (`src/server.js`) ✅ +- Task 5.2 — ask_chatgpt MCP tool registered on the server ✅ + + **ask_chatgpt registration details:** + - `src/server.js` registers `ask_chatgpt` with `registerTool()` using the shared `baseInputSchema`. + - All three external deps injected: `loadConfig`, `createOpenAIClient`, `sendOpenAIResponse`. + - Returns structured MCP tool result: `{ content: [{ type: "text", text }], isError, warnings }`. + + **Smoke test results (all passing):** + - initialize → server returns `chatgpt-mcp` v0.1.0 ✅ + - tools/list → exposes `ask_chatgpt` with correct schema (`question` required + 7 optional) ✅ + - tools/call (happy path, mocked OpenAI) → `{ content: [...], isError: false }` with answer ✅ + - tools/call (minimal input `{ question: "hi" }`) → works ✅ + - tools/call (full input, 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 ✅ + +- Task 5.3 — Register remaining MCP tools (NEXT) ## Phase 3 Completion Summary @@ -89,4 +107,4 @@ All five tool handlers are implemented and tested: ## Next Pending -### Task 5.2 - Register ask_chatgpt MCP tool +### Task 5.3 - Register remaining MCP tools (review_plan, review_code, debug_issue, architecture_review) diff --git a/TASKS.md b/TASKS.md index a44ed03..ae30eea 100644 --- a/TASKS.md +++ b/TASKS.md @@ -440,4 +440,55 @@ Status: ✅ Complete - MCP initialize handshake succeeds. - No tools registered yet — that belongs to Task 5.2. -### Task 5.2 - Register ask_chatgpt MCP tool (NEXT) +### 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 (NEXT) diff --git a/src/server.js b/src/server.js index 9708c65..ba6847c 100644 --- a/src/server.js +++ b/src/server.js @@ -1,9 +1,38 @@ 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 for advice, alternatives, risks, and clarification.", + inputSchema: baseInputSchema, + }, + async (input) => { + const result = await handleAskChatGpt(input, { + loadConfig, + createOpenAIClient, + sendOpenAIResponse, + }); + + return { + content: [ + { type: "text", text: result.ok ? result.answer : `Error: ${result.error}` }, + ], + isError: !result.ok, + warnings: result.warnings?.length ? result.warnings : undefined, + }; + } +); + await server.connect(new StdioServerTransport());