# How to Integrate TREK with MCP (Model Context Protocol): A Complete Developer Guide

> Integrate TREK with MCP using the built-in MCP server at /mcp. Securely query and manipulate travel data via JSON-RPC API. Follow this developer guide for easy setup.

- Repository: [Maurice/TREK](https://github.com/mauriceboe/TREK)
- Tags: deep-dive
- Published: 2026-07-03

---

**TREK exposes a built-in MCP server at `/mcp` that enables AI assistants to securely query and manipulate travel data through a JSON-RPC API, requiring only the MCP add-on to be enabled and a valid OAuth 2.1, static, or JWT token for authentication.**

Integrating TREK with the Model Context Protocol (MCP) allows Claude, Cursor, and other AI assistants to interact with your travel data using a standardized JSON-RPC interface. According to the `mauriceboe/TREK` source code, the integration centers on a single HTTP endpoint that handles authentication, session management, and tool registration. This guide walks through the architectural flow, authentication requirements, and implementation details needed to connect your AI client to a TREK instance.

## Enable the MCP Add-On

Before any client can connect, the MCP feature must be activated in the database. In [`server/src/mcp/index.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/index.ts) (lines 18-22), the handler checks `isAddonEnabled(ADDON_IDS.MCP)` and returns a **403 Forbidden** if the add-on is disabled.

Enable the add-on by inserting the record into your SQLite database:

```sql
INSERT INTO addons (id, enabled) VALUES ('mcp', 1);

```

Once enabled, the `/mcp` endpoint becomes active and accepts POST requests carrying JSON-RPC 2.0 payloads.

## Authenticate Incoming Requests

The `verifyToken` function in [`server/src/mcp/index.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/index.ts) (lines 71-102) supports three credential types, returning a payload of `{user, scopes, clientId, isStaticToken}` that drives permission enforcement:

- **OAuth 2.1 access tokens** (prefix `trekoa_`): Validated via `getUserByAccessToken` in [`server/src/services/oauthService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/oauthService.ts). The audience must match the MCP URL, and the resulting scopes control which tools the client can invoke.
- **Legacy static tokens** (prefix `trek_`): Verified with `verifyMcpToken` in [`server/src/services/authService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/authService.ts). These grant full access but trigger a deprecation notice that the server automatically appends to the model’s response.
- **Short-lived JWTs**: Used by the TREK web UI, verified via `verifyJwtToken`.

Client implementations should obtain an OAuth token from TREK Settings → MCP → OAuth Clients, then include it in the `Authorization: Bearer` header.

## Handle Sessions and Rate Limits

TREK enforces a multi-layered gatekeeping system after authentication.

### Rate Limiting

An in-memory `rateLimitMap` tracks requests per user and client. The `isRateLimited` utility (lines 11-21 of [`server/src/mcp/index.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/index.ts)) reads the `MCP_RATE_LIMIT` environment variable, defaulting to **300 requests per minute**. Exceeding this returns a rate-limit error before the request reaches the business logic.

### Session Creation and Resumption

The server distinguishes between new and existing sessions via the `Mcp-Session-Id` header:

1. **New Session**: For requests without a session ID, the server checks `MCP_MAX_SESSION_PER_USER` (default 20) against the in-memory `sessions` registry in [`server/src/mcp/sessionManager.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/sessionManager.ts). If under the limit, it instantiates an `McpServer` from `@modelcontextprotocol/sdk/server/mcp`, configures capabilities (tools, resources, prompts) with `listChanged: true`, and attaches base instructions describing TREK’s data model. The `StreamableHTTPServerTransport` generates a UUID, stores the session, and returns it in the `Mcp-Session-Id` response header.
2. **Resuming**: Requests bearing an existing `Mcp-Session-Id` validate ownership and client-id, update the activity timestamp, and forward the payload to the existing transport.

A sweep interval periodically removes stale sessions after a one-hour TTL and cleans expired rate-limit entries.

## Expose Travel Data via Tools and Resources

Each session registers a curated catalog scoped to the authenticated user. In [`server/src/mcp/resources.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/resources.ts) and the `server/src/mcp/tools/` directory, the server calls `registerResources` and `registerTools` to expose:

- **Tools**: Domain-specific operations like `list_trips`, `search_place`, `create_accommodation`, and `budget/*` grouped by functionality (vacations, packing, etc.).
- **Resources**: Read-only snapshots of travel data.

The `scopes` array from the OAuth token determines which tools are available, enforcing fine-grained permissions at runtime.

## Audit and Monitor Usage

Every tool invocation passes through `writeAudit` (implemented near lines 4-16 of [`server/src/mcp/index.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/index.ts)), logging the user ID, tool name, client ID (or "native" for static tokens), and source IP to `logToolCallAudit`. This creates an immutable trail of AI interactions for security review.

## Graceful Shutdown and Invalidation

When the MCP add-on state changes, `invalidateMcpSessions()` forces all clients to reconnect, ensuring they receive an updated tool catalog. The `closeMcpSessions()` function (bottom of [`server/src/mcp/index.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/index.ts)) stops the sweep timer and terminates all transports cleanly during server shutdown.

## Code Examples

### Initialize a Connection with OAuth

Use this Node.js pattern to establish an MCP session:

```javascript
import fetch from 'node-fetch';

const token = 'trekoa_abc123…'; // From TREK Settings → MCP → OAuth Clients
const response = await fetch('https://your-trek.example.com/mcp', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Accept': 'application/json, text/event-stream',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    jsonrpc: '2.0',
    method: 'initialize',
    id: 1,
    params: {
      protocolVersion: '2024-11-05',
      capabilities: {},
      clientInfo: { name: 'my-assistant', version: '1.0' },
    },
  }),
});

const json = await response.json();
console.log('MCP Session ID:', response.headers.get('Mcp-Session-Id'));

```

### Reuse an Existing Session

Subsequent calls reuse the session ID to maintain context:

```javascript
const sessionId = 'c1d2e3f4-…';
await fetch('https://your-trek.example.com/mcp', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Mcp-Session-Id': sessionId,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    jsonrpc: '2.0',
    method: 'tools/call',
    id: 2,
    params: { name: 'list_trips', args: {} },
  }),
});

```

### Handle Static Token Deprecation

When authenticating with a legacy `trek_` token, the server prepends `STATIC_TOKEN_DEPRECATION_NOTICE` to the response result. Your client should surface this warning to the user before displaying tool results, as these tokens are scheduled for removal.

## Summary

- **Enable first**: The MCP add-on must be active in the database (`isAddonEnabled`) or the endpoint returns 403.
- **Token flexibility**: Support OAuth 2.1 (`trekoa_`), legacy static (`trek_`), and JWT tokens via `verifyToken`.
- **Session aware**: Use `Mcp-Session-Id` headers to persist state, respecting the default limit of 20 sessions per user.
- **Rate guarded**: Default 300 req/min limit controlled by `MCP_RATE_LIMIT`.
- **Scoped access**: OAuth scopes filter available tools during `registerTools` execution.
- **Fully audited**: Every `tools/call` is logged with user ID and client context.

## Frequently Asked Questions

### What authentication method should I use for production integrations?

**OAuth 2.1 access tokens** are the recommended method for production. According to the `mauriceboe/TREK` source code, these tokens provide scoped access via the `scopes` array and are validated against the MCP URL audience. Legacy static tokens (`trek_` prefix) function but trigger a deprecation notice, while JWTs are intended primarily for the native web UI.

### How do I handle rate limiting when making consecutive tool calls?

The server enforces a default limit of 300 requests per minute per user via the `MCP_RATE_LIMIT` environment variable. If you receive a rate-limit error, implement exponential backoff in your client. The `rateLimitMap` tracks both user and client IDs, so distributing requests across multiple clients for the same user does not bypass the limit.

### Why does my client receive a 403 error when calling `/mcp`?

A 403 response indicates the MCP add-on is disabled. In [`server/src/mcp/index.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/index.ts) (lines 18-22), the handler explicitly checks `isAddonEnabled(ADDON_IDS.MCP)` and rejects the request if the value is false. Run the SQL `INSERT INTO addons (id, enabled) VALUES ('mcp', 1)` to enable the endpoint.

### How are tool permissions determined for OAuth-authenticated clients?

Permissions are derived from the `scopes` field returned by `getUserByAccessToken` in [`server/src/services/oauthService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/oauthService.ts). During session initialization in [`server/src/mcp/index.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/mcp/index.ts), these scopes are passed to `registerTools`, which filters the available tool catalog to only those matching the granted scopes. This ensures AI assistants cannot access travel data outside their OAuth permission grant.