You can close this window and return to the app.
`; return new NextResponse(html, { headers: { "Content-Type": "text/html" }, }); } else if (error) { const html = `Error: ${error}
`; return new NextResponse(html, { headers: { "Content-Type": "text/html" }, }); } return new NextResponse("Bad request", { status: 400 }); } ``` ### Finalize the OAuth flow This endpoint finalizes the OAuth flow. ```typescript /app/api/mcp/auth/finish/route.ts expandable theme={null} import { NextRequest, NextResponse } from "next/server"; import { sessionStore } from "@/lib/session-store"; interface FinishAuthRequestBody { authCode: string; sessionId: string; } export async function POST(request: NextRequest) { try { const body: FinishAuthRequestBody = await request.json(); const { authCode, sessionId } = body; if (!authCode || !sessionId) { return NextResponse.json( { error: "Authorization code and session ID are required" }, { status: 400 } ); } const client = sessionStore.getClient(sessionId); if (!client) { return NextResponse.json( { error: "No active OAuth session found" }, { status: 400 } ); } await client.finishAuth(authCode); return NextResponse.json({ success: true }); } catch (error: unknown) { if (error instanceof Error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json({ error: String(error) }, { status: 500 }); } } ``` ### Disconnect from the MCP server This endpoint disconnects from the MCP server. ```typescript /app/api/mcp/auth/disconnect/route.ts expandable theme={null} import { NextRequest, NextResponse } from "next/server"; import { sessionStore } from "@/lib/session-store"; interface DisconnectRequestBody { sessionId: string; } export async function POST(request: NextRequest) { try { const body: DisconnectRequestBody = await request.json(); const { sessionId } = body; if (!sessionId) { return NextResponse.json( { error: "Session ID is required" }, { status: 400 } ); } sessionStore.removeClient(sessionId); return NextResponse.json({ success: true }); } catch (error: unknown) { if (error instanceof Error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json({ error: String(error) }, { status: 500 }); } } ``` ## 4. List/Call Tools Next, you'll want to create a few API routes to handle actually using the tools provided by the MCP server. Create the following API routes in a directory at `/app/api/mcp`: * `/app/api/mcp/tool/list` - Lists the available tools on the MCP server. * `/app/api/mcp/tool/call` - Calls a tool on the MCP server. ### List the available tools This endpoint lists the available tools on the MCP server. ```typescript /app/api/mcp/tool/list/route.ts expandable theme={null} import { NextRequest, NextResponse } from "next/server"; import { sessionStore } from "@/lib/session-store"; export async function GET(request: NextRequest) { try { const sessionId = request.nextUrl.searchParams.get("sessionId"); if (!sessionId) { return NextResponse.json( { error: "Session ID is required" }, { status: 400 } ); } const client = sessionStore.getClient(sessionId); if (!client) { return NextResponse.json( { error: "Not connected to server" }, { status: 400 } ); } const result = await client.listTools(); return NextResponse.json({ tools: result.tools || [] }); } catch (error: unknown) { if (error instanceof Error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json({ error: String(error) }, { status: 500 }); } } ``` ### Call a tool This endpoint calls a tool on the MCP server. ```typescript /app/api/mcp/tool/call/route.ts expandable theme={null} import { NextRequest, NextResponse } from "next/server"; import { sessionStore } from "@/lib/session-store"; interface CallToolRequestBody { toolName: string; toolArgs?: Record