> ## Documentation Index
> Fetch the complete documentation index at: https://terminal49.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Terminal49 MCP Server Quickstart

> Set up the Terminal49 MCP server in Claude Desktop, Cursor, or another MCP-compatible client to query live shipment and container tracking data.

This guide covers everything you need to connect Claude or Cursor to Terminal49's container tracking data via MCP.

<Note>
  Just want to get started fast? See [MCP Overview](/mcp/home) for a 5-minute setup.
</Note>

## Prerequisites

Before you begin, make sure you have:

<CardGroup cols={2}>
  <Card title="Terminal49 account" icon="user">
    A Terminal49 account with API access
  </Card>

  <Card title="API key" icon="key">
    An API key from the [developer portal](https://app.terminal49.com/developers/api-keys)
  </Card>

  <Card title="Node.js 24.x" icon="node-js">
    Required if running the MCP server locally
  </Card>

  <Card title="MCP client" icon="robot">
    Claude Desktop or Cursor IDE
  </Card>
</CardGroup>

**Technical Details:**

* **MCP SDK**: `@modelcontextprotocol/sdk ^1.29.0`
* **TypeScript SDK**: `@terminal49/sdk 0.3.0`
* **Sentry MCP Monitoring**: `@sentry/node ^10.55.0` (optional)
* **Runtime**: Node.js 24.x

***

## Transports

| Transport         | Endpoint                          | Best For                         |
| ----------------- | --------------------------------- | -------------------------------- |
| HTTP (streamable) | `POST https://mcp.terminal49.com` | Serverless, short-lived requests |

**Authentication**: API key only (OAuth not required for this release).
Pass `Authorization: Token YOUR_API_KEY`. Use the `Token` scheme for API keys. The `Bearer` scheme is reserved for WorkOS OAuth access tokens — it currently accepts API keys for backward compatibility, but once OAuth is enabled, `Bearer` accepts only WorkOS tokens.

The hosted endpoint always requires the `Authorization` header. Only the [local stdio server](#local-stdio-development) reads the `T49_API_TOKEN` environment variable instead of a header.

<Tip>
  Claude Desktop and Cursor use the HTTP transport. For hosted production usage, connect to `https://mcp.terminal49.com` — the root origin is the canonical connector URL.
</Tip>

***

## Observability

The MCP server supports optional [Sentry MCP Monitoring](https://docs.sentry.io/ai/monitoring/mcp/). Set `SENTRY_DSN` to capture MCP server connections, tool executions, resource access, prompts, performance spans, and errors in Sentry.

```bash theme={null}
SENTRY_DSN=___PUBLIC_DSN___
SENTRY_TRACES_SAMPLE_RATE=1.0
SENTRY_MCP_RECORD_INPUTS=false
SENTRY_MCP_RECORD_OUTPUTS=false
SENTRY_SEND_DEFAULT_PII=false
```

<Warning>
  `SENTRY_MCP_RECORD_INPUTS` and `SENTRY_MCP_RECORD_OUTPUTS` are disabled by default because MCP payloads can include shipment identifiers, references, and customer data. Enable them only if your Sentry project is approved for that data.
</Warning>

***

## Configure your MCP client

### Claude Desktop

<Tabs>
  <Tab title="macOS">
    Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

    ```json theme={null}
    {
      "mcpServers": {
        "terminal49": {
          "url": "https://mcp.terminal49.com",
          "headers": {
            "Authorization": "Token YOUR_API_KEY"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Windows">
    Edit `%APPDATA%\Claude\claude_desktop_config.json`:

    ```json theme={null}
    {
      "mcpServers": {
        "terminal49": {
          "url": "https://mcp.terminal49.com",
          "headers": {
            "Authorization": "Token YOUR_API_KEY"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Linux">
    Edit `~/.config/Claude/claude_desktop_config.json`:

    ```json theme={null}
    {
      "mcpServers": {
        "terminal49": {
          "url": "https://mcp.terminal49.com",
          "headers": {
            "Authorization": "Token YOUR_API_KEY"
          }
        }
      }
    }
    ```
  </Tab>
</Tabs>

### Cursor IDE

Add to your Cursor settings:

```json theme={null}
{
  "mcp": {
    "servers": {
      "terminal49": {
        "url": "https://mcp.terminal49.com",
        "headers": {
          "Authorization": "Token YOUR_API_KEY"
        }
      }
    }
  }
}
```

### Local stdio (development)

For local development without a hosted server:

```json theme={null}
{
  "mcpServers": {
    "terminal49": {
      "command": "node",
      "args": ["/path/to/API/packages/mcp/dist/index.js"],
      "env": {
        "T49_API_TOKEN": "YOUR_API_KEY"
      }
    }
  }
}
```

<Warning>
  Build the MCP server first:
  `cd packages/mcp && npm install && T49_SDK_SOURCE=published npm run sdk:setup && npm run build`
</Warning>

<Accordion title="Contributor mode: switch SDK source">
  Use published SDK by default:

  ```bash theme={null}
  cd packages/mcp
  T49_SDK_SOURCE=published npm run sdk:setup
  ```

  Use local SDK build during development:

  ```bash theme={null}
  cd packages/mcp
  T49_SDK_SOURCE=local npm run sdk:setup
  ```
</Accordion>

***

## Test your setup

Once configured, verify everything works:

<Steps>
  <Step title="Restart your MCP client">
    Close and reopen Claude Desktop or Cursor to load the new config.
  </Step>

  <Step title="Ask Claude to list tools">
    > "List the tools available in the Terminal49 MCP server."

    Claude should respond with a list of 10 tools including `search_container`, `track_container`, and list tools.
  </Step>

  <Step title="Search for a test container">
    > "Using the Terminal49 MCP server, search for container TCLU1234567 and summarize its status."

    If configured correctly, Claude will call `search_container` and return container details.
  </Step>

  <Step title="Try a multi-step query">
    > "Using Terminal49, find container CAIU1234567, check its demurrage risk, and tell me if I need to pick it up urgently."

    Claude should chain multiple tools together to answer.
  </Step>
</Steps>

<Note>
  Need test container numbers? See [Test Numbers](/api-docs/useful-info/test-numbers) for containers you can use during development.
</Note>

***

## Troubleshooting

| Symptom                        | Likely Cause               | How to Fix                                                                                                                                                   |
| ------------------------------ | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| "Cannot connect to MCP server" | Wrong URL or config path   | Confirm URL is `https://mcp.terminal49.com` and config file path matches your OS                                                                             |
| `401 Unauthorized`             | Missing or invalid API key | Create a new API key in the [developer portal](https://app.terminal49.com/developers/api-keys); ensure the `Authorization: Token YOUR_API_KEY` header is set |
| `429 Too Many Requests`        | Rate limit exceeded        | See [Rate Limiting](/api-docs/in-depth-guides/rate-limiting); use webhooks instead of polling                                                                |
| Tools list is empty            | Config not loaded          | Restart Claude/Cursor; check MCP inspector for errors                                                                                                        |
| "Tool not found"               | Typo in tool name          | Use exact names: `search_container`, `get_container`, etc.                                                                                                   |
| Slow responses                 | Large data requests        | Use `include` parameter to load only what you need                                                                                                           |

<Accordion title="Check MCP server logs">
  If using the hosted server, check your Terminal49 dashboard for API logs.

  If running locally:

  ```bash theme={null}
  cd packages/mcp
  T49_API_TOKEN=YOUR_API_KEY npm run mcp:stdio 2>&1 | head -20
  ```
</Accordion>

***

## MCP capabilities

### Tools

| Tool                             | Description                                    | Parameters                                                                                     |
| -------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `search_container`               | Find containers by number, BL, booking, or ref | `query: string`                                                                                |
| `track_container`                | Start tracking a container                     | `number`, `numberType?`, `scac?`, `refNumbers?`                                                |
| `get_container`                  | Get container with optional includes           | `id: uuid`, `include?: ['shipment', 'pod_terminal', 'transport_events']`                       |
| `get_shipment_details`           | Get shipment and containers                    | `id: uuid`, `include_containers?: boolean`                                                     |
| `get_container_transport_events` | Get event timeline                             | `id: uuid`                                                                                     |
| `get_supported_shipping_lines`   | List carriers with SCAC codes                  | `search?: string`                                                                              |
| `get_container_route`            | Get multi-leg routing (paid feature)           | `id: uuid`                                                                                     |
| `list_shipments`                 | List shipments with filters + pagination       | `status?`, `port?`, `carrier?`, `updated_after?`, `include_containers?`, `page?`, `page_size?` |
| `list_containers`                | List containers with filters + pagination      | `status?`, `port?`, `carrier?`, `updated_after?`, `include?`, `page?`, `page_size?`            |
| `list_tracking_requests`         | List tracking requests with filters            | `filters?`, `status?`, `request_type?`, `page?`, `page_size?`                                  |

### Prompts

| Prompt            | Description             | Arguments                      |
| ----------------- | ----------------------- | ------------------------------ |
| `track-shipment`  | Quick tracking workflow | `container_number`, `carrier?` |
| `check-demurrage` | Demurrage risk analysis | `container_id`                 |
| `analyze-delays`  | Journey delay analysis  | `container_id`                 |

### Resources

| URI                                    | Description                |
| -------------------------------------- | -------------------------- |
| `terminal49://container/{id}`          | Container data as resource |
| `terminal49://docs/milestone-glossary` | Event/milestone reference  |

For detailed examples and response formats, see [MCP Overview → Tools Reference](/mcp/home#tools-reference).

***

## SDK usage

The TypeScript SDK provides the same capabilities as MCP tools, plus additional APIs not yet exposed via MCP.

```bash theme={null}
npm install @terminal49/sdk
```

```typescript theme={null}
import { Terminal49Client } from '@terminal49/sdk';

const client = new Terminal49Client({
  apiToken: process.env.T49_API_TOKEN!,
  defaultFormat: 'mapped'
});

// Get container with shipment and terminal
const container = await client.containers.get(
  'container-uuid',
  ['shipment', 'pod_terminal']
);

// Search for containers
const results = await client.search('CAIU1234567');

// List shipments with filters (not available via MCP)
const shipments = await client.shipments.list({
  status: 'in_transit',
  carrier: 'MAEU'
});
```

### Response formats

| Format   | Description                                                  |
| -------- | ------------------------------------------------------------ |
| `raw`    | JSON:API response with `data`, `attributes`, `relationships` |
| `mapped` | Simplified, camelCase objects with IDs resolved              |
| `both`   | `{ raw, mapped }` for debugging                              |

<Accordion title="Raw vs Mapped example">
  **Raw format:**

  ```json theme={null}
  {
    "data": {
      "type": "container",
      "id": "abc-123",
      "attributes": {
        "container_number": "CAIU1234567",
        "available_for_pickup": true
      }
    }
  }
  ```

  **Mapped format:**

  ```json theme={null}
  {
    "id": "abc-123",
    "containerNumber": "CAIU1234567",
    "availableForPickup": true
  }
  ```
</Accordion>

***

## Deployment

### Vercel (production)

The `vercel.json` configures the MCP server (excerpt):

```json theme={null}
{
  "installCommand": "npm ci",
  "buildCommand": "npm run build --workspace @terminal49/sdk && npm run build --workspace @terminal49/mcp",
  "functions": {
    "api/mcp.ts": { "maxDuration": 30 }
  },
  "rewrites": [
    { "source": "/mcp", "destination": "/api/mcp" },
    { "source": "/", "destination": "/api/mcp" }
  ]
}
```

### Environment variables

| Variable                    | Required        | Description                                                                                               |
| --------------------------- | --------------- | --------------------------------------------------------------------------------------------------------- |
| `T49_API_TOKEN`             | For local stdio | Terminal49 API key. The hosted HTTP endpoint authenticates callers via the `Authorization` header instead |
| `T49_API_BASE_URL`          | No              | Override API URL (default: `https://api.terminal49.com/v2`)                                               |
| `T49_MCP_ALLOWED_HOSTS`     | No              | Comma-separated host allowlist for request Host validation                                                |
| `T49_MCP_ALLOWED_ORIGINS`   | No              | Comma-separated origin allowlist for request Origin validation                                            |
| `SENTRY_DSN`                | No              | Enables Sentry MCP Monitoring                                                                             |
| `SENTRY_ENVIRONMENT`        | No              | Sentry environment name; defaults to `NODE_ENV`                                                           |
| `SENTRY_RELEASE`            | No              | Sentry release identifier; defaults to `VERCEL_GIT_COMMIT_SHA`                                            |
| `SENTRY_TRACES_SAMPLE_RATE` | No              | Trace sampling rate from `0` to `1`; defaults to `1.0`                                                    |
| `SENTRY_MCP_RECORD_INPUTS`  | No              | Records MCP inputs in Sentry when set to `true`; defaults to `false`                                      |
| `SENTRY_MCP_RECORD_OUTPUTS` | No              | Records MCP outputs in Sentry when set to `true`; defaults to `false`                                     |
| `SENTRY_SEND_DEFAULT_PII`   | No              | Enables Sentry default PII behavior; defaults to `false`                                                  |

***

## Testing locally

```bash theme={null}
# Build the MCP server
cd packages/mcp
npm install
npm run build

# Test tools/list
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | T49_API_TOKEN=YOUR_API_KEY npm run mcp:stdio

# Test search_container
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"search_container","arguments":{"query":"CAIU1234567"}},"id":2}' | T49_API_TOKEN=YOUR_API_KEY npm run mcp:stdio

# Test the hosted endpoint
curl -X POST https://mcp.terminal49.com \
  -H "Authorization: Token $T49_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
```

***

## Related guides

* [MCP Overview](/mcp/home) – Quick start and tools reference
* [Rate Limiting](/api-docs/in-depth-guides/rate-limiting) – API limits (same for MCP)
* [Test Numbers](/api-docs/useful-info/test-numbers) – Containers for testing
* [Webhooks](/api-docs/in-depth-guides/webhooks) – Real-time updates
* [API Data Sources](/api-docs/useful-info/api-data-sources-availability) – Data freshness and coverage
