# Project: Next.js MCP Server (MBTA) on Vercel
## Overview
This is a lightweight Next.js application deployed on Vercel. It functions as a **Model Context Protocol (MCP) Server** using **Server-Sent Events (SSE)**. It provides a tool for AI assistants to query real-time MBTA train schedules.
## 1. Architecture & Hosting
- **Framework:** Next.js (App Router).
- **Hosting:** Vercel (Serverless/Edge Functions).
- **Transport:** SSE (Server-Sent Events) over HTTP.
- *Constraint:* Vercel Serverless functions have timeout limits. Ensure `maxDuration` is set high enough (e.g., 60s) or use Edge Runtime if supported by the MCP SDK dependencies.
- **Route Structure:**
- `GET /api/sse`: Establishes the SSE connection.
- `POST /api/messages`: Handles incoming JSON-RPC messages (tool calls).
## 2. Data Source: MBTA V3 API
**Base URL:** `https://api-v3.mbta.com`
**Docs:** https://api-v3.mbta.com/
### Endpoint Strategy
Fetch data dynamically based on the user's request.
- **Endpoint:** `/schedules`
- **Required Query Params:**
- `filter[route]=CR-Worcester`
- `filter[direction_id]=0` (Outbound: Boston -> Worcester)
- `filter[date]=<YYYY-MM-DD>` (Input from tool)
- `filter[stop]=place-sstat,place-Wboro` (Optimization: Only fetch South Station & Westborough)
- `include=trip` (To get the train number from the Trip ID)
- `sort=departure_time`
### Logic Mapping
1. **Group by Trip ID:** The API returns flat schedule objects. Group them by `relationships.trip.data.id`.
2. **Validate Trip:** A trip is valid ONLY if it has:
- A `departure_time` from `place-sstat`.
- An `arrival_time` at `place-Wboro`.
3. **Extract Train #:** Found in the `included` array (type `trip`) matching the Trip ID. Attribute: `name`.
## 3. Tool Definition
Register a single tool named `get_worcester_schedule`.
```typescript
{
name: "get_worcester_schedule",
description: "Fetches train times for the Worcester Line (Outbound: South Station to Westborough).",
inputSchema: {
type: "object",
properties: {
date: {
type: "string",
description: "Date of travel in YYYY-MM-DD format. Defaults to today/now if not specified."
}
}
}
}
```
## 4. Auth & Security ("Friends Only")
Since Vercel deployments are public, we must restrict access.
* **Mechanism:** Bearer Token or Shared Secret via Query Param.
* **Env Var:** Store `MCP_API_KEY` in Vercel Environment Variables.
* **Implementation:** - In `GET /api/sse`, check `req.query.token` or `req.headers['authorization']`.
* If it does not match `process.env.MCP_API_KEY`, return `401 Unauthorized`.
## 5. Implementation Notes for Next.js
* **Dynamic Rendering:** Ensure the API route is not cached.
```typescript
export const dynamic = 'force-dynamic';
export const maxDuration = 60; // Extend Vercel timeout for SSE persistence
```
* **SDK Usage:** Use `@modelcontextprotocol/sdk`.
* Implement an `SSEServerTransport`.
* Connect the transport to the `McpServer` instance.
## 6. Client Configuration (Reference)
How users (friends) will add this to their Claude/MCP config:
```json
"mcpServers": {
"mbta-vercel": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sse-client", "https://<YOUR-VERCEL-URL>/api/sse?token=<YOUR-SECRET>"]
}
}
```