feat: adds mcp functionality to fullstack app#670
Conversation
Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com>
There was a problem hiding this comment.
Pull Request Overview
This PR integrates Model Context Protocol (MCP) functionality into the fullstack app by adding new API key–protected MCP routes and a standalone MCP server.
- Adds
isMcpApiRouteto skip Clerk auth on/api/mcpendpoints - Implements CRUD and debug routes under
app/api/mcp/todoswith simple API key authentication - Introduces a separate MCP server (
mcp-server) with tool handlers, API client, tests, and documentation
Reviewed Changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/javascript/fullstack_demo/src/middleware.ts | Added isMcpApiRoute matcher and excluded MCP routes from Clerk protection |
| lib/javascript/fullstack_demo/src/app/api/mcp/todos/route.ts | Created GET/POST handlers with API key auth for todos |
| lib/javascript/fullstack_demo/src/app/api/mcp/todos/[id]/route.ts | Created DELETE/PATCH handlers, path parameter handling |
| lib/javascript/fullstack_demo/src/app/api/mcp/debug/route.ts | Added debug endpoint for MCP readiness |
| lib/javascript/fullstack_demo/mcp-server/src/index.ts | Built MCP server with tool definitions and request handlers |
| lib/javascript/fullstack_demo/mcp-server/src/api-client.ts | Implemented TodoApiClient for communicating with MCP API |
Files not reviewed (1)
- lib/javascript/fullstack_demo/mcp-server/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)
lib/javascript/fullstack_demo/src/app/api/mcp/todos/[id]/route.ts:37
- The DELETE endpoint returns status 200 with a message body. For REST conventions, consider using status 204 No Content and an empty body instead.
return new Response('No content', { status: 200 });
| export async function PATCH(request: Request) { | ||
| const userId = authenticateApiKey(request); | ||
|
|
||
| if (!userId) { | ||
| return new Response('Unauthorized - Invalid API Key', { status: 401 }); | ||
| } | ||
|
|
||
| const todo = await request.json(); | ||
|
|
||
| try { | ||
| const updatedTodo = await todoRepository.patch(todo, userId); |
There was a problem hiding this comment.
The PATCH handler doesn’t accept or extract the id path parameter, so it can’t target a specific todo. Update the signature to PATCH(request: Request, { params }: { params: { id: string } }) and use params.id.
| export async function PATCH(request: Request) { | |
| const userId = authenticateApiKey(request); | |
| if (!userId) { | |
| return new Response('Unauthorized - Invalid API Key', { status: 401 }); | |
| } | |
| const todo = await request.json(); | |
| try { | |
| const updatedTodo = await todoRepository.patch(todo, userId); | |
| export async function PATCH( | |
| request: Request, | |
| { params }: { params: { id: string } } | |
| ) { | |
| const userId = authenticateApiKey(request); | |
| if (!userId) { | |
| return new Response('Unauthorized - Invalid API Key', { status: 401 }); | |
| } | |
| const { id } = params; | |
| const todo = await request.json(); | |
| try { | |
| const updatedTodo = await todoRepository.patch(Number(id), todo, userId); |
| console.error('[MCP] Getting todos...'); | ||
| const todos = await this.apiClient.getTodos(); | ||
| console.error(`[MCP] Retrieved ${todos.length} todos`); |
There was a problem hiding this comment.
[nitpick] Using console.error for standard informational messages may blur error vs info levels. Switch to console.log or use a logging library with levels.
| console.error('[MCP] Getting todos...'); | |
| const todos = await this.apiClient.getTodos(); | |
| console.error(`[MCP] Retrieved ${todos.length} todos`); | |
| console.log('[MCP] Getting todos...'); | |
| const todos = await this.apiClient.getTodos(); | |
| console.log(`[MCP] Retrieved ${todos.length} todos`); |
Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com>
Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com>
Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com>
Signed-off-by: Anthony D. Mays anthony@morganlatimer.com