mcpField
T
Terminal49

Terminal49

Remote
docs.terminal49.comMaps & Travel2Updated 1d ago

About Terminal49

Terminal49 MCP Server exposes the Terminal49 API to MCP clients for teams tracking ocean containers, shipments, and trade data. It combines lookup and analysis tools with workflow prompts and on-demand container resources.

Key features

  1. 01Search and track containers and shipments
  2. 02Inspect routes, events, and vessel data
  3. 03Search importers and analyze trade data
  4. 04Offer three workflow prompts
  5. 05Load container details on demand through resource links

Use cases

  1. 01Create tracking requests and check shipment progress
  2. 02Analyze delays or demurrage risk
  3. 03Research importers by product, port, or origin
  4. 04Filter containers and retrieve details as needed

MCP support

The server connects to MCP clients through Streamable HTTP or local stdio and exposes tools, prompts, and resources. Access uses a Terminal49 API token.

Configuration

Remote servers need no local install. Pick your client, then copy the config or install in one click.

Endpointhttps://mcp.terminal49.com
Copy install command
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.

Tools

Details

From the project README

Terminal49 MCP Server (TypeScript)

Vercel-native Model Context Protocol server for Terminal49's API, built with TypeScript and the official MCP SDK.

🚀 Quick Deploy to Vercel

Deploy with Vercel

  1. Click "Deploy" above
  2. Add environment variable: T49_API_TOKEN=your_token_here
  3. Deploy!
  4. Your MCP server will be available at: https://your-deployment.vercel.app/api/mcp

📦 What's Included

🛠️ Tools (30 Available)
ToolDescriptionKey Features
search_containerSearch by container#, BL, booking, or referenceFast fuzzy search
track_containerCreate tracking request and get container dataSCAC autocomplete ✨
identify_tracking_numberPredict a number's type and carrier and check whether it is already trackedCreates nothing
get_containerGet detailed container info with flexible data loadingOptional custom fields and party roles
get_shipment_detailsGet shipment routing, BOL, containers, portsOptional custom fields and party roles
get_container_transport_eventsGet full event timeline for a containerMilestone history
get_supported_shipping_linesList 40+ major carriers with SCAC codesFilterable by name/code
get_container_routeGet ports in route order with ETAs and the current vesselPremium feature
get_locationGet a port, terminal, or metro areaFIRMS code, address, time zone
get_vesselGet a vessel's position and, optionally, its projected track to a portProjection is a premium feature
list_shipmentsList shipments with filters and paginationFleet-level visibility
list_containersList containers with filters and paginationReturns ResourceLinks ✨
summarize_containersCount containers grouped by terminal, status, carrier, port, hold, or dateSame filters as list_containers
list_partiesFind parties by company name, or read one by IDFeeds advanced_filters.parties
list_custom_field_definitionsList the account's custom fields, their types, and enum optionsNeeds a signed-in user
list_tracking_requestsList tracking requests and statusesAudit and monitoring
get_tracking_requestGet one tracking request's status, failure reason, and shipmentFollow-up after tracking
list_documentsFind documents by file name, reference, or typeNever returns extracted data or file links
get_documentGet one document, with opt-in extracted data, source email, and download linkUntrusted content is labeled
search_docsSearch the public Terminal49 documentationReturns links to cite
whoamiIdentify the credential, its account, the features it can use, and the session's toolsetsExplains empty or unauthorized results
set_party_roleAttach, replace, or detach a party (such as the drayage carrier) on containers or shipmentsDestructive write, only on request
set_custom_fieldSet or clear one of the account's custom fields on containers or shipmentsDestructive write, only on request
search_importersFind US importers by name, by what they import, or bothTrade intelligence, per account
get_importer_profileOne importer's totals, monthly series, ports, origins, carriers, and productsTrade intelligence, per account
search_commoditiesTurn a product description or HS prefix into four-digit HS codesTrade intelligence, per account
rank_importersRank importers by containers for a product, US port, or origin countryTrade intelligence, per account
get_trade_trendsTime series of containers, TEUs, or estimated valueTrade intelligence, per account
get_trade_breakdownNested totals over one to three dimensionsTrade intelligence, per account
get_trade_data_coverageWhere trade data starts, the latest and last full monthTrade intelligence, per account
🎯 Prompts (3 Workflows)
PromptDescriptionUse Case
track-shipmentTrack container with optional carrierQuick tracking start (SCAC autocomplete ✨)
check-demurrageAnalyze demurrage/detention riskLFD calculations
analyze-delaysIdentify delays and root causesTimeline analysis

The track-shipment prompt's carrier argument supports MCP completions (completion/complete): suggestions are sourced live from get_supported_shipping_lines, filtered by what the user has typed, and returned as SCAC codes.

📚 Resources
  • ✅ terminal49://docs/milestone-glossary - Complete milestone reference guide
  • ✅ terminal49://docs/mcp-query-guidance - Internal tool-routing hints
  • ✅ terminal49://container/{id} - Dynamic container data access (also the target of list_containers ResourceLinks)
🧭 Server Instructions

The server advertises MCP instructions (a server-level operating guide) at initialize time: it explains the ocean container/shipment tracking domain, key vocabulary (SCAC, BOL/booking, POL/POD, LFD, demurrage, holds), the read tools vs the single write tool (track_container), and the canonical tool-chaining order.

🔗 ResourceLinks (context reduction)

list_containers returns MCP resource_link content blocks — one per container row — that point at the registered terminal49://container/{id} resource. Clients can render the compact list and resolve full per-container detail on demand via resources/read, instead of paying for every container's full payload up front.

🙈 Content Audience Annotations

Tool results separate the human-readable answer from agent-steering metadata. The steering block (presentation guidance + suggested follow-up tools, derived from the _response_contract) is tagged with annotations: { audience: ['assistant'] } so spec-aware clients can hide it from end users, while the answer block stays user-visible.

✨ Current Features (v1.0.0 - Phase 1 & 2.1 Complete)
✅ Modern McpServer API
  • High-level registerTool(), registerPrompt(), registerResource() patterns
  • Type-safe Zod schemas for all tool inputs
  • Cleaner, maintainable code (71% code reduction in HTTP handler)
  • MCP SDK: @modelcontextprotocol/sdk ^1.29.0
  • Terminal49 SDK: @terminal49/sdk 0.2.0
✅ Production Transport Support
  • HTTP (streamable): POST /api/mcp - stateless, JSON responses
  • SSE was removed from the hosted deployment path in favor of Streamable HTTP transport.
✅ Sentry MCP Monitoring
  • Optional instrumentation with @sentry/node ^10.55.0
  • Captures MCP connections, tool calls, resources, prompts, performance spans, and errors when SENTRY_DSN is set
  • Tool input/output recording is disabled by default; enable it only after reviewing data handling requirements
✅ 3 Workflow Prompts
  • track-shipment: Quick container tracking with optional carrier
  • check-demurrage: Demurrage/detention risk analysis
  • analyze-delays: Journey delay identification and root cause
✅ MCP Spec Adherence
  • Server instructions: server-level operating guide advertised at initialize
  • SCAC code completions: completion/complete on the track-shipment prompt's carrier arg, sourced from get_supported_shipping_lines
  • ResourceLinks: list_containers rows link to the terminal49://container/{id} resource
  • Content audience annotations: steering metadata tagged audience: ['assistant']
🚧 Deferred (future RFC — needs a stateful transport)
  • Resource subscriptions, progress notifications, server logging, elicitation, and sampling all require a stateful (non-stateless-HTTP) transport and are out of scope here.
  • Shipment ResourceLinks await a dedicated terminal49://shipment/{id} resource template (only the container template is currently registered).

🏗️ Architecture

/api/mcp.ts                  # Vercel serverless function (HTTP)
/packages/mcp/
  ├── src/
  │   ├── server.ts          # MCP server (stdio)
  │   ├── index.ts           # Stdio entry point
  │   ├── tools/             # MCP tools
  │   └── resources/         # MCP resources
  └── package.json

MCP uses published @terminal49/sdk by default, with optional local override for contributors.

Transport:

  • HTTP: Vercel serverless function at /api/mcp (for hosted use)
  • stdio: Local binary for Claude Desktop (run via npm run mcp:stdio)

Store submission

The public connector URL is https://mcp.terminal49.com. Store assets and submission metadata are checked in at the repository root:

  • chatgpt-app-submission.json — locked ChatGPT listing copy and review cases
  • claude-connector-submission.json — values to enter in Claude's submission portal
  • server.json — official MCP Registry metadata used for Copilot discovery
  • public/store-icons/terminal49-{light,dark}.png — 512×512 brand icons
Verify the domain for ChatGPT

OpenAI generates a unique domain-verification token during submission. Add that exact value to the existing MCP Vercel project:

vercel env add OPENAI_APPS_CHALLENGE

After the project redeploys, verify that the well-known endpoint returns only the token you pasted:

curl --fail --silent \
  https://mcp.terminal49.com/.well-known/openai-apps-challenge

Do not commit the token. The endpoint returns an empty 404 response while OPENAI_APPS_CHALLENGE is unset. Submit the connector and the values in chatgpt-app-submission.json through the OpenAI plugin submission flow.

Submit to Claude

Use the Claude Connectors Directory portal and enter the values in claude-connector-submission.json. Upload the light icon from public/store-icons/terminal49-light.png; the dark variant is available for clients that support theme-specific assets.

Publish for Copilot discovery

GitHub's Copilot registry is a curated downstream discovery surface. Publish server.json to the official MCP Registry to make Terminal49 eligible for that surface:

mcp-publisher validate server.json
mcp-publisher login github
mcp-publisher publish server.json

The publisher must authenticate as an owner of the Terminal49 GitHub organization because the registry name uses its io.github.Terminal49 namespace.


🛠️ Local Development

Prerequisites
Setup
cd packages/mcp
npm install
T49_SDK_SOURCE=published npm run sdk:setup
cp .env.example .env
# Add your T49_API_TOKEN to .env

Use a local SDK build during MCP development:

cd packages/mcp
T49_SDK_SOURCE=local npm run sdk:setup
Run Locally
# Stdio mode (for Claude Desktop testing)
npm run mcp:stdio

# Development mode with auto-reload
npm run dev
Test the API
# List tools
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | npm run mcp:stdio

# Get container
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"get_container","arguments":{"id":"123e4567-e89b-12d3-a456-426614174000"}},"id":2}' | npm run mcp:stdio

🌐 Using with Vercel Deployment

Deploy
# Install Vercel CLI
npm i -g vercel

# Deploy to Vercel
vercel

# Set environment variable
vercel env add T49_API_TOKEN
Configure MCP Client

Once deployed, your MCP server will be at: https://your-deployment.vercel.app/api/mcp

For Claude Desktop or other MCP clients:

{
  "mcpServers": {
    "terminal49": {
      "url": "https://your-deployment.vercel.app/api/mcp",
      "headers": {
        "Authorization": "Token your_api_token_here"
      }
    }
  }
}

For Cursor IDE:

{
  "mcp": {
    "servers": {
      "terminal49": {
        "url": "https://your-deployment.vercel.app/api/mcp",
        "headers": {
          "Authorization": "Token your_api_token_here"
        }
      }
    }
  }
}

🔧 API Reference

HTTP Endpoint

URL: POST /api/mcp

Headers:

Authorization: Token your_api_token_here
Content-Type: application/json

Request (JSON-RPC):

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "get_container",
    "arguments": {
      "id": "123e4567-e89b-12d3-a456-426614174000"
    }
  },
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"id\":\"...\",\"container_number\":\"...\", ...}"
      }
    ]
  },
  "id": 1
}
Available Methods
MethodDescription
initializeInitialize MCP connection
tools/listList available tools
tools/callExecute a tool
resources/listList available resources
resources/readRead a resource

🔐 Authentication

For Vercel Deployment (HTTP)

Set as environment variable in Vercel dashboard:

T49_API_TOKEN=your_token_here

Or include in request headers:

Authorization: Token your_token_here

Token is the preferred scheme. Bearer your_token_here is also accepted for backward compatibility.

For Local stdio

Set in your environment:

export T49_API_TOKEN=your_token_here

🧪 Testing

# Run tests
npm test

# Type checking
npm run type-check

# Linting
npm run lint

📝 Environment Variables

VariableRequiredDefaultDescription
T49_API_TOKEN✅ Yes-Terminal49 API token
T49_API_BASE_URLNohttps://api.terminal49.com/v2API base URL
T49_MCP_TOOLSETSNocore,documents,operations,tradeComma-separated toolsets this deployment serves. See Toolsets.
T49_MCP_READ_ONLYNofalseServe only tools whose readOnlyHint is true. Accepts true, false, 1 or 0, in any case.
T49_MCP_ALLOW_SHARED_TOKEN_WRITESNofalseServe toolsets other than core and trade when callers share T49_API_TOKEN
OPENAI_APPS_CHALLENGEOnly for ChatGPT submission-Exact domain-verification token issued by the OpenAI submission portal
NODE_ENVNodevelopmentEnvironment
LOG_LEVELNoinfoLogging level
REDACT_LOGSNotrueRedact tokens in logs
SENTRY_ENABLEDNotrueEnables or disables Sentry when a DSN is configured
SENTRY_DSNNo-Enables Sentry MCP Monitoring when set
SENTRY_ENVIRONMENTNoNODE_ENVSentry environment name
SENTRY_RELEASENoVERCEL_GIT_COMMIT_SHASentry release identifier
SENTRY_TRACES_SAMPLE_RATENo1.0Trace sampling rate from 0 to 1
SENTRY_MCP_RECORD_INPUTSNofalseRecord MCP tool/prompt inputs in Sentry
SENTRY_MCP_RECORD_OUTPUTSNofalseRecord MCP tool/prompt outputs in Sentry
SENTRY_SEND_DEFAULT_PIINofalseEnables Sentry default PII behavior

Only enable SENTRY_MCP_RECORD_INPUTS or SENTRY_MCP_RECORD_OUTPUTS after confirming that your Sentry project is approved to store shipment identifiers, references, and customer data.

Credential headers (Authorization, cookies, and any header whose name contains auth, token, secret, cookie, session, api-key, password, or signature) and request cookies are removed from every error and transaction event before it is sent, regardless of SENTRY_SEND_DEFAULT_PII.

Signed URLs, such as the document download link that get_document returns, are replaced with [REDACTED_URL] in logs, Sentry events and PostHog events. This holds even when SENTRY_MCP_RECORD_OUTPUTS is on.

Toolsets

Each tool belongs to one toolset in src/tools/registry.ts: core, documents, operations, documents_write, developer or trade. list_documents and get_document are in documents. set_party_role and set_custom_field are in operations. The trade intelligence tools are in trade. Every other tool today is in core. whoami reports the toolsets a session serves and whether it has write tools.

  • T49_MCP_TOOLSETS lists the toolsets the server allows. stdio and the HTTP gateway both read it. An unknown name, or a value made only of commas, stops stdio with an error that names the variable. HTTP requests fail with a generic 500, and the gateway logs the cause.
  • The X-T49-MCP-Toolsets request header can only narrow that list. The server serves the toolsets that appear in both. An unknown name, or a value made only of commas, returns 400.
  • X-T49-MCP-Read-Only: true or T49_MCP_READ_ONLY=true removes every tool whose readOnlyHint is false, including track_container. Both accept true, false, 1 or 0, in any case. Any other header value returns 400. The header cannot turn off read-only mode that the env turned on.
  • The server instructions name only the tools the session serves.
  • When the gateway uses one shared T49_API_TOKEN, it serves only core and the read-only trade toolset unless T49_MCP_ALLOW_SHARED_TOKEN_WRITES=true.
  • Toolsets are never read from the connector URL. The OAuth resource stays the root origin.

🆚 Ruby vs TypeScript

This repo includes two implementations:

FeatureRuby (/mcp)TypeScript (/packages/mcp + /api)
DeploymentRailway, Fly.io, Heroku✅ Vercel (native)
HTTP TransportRack/Puma✅ Vercel Serverless
stdio Transport✅ Yes✅ Yes
StatusCompleteComplete
Use CaseStandalone serversVercel deployments

Recommendation: Use TypeScript for Vercel deployments (zero-config, auto-scaling).


🚦 Vercel Configuration

The project includes vercel.json for optimal Vercel deployment:

{
  "functions": {
    "api/mcp.ts": {
      "runtime": "nodejs20.x",
      "maxDuration": 30,
      "memory": 1024
    }
  }
}
Configuration Notes
  • Runtime: Node.js 20.x
  • Max Duration: 30 seconds (adjustable for Pro/Enterprise)
  • Memory: 1024 MB
  • CORS: Enabled for all origins (Access-Control-Allow-Origin: *)

🐛 Troubleshooting

"T49_API_TOKEN is required" error

Solution: Set environment variable in Vercel dashboard or locally:

vercel env add T49_API_TOKEN
"Method not allowed" error

Solution: Ensure you're using POST method, not GET:

curl -X POST https://your-deployment.vercel.app/api/mcp \
  -H "Authorization: Token your_token" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
CORS errors in browser

Solution: CORS is configured in vercel.json. If issues persist, check Vercel deployment logs:

vercel logs
Timeout errors

Solution: Increase maxDuration in vercel.json (requires Vercel Pro/Enterprise):

{
  "functions": {
    "api/mcp.ts": {
      "maxDuration": 60
    }
  }
}

📚 Documentation


🤝 Contributing

  1. Fork the repo
  2. Create a feature branch: git checkout -b feature/my-tool
  3. Make changes in /packages/mcp/src/
  4. Add tests
  5. Run type check: npm run type-check
  6. Submit PR

📄 License

Copyright 2024 Terminal49. All rights reserved.


🆘 Support


Built with MCP TypeScript SDK 🚀

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.