github Python re-analysis due

malkreide/swisstopo-mcp

github

MCP server for Swiss federal geodata (Swisstopo APIs) — 13 tools for geocoding, height, STAC, WMTS, ÖREB and more

maintainer
malkreide
license
MIT
first seen
2026-06-04
last seen
2026-08-24
releases · 30d
2
short id

Drift inferred · capture-to-capture

tool count over time

06-04 15:22 now
13t
25t
capabilities 25 tools
transport stdio · streamable-http · http verified reported listed in the official MCP registry counts 25 tools · 0 res · 0 prompts permission surface via README inference

tools

  • feature_by_id

    Give me this one feature in full, with geometry

  • features_at_point

    What is at this coordinate?

  • features_by_attribute

    Which features carry this value? (e.g. buildings by EGID)

  • layer_info

    What fields can I query on this layer, and what is its legend?

  • operation

    Answers

  • search_layers

    Which layers exist for a keyword? (500+ catalogue)

  • swisstopo_convert_coordinates

    Official WGS84 ↔ LV95 conversion via the swisstopo REFRAME service

  • swisstopo_elevation_profile

    Compute an elevation profile along a line

  • swisstopo_find_commune

    Resolve a commune both directions (name ↔ bfs_number) or list all communes of a canton / district. Accepts canton abbreviation (ZH) or key (1); resolution happens server-side

  • swisstopo_geocode

    Convert Swiss addresses, place names, or postal codes to coordinates

  • swisstopo_get_collection

    Get details and download links for a STAC collection

  • swisstopo_get_egrid

    Resolve a cadastral property ID (EGRID) from coordinates

  • swisstopo_get_height

    Get elevation above sea level (m a.s.l.) at a coordinate

  • swisstopo_get_oereb_extract

    Retrieve public-law land-use restrictions (OEREB) for a parcel

  • swisstopo_list_available_layers

    Discover layer keys for swisstopo_query_geodata (strassenverzeichnis, oereb-verfuegbarkeit, geodienste:<topic>:<canton>); filters to contract-free geodienste datasets

  • swisstopo_lookup_postal_code

    Resolve a Swiss postal code → locality, commune (+BFS number), district, canton

  • swisstopo_map_query

    The national map catalogue (api3.geo.admin.ch). One operation per call — see the five below

  • swisstopo_map_url

    Generate a map.geo.admin.ch URL for browser display

  • swisstopo_municipality_at

    Municipality, canton and official BFS number at a coordinate

  • swisstopo_query_geodata

    Query a chosen layer by point / bbox / commune — amtliches Strassenverzeichnis, interkantonale geodienste.ch data (OGC API Features), or ÖREB availability

  • swisstopo_query_osm_features

    OpenStreetMap POIs (schools, playgrounds, pharmacies, …) around a point via Overpass — separate source, ODbL (© OpenStreetMap contributors)

  • swisstopo_reverse_geocode

    Find the nearest address for given coordinates

  • swisstopo_search_address

    Full-text search over Swiss streets and localities, returning commune + BFS number per hit

  • swisstopo_search_geodata

    Search the STAC catalog for downloadable geodatasets

  • swisstopo_zoning_at

    Harmonised building zone at a coordinate — one call, no layer lookup (not legally binding)

skills & danger signals github-tarball
prompt-surface shipped agent-instruction files + hidden-content / dangerous-code findings — quoted from the analyzed source

analyzed commit a1e3b6f · analyzer v33 · 1w ago

danger signals2

code evidence vv0.4.1 · github-tarball
evidence-backed findings quoted directly from the published source artifact — not inferred

code files: 59

filesystem 14

  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/scripts/check_version_sync.py :35 from pathlib import Path
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/scripts/record_fixtures.py :45 from pathlib import Path
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/scripts/render_egress_acl.py :15 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/scripts/snapshot_tool_hashes.py :22 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/fixture_data.py :3 Ein Loader statt `open()` an jeder Stelle: so gibt es genau einen Ort, der weiss,
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_context.py :304 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_deploy_manifests.py :26 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_egress_allowlist.py :166 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_empty_results.py :21 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_live_coverage.py :22 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_responses.py :211 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_tool_hygiene.py :301 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_tool_namespace.py :16 import pathlib
  • fs (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_version.py :12 from pathlib import Path

shell / exec 2

  • shell (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_live_coverage.py :199 import subprocess
  • shell (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_tool_namespace.py :17 import subprocess

network 29

  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/scripts/record_fixtures.py :48 import httpx
  • net malkreide-swisstopo-mcp-a1e3b6f/src/swisstopo_mcp/api_client.py :8 import socket
  • net malkreide-swisstopo-mcp-a1e3b6f/src/swisstopo_mcp/observability.py :29 from urllib.parse import urlsplit, urlunsplit
  • net malkreide-swisstopo-mcp-a1e3b6f/src/swisstopo_mcp/oereb.py :6 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/conftest.py :9 `httpx.AsyncHTTPTransport` — which is precisely the layer `respx` patches. With
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/fixture_data.py :30 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_api_client.py :4 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_context.py :91 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_coords.py :6 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_deploy_manifests.py :345 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_dns_pinning.py :25 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_egress_allowlist.py :6 import socket
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_geocoding.py :267 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_geodata.py :6 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_height.py :237 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_http_app.py :6 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_lv95_input.py :11 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_observability.py :189 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_oereb.py :6 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_openplz.py :7 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_overpass.py :8 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_places.py :11 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_protocol_version.py :78 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_recorded_fixtures.py :33 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_rest_api.py :345 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_retry.py :6 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_retry_policy.py :12 import httpx
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_shared_client.py :2 """Regression tests for SDK-001: shared httpx.AsyncClient reuse via lifespan."""
  • net (weak) malkreide-swisstopo-mcp-a1e3b6f/tests/test_stac.py :314 import httpx

declared dependencies 16

  • mcp@>=2.0.0,<3
  • httpx@>=0.27.0
  • pydantic@>=2.0.0
  • pydantic-settings@>=2.0.0
  • structlog@>=24.1.0,<27
  • opentelemetry-api@>=1.27.0
  • opentelemetry-sdk@>=1.27.0
  • opentelemetry-exporter-otlp@>=1.27.0
  • opentelemetry-instrumentation-httpx@>=0.48b0
  • pytest@>=8.0.0
  • pytest-asyncio@>=0.23.0
  • pytest-cov@>=5.0.0
  • respx@>=0.21.0
  • ruff@>=0.4.0,<0.17
  • mypy@>=1.10.0
  • PyYAML@>=6.0