Wraps the Washington State Department of Transportation's Traveler and Ferry APIs into twelve MCP tools covering highway conditions, ferry operations, tolls, and border crossings. Pull real-time traffic alerts filtered by route and milepost, check mountain pass conditions and traction laws, query dynamic toll rates for express lanes, or grab ferry schedules and vessel positions via AIS. The terminal space tool tells you drive-up availability for upcoming sailings, which is critical for San Juan or Bainbridge runs during peak times. Supports both stdio and streamable HTTP transports, and there's a public hosted instance at wsdot.caseyjhand.com. Reach for this when you need live Washington State transportation data without stitching together multiple state APIs yourself.
Query WA highway conditions, ferry schedules, vessel locations, toll rates, border waits, and alerts via MCP. STDIO or Streamable HTTP.
12 tools split across two domains — traffic (WSDOT Traveler API) and ferries (WSF Ferry API):
| Tool | Description |
|---|---|
wsdot_get_mountain_passes | Current conditions for all WA mountain passes: status, road condition, traction laws, temperature, elevation. |
wsdot_search_alerts | Active highway alerts — incidents, construction, closures — filterable by state route, WSDOT region, and milepost range. |
wsdot_get_travel_times | Current vs. average travel times for named WA highway corridors (I-5, I-90, SR 520, etc.) with congestion delay. |
wsdot_get_toll_rates | Dynamic toll rates for WA express lanes and tolled facilities: SR 99, SR 520, I-405, I-90 Two-Way, SR 167 HOT. |
wsdot_get_border_waits | Current vehicle wait times at all WA/Canada land border crossings. |
wsdot_search_cameras | Highway camera metadata and image URLs, filterable by state route, region, and milepost range. |
wsdot_get_ferry_terminals | All WSF ferry terminals with numeric IDs needed for schedule and space lookups. |
wsdot_get_ferry_routes | WSF routes operating on a given date with terminal ID pairs and crossing times. |
wsdot_get_ferry_schedule | Departure times for a specific WSF route — today-remaining or full-day future mode. |
wsdot_get_vessel_locations | Real-time AIS positions, speed, heading, ETA, and dock status for all active WSF vessels. |
wsdot_get_terminal_space | Drive-up and reservable vehicle space available at WSF terminals for upcoming sailings. |
wsdot_get_ferry_alerts | Active WSF service disruptions and bulletins with impacted route IDs. |
wsdot_get_mountain_passesCurrent road conditions for all WA mountain passes.
wsdot_search_alertsActive WA highway alerts — incidents, construction, closures, restrictions.
"005" for I-5, "090" for I-90, "520" for SR 520)wsdot_get_travel_timesCurrent vs. average travel times for named WA highway corridors.
"I-5", "SR 520") to narrow resultswsdot_get_toll_ratesCurrent dynamic toll rates for WA tolled facilities.
wsdot_get_border_waitsCurrent vehicle wait times at WA/Canada land border crossings.
crossingName is a route code (e.g. I5, SR539); location.description holds the readable nameupdateTime is ISO 8601wsdot_search_camerasWSDOT highway camera metadata and image URLs.
wsdot_get_ferry_terminalsAll WSF ferry terminals with numeric IDs.
wsdot_get_ferry_schedule and wsdot_get_terminal_spacewsdot_get_ferry_routesWSF ferry routes operating on a given date.
impactedRouteIds in wsdot_get_ferry_alertswsdot_get_ferry_scheduleDeparture times for a specific WSF ferry route.
wsdot_get_ferry_terminals firstremainingOnly: true returns only future departures for today (useful for "next ferry" queries)wsdot_get_vessel_locationsReal-time AIS positions for all active WSF vessels.
wsdot_get_terminal_spaceReal-time vehicle space availability at WSF terminals for upcoming sailings.
DriveUpSpaceCount is the key field — zero means the drive-up lane is fullwsdot_get_ferry_terminals)wsdot_get_ferry_alertsActive WSF ferry service disruptions, delays, and bulletins.
impactedRouteIds — cross-reference with wsdot_get_ferry_routes to map route IDs to namesBuilt on @cyanheads/mcp-ts-core:
none, jwt, oauth)in-memory, filesystem, Supabase, Cloudflare KV/R2/D1WSDOT-specific:
Agent-friendly output:
DriveUpSpaceCount: 0 and congestion delta fields give agents actionable signal without string parsingnull/undefined rather than synthetic defaultsAdd the following to your MCP client configuration file. You'll need a WSDOT Traveler API access code — register at wsdot.wa.gov/Traffic/api/.
{
"mcpServers": {
"wsdot-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/wsdot-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"WSDOT_ACCESS_CODE": "your-access-code"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"wsdot-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/wsdot-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"WSDOT_ACCESS_CODE": "your-access-code"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"wsdot-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "WSDOT_ACCESS_CODE=your-access-code",
"ghcr.io/cyanheads/wsdot-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 WSDOT_ACCESS_CODE=your-access-code bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/wsdot-mcp-server.git
cd wsdot-mcp-server
bun install
cp .env.example .env
# edit .env and set WSDOT_ACCESS_CODE
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
| Variable | Description | Default |
|---|---|---|
WSDOT_ACCESS_CODE | Required. WSDOT Traveler API access code. Register at wsdot.wa.gov/Traffic/api/. | — |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_HTTP_HOST | HTTP server hostname. | 127.0.0.1 |
MCP_HTTP_ENDPOINT_PATH | HTTP endpoint path. | /mcp |
MCP_PUBLIC_URL | Public origin for TLS-terminating reverse-proxy deployments. | — |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, notice, warning, error). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry instrumentation (spans, metrics, completion logs). | false |
See .env.example for the full list of optional overrides.
Build and run:
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t wsdot-mcp-server .
docker run --rm -e WSDOT_ACCESS_CODE=your-access-code -p 3010:3010 wsdot-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/wsdot-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers all 12 tools and initializes services. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts) — 6 traffic tools, 6 ferry tools. |
src/services/traffic | WSDOT Traffic API service (mountain passes, alerts, travel times, toll rates, border waits, cameras). |
src/services/ferry | WSF Ferry API service (terminals, routes, schedule, vessel locations, space, alerts). |
tests/ | Unit and integration tests, mirroring the src/ structure. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagecreateApp() arrays in src/index.tsIssues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
WSDOT_ACCESS_CODE*WSDOT Traveler API access code. Register at wsdot.wa.gov/Traffic/api/.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.