K-Stra developers

MCP server

K-Stra is also a Model Context Protocol server: connect Claude, ChatGPT, an IDE agent or any MCP client to https://www.k-stra.com/mcp and it can search addresses, draw catchments, quote and run analyses, and read saved results — with the same API key and the same rules as the REST API.

Endpoint https://www.k-stra.com/mcp
Transport Streamable HTTP, stateless (no session id, every request stands alone)
Authentication Authorization: Bearer ks_live_… — the key from Account → API
Tools, resources generated from the action registry on every request: the same schemas as /api/v1

Connect

Clients that take a remote server as URL plus headers (Claude Code, Cursor, VS Code, most SDKs):

{
  "mcpServers": {
    "k-stra": {
      "type": "http",
      "url": "https://www.k-stra.com/mcp",
      "headers": { "Authorization": "Bearer ks_live_…" }
    }
  }
}

With Claude Code from a terminal:

claude mcp add --transport http k-stra https://www.k-stra.com/mcp --header "Authorization: Bearer ks_live_…"

Claude Desktop reaches remote servers through the mcp-remote bridge (it needs Node.js). Edit claude_desktop_config.json (Settings → Developer → Edit Config; on Windows it lives in %APPDATA%\Claude), then restart Claude Desktop:

{
  "mcpServers": {
    "k-stra": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://www.k-stra.com/mcp", "--transport", "http-only", "--header", "Authorization:${KSTRA_AUTH}"],
      "env": { "KSTRA_AUTH": "Bearer ks_live_…" }
    }
  }
}

On Windows, if npx is not found, use "command": "cmd" and put "/c", "npx" in front of the arguments. The key goes in env because the bridge does not accept spaces inside a header argument. The server is stateless and has no OAuth: a key is the only way in, and without one the endpoint answers 401 with WWW-Authenticate: Bearer.

Tools

The tools are the same actions as the REST API — the geomarketing computations and the lookups that build their input (see the table in the Quickstart) — so what an assistant can do over MCP is exactly what a program can do over REST. Action ids become tool names with _ instead of . (search.addresses → search_addresses).

Tool What it does Scope
<action> for every free action runs it directly: search_addresses, search_resolve_address, areas_list, markets_sectors, … read
quote_<action> for every charged action quotes it in credits without charging or computing; returns quotedCredits read
run_<action> for every charged action runs it and charges. Requires quotedCredits from the quote; refused without charging if the quote changed (quote_changed) or credits are insufficient (insufficient_credits) run
list_analyses your saved analyses and the ones shared with you, with the last run of each read
get_analysis one analysis with its latest saved results, for free read
get_credits balance, limits and this key's monthly usage read
get_data_versions the data versions available today read
get_job, get_job_results the state of a background job (an enrich.points batch) and its results, one row per point or one point in full read

The quote/run pair is the web app's confirmation dialog in protocol form: no agent spends credits without having declared how many. A typical exchange for People & Economy:

  1. quote_analysis_people_economy with the input (origins, bands, mode, traffic, topics) → { "quotedCredits": 4, "quote": { … }, "polesInvolved": 27543 }
  2. run_analysis_people_economy with the same input plus "quotedCredits": 4 → { "actionId": "analysis.people_economy", "result": { "charged": true, "creditsCharged": 4, … } }

Every tool result carries the JSON both as text and as structuredContent. Free and run_ tools whose action returns an object declare an outputSchema ({ actionId, result }); quote_ tools declare the quote (actionId, quotedCredits, quote, polesInvolved, blockedBy).

Errors

A tool that cannot do its job returns a result with isError: true whose text is the same problem the REST API would send: error (the code), status, type, title, detail and the extra data — missing for a required field left out, quotedCredits for a changed quote, blockedBy for insufficient credits. A name that matches no tool gives unknown_tool. The catalogue is in Errors, limits & versions.

Resources

Every saved analysis visible to the key (the 100 most recently updated, as in list_analyses) is a resource kstra://analyses/<code> (application/json): the analysis with its latest saved results, the same document GET /api/v1/analyses/{code} returns. Reading a resource never spends credits.

Binding a run to a saved analysis

Pass analysisCode (the 12-character code from list_analyses) in the input of a run_ tool: when the run is charged it is stored as a new version of that analysis, exactly like the X-Analysis-Id header over REST, and the tool result carries the version summary. The analysis must be yours; run_analysis_isochrone is never stored as a version. Read it back later with get_analysis or the resource, for free.

Limits

The key's limits apply unchanged: 600 requests a minute per key, the monthly cap you set on the key, and the organization, team and personal credit limits. The per-key limit of 60 charged executions a minute applies to REST; over MCP the general quota is the ceiling.