/ src / app / api / mcp-servers / [id] / route.ts
route.ts
 1  import { NextResponse } from 'next/server'
 2  import { safeParseBody } from '@/lib/server/safe-parse-body'
 3  import { loadMcpServers, saveMcpServers, deleteMcpServer } from '@/lib/server/storage'
 4  import { mutateItem, deleteItem, notFound, type CollectionOps } from '@/lib/server/collection-helpers'
 5  import { evictMcpClient } from '@/lib/server/mcp-connection-pool'
 6  
 7  // eslint-disable-next-line @typescript-eslint/no-explicit-any
 8  const ops: CollectionOps<any> = { load: loadMcpServers, save: saveMcpServers, deleteFn: deleteMcpServer }
 9  
10  export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
11    const { id } = await params
12    const servers = loadMcpServers()
13    if (!servers[id]) return notFound()
14    return NextResponse.json(servers[id])
15  }
16  
17  export async function PUT(req: Request, { params }: { params: Promise<{ id: string }> }) {
18    const { id } = await params
19    const { data: body, error } = await safeParseBody(req)
20    if (error) return error
21    const result = mutateItem(ops, id, (server) => ({
22      ...server, ...body, id, updatedAt: Date.now(),
23    }))
24    if (!result) return notFound()
25    // Connection pool caches by config fingerprint; evicting here is defense in
26    // depth — getOrConnectMcpClient also detects fingerprint mismatches.
27    await evictMcpClient(id)
28    return NextResponse.json(result)
29  }
30  
31  export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
32    const { id } = await params
33    if (!deleteItem(ops, id)) return notFound()
34    await evictMcpClient(id)
35    return NextResponse.json({ deleted: id })
36  }