Back to Discover

openchargemap-mcp-server

connector

cyanheads

Find EV charging stations, detail, and reliability check-ins via the global Open Charge Map.

View on GitHub
0 starsSynced Aug 6, 2026

Install to Claude Code

/plugin marketplace add cyanheads/openchargemap-mcp-server

README

@cyanheads/openchargemap-mcp-server

Find EV charging stations worldwide by location and connector via the global Open Charge Map registry — full station detail, reference-ID resolution, and community reliability check-ins via MCP. STDIO or Streamable HTTP.

4 Tools • 1 Resource

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework


Tools

Four tools across the find-and-detail surface — search, detail, offline ID resolution, and the community reliability layer:

ToolDescription
openchargemap_find_stationsFind charging stations near a point or within a bounding box, filtered by connector, power, network, usage, status, and charge points. Coordinate-native.
openchargemap_get_stationFull record for one station by numeric OCM ID — every connection, operator, access rules, charge points, cost, media, and a computed reliability note.
openchargemap_lookup_referenceResolve connector/operator/usage/status/country names to the integer filter IDs find_stations needs. Served from a bundled snapshot — offline and instant.
openchargemap_get_station_commentsCommunity check-ins for one station alongside the registry status and last-verified date, so registry-vs-reality mismatch is visible.

openchargemap_find_stations

The workhorse. Search the global registry by location, then narrow with filters.

  • Radius search (latitude + longitude + distance, in KM or Miles) or boundingbox — exactly one mode per call. A boundingbox sent alongside a latitude or a longitude is rejected rather than searched with the coordinate quietly dropped
  • Optional country scope via ISO 3166-1 alpha-2 countrycode; global by default, no implicit country
  • Filters: connector type, minimum power (kW), operator/network, usage type, charge level, operational status, minimum charge points — all integer IDs, single or OR-matched arrays
  • Resolve a connector or network name to its filter ID with openchargemap_lookup_reference first (e.g. "CCS"33)
  • Each result carries title, address, distance, connections (type/power/current/count), operator, access rules, registry status, and dateLastVerified
  • maxresults caps the page (default 25, max 200), ordered by distance. A truncated page reports nextOffset; pass it back as offset for the next page. OCM has no offset parameter of its own, so paging runs over an over-fetched candidate page — reachable depth is 500 stations per search (offset 0–499), and totalCount is what the search retrieved rather than a registry-wide total (OCM publishes none). It is exact only when the candidate page came back short of its cap; otherwise it is a floor, and the notice says so
  • Local filters (minchargepoints, and the drop of OCM's 0,0 coordinate sentinels) run over that whole candidate page, so a match ranked past maxresults is not lost and a page emptied by filtering is reported as truncated, not as "no stations"
  • Coordinate-native — does not geocode place names. Resolve a place like "Ballard, Seattle" to coordinates with a geocoding server (e.g. the openstreetmap MCP server's openstreetmap_geocode) first, then pass them here

openchargemap_get_station

Full detail for one station by its numeric OCM ID (fetched with verbose=true).

  • Every connection: type, level, power, current, amperage, voltage, quantity
  • Operator and network, usage and access restrictions (pay-at-location, membership, access key), number of charge points
  • General comments, usage cost, data provider, submitted media, verification recency
  • Optional inline community check-ins with includeComments
  • Computes a plain-prose reliabilityNote from observable facts (verification age, registry status, operational flag, fault-vs-positive check-in counts) — no synthetic score; omitted when status is fresh and uncontested
  • A status of "Temporarily Unavailable" or "Partly Operational (Mixed)" raises a caveat of its own — OCM flags both operational, so the flag alone would read as all-clear on a station the operator has said is down
  • Obtain an ID from openchargemap_find_stations. UUID lookup is not supported by the OCM API.

openchargemap_lookup_reference

Resolve Open Charge Map reference data to the integer IDs the find_stations filters require — served from a bundled snapshot, so it makes no network call (offline, instant).

  • Categories: connectiontypes, operators, usagetypes, statustypes, currenttypes, levels, countries
  • Pass a query to resolve a name, title, code, or alias ("CCS", "Tesla Supercharger", "ChargePoint", "Public - Pay At Location", "France", "FR") — case-insensitive, matched on title, formal name, and curated connector aliases
  • Omit the query to browse the whole category (up to limit, max 100). Browsing and querying both page: totalCount is the full match count, and a truncated page reports nextOffset to pass back as offset — every entry in a large category like operators (974) or countries (250) is reachable
  • Returns the matching id(s) plus the filterParam they feed and the vintage of the data actually served — snapshotDate with a source of live or bundled, so a fresh fetch is never mistaken for a freshly cut bundle
  • An optional startup refresh keeps the snapshot from drifting — see OPENCHARGEMAP_REFERENCE_REFRESH below. When it succeeds, source is live and snapshotDate is the day it ran; when it is off or it failed, source is bundled and the date is the bundle's own

openchargemap_get_station_comments

Community check-ins for one station — the honest reliability signal beyond the operator-reported registry flag.

  • Returns user comments and fault reports with ratings, dates, and the recorded check-in outcome ("Charged Successfully", "Failed to Charge (Equipment Not Operational)", …), newest first (maxresults caps the page, max 100)
  • One POI fetch carries every comment the station has, so totalCount is exact and offset (paired with the nextOffset a truncated page reports) reads the rest without a further upstream call
  • Every count states its population: totalComments is the station's whole set, the rendered header reads 2 of 6 comment(s) when a page is only part of it, and reliabilityNote's fault ratio is counted over the whole set so it does not move with maxresults
  • The check-in outcome is the charge-attempt result and drives fault detection — a failed charge counts even when it was filed as a plain comment
  • Surfaces the station's registry status, operational flag, and dateLastVerified alongside the comments so you can flag mismatches like "listed operational, but recent check-ins report a fault"
  • An empty result is not an error — a station with no check-ins returns comments: []; absence of reports is not evidence the charger works
  • Backed by the POI fetch with includecomments=true (OCM has no standalone comments endpoint)
  • Obtain a station ID from openchargemap_find_stations

Resource

TypeNameDescription
Resourceopenchargemap://station/{id}Full station record (with community comments) by numeric OCM ID — the URI-addressable twin of openchargemap_get_station.

All station data is also reachable via the tools. The station corpus (~200k locations, geo-scoped) is not exposed as a listable resource — discover stations with openchargemap_find_stations. Reference data is a resolve surface, not a stable-by-URI record, so it is served by openchargemap_lookup_reference rather than a resource.

Features

Built on @cyanheads/mcp-ts-core:

  • Declarative tool and resource definitions — single file per primitive, framework handles registration and validation
  • Unified error handling — handlers throw, framework catches, classifies, and formats; typed error contracts with recovery hints
  • Pluggable auth: none, jwt, oauth
  • Swappable storage backends: in-memory, filesystem, Supabase, Cloudflare KV/R2/D1
  • Structured logging with optional OpenTelemetry tracing
  • STDIO and Streamable HTTP transports

Open Charge Map–specific:

  • Type-safe client for the OCM v3 POI API with retry and session-scoped result caching
  • Reference data (connectors, operators, usage/status types, countries) bundled as an offline snapshot — name→ID resolution needs no live /referencedata call, with an optional startup refresh to prevent drift
  • Curated connector aliases (CCS, NACS/Supercharger, J1772, Type 2, CHAdeMO) so the names agents actually use resolve to the right IDs
  • Geocoding intentionally delegated — the server is coordinate-native and composes with any geocoding MCP server rather than rebuilding place-name lookup

Agent-friendly output:

  • Reliability surfaced as first-class signal — status, statusTypeId, isOperational, and dateLastVerified on every station, plus a plain-prose reliabilityNote derived only from observable facts (no fabricated confidence score). Upstream values are passed through verbatim; where a status contradicts its own operational flag, the judgment lives in the note and the rendered text, never in the boolean
  • Honest sparsity — heavily-omitted upstream fields are optional with "absence means unknown, not zero/false" descriptions; the server never invents data OCM didn't return. An explicit false is a fact and reaches the text output, not just structuredContent
  • CC BY 4.0 attribution on every tool response and in the server-level instructions, per the data license

Getting started

Public Hosted Instance

A public instance is available at https://openchargemap.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP, with this client config:

{
  "mcpServers": {
    "openchargemap-mcp-server": {
      "type": "streamable-http",
      "url": "https://openchargemap.caseyjhand.com/mcp"
    }
  }
}

Local / self-hosted

Add the following to your MCP client configuration file. An Open Charge Map API key is required — see Prerequisites.

{
  "mcpServers": {
    "openchargemap-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/openchargemap-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "OPENCHARGEMAP_API_KEY": "your-api-key"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "openchargemap-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/openchargemap-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "OPENCHARGEMAP_API_KEY": "your-api-key"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "openchargemap-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "-e", "OPENCHARGEMAP_API_KEY=your-api-key",
        "ghcr.io/cyanheads/openchargemap-mcp-server:latest"
      ]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 OPENCHARGEMAP_API_KEY=... bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.3 or higher (or Node.js v24+).
  • An Open Charge Map API key — free instant signup: register an application at openchargemap.org. Sent as the X-API-Key header on every request; the server fails fast at startup if it's unset.

Installation

  1. Clone the repository:
git clone https://github.com/cyanheads/openchargemap-mcp-server.git
  1. Navigate into the directory:
cd openchargemap-mcp-server
  1. Install dependencies:
bun install
  1. Configure environment:
cp .env.example .env
# edit .env and set OPENCHARGEMAP_API_KEY

Configuration

All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:

VariableDescriptionDefault
OPENCHARGEMAP_API_KEYRequired. Open Charge Map API key, sent as the X-API-Key header. Free signup at openchargemap.org.
OPENCHARGEMAP_BASE_URLOCM API base URL. Override for a private mirror or testing.https://api.openchargemap.io/v3
OPENCHARGEMAP_REFERENCE_REFRESHWhen true, refresh reference data from the live /referencedata endpoint at startup, falling back to the bundled snapshot on failure. When false, stay fully offline on the bundled snapshot.false
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTPort for the HTTP server.3010
MCP_AUTH_MODEAuth mode: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (RFC 5424).info
LOGS_DIRDirectory for log files (Node.js only).<project-root>/logs
STORAGE_PROVIDER_TYPEStorage backend.in-memory
OTEL_ENABLEDEnable OpenTelemetry instrumentation (spans, metrics, completion logs).false

See .env.example for the full list of optional overrides.

Running the server

Local development

  • 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, changelog sync
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against spec
    

Docker

docker build -t openchargemap-mcp-server .
docker run --rm -e OPENCHARGEMAP_API_KEY=your-key -p 3010:3010 openchargemap-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/openchargemap-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers tools/resources and inits services.
src/configServer-specific environment variable parsing and validation with Zod.
src/dataBundled Open Charge Map reference snapshot (ocm-reference-data.ts) — the offline source for ID resolution.
src/mcp-server/toolsTool definitions (*.tool.ts) plus the shared station schema and renderers.
src/mcp-server/resourcesResource definitions (*.resource.ts).
src/services/openchargemapOCM POI API client, response normalization, attribution, and the reliability-note helper.
src/services/reference-dataReference-data service — snapshot loading, lookup indices, curated aliases, optional live refresh.
tests/Unit and integration tests mirroring src/.

Development guide

See AGENTS.md (and CLAUDE.md) for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • Register new tools and resources in the createApp() arrays
  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Attribution and data license

Charging-station, connector, and operator data is sourced from Open Charge Map, the community-maintained global registry of EV charging locations, and is licensed under CC BY 4.0.

Station data © Open Charge Map contributors, licensed under CC BY 4.0 (openchargemap.org).

Attribution is mandatory: every tool response carries this attribution string, and the server restates it in its session-level instructions. Any downstream use of the data must credit Open Charge Map and its contributors. This server's own code is Apache-2.0 (below); the license terms above apply to the data, not the software.

Contributing

Issues and pull requests are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details. Open Charge Map data carries its own license; see Attribution and data license.

Rendered live from cyanheads/openchargemap-mcp-server's GitHub README — not stored, always reflects the source repo.

3 Install Methods

NameDescriptionCategorySource
npm packageInstall via npm (stdio transport)mcp-server@cyanheads/openchargemap-mcp-server
npm packageInstall via npm (streamable-http transport)mcp-server@cyanheads/openchargemap-mcp-server
streamable-http remoteHosted streamable-http endpointmcp-serverhttps://openchargemap.caseyjhand.com/mcp

0 Comments

Login required
Log in to post a comment or update on this repo.

No comments yet — be the first to share an update.