Odel
openchargemap mcp server

openchargemap mcp server

@cyanheadsDeveloper Tools1TypeScriptApache-2.0Updated 6 days ago

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

Server endpointStreamable HTTPNo authProbed

This is the third-party server itself — Odel doesn't run it. Hitting this URL directly talks straight to the upstream server with no auth or proxying. Connect through Odel to front it with managed auth.

@cyanheads/openchargemap-mcp-server

Find EV charging stations by location and connector, get full station detail, resolve reference IDs, and read 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
  • 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 set (default 25, max 200), ordered by distance; truncation is disclosed when the cap is hit
  • 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, operational flag, fault-vs-positive comment counts) — no synthetic score; omitted when status is fresh and uncontested
  • 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)
  • Returns the matching id(s) plus the filterParam they feed and the snapshot vintage (snapshotDate)
  • An optional startup refresh keeps the snapshot from drifting — see OPENCHARGEMAP_REFERENCE_REFRESH below

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 and dates, newest first (maxresults caps, max 100)
  • 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, isOperational, and dateLastVerified on every station, plus a plain-prose reliabilityNote derived only from observable facts (no fabricated confidence score)
  • 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
  • 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.