npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@transit-se/mcp

v1.1.0

Published

MCP server for Swedish public transit (Trafiklab, GTFS-RT). Real-time departures, service alerts, and stop lookups as AI-callable tools.

Downloads

625

Readme

@transit-se/mcp

MCP (Model Context Protocol) server for Swedish public transit. Exposes Trafiklab real-time APIs as tools that AI assistants like Claude can call directly.

Built on top of @transit-se/sdk.

Table of Contents


Quick Start

1. Get API keys (optional)

Some tools require Trafiklab API keys. Stockholm (SL) tools work without any keys.

  1. Sign up at developer.trafiklab.se
  2. Create a project
  3. Enable the API products you need:
    • Trafiklab Realtime APIs → for trafiklab_search_stops, trafiklab_get_departures, trafiklab_get_arrivals
    • GTFS Sweden 3 Realtime → for gtfs_service_alerts, gtfs_trip_updates, gtfs_vehicle_positions, combined_nearby_vehicles
  4. Copy each API key

2. Try it out

To interactively test tools in a web UI, use the MCP Inspector:

# From the repo root
bun run --filter @transit-se/mcp inspect

3. Configure your MCP client

Add the server to your MCP client configuration. Both keys are optional — without them, only the SL tools (Stockholm) are available.

Via npx (recommended)

No installation needed — npx downloads and runs the package automatically. Works with any MCP client that supports the command + args format.

  • Claude Desktop — edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows).
  • Claude Code — add to .mcp.json in your project root or ~/.claude/settings.json.
  • Cursor — add to .cursor/mcp.json in your project root:
{
  "mcpServers": {
    "transit-se": {
      "command": "npx",
      "args": ["-y", "@transit-se/mcp"],
      "env": {
        "TRAFIKLAB_API_KEY": "your-key-here",
        "TRAFIKLAB_GTFS_KEY": "your-key-here"
      }
    }
  }
}

From source (for development)

If you've cloned the repo and want to run from source:

{
  "mcpServers": {
    "transit-se": {
      "command": "node",
      "args": ["/absolute/path/to/packages/mcp/dist/index.js"],
      "env": {
        "TRAFIKLAB_API_KEY": "your-key-here",
        "TRAFIKLAB_GTFS_KEY": "your-key-here"
      }
    }
  }
}

Build first with bun run --filter @transit-se/mcp build.


Available Tools

SL tools (no API key required)

| Tool | Description | Key Parameters | | --------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | | sl_departures | Stockholm (SL) departures | site_id: SL site ID (e.g. 9192), forecast?: minutes, direction?: 1 or 2, line?: line ID, transport?: METRO/BUS/etc. | | sl_sites | Search SL stations (cached) | query?: station name | | sl_deviations | Service disruptions and alerts | transport_modes?: e.g. ["METRO"], line_ids?, site_ids?, future? |

Trafiklab tools (require TRAFIKLAB_API_KEY)

| Tool | Description | Key Parameters | | -------------------------- | -------------------- | --------------------------------------------- | | trafiklab_search_stops | Search stops by name | query: stop name (e.g. "T-Centralen") | | trafiklab_get_departures | Real-time departures | area_id: stop ID, time?: YYYY-MM-DDTHH:mm | | trafiklab_get_arrivals | Real-time arrivals | area_id: stop ID, time?: YYYY-MM-DDTHH:mm |

GTFS tools (require TRAFIKLAB_GTFS_KEY)

| Tool | Description | Key Parameters | | ------------------------ | -------------------------------------------------------- | ---------------------------------------------------- | | gtfs_service_alerts | Service alerts for any Swedish operator (GTFS-RT) | operator: e.g. "ul" (Uppsala), "skane" (Skåne) | | gtfs_trip_updates | Real-time trip delays and cancellations for any operator | operator: e.g. "ul" (Uppsala), "skane" (Skåne) | | gtfs_vehicle_positions | Real-time GPS positions for vehicles in service | operator: e.g. "ul" (Uppsala), "skane" (Skåne) |

Note: For Stockholm (SL) disruptions, prefer sl_deviations — it provides richer data and requires no API key.

Combined tools (require TRAFIKLAB_GTFS_KEY)

| Tool | Description | Key Parameters | | -------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | combined_nearby_vehicles | Find vehicles near a Stockholm location with transport mode classification | site_name?, site_id?, latitude?+longitude?, radius_km? (0–20, default 1.0) |

Combines GTFS-RT vehicle positions with SL stop point data to classify each vehicle as metro, bus, tram, train, ferry, or ship.

Location resolution — provide exactly one of these (if multiple are given, precedence is site_id > site_name > latitude+longitude):

  • site_name — SL station name (e.g. "Solna centrum"), resolved via cached site data
  • site_id — SL site ID (e.g. 9305), use sl_sites to find IDs
  • latitude + longitude — raw coordinates; the nearest SL site is auto-detected

SDK methods not exposed as MCP tools

The following SDK methods are available for programmatic use but intentionally excluded from the MCP server. They return bulk data that is useful for apps (UI lists, caches) but wasteful for AI agents, which reason better with focused, filtered results.

| SDK Method | Why not exposed | | ------------------------------ | --------------------------------------------------------------------------- | | sl.getLines() | Returns all SL lines. Departures already include line info per station. | | sl.getSites() | Full site response. sl_sites uses the cached/lightweight version instead. | | sl.getStopPoints() | Bulk stop point data. Useful for maps, not for agent queries. | | sl.getTransportAuthorities() | Admin metadata. No agent use case. | | stops.listAll() | Returns thousands of stops. Use trafiklab_search_stops to search by name. |

Typical workflow

The AI will typically chain tools like this:

  1. User: "When does the next train leave from Slussen?"
  2. AI calls sl_sites with query: "Slussen" → gets site ID 9192
  3. AI calls sl_departures with site_id: 9192 → gets real-time departures
  4. AI responds with formatted departure information

Environment Variables

| Variable | Trafiklab product | Required | Description | | -------------------- | ----------------------- | -------- | ------------------------------------------------------------------------------------------ | | TRAFIKLAB_API_KEY | Trafiklab Realtime APIs | No | Stop lookup, departures, arrivals. Without it, only the SL tools work. | | TRAFIKLAB_GTFS_KEY | GTFS Sweden 3 Realtime | No | GTFS-RT feeds (service alerts, trip updates, vehicle positions, nearby vehicles). | | TRAFIKLAB_VALIDATE | — | No | Set to "true" to enable runtime response validation via Valibot schemas. Off by default. |

Without API Keys

If no API keys are set, the server still starts and registers all tools. The 3 SL tools work normally. The Trafiklab and GTFS tools return helpful messages explaining how to get and configure keys.


Development

Build

The MCP server is compiled to JavaScript for Node.js compatibility, so it can be run via npx without requiring Bun.

# Build the MCP package (compiles src/ → dist/)
bun run --filter @transit-se/mcp build

# Build is also run automatically before npm publish via prepublishOnly

Type-check

# Type-check just the MCP package
bun run --filter @transit-se/mcp tc

# Type-check everything (SDK + MCP)
bun run tc

Run tests

# All tests (SDK + MCP)
bun test

# MCP tests only
bun test packages/mcp/

Lint

bun run lint

Format

bun run format

How It Works

┌─────────────────┐    stdio     ┌──────────────────┐    HTTPS    ┌──────────────┐
│  Claude / IDE   │ ◄──────────► │  @transit-se/mcp │ ──────────► │  Trafiklab   │
│  (MCP Client)   │   JSON-RPC   │  (this package)  │   REST API  │  APIs        │
└─────────────────┘              └──────────────────┘             └──────────────┘
                                        │
                                        ▼
                                 @transit-se/sdk
                                 (TransitClient)

The MCP server is a thin bridge between AI assistants and the transit APIs:

  1. MCP Client (Claude, Cursor, etc.) discovers the available tools via the MCP protocol
  2. Tool calls arrive as JSON-RPC messages over stdin
  3. This server validates parameters (via Zod schemas), calls the appropriate SDK method, and formats the response as human-readable text
  4. Formatted results go back to the AI, which uses them to answer the user

Why formatted text instead of raw JSON?

AI assistants work better with concise, structured text than massive JSON blobs. The formatters turn API responses into clean departure boards and station lists that the model can reason about efficiently.


Project Structure

packages/mcp/
├── src/
│   ├── index.ts                              # Server entry — creates McpServer, registers tools, connects stdio
│   ├── index.test.ts                         # Server integration tests
│   ├── formatting.ts                         # Human-readable output formatters
│   ├── formatting.test.ts                    # Formatter tests
│   └── tools/
│       ├── sl/
│       │   ├── transport.ts                  # sl_departures, sl_sites
│       │   ├── transport.test.ts
│       │   ├── deviations.ts                 # sl_deviations
│       │   └── deviations.test.ts
│       ├── trafiklab/
│       │   ├── stop-lookup.ts                # trafiklab_search_stops
│       │   ├── stop-lookup.test.ts
│       │   ├── timetables.ts                 # trafiklab_get_departures, trafiklab_get_arrivals
│       │   └── timetables.test.ts
│       ├── gtfs/
│       │   ├── operators.ts                  # Shared GTFS operator list (re-exported from SDK)
│       │   ├── service-alerts.ts             # gtfs_service_alerts
│       │   ├── service-alerts.test.ts
│       │   ├── trip-updates.ts               # gtfs_trip_updates
│       │   ├── trip-updates.test.ts
│       │   ├── vehicle-positions.ts          # gtfs_vehicle_positions
│       │   └── vehicle-positions.test.ts
│       └── combined/
│           ├── nearby-vehicles.ts            # combined_nearby_vehicles
│           └── nearby-vehicles.test.ts
├── package.json
├── tsconfig.json
└── README.md                                 # This file

License

MIT