Skip to main content
Glama
aminamos

metrotransit-mcp

by aminamos

metrotransit-mcp

npm version License: MIT

A unified Model Context Protocol (MCP), Command Line Interface (CLI), and Agent Capabilities Protocol (ACP) toolkit for Metro Transit in the Minneapolis–Saint Paul metropolitan area.

Connect your AI assistants (Claude Desktop, Cursor, Antigravity, custom agents) or query directly from your terminal for real-time bus & light rail departures, station search, route schedules, and live alerts.

Zero API keys or signups required — built on Metro Transit's open public REST API.


What's Included

  • 🔌 MCP Server: Stdio server implementing the official Model Context Protocol for Claude, Cursor, Antigravity, and other MCP clients.

  • 💻 Interactive CLI: Beautiful terminal tool for departures, routes, directions, stops, and incident reports.

  • 🤖 ACP (Agent Capabilities Protocol): Ready-to-use function calling declarations and execution handlers for OpenAI, Anthropic Claude, and Google Gemini agents.

  • 📜 Downloaded OpenAPI / Swagger Specs: Full OpenAPI 3.0.4 definitions for NexTrip v2, Alerts v1, Trip Planner v1, and Schedule v1 included in spec/.


Related MCP server: BusTime MCP

1. CLI Usage

You can run commands directly using npx metrotransit-mcp <command> or by installing globally (npm i -g metrotransit-mcp).

# List all routes or search by name/number
metrotransit routes
metrotransit routes green
metrotransit routes 94

# Show route travel directions
metrotransit directions 902

# List stops for a route in a specific direction (0 = EB/NB, 1 = WB/SB)
metrotransit stops 902 0

# Search for a station on a route
metrotransit search 902 "U.S. Bank"
metrotransit search 902 "Nicollet"

# Live countdown departure board by Stop ID (posted at bus stops & platforms)
metrotransit departures 51408

# Live countdown departure board by Route + Direction + Place Code
metrotransit departures 902 0 5SNI

# Check active detours, service advisories, and closures
metrotransit alerts
metrotransit alerts 902
metrotransit alerts 94 --keyword detour

# Inspect downloaded OpenAPI / Swagger specs
metrotransit spec

2. Model Context Protocol (MCP) Setup

Run via NPX

npx metrotransit-mcp

(When launched by an MCP client or without arguments on a piped stdio, it automatically starts the MCP server).

Claude Desktop Configuration

Add to your claude_desktop_config.json:

macOS / Linux

{
  "mcpServers": {
    "metrotransit": {
      "command": "npx",
      "args": ["-y", "metrotransit-mcp"]
    }
  }
}

Windows

{
  "mcpServers": {
    "metrotransit": {
      "command": "cmd.exe",
      "args": ["/c", "npx", "-y", "metrotransit-mcp"]
    }
  }
}

Cursor / Antigravity / Other MCP Clients

{
  "mcpServers": {
    "metrotransit": {
      "command": "node",
      "args": ["/path/to/metrotransit-mcp/dist/index.js", "mcp"]
    }
  }
}

MCP Tools Provided

  1. list_routes – List or search all Twin Cities transit routes.

  2. get_route_directions – Get directional travel options (Eastbound/Westbound, Northbound/Southbound).

  3. get_route_stops – Get all stations/stops and place codes for a route.

  4. search_stops – Fuzzy search stations along a route.

  5. get_departures – Live GPS countdowns, departure times, and stop alerts by 4–5 digit Stop ID or Route + Place Code.

  6. get_service_alerts – Check active detours, stop closures, or incident advisories.


3. Agent Capabilities Protocol (ACP)

Need to equip a custom agent with Metro Transit tools without MCP?

Run:

# Output OpenAI function definitions
metrotransit acp --format openai

# Output Anthropic tool definitions
metrotransit acp --format anthropic

# Output Google Gemini tool declarations
metrotransit acp --format gemini

Or import directly in TypeScript / JavaScript:

import {
  getOpenAITools,
  getAnthropicTools,
  getGeminiTools,
  executeAgentTool,
} from "metrotransit-mcp";

// 1. Pass tool definitions to your model
const tools = getOpenAITools();

// 2. Execute when tool is called
const result = await executeAgentTool("metrotransit_get_departures", {
  stop_id: 51408,
});

4. OpenAPI / Swagger Specs

The repository includes the official OpenAPI 3.0.4 schemas directly in the spec/ folder:


Development & Testing

# Install dependencies
npm install

# Build
npm run build

# Run unit tests
npm test

# Test CLI
node dist/index.js departures 51408

License

MIT © Amin

Available Tools

6 tools
get_departuresA

Get real-time departure predictions, vehicle countdowns, and stop alerts for a Metro Transit stop or station. You can query either by a 4-5 digit Stop ID, or by Route ID + Direction ID + Place Code.

ParametersJSON Schema
NameRequiredDescriptionDefault
stop_idNoThe 4-to-5 digit Stop ID (posted on bus stop signs and train platforms, e.g. 51408 for Nicollet Mall Station).
route_idNoRoute ID (e.g. '902' for Green Line).
place_codeNoStation place code (e.g. '5SNI', 'TF1', 'WARE', from get_route_stops).
direction_idNoDirection ID (0 or 1).

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

There are no annotations, so the description carries the behavioral disclosure burden. It does disclose that the tool returns real-time predictions, countdowns, and alerts, which conveys read-only behavior. However, it does not clarify that no parameters are marked required in the schema despite needing at least one query mode, nor does it describe error behavior or what happens if conflicting parameters are supplied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loads the core purpose, and adds the key query-mode distinction without any filler. Every sentence earns its place, and the structure makes the tool's behavior immediately understandable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose and the two query modes, but it does not explicitly state that at least one mode is required, despite the schema listing zero required parameters. There is no output schema, so the description's brief mention of predictions, countdowns, and alerts partially compensates, but the missing invocation constraint leaves a meaningful gap for correct usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaningful grouping by explaining that parameters can be combined as either a Stop ID or a Route ID + Direction ID + Place Code. This adds relational meaning beyond the individual parameter descriptions in the schema, although it stops short of explaining mutual exclusivity or required groups.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Get') with a clear resource ('real-time departure predictions, vehicle countdowns, and stop alerts') and scopes it to 'a Metro Transit stop or station.' It is clearly distinct from the sibling tools like get_route_stops or get_service_alerts, so an agent can identify what this tool is for without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the two accepted query modes ('Stop ID' or 'Route ID + Direction ID + Place Code'), which gives practical input guidance. However, it does not explicitly say when to prefer this tool over siblings, nor does it mention exclusions or conditions such as needing get_route_stops to obtain a place code. Usage is implied rather than fully spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_route_directionsA

Get valid travel directions for a specific route (e.g., Eastbound/Westbound, Northbound/Southbound) and their direction IDs.

ParametersJSON Schema
NameRequiredDescriptionDefault
route_idYesRoute ID (e.g. '902' for Green Line, '901' for Blue Line, '94', '4').

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. 'Get' implies a read operation, but the description does not disclose rate limits, error behavior for invalid route IDs, whether data is cached, or any other behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that conveys the operation, scope, and output with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter lookup, the description is largely complete: it states the input, the resource, and what is returned (directions and direction IDs). No output schema exists, so this return information is valuable, though it could mention how the returned direction IDs are intended to be used.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the schema already documents route_id with examples. The description adds no parameter-level detail beyond the schema, which is acceptable given full coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource: 'Get valid travel directions for a specific route' and clarifies the output as direction IDs. This clearly distinguishes it from sibling tools like get_route_stops, get_departures, and list_routes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool: when you need valid directions for a specific route. However, it does not explicitly state when not to use it or name alternatives, leaving the usage context implicit rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_route_stopsA

Get all scheduled stops for a route in a specific direction, including their place codes and station descriptions.

ParametersJSON Schema
NameRequiredDescriptionDefault
route_idYesRoute ID (e.g. '902', '901', '94').
direction_idYesDirection ID (0 or 1, obtained from get_route_directions).

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the operation is 'Get all scheduled stops', implying a read-only action, and mentions the return includes place codes and station descriptions. However, it does not disclose potential limitations (e.g., no real-time updates, no pagination), authentication requirements, or what happens if no stops exist. It is minimally transparent but not misleading.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the action and includes the key output detail (place codes and station descriptions). Every word earns its place; there is no filler or redundant phrasing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (2 parameters, no output schema, no annotations), the description is largely sufficient. It tells the agent what the tool returns (stops with place codes and descriptions) and the necessary parameters are fully defined in the schema. The only missing piece is explicit usage guidance relative to siblings, but that is not critical for correctly calling this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, meaning the input schema already fully documents both route_id and direction_id, including examples and the source of direction_id. The description adds no extra parameter semantics beyond what the schema provides, so it meets the baseline for high coverage without adding value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('Get') and resource ('scheduled stops for a route in a specific direction'), and even specifies the output content ('place codes and station descriptions'). This distinguishes it from siblings like get_route_directions (which returns directions) and get_departures (which returns departure times), so an agent can easily tell what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives or any exclusions. It implies usage by naming 'route' and 'direction', but the prerequisite that direction_id comes from get_route_directions is only mentioned in the schema, not the description. There is no guidance on when not to use it, so the usage context is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_service_alertsA

Get active service alerts, detours, stop closures, and disruptions across the Metro Transit network, optionally filtered by route ID or keyword.

ParametersJSON Schema
NameRequiredDescriptionDefault
keywordNoOptional keyword to filter alerts (e.g. 'Vikings', 'closure', 'detour').
route_idNoOptional route ID to filter alerts (e.g. '902', '901', '94').

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It mentions 'active' alerts but does not disclose response format, pagination, data freshness, authorization requirements, or what happens when no alerts match. The behavior beyond the basic 'get' is underexplained.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence that conveys the purpose and filters without redundancy. Every word contributes value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with two optional parameters and no output schema, but the description does not describe the return structure or any edge-case behavior. An agent knows when to call it and what to pass, but not what to expect back, which is a notable gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with both parameters having clear descriptions. The description adds minimal extra value by noting the filters are optional, but does not introduce new semantic details beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action (Get) on a specific resource (service alerts, detours, stop closures, disruptions) across the network, with optional filters. This distinguishes it from sibling tools that focus on routes, stops, and departures.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for alert-related queries but does not explicitly mention when to use this tool over siblings or provide exclusions. The context of the sibling names makes it inferable, but no direct guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_routesA

Get all Metro Transit routes in the Minneapolis-St. Paul metro area (METRO Blue/Green/Gold/Orange/Red/A/B/C/D/E lines and bus routes). Supports optional filtering by search query.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoOptional search string to filter routes by name or number (e.g. 'green', 'blue', 'orange', '94', 'e line').

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. The verb 'Get' and the phrase 'Supports optional filtering' disclose read-only behavior and filter support, but the description does not mention response structure, route identifiers, or edge cases like empty results. That is acceptable for a simple listing tool but not rich disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence: it states the core action first, then the optional filtering behavior. The enumeration of line names and bus routes is somewhat redundant with 'all routes' but remains compact and useful for clarifying scope.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple: one optional parameter, no required arguments, and no nested objects. The description supplies the geographic scope, route categories, and filter capability, which is enough to invoke it correctly. The lack of an output schema means response field details are not described, but that is a minor gap for a basic list-all-routes tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the input schema already documents the optional query parameter with examples. The description only restates that filtering is supported, adding no meaning beyond the structured schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Get') and resource ('all Metro Transit routes'), with geographic scope and route categories. Brother tools like get_route_directions, get_route_stops, and get_departures are clearly narrower, so list_routes is easily distinguishable as the route-catalog tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when a full or filtered route list is needed, and the optional query hint gives some context. However, it never explicitly says when to use this tool versus siblings such as search_stops, and it provides no when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_stopsA

Search for stops/stations along a specific route by keyword or station name (e.g., search 'Stadium' or 'Nicollet' on the Green Line).

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesText to search in the stop name/description.
route_idYesRoute ID (e.g. '902', '901', '94').
direction_idNoDirection ID (0 or 1). Default is 0 if omitted.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It discloses that the search is route-scoped, but does not specify whether results are limited to that route, what happens with no matches, or the return format. It does not contradict anything but adds minimal behavioral context beyond the core action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence with a concrete example, no filler. The core purpose is front-loaded and the example aids comprehension. Extremely efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Tool is simple, but without an output schema, the description should hint at what is returned. It does not mention that it returns a list of matching stops or any field details. Also does not clarify direction_id behavior beyond the schema. Adequate for basic usage but leaves some expectations unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters, so baseline is 3. The description adds an example for query but does not elaborate on query semantics beyond 'keyword or station name' or the role of direction_id. It provides marginal extra value over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the verb 'search' with resource 'stops/stations', scoped to 'along a specific route', and method 'by keyword or station name'. Provides a concrete example and implicitly differentiates from sibling get_route_stops which likely lists all stops. The purpose is unambiguous and actionable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Does not explicitly state when to use this tool versus alternatives such as get_route_stops. The description implies that it is for keyword-based lookup, but there is no guidance on when not to use it, or how it compares to listing all stops. An agent must infer the appropriate context from the sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv1.1.0
    • First observedget_departures
    • First observedget_route_directions
    • First observedget_route_stops
    • First observedget_service_alerts
    • First observedlist_routes
    • First observedsearch_stops

TDQS

A3.9/5.0

Scored across 6 tools

Disambiguation4/5

Each tool targets a distinct transit resource (routes, directions, stops, departures, alerts), but get_route_stops and search_stops overlap in purpose—one returns all stops while the other filters them by keyword. Descriptions are clear enough to differentiate, though minor boundary ambiguity exists.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern (list_routes, get_route_directions, get_departures, search_stops). No mixed conventions or vague verbs, making the set highly predictable.

Tool Count5/5

Six tools is well-scoped for a transit information server, covering route discovery, stop lookup, departures, and alerts without unnecessary bloat. Each tool earns its place in the workflow.

Completeness4/5

The core transit query surface is covered: routes, directions, stops, departures, and alerts. Minor gaps exist such as no route-by-ID lookup or stop details endpoint, but agents can achieve common tasks with the provided operations.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    C
    maintenance
    Wraps the CTA Bus Tracker API to provide live access to bus routes, stops, predictions, vehicle locations, patterns, and detours via MCP clients.
    11
    -