caltopo-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@caltopo-mcplist my maps"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
caltopo-mcp
HTTP MCP server for managing CalTopo maps from headless agents.
This server is designed for a Hermes/Codex-style agent that needs to list maps, create folders, manage markers, and import/export GPX/KML without using a browser session.
Status
Uses CalTopo private-account activation credentials.
Does not require Chrome, Playwright, a desktop login, or a UI session.
Runs as a normal headless Node.js process.
Exposes a local HTTP MCP endpoint.
Tested against a private CalTopo account for read/write marker and folder operations.
CalTopo does not publicly document this private-account API for general third-party use. Treat the integration as pragmatic and test bulk writes on disposable maps first.
Related MCP server: mapbox-mcp-server
Repository
Canonical repository:
https://github.com/sttts/caltopo-mcpDo not commit local credentials. Runtime secrets belong in .data/, environment variables, or a local secret manager.
Features
Account auth check
Map listing
Raw map data retrieval
Folder list/create/update/delete
Marker list/create/update/delete
GPX waypoint import as CalTopo markers
KML point placemark import as CalTopo markers
GPX/KML marker export
Optional Bearer token on the MCP endpoint
macOS LaunchDaemon template for headless operation
Requirements
Node.js 22 or newer
npm
A CalTopo account
CalTopo activation credentials
On the Hermes Mac mini, the bundled Node runtime is expected at:
/Users/hermes/.hermes/node/bin/nodeCredentials
The server supports two credential modes.
Activation File
Preferred for local operation:
CALTOPO_ACTIVATION_FILE=.data/activation.local.jsonThe activation file has this shape:
{
"account": {
"id": "..."
},
"code": "...",
"key": "..."
}Keep the file outside Git:
mkdir -p .data
chmod 700 .data
chmod 600 .data/activation.local.json.data/ is ignored by Git.
Environment Variables
Alternative for service managers or secret stores:
CALTOPO_ACCOUNT_ID=...
CALTOPO_CREDENTIAL_ID=...
CALTOPO_CREDENTIAL_KEY=...Never hardcode these values in source files, plist files, shell scripts, README examples, or committed config.
Getting Activation Credentials
Open an activation URL in a browser where you are logged in to CalTopo:
https://caltopo.com/app/activate/localhost/client/finish-activate?code=<CODE>&name=mcpThen resolve the code locally:
CALTOPO_ACTIVATION_CODE=<CODE> python3 - <<'PY'
import os
import urllib.request
code = os.environ["CALTOPO_ACTIVATION_CODE"]
path = ".data/activation.local.json"
os.makedirs(".data", exist_ok=True)
with urllib.request.urlopen(f"https://caltopo.com/api/v1/activate?code={code}", timeout=20) as response:
data = response.read()
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
with os.fdopen(fd, "wb") as handle:
handle.write(data)
print(f"wrote {path}")
PYLocal Development
npm install
npm run typecheck
npm run build
CALTOPO_ACTIVATION_FILE=.data/activation.local.json npm startDefault endpoint:
http://127.0.0.1:8788/mcpHealth check:
curl -sS http://127.0.0.1:8788/healthThe health endpoint intentionally does not return credential values or account IDs.
Configuration
Environment variables:
CALTOPO_ACTIVATION_FILE=.data/activation.local.json
CALTOPO_ACCOUNT_ID=...
CALTOPO_CREDENTIAL_ID=...
CALTOPO_CREDENTIAL_KEY=...
CALTOPO_DOMAIN=caltopo.com
CALTOPO_MCP_HOST=127.0.0.1
CALTOPO_MCP_PORT=8788
CALTOPO_MCP_TOKEN=optional-bearer-tokenCALTOPO_MCP_TOKEN protects the MCP endpoint with:
Authorization: Bearer <token>Keep the server bound to 127.0.0.1 unless you also configure authentication and network-level access control.
MCP Tools
caltopo_auth_statuscaltopo_list_mapscaltopo_get_mapcaltopo_list_folderscaltopo_create_foldercaltopo_update_foldercaltopo_delete_foldercaltopo_list_markerscaltopo_create_markercaltopo_update_markercaltopo_delete_markercaltopo_import_markerscaltopo_export_markers
Example Tool Payloads
Create a marker:
{
"map_id": "ABCDE12",
"title": "Camp",
"lat": 65.90993,
"lon": -23.84598,
"description": "Overnight stop",
"color": "#00AAFF",
"symbol": "point"
}Import GPX waypoints:
{
"map_id": "ABCDE12",
"format": "gpx",
"content": "<?xml version=\"1.0\"?><gpx><wpt lat=\"65.9\" lon=\"-23.8\"><name>Test</name></wpt></gpx>",
"dry_run": true
}Use dry_run: true before bulk imports.
Headless Service Scripts
Manual operation:
bin/start-caltopo-mcp.sh
bin/status-caltopo-mcp.sh
bin/stop-caltopo-mcp.shDo not use cron for this service. On macOS, use the LaunchDaemon in deploy/local.caltopo-mcp.plist if the server must survive reboots without an active UI login.
Hermes Deployment
Recommended layout on the Mac mini:
/Users/hermes/Quellen/caltopo-mcp
/Users/hermes/Quellen/caltopo-mcp/.data/activation.local.jsonClone and build:
cd /Users/hermes/Quellen
git clone https://github.com/sttts/caltopo-mcp.git caltopo-mcp
cd caltopo-mcp
PATH=/Users/hermes/.hermes/node/bin:$PATH npm install
PATH=/Users/hermes/.hermes/node/bin:$PATH npm run buildStart manually:
cd /Users/hermes/Quellen/caltopo-mcp
bin/start-caltopo-mcp.shRegister with Hermes:
/Users/hermes/.local/bin/hermes mcp add caltopo --url http://127.0.0.1:8788/mcp
/Users/hermes/.local/bin/hermes mcp test caltopomacOS LaunchDaemon
For reboot-safe headless operation, install the LaunchDaemon as root:
cd /Users/hermes/Quellen/caltopo-mcp
sudo bin/install-launchdaemon.shThe plist runs the process as hermes:
/Library/LaunchDaemons/local.caltopo-mcp.plistCheck the service:
launchctl print system/local.caltopo-mcp
bin/status-caltopo-mcp.sh
/Users/hermes/.local/bin/hermes mcp test caltopoRemove it:
sudo launchctl bootout system /Library/LaunchDaemons/local.caltopo-mcp.plist
sudo rm -f /Library/LaunchDaemons/local.caltopo-mcp.plistUpdating
cd /Users/hermes/Quellen/caltopo-mcp
git pull --ff-only
PATH=/Users/hermes/.hermes/node/bin:$PATH npm install
PATH=/Users/hermes/.hermes/node/bin:$PATH npm run build
bin/stop-caltopo-mcp.sh
bin/start-caltopo-mcp.shIf the LaunchDaemon is installed:
sudo launchctl kickstart -k system/local.caltopo-mcpSecurity Checklist
.data/is ignored by Git.Activation credentials are not present in source files.
The health endpoint does not expose account IDs or credential metadata.
The default bind address is
127.0.0.1.Use
CALTOPO_MCP_TOKENbefore exposing the endpoint beyond loopback.Prefer
dry_runfor imports before writing many markers.
Before publishing:
git status --short
git ls-files
rg -n "activation\\.local|CALTOPO_CREDENTIAL|credentialKey|Bearer|token|gmail|account_id" . \
-g '!node_modules' -g '!dist' -g '!.data' -g '!.git'This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/sttts/caltopo-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server