[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "swiss-transport-mcp" version = "0.4.0" description = "MCP server for Swiss public transport – OJP journey planner, real-time departures, disruptions, occupancy, ticket prices, train formations and open data from opentransportdata.swiss" readme = "README.md" license = { file = "LICENSE" } requires-python = ">=3.11" keywords = [ "mcp", "model-context-protocol", "swiss-transport", "ojp", "public-transport", "sbb", "open-data", "gtfs", "real-time", "switzerland", "zurich", "education", "siri-sx", "disruptions", "occupancy", "train-formation", "fare", ] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Scientific/Engineering :: GIS", ] dependencies = [ # ARCH-012: cap the MCP SDK major version to avoid unreviewed protocol / # API drift; bump deliberately after testing against a new major. # Now on the 2.x API (`mcp.server.mcpserver`). The floor is hard: 2.0.0 # removed `mcp.server.fastmcp` with no compatibility shim, so this code # cannot run on 1.x — a `>=1.x` range would let a resolver pick a version # that fails at import. # Existing clients see no difference: the legacy `initialize` handshake # still caps at 2025-11-25. mcp 2.x additionally serves a "modern" # per-request envelope era reaching 2026-07-28, so a 2.x-aware client # negotiates the newer revision. Not a break, but not a no-op either. "mcp[cli]>=2.0.0,<3", "httpx>=0.27.0,<1.0.0", "pydantic>=2.0.0,<3.0.0", ] [project.optional-dependencies] dev = [ "pytest>=8.0.0", "pytest-asyncio>=0.23.0", "pytest-cov>=5.0.0", "respx>=0.21.0", # Exakt gepinnt, nicht `>=`: ruff ist ein Gate, kein Hilfsmittel. Eine # neuere Version meldet Abweichungen an Code, den niemand angefasst hat. # Der Pin steht hier und nur hier — die CI installiert ihn ueber # `pip install -e ".[dev]"` mit und hat keinen eigenen Pin-Schritt mehr. # Beim Anheben: Version aendern, `ruff format` einmal ueber src/ tests/ # scripts/ laufen lassen und das Ergebnis mit committen. "ruff==0.16.5", ] # OBS-006: opt-in OpenTelemetry tracing. Enable at runtime with # OTEL_TRACES_ENABLED=1. Without this extra, tracing is a no-op. otel = [ "opentelemetry-sdk>=1.20.0,<2.0.0", ] [project.scripts] swiss-transport-mcp = "swiss_transport_mcp.server:main" [project.urls] Homepage = "https://github.com/malkreide/swiss-transport-mcp" Repository = "https://github.com/malkreide/swiss-transport-mcp" Issues = "https://github.com/malkreide/swiss-transport-mcp/issues" [tool.hatch.build.targets.wheel] packages = ["src/swiss_transport_mcp"] [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] addopts = "-v --tb=short" markers = [ "live: live API tests (skipped in CI by default)", ] [tool.ruff] line-length = 100 target-version = "py311" [tool.ruff.lint] select = ["E", "F", "W", "I", "UP"] ignore = ["E501"]