-
Notifications
You must be signed in to change notification settings - Fork 0
Implement MCP capture and read tools #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
b9a01db
Implement MCP capture and read tools
krishna916 ada0fa3
Expose strict MCP input schemas
krishna916 e4c8b95
Complete MCP lifecycle review coverage
krishna916 a7d77b0
Complete issue 26 MCP contract coverage
krishna916 8984f65
Cover remaining MCP validation boundaries
krishna916 a101bed
Close issue 26 MCP acceptance gaps
krishna916 43f7878
Address MCP review findings
krishna916 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # Issue 26 MCP Tools Implementation Plan | ||
|
|
||
| > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. | ||
|
|
||
| **Goal:** Expose the approved task application through five safe, versioned MCP stdio tools. | ||
|
|
||
| **Architecture:** `main.ts` composes one shared `TaskRuntime`, injects its `TaskApplication` into `createMcpServer`, and owns idempotent cleanup. Focused MCP modules validate #19 contracts, invoke application operations only, and map tasks/results/errors to structured MCP responses; they never access SQLite. | ||
|
|
||
| **Tech Stack:** TypeScript, Zod 4, MCP SDK 1.29, Vitest, SQLite runtime. | ||
|
|
||
| ## Global Constraints | ||
|
|
||
| - Preserve `relay_health` and protocol-clean stdout. | ||
| - Success payloads are `{ schemaVersion: 1, data, warnings }`; structured content is authoritative. | ||
| - Strictly reject unknown input keys and caller-controlled task status/provenance. | ||
| - Error codes are `VALIDATION_ERROR`, `NOT_FOUND`, `STORAGE_ERROR`, and `INTERNAL_ERROR`; never leak causes, SQL, paths, or stacks. | ||
| - `task_capture` always creates after advisory duplicate lookup and forces `creator.type: 'AGENT'`. | ||
| - No direct persistence access in MCP modules and no unrelated mutation tools. | ||
|
|
||
| --- | ||
|
|
||
| ### Task 1: Complete the approved list-query contract | ||
|
|
||
| **Files:** Modify `src/application/tasks/{task-application.ts,use-cases/list-tasks.ts,task-repository.ts}`, `src/database/tasks/sqlite-task-repository.ts`; test `tests/{unit/application/tasks/task-application.test.ts,integration/task-repository.test.ts}`. | ||
|
|
||
| - [ ] Write failing tests that pass `workspace` with a list request and prove an exact workspace filter is applied in the repository before `limit`. | ||
| - [ ] Run the focused tests and confirm they fail because the application query lacks `workspace`. | ||
| - [ ] Extend `ListTasksInput`/`TaskListQuery` with optional normalized workspace; validate it in the application and add SQL `workspace = ?` before ordering/limit. | ||
| - [ ] Re-run focused unit and repository integration tests; commit the narrowly scoped #19 contract correction. | ||
|
|
||
| ### Task 2: Establish MCP schemas and stable mappers | ||
|
|
||
| **Files:** Create `src/interfaces/mcp/{schemas/read-tool-schemas.ts,mapping/task-mcp-dto.ts,mapping/mcp-result.ts,mapping/mcp-errors.ts}`; modify MCP unit tests. | ||
|
|
||
| - [ ] Write failing in-memory server tests for strict schemas, `schemaVersion: 1`, structured data, and mapped validation/not-found/storage/internal errors without implementation text. | ||
| - [ ] Run the test and confirm failures reflect absent task-tool registration/mapping. | ||
| - [ ] Re-export/compose only #19 schemas, map domain tasks to contract DTOs, emit compact JSON text plus `structuredContent`, and map known error classes to safe error envelopes. | ||
| - [ ] Re-run MCP unit tests and commit. | ||
|
|
||
| ### Task 3: Register the four read-only handlers | ||
|
|
||
| **Files:** Create `src/interfaces/mcp/tools/{register-read-tools.ts,task-list.ts,task-get.ts,task-find-similar.ts,session-captures-list.ts}`; modify `create-mcp-server.ts`; test `tests/unit/interfaces/mcp/create-mcp-server.test.ts`. | ||
|
|
||
| - [ ] Add failing in-memory tests covering discovery plus list/get/find/session success, invalid session/unknown keys, not-found, persisted order, isolation, and result bounds. | ||
| - [ ] Run the focused test and verify the new tools are unavailable. | ||
| - [ ] Register handlers that parse input, call the injected `TaskApplication`, and convert results only through Task 2 mapping helpers. | ||
| - [ ] Re-run focused tests, then commit. | ||
|
|
||
| ### Task 4: Add autonomous capture last | ||
|
|
||
| **Files:** Create `src/interfaces/mcp/tools/task-capture.ts`; modify `register-read-tools.ts` or a focused registration module; test MCP unit tests. | ||
|
|
||
| - [ ] Add failing tests showing capture calls `findSimilar` before `create`, rejects `status`/creator type, forces AGENT provenance, preserves session metadata, and returns advisory duplicate candidates without blocking creation. | ||
| - [ ] Run the focused test and verify the capture tool is unavailable. | ||
| - [ ] Implement strict capture parsing, duplicate warning construction, forced creator mapping, and `CREATED` result mapping without persistence/lifecycle logic. | ||
| - [ ] Re-run focused tests and commit. | ||
|
|
||
| ### Task 5: Compose lifecycle, built-process proof, and documentation | ||
|
|
||
| **Files:** Modify `src/interfaces/mcp/main.ts`, `tests/integration/mcp-stdio.test.ts`, `README.md`, `docs/mcp-tools.md`, and asset tests only if paths change. | ||
|
|
||
| - [ ] Add failing tests for built-process capture followed by session retrieval using an isolated `RELAY_DB_PATH`, clean stdout, runtime cleanup exactly once on signal, and cleanup after startup/connect failure where dependency seams permit. | ||
| - [ ] Run the focused integration tests and confirm the missing runtime injection/lifecycle behavior. | ||
| - [ ] Create runtime in `main.ts`, inject it, close server/runtime exactly once on signal and construction/connect failures, and send diagnostics only to stderr; document all five tools and contract guarantees. | ||
| - [ ] Run `pnpm test -- tests/unit/interfaces/mcp`, `pnpm test -- tests/integration/mcp-stdio.test.ts`, then `pnpm verify`; commit the final implementation. | ||
|
|
||
| ## Spec coverage review | ||
|
|
||
| Tasks 2-4 cover all five tool schemas, success/error envelopes, provenance, duplicate warnings, session isolation/order, and strict input handling. Task 1 is the documented #19/#20 workspace-filter correction. Task 5 covers stdio lifecycle, disposable database integration, documentation, assets, and the full quality gate. No out-of-scope mutation, persistence redesign, packaging, auth, or daemon work is included. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,43 +1,20 @@ | ||
| import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; | ||
| import { createMcpServer } from './create-mcp-server.js'; | ||
| import { mcpLogger } from './logger.js'; | ||
| import { createTaskRuntime } from '../shared/create-task-runtime.js'; | ||
| import { runMcpServer } from './run-mcp-server.js'; | ||
|
|
||
| async function main(): Promise<void> { | ||
| try { | ||
| const server = createMcpServer(); | ||
| const transport = new StdioServerTransport(); | ||
| let shuttingDown = false; | ||
|
|
||
| const shutdown = async (signal: 'SIGINT' | 'SIGTERM'): Promise<void> => { | ||
| if (shuttingDown) { | ||
| return; | ||
| } | ||
|
|
||
| shuttingDown = true; | ||
| mcpLogger.info(`Received ${signal}, shutting down MCP server...`); | ||
|
|
||
| try { | ||
| await server.close(); | ||
| process.exitCode = 0; | ||
| } catch (error) { | ||
| mcpLogger.error('Failed during MCP shutdown', error); | ||
| process.exitCode = 1; | ||
| } | ||
| }; | ||
|
|
||
| process.on('SIGINT', () => { | ||
| void shutdown('SIGINT'); | ||
| }); | ||
|
|
||
| process.on('SIGTERM', () => { | ||
| void shutdown('SIGTERM'); | ||
| }); | ||
|
|
||
| await server.connect(transport); | ||
| } catch (error) { | ||
| mcpLogger.error('Fatal error starting MCP stdio server', error); | ||
| process.exit(1); | ||
| } | ||
| await runMcpServer({ | ||
| createRuntime: createTaskRuntime, | ||
| createServer: createMcpServer, | ||
| createTransport: () => new StdioServerTransport(), | ||
| onSignal: (signal, handler) => process.on(signal, handler), | ||
| reportFatal: (error) => { | ||
| mcpLogger.error('Fatal error starting MCP stdio server', error); | ||
| process.exitCode = 1; | ||
| }, | ||
| }); | ||
| } | ||
|
|
||
| void main(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { ZodError } from 'zod'; | ||
| import { | ||
| InvalidTaskRequestError, | ||
| TaskNotFoundError, | ||
| TaskPersistenceError, | ||
| } from '../../../application/tasks/task-application-errors.js'; | ||
| import { TaskDomainError } from '../../../domain/task/task-errors.js'; | ||
| import { mcpError } from './mcp-result.js'; | ||
|
|
||
| export function toMcpError(error: unknown) { | ||
| if ( | ||
| error instanceof ZodError || | ||
| error instanceof InvalidTaskRequestError || | ||
| error instanceof TaskDomainError | ||
| ) | ||
| return mcpError('VALIDATION_ERROR', 'Request validation failed.'); | ||
| if (error instanceof TaskNotFoundError) return mcpError('NOT_FOUND', 'Task was not found.'); | ||
| if (error instanceof TaskPersistenceError) | ||
| return mcpError('STORAGE_ERROR', 'Task storage operation failed.'); | ||
| return mcpError('INTERNAL_ERROR', 'An unexpected internal error occurred.'); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { CONTRACT_SCHEMA_VERSION } from '../../contracts/contract-version.js'; | ||
|
|
||
| export function mcpSuccess(data: Record<string, unknown>, warnings: readonly unknown[] = []) { | ||
| const structuredContent = { schemaVersion: CONTRACT_SCHEMA_VERSION, data, warnings }; | ||
| return { | ||
| structuredContent, | ||
| content: [{ type: 'text' as const, text: JSON.stringify(structuredContent) }], | ||
| }; | ||
| } | ||
|
|
||
| export function mcpError(code: string, message: string) { | ||
| const structuredContent = { schemaVersion: CONTRACT_SCHEMA_VERSION, error: { code, message } }; | ||
| return { | ||
| isError: true, | ||
| structuredContent, | ||
| content: [{ type: 'text' as const, text: JSON.stringify(structuredContent) }], | ||
| }; | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.