Server definition
- Hash
- sha256:c80e6bb2b0de5313fb4878fd71af62b2079c5cd77500904157556289287dc34a
- What it is
- What a remote MCP server returned when asked what it offers: 5 tools
The blob, as servednamed by its sha256
{
"instructions": "LatLong Maps MCP Server — Usage Guide\n\n## Authentication\nAll tool calls require a valid token. For HTTP transport, send the \"X-Authorization-Token\" header. For stdio transport, set the \"X_AUTHORIZATION_TOKEN\" environment variable in your MCP client config.\n\n## SVG artifacts\nMap tools return a version-pinned signed \"svg_url\" and \"svg_expires_at\"; the default TTL is about 8 hours and is configurable by the server. Do not expect raw SVG markup in tool JSON.\n\nTo display the map to the user:\n1. ALWAYS render the svg_url as a clickable image using markdown: \n2. The URL is a direct link to an SVG file — it renders in any browser or image viewer.\n3. Include the image inline in your response so the user sees the map immediately.\n4. Copy svg_url EXACTLY, character for character, including EVERY query parameter (versionId, Expires, Key-Pair-Id, Signature). Never shorten, clean up, re-encode or drop any part of it. The signature covers the whole URL: removing or changing even one parameter makes the link return \"AccessDenied\".\n\nExample response format:\n\n\nFor saving locally: fetch the URL without altering its query string:\n\"curl --fail --location --output map.svg <svg_url>\"\n\n## Chaining Policy\n- When a result carries a \"guidance\" object, prefer its numbered menu and its next_actions over improvising a follow-up.\n- An action with \"arguments_from\" names an object already in the exchange. Use that object as the base request and overlay the small \"arguments\" map on top. \"render_map_input\" means the field of that name in the result you just received; \"previous_call_input\" means the arguments you just sent. Never rebuild a data table by hand.\n- An action with a label but no arguments is an invitation, not a complete call: you still have to supply the missing choice.\n- If you do not understand an action, ignore the whole guidance object rather than acting on part of it.\n- Do not invent tools, output formats, or capabilities. get_capabilities reports which tools are actually available in this process — treat its available_tools list as authoritative over anything below.\n\n## Tools\n\n### 1. get_capabilities\nReturns the server's capability matrix: supported map types (choropleth, categorical), output formats (SVG is the default; PNG and both are opt-in), classification methods, feature flags, and available_tools — the tools actually registered in this process. Call this first to discover what the server can do.\n\n## Recommended Workflows\n\n### Upload-then-map workflow\n1. Call upload_file with file_name, file_size, and question to get a signed upload URL.\n2. Run the curl command from the response to upload the file bytes.\n3. Read the curl response for file_key, columns, and row preview.\n4. If the response is 'sheet_selection_required' (multi-sheet XLSX), note the returned file_key and sheet names. Pass file_key + sheet directly to question_to_map (or any other tool that accepts file_key) — do not call upload_file again.\n5. Call question_to_map with the returned file_key and question: {\"question\": \"...\", \"file_key\": \"mcp-uploads/2026/01/15/<uuid>.csv\"}\n6. For subsequent questions on the same file, reuse the same file_key — do not re-upload. The server re-fetches the file from S3 on each call.\n\n## Data Format\nPass data as an array of row objects (key-value maps). Each row must contain at least the geo_column and value_column fields.\n\nExample:\n{\"data\": [{\"state\": \"Maharashtra\", \"population\": 123456789}, {\"state\": \"Karnataka\", \"population\": 67562686}], \"map_type\": \"choropleth\", \"geo_type\": \"state\", \"geo_column\": \"state\", \"value_column\": \"population\"}\n\n## Parameters (question_to_map)\n\n- map_type: \"choropleth\" (numeric values) or \"categorical\" (qualitative classes)\n- geo_type: \"state\", \"district\", \"city\", \"ac\", \"pc\", \"scr\", \"rto\", \"pincode\"\n- geo_column: Column name containing geographic names\n- value_column: Column name containing values to color-code\n- label_column: Optional column for categorical map labels\n- state_hint: Optional array of state names to scope sub-state matching\n- filters: Optional row filter object\n- style: Optional style object (see Style Options)\n- mid_aa_order: Administrative level for mid-order boundary overlay\n- query: Optional natural-language description of the desired map\n- output_format: \"svg\" (default), \"png\", or \"both\"\n- viewport_mode: \"india\" (default, full India extent) or \"fit_data\" (zoom to matched regions)\n- title: Optional map title (sets legend_title)\n- tooltip: Set true to enable labels and data display on the map\n- no_cache: Set true to bypass SVG engine cache and get fresh render\n\n## Style Options\nPass via the \"style\" object. All keys are optional.\n\n### Coloring\n- palette: Named color palette string (e.g. \"blue\", \"green\", \"red\", \"sunrise\", \"aurora\")\n- distribution: \"continuous\" (smooth gradient) or \"steps\" (discrete class breaks)\n- distribution_mode: \"jenks\" (default), \"natural_breaks\", \"equal_interval\", \"quantile\", \"linear\", \"custom\"\n- steps_count: Number of class breaks (default 5)\n- custom_palette_start_color / custom_palette_end_color: Hex colors for custom palette gradient\n- single_color: Hex color to fill all regions (overrides palette)\n- category_colors: Object mapping category → hex color (for categorical maps)\n\n### Legend & Labels\n- legend_show: Boolean\n- legend_title: String\n- show_labels: Boolean\n- show_data: Boolean\n- font_family: Label font family (default: Inter)\n\n### Stroke\n- child_stroke: {color, width} — border style for region paths\n- parent_stroke: {aa_order, color, width} — parent boundary overlay\n- mid_aa_order: Administrative level for mid-order boundary overlay\n\n## Server Behavior\n- Stateless: each call is independent with no session persistence\n- SVG is the default output format and is returned through svg_url\n- Font: Inter is the default font\n- Circuit breaker protects against SVG engine outages\n- LLM fallback: if AI model is unavailable, renders with default styling\n\n## Data Analysis Tools\n\nThese tools work with uploaded data. Default response is always a rendered map (SVG URL). Data tables only when explicitly asked.\n\n### Response Format Guide (for the LLM client presenting to users)\n\nWhen presenting results to the user, ALWAYS include ALL THREE parts:\n\n1. **MAP** (primary) — the rendered SVG map. Display it inline or as a viewable link.\n2. **TABLE** (supporting) — a brief top-5 summary table of key regions with values. A preview of up to 20 rows is included directly in the map response under computed_data when the data is your own uploaded file (not a DB-backed query) — use those numbers, formatted with commas (e.g. 15,245), with the metric name and unit. If computed_data is absent (a DB-backed request), or you need more than its 20 rows, say so and either offer the \"get_data\" follow-up in guidance.next_actions for a different sort/subset, or note that the user's own uploaded file has the complete data. Never invent placeholder values.\n3. **EXPLANATION** (narrative) — 2-3 sentences explaining: what the map shows, any geographic complexity (e.g. \"GHMC crosses multiple districts\", \"Delhi NCR spans multiple states\"), top/bottom performers, and key insight.\n\nExample for \"Show sales by state from my uploaded file\" (a numeric value_column):\n- MAP TYPE: CHOROPHLETH (color gradient by value — states with higher sales are darker)\n- MAP: India (or the matched states) colored by the sales value per state\n- TABLE: Top 5 states by sales, with values formatted (e.g. 15,245) — from the computed_data preview in the response\n- EXPLANATION: \"This map shows sales by state from your uploaded data. Geo-matching covered N of M states. Maharashtra leads at 15,245, followed by...\"\n\nExample for \"Show party affiliation by constituency from my uploaded file\" (a qualitative/category value_column):\n- MAP TYPE: CATEGORICAL (a distinct color per category — NOT choropleth)\n- MAP: The matched constituencies colored by their category value\n- TABLE: Category breakdown (e.g. counts per party) — from the computed_data preview in the response\n- EXPLANATION: \"This map shows [category] by constituency from your uploaded data. [Category A] leads with N constituencies, followed by...\"\n- NOTE: For \"which is more common\" or \"distribution of X\" questions with a text/category column, use map_type=\"categorical\" with that column as value_column\n\n### upload_file\nUpload a CSV or XLSX file for ingestion under policy (auth, size cap, malware scan, injected-intent scan) and receive a signed upload URL plus a file_key. This is step 1 of the upload-then-map workflow.\n\nStep 1 — request a signed upload URL:\n- Pass file_name (must end in .csv or .xlsx), file_size (bytes), and question (your analysis question).\n- The response contains: status=\"upload_required\", upload_url, curl (a ready-to-run curl command), file_key, and question.\n\nStep 2 — upload the file bytes:\n- Run the curl command from the response. It POSTs the raw file bytes to the signed upload_url.\n- The curl response contains: file_key, columns, rows (bounded preview), row_count, warnings, and optionally intent + guidance.\n- The 'intent' field (when present) carries the geo-match service's detected geo_column, geo_level, value_column, map_type, and confidence. It is advisory — forward these into question_to_map as geo_column, value_column, geo_level, and render_params.map_type to skip auto-detection and render immediately.\n- The 'guidance' field (when present) contains a ready-to-fire question_to_map action with all detected parameters pre-filled. Use it directly if the intent looks correct.\n- The 'question' field echoes back the question you passed in step 1.\n- For multi-sheet XLSX: the curl response is 'sheet_selection_required' with a file_key and sheets list. Pass file_key and sheet to question_to_map (or any other tool that accepts file_key) — do not call upload_file again. The server parses the chosen sheet from S3 on that call.\n\nAfter upload: pass the returned file_key to question_to_map to render a map from the full dataset. The server fetches and parses the file from S3 internally — no need to pass raw rows. When the upload verdict includes intent + guidance, forward the detected columns into question_to_map for a zero-round-trip render.\n\nThe file_key is reusable — for additional questions on the same file, just pass the same file_key again. Do not re-upload the file.\n\n### question_to_map\nRender a geographic map from your uploaded data. This is step 2 of the upload-then-map workflow.\n\nPass the file_key from upload_file: {\"question\": \"show total by pincode\", \"file_key\": \"mcp-uploads/2026/01/15/<uuid>.csv\"}\nThe server fetches and parses the full file from S3 — no need to pass raw rows. The same file_key can be reused across multiple question_to_map calls without re-uploading.\n\nAlternatively, pass rows directly as 'data' (e.g. from the upload_file preview): {\"question\": \"show total by pincode\", \"data\": [<rows>]}\n\nRules:\n- geo_column and value_column are preferred if easily identifiable from the column names, but not required — the server auto-detects them using a geo-match service.\n- When the upload_file verdict includes an 'intent' block, forward geo_column, value_column, geo_level, and render_params.map_type from it into question_to_map to skip auto-detection entirely.\n- Hints: geo_column usually contains place names (state, district, city, pincode, constituency) or numeric codes (pincode=560049); value_column usually contains the metric to plot (sales, count, total, percentage) or a category (party affiliation, status, type).\n- If value_column is 'total' and doesn't exist in data, all numeric columns are summed automatically.\n- String value columns render as categorical maps (each distinct value gets its own color).\n- Supported geo types: state, district, pincode, rto, city, ac, pc.\n- Default output is a rendered SVG map. When the data is your own upload, a bounded preview (up to 20 rows) of the underlying data is included in the map response as computed_data — use it for a supporting table. Say \"data\", \"table\", or \"numbers\" in the question to instead get a data-mode response focused on the numbers (a different sort/subset, still capped at 20 rows). If the request involves internal DB data, no preview is included — request a data-mode question for the numbers.\n- When the server cannot detect columns (service unavailable or no geo column found), it returns a 'clarification_required' response with classified column candidates and suggested next actions — never guesses.\n\nClarification responses:\n- When the server cannot determine which columns to use, it returns a 'clarification_required' response instead of an error.\n- The response includes a 'columns' list (classified as geo, quantitative, qualitative, or identifier), 'suggested_geo_columns', 'suggested_value_columns', and 'guidance' with ready-to-use next actions.\n- Pick a geo_column and value_column from the suggestions (or ask your user) and re-call question_to_map with those explicit parameters.\n\nPoints mode (plotting markers instead of shaded regions):\n- Triggers automatically when the file has latitude/longitude columns and the question asks to plot/pin/mark locations (e.g. \"plot my stores\", \"show me the outlet locations\", \"mark these\"). No geo_column or value_column needed — coordinate columns are detected the same way reverse_geocode detects them.\n- The boundary lines drawn beneath the markers, and how far the map zooms, are chosen automatically from where the points actually land — it tightens to a single state or district for a local cluster, and falls back to an all-India view for a nationwide spread. Name a level explicitly in the question (\"plot by assembly constituency\", \"rto wise\", \"by pincode\") to force it.\n- A response may report points that fall outside every boundary at the chosen level (offshore coordinates, or lat/lon swapped) in its warnings — check for that before telling the user every point plotted.\n- Works directly on lat/lon columns already in the uploaded file, whether they came from a prior geocode call or were already in the source data.\n\n### geocode\nTurn addresses in an uploaded CSV/XLSX into latitude/longitude. Requires a file_key from upload_file.\n\nCall: {\"file_key\": \"mcp-uploads/2026/01/15/<uuid>.csv\"} and let the server detect the address column,\nor name it yourself: {\"file_key\": \"...\", \"address_column\": \"Shipping Address\"}\n\nColumn selection:\n- address_column names one column; address_columns names several (each is geocoded separately).\n- compose_columns is an ordered list to join into one address per row, for files where the address is\n split across columns (e.g. [\"Street\",\"District\",\"State\",\"PIN\"]). Mutually exclusive with address_column(s).\n- Anything you pass explicitly is used as-is and skips detection entirely.\n\nClarification responses — this tool asks rather than guesses, because every row costs an API call:\n- status 'clarification_required' with reason 'multiple_candidates' means the file has more than one\n address column. Show the candidates (each has a score and evidence) and ask the user which to geocode.\n The guidance actions include one per column plus one for all of them.\n- reason 'low_score' means a single weak candidate — ask the user to confirm it.\n- reason 'compose_confirm' means the file has structured columns (District/State/PIN) and no single\n full-address column. 'proposed_order' is the suggested join; confirm it or send your own compose_columns.\n Columns marked eligible=false (RTO/SCR/AC/PC) are electoral or administrative overlays, not postal parts.\n- reason 'no_candidates' or 'detect_unavailable' means you must name the column; 'all_columns' lists them.\n- Answer by re-calling geocode with the chosen columns. Never invent a column name.\n\nLarge files run as a background job:\n- Small requests (<= GEOCODE_MAX_SYNC_ADDRESSES, default 200 addresses) return the finished file directly.\n- Larger ones return status 'accepted' with a job_id. Poll by calling geocode with ONLY that job_id\n ({\"job_id\": \"gc_...\"}) — never with file_key as well. Each poll returns status, total, completed,\n failed, and progress_percent computed from finished work only.\n- Statuses: accepted/running (keep polling), completed (file_key ready), completed_partial (some rows\n were never reached and carry geocode_status=pending), interrupted (paused after a sustained upstream\n failure — poll again to resume from where it stopped, already-done work is not repeated),\n failed (reason explains why).\n- Polling etiquette: poll a few times with a short gap between polls. If the job is still\n accepted/running after 2-3 polls, do NOT keep blocking — tell the user it is processing, report the\n latest progress_percent (X of N addresses), and note that they can ask you to check again whenever\n they like and are free to do other things meanwhile. Keep the job_id so a later check is one poll\n away. Early polls may briefly show 0 done before the first progress flush lands; that is normal, not\n a stall.\n- Retrying an identical call is safe: the job id is derived from the request, so a retry rejoins the\n running job or returns the already-written file instead of geocoding everything a second time.\n Pass force_new: true only when you genuinely want a fresh run.\n\nResult:\n- The result is written back to the SAME uploaded file as a new version, not a new object: file_key in\n the response equals the file_key you passed. Pass it to question_to_map with a plotting question (e.g.\n \"plot these locations\") to render the new latitude/longitude columns as markers — points mode detects\n them automatically, no geo_column or value_column needed — or hand the user file_url (below) to\n download the file directly.\n- file_url is a signed, time-limited CDN link to the geocoded file, for direct download by a human or\n client. It may be absent if a link could not be generated — in that case a warning says so and file_key\n still works with question_to_map. Do not treat a missing file_url as a failure.\n- Each geocoded column adds latitude, longitude, latlong, and geocode_status, prefixed by the source\n column name (e.g. shipping_address_latitude) so results stay attributable when a file is geocoded more\n than once. Existing columns are never overwritten; re-geocoding a file appends a new set alongside any\n prior results (a warning notes this).\n- For a multi-sheet XLSX, only the geocoded sheet is modified; all other sheets are preserved unchanged.\n- geocode_status per row: ok, not_found (no match — retrying will not help), error (transport failure —\n worth retrying), empty_address. Individual failures never stop the other rows.\n- Large files: total addresses = rows x address columns and is capped by GEOCODE_MAX_ADDRESSES; the call\n is rejected up front rather than part-way through if it would exceed the limit.\n- After geocoding, the response includes a \"map these points\" next action, but the results are also\n useful standalone — the file_url download is enough on its own if the user just wanted coordinates. If\n the user seems unsure what to do next, mention you can also download the file to a location for them,\n or answer basic questions about the results directly from the file.\n\n### reverse_geocode\nTurn latitude/longitude in an uploaded CSV/XLSX into addresses. Requires a file_key from upload_file.\n\nCall: {\"file_key\": \"...\"} and let the server detect the coordinate columns, or name them:\n {\"file_key\": \"...\", \"latitude_column\": \"lat\", \"longitude_column\": \"lng\"}\n {\"file_key\": \"...\", \"latlong_column\": \"coords\"} // one column: \"12.9148,77.5949\"\n {\"file_key\": \"...\", \"coordinate_pairs\": [ // several sets in one call\n {\"latitude_column\": \"pickup_lat\", \"longitude_column\": \"pickup_lng\"},\n {\"latitude_column\": \"drop_lat\", \"longitude_column\": \"drop_lng\"}]}\n\nClarification responses — this tool asks rather than guesses, because every coordinate costs an API call:\n- 'multiple_candidates': the file has more than one coordinate set. Show the candidates (each has a score\n and evidence) and ask which to resolve; guidance includes one action per pair plus one for all of them.\n- 'low_score': a single weak candidate — ask the user to confirm it.\n- 'no_candidates': name the columns; 'all_columns' lists what is available.\n- 'out_of_bounds': too many coordinates fall outside the supported region. This deployment is configured\n for India only. Either the columns are wrong (name the correct ones) or the data cannot be processed —\n there is no override flag.\n- 'low_precision': coordinates have no decimal places, so addresses may be ~111 km off. This one is NOT\n answered by naming a column: re-call with accept_low_precision: true to proceed, after telling the user\n what the warning says.\n\nBehaviour worth knowing:\n- Latitude and longitude that are clearly reversed are swapped automatically, and the response says so.\n- Rows that are empty, unparseable, or outside the region are skipped without an API call and reported in\n 'skipped_by_reason'. Row count out always equals row count in.\n- Explicitly named columns are still bounds- and precision-checked. Unlike geocode, wrong coordinates\n return confidently wrong addresses instead of failing loudly, so the checks are not skipped.\n- Columns written by an earlier geocode run are excluded from auto-detection; name them to resolve those.\n\nResult:\n- The resolved file is written back over the uploaded file. The response carries file_key, a signed\n file_url, a <=20-row preview, and counts — not the full rows.\n- Each pair adds address, pincode, landmark and reverse_geocode_status columns, plus building_name when\n any row returned one, plus latitude/longitude when the input was a single combined column.\n- reverse_geocode_status per row: ok, not_found, error, empty_coordinates, invalid_coordinates,\n out_of_bounds, pending (only in a partially delivered file).\n\nLarge files:\n- At or below BULK_GEOCODE_THRESHOLD (default 50) coordinates the work runs inline and returns the file.\n- Above it, the request is registered with the bulk processing service and the response is\n status=accepted with a job_id. Poll by calling reverse_geocode with ONLY that job_id, about every\n 5 minutes. The same statuses and polling rules as geocode apply.\n\n## Token/Credit Usage\nEach call consumes credits from your monthly budget. SVG render = 10 credits, analysis = 2 credits.\nEvery response includes a \"usage\" field showing this_call cost and monthly remaining balance.",
"tools": [
{
"description": "Geocode addresses from an uploaded CSV or XLSX file into latitude/longitude. Pass a file_key from upload_file.\n\nColumn selection: if you know it, pass address_column (or address_columns for several). Otherwise the server asks the geo-match service to detect it. When the answer is not unambiguous — several address columns, a weak match, or only structured columns like District/State/PIN that must be combined — the response is status=clarification_required with candidates and ready-to-fire guidance actions. Present the choice to the user and re-call with their answer; never invent a column name.\n\nThe result overwrites the same file_key as a new version, plus a small preview, not the full rows. Pass that file_key to question_to_map to map the coordinates, or hand the user file_url (a signed download link, when present) to fetch the file directly.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"address_column": {
"type": "string"
},
"address_columns": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"compose_columns": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"file_key": {
"type": "string"
},
"force_new": {
"type": "boolean"
},
"job_id": {
"type": "string"
},
"sheet": {
"type": "string"
}
},
"type": "object"
},
"name": "geocode",
"outputSchema": null
},
{
"description": "Return the server's capability matrix: supported map types, geo types, output formats, classification methods, and the list of tools available in this process (which varies by configuration). Call this first to discover what the server can do.",
"inputSchema": {
"additionalProperties": false,
"type": "object"
},
"name": "get_capabilities",
"outputSchema": {
"additionalProperties": false,
"properties": {
"auto_level_detection": {
"type": "boolean"
},
"available_indices": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"available_tools": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"classification_methods": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"default_output": {
"type": "string"
},
"geo_detection": {
"type": "boolean"
},
"geo_levels": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"guidance": {
"additionalProperties": false,
"properties": {
"allow_freeform": {
"type": "boolean"
},
"next_actions": {
"items": {
"additionalProperties": false,
"properties": {
"arguments": {
"additionalProperties": true,
"type": "object"
},
"arguments_from": {
"type": "string"
},
"id": {
"type": "string"
},
"label": {
"type": "string"
},
"reason": {
"type": "string"
},
"tool": {
"type": "string"
}
},
"required": [
"id",
"label",
"tool"
],
"type": "object"
},
"type": [
"null",
"array"
]
},
"next_steps_text": {
"type": "string"
}
},
"required": [
"next_actions",
"allow_freeform",
"next_steps_text"
],
"type": [
"null",
"object"
]
},
"index_modes": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"map_types": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"output_formats": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"png_supported": {
"type": "boolean"
},
"stateless_only": {
"type": "boolean"
},
"svg_default": {
"type": "boolean"
}
},
"required": [
"map_types",
"geo_levels",
"output_formats",
"default_output",
"classification_methods",
"available_indices",
"index_modes",
"geo_detection",
"auto_level_detection",
"svg_default",
"png_supported",
"stateless_only",
"available_tools"
],
"type": "object"
}
},
{
"description": "Render a geographic map from your data. Call upload_file first to ingest a CSV/XLSX file, then pass the returned file_key: {\"question\": \"show total by pincode\", \"file_key\": \"mcp-uploads/2026/01/15/<uuid>.csv\"}. The file_key is reusable — for additional questions on the same file, pass the same file_key again without re-uploading.\n\nAlternatively, pass rows directly as 'data' (e.g. from the upload_file preview): {\"question\": \"show total by pincode\", \"data\": [<rows>]}\n\ngeo_column and value_column are preferred if easily identifiable from the column names, but not required — the server auto-detects them using a geo-match service that matches your data against known Indian geographies (states, districts, ACs, PCs, pincodes, RTOs, cities).\nHints: geo_column usually contains place names (state, district, city, pincode, constituency) or numeric codes (pincode=560049); value_column usually contains the metric to plot (sales, count, total, percentage) or a category (party affiliation, status, type).\nIf value_column is 'total' and doesn't exist in data, all numeric columns are summed automatically. String value columns render as categorical maps (each distinct value gets its own color, e.g. party affiliation). If the server cannot determine which columns to use, it returns a 'clarification_required' response with suggested columns and guidance — pick a geo_column and value_column from the suggestions and re-call.\nSupported geo types: state, district, pincode, rto, city, ac, pc.\n\nPoints mode: if your file has latitude/longitude columns (e.g. from a prior geocoding step, or coordinates you already had) and your question asks to plot/pin/mark locations (\"plot my stores\", \"show me the outlet locations\", \"mark these points\"), the server detects the coordinate columns automatically and renders markers instead of shaded regions — no geo_column/value_column needed. The boundary lines drawn beneath the markers and how far the map zooms are chosen automatically from where the points actually fall (tightens to a state or district for a local cluster, falls back to all-India for a nationwide spread); you can also name a level explicitly (\"plot by assembly constituency\", \"rto wise\") to force it. A response may report points that fall outside every boundary (e.g. offshore or swapped lat/lon) — check for that in the warnings.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"type": [
"null",
"array"
]
},
"detected_geo": {
"additionalProperties": false,
"properties": {
"column": {
"type": "string"
},
"confidence": {
"type": "number"
},
"geo_type": {
"type": "string"
},
"matched_count": {
"type": "integer"
},
"parent": {
"type": "string"
},
"total_count": {
"type": "integer"
}
},
"required": [
"column",
"geo_type",
"confidence",
"matched_count",
"total_count"
],
"type": [
"null",
"object"
]
},
"enrich_with": {
"additionalProperties": false,
"properties": {
"columns": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"join_on": {
"type": "string"
},
"table": {
"type": "string"
}
},
"required": [
"table",
"columns"
],
"type": [
"null",
"object"
]
},
"file_key": {
"type": "string"
},
"geo_column": {
"type": "string"
},
"geo_level": {
"type": "string"
},
"map_type": {
"type": "string"
},
"output_format": {
"type": "string"
},
"question": {
"type": "string"
},
"render_params": {
"additionalProperties": true,
"type": "object"
},
"sheet": {
"type": "string"
},
"state_hint": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"style": {
"additionalProperties": true,
"type": "object"
},
"table": {
"type": "string"
},
"value_column": {
"type": "string"
}
},
"required": [
"question"
],
"type": "object"
},
"name": "question_to_map",
"outputSchema": {
"additionalProperties": false,
"properties": {
"aggregation_applied": {
"additionalProperties": false,
"properties": {
"aggregated_rows": {
"type": "integer"
},
"grouped_by": {
"type": "string"
},
"method": {
"type": "string"
},
"note": {
"type": "string"
},
"original_rows": {
"type": "integer"
}
},
"required": [
"original_rows",
"aggregated_rows",
"method",
"note"
],
"type": [
"null",
"object"
]
},
"clarification": {
"additionalProperties": false,
"properties": {
"columns": {
"items": {
"additionalProperties": false,
"properties": {
"class": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
},
"required": [
"name",
"type",
"class"
],
"type": "object"
},
"type": [
"null",
"array"
]
},
"guidance": {
"additionalProperties": false,
"properties": {
"allow_freeform": {
"type": "boolean"
},
"next_actions": {
"items": {
"additionalProperties": false,
"properties": {
"arguments": {
"additionalProperties": true,
"type": "object"
},
"arguments_from": {
"type": "string"
},
"id": {
"type": "string"
},
"label": {
"type": "string"
},
"reason": {
"type": "string"
},
"tool": {
"type": "string"
}
},
"required": [
"id",
"label",
"tool"
],
"type": "object"
},
"type": [
"null",
"array"
]
},
"next_steps_text": {
"type": "string"
}
},
"required": [
"next_actions",
"allow_freeform",
"next_steps_text"
],
"type": [
"null",
"object"
]
},
"message": {
"type": "string"
},
"status": {
"type": "string"
},
"suggested_geo_columns": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"suggested_value_columns": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
}
},
"required": [
"status",
"message",
"columns",
"suggested_geo_columns",
"suggested_value_columns"
],
"type": [
"null",
"object"
]
},
"computed_data": {
"additionalProperties": false,
"properties": {
"columns": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"returned_rows": {
"type": "integer"
},
"rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"type": [
"null",
"array"
]
},
"sort_column": {
"type": "string"
},
"sort_order": {
"type": "string"
},
"total_rows": {
"type": "integer"
}
},
"required": [
"columns",
"rows",
"total_rows",
"returned_rows"
],
"type": [
"null",
"object"
]
},
"confidence": {
"type": "number"
},
"guidance": {
"additionalProperties": false,
"properties": {
"allow_freeform": {
"type": "boolean"
},
"next_actions": {
"items": {
"additionalProperties": false,
"properties": {
"arguments": {
"additionalProperties": true,
"type": "object"
},
"arguments_from": {
"type": "string"
},
"id": {
"type": "string"
},
"label": {
"type": "string"
},
"reason": {
"type": "string"
},
"tool": {
"type": "string"
}
},
"required": [
"id",
"label",
"tool"
],
"type": "object"
},
"type": [
"null",
"array"
]
},
"next_steps_text": {
"type": "string"
}
},
"required": [
"next_actions",
"allow_freeform",
"next_steps_text"
],
"type": [
"null",
"object"
]
},
"level_resolution": {
"additionalProperties": false,
"properties": {
"aggregations": {
"items": {
"additionalProperties": false,
"properties": {
"columns": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"dataset": {
"type": "string"
},
"from_level": {
"type": "string"
},
"method": {
"type": "string"
},
"to_level": {
"type": "string"
}
},
"required": [
"dataset",
"from_level",
"to_level",
"method",
"columns"
],
"type": "object"
},
"type": [
"null",
"array"
]
},
"alternatives": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"datasets": {
"items": {
"additionalProperties": false,
"properties": {
"geo_col": {
"type": "string"
},
"level": {
"type": "string"
},
"rows": {
"type": "integer"
},
"source": {
"type": "string"
}
},
"required": [
"source",
"level",
"geo_col",
"rows"
],
"type": "object"
},
"type": [
"null",
"array"
]
},
"method": {
"type": "string"
},
"reason": {
"type": "string"
},
"resolved_level": {
"type": "string"
}
},
"required": [
"datasets",
"resolved_level",
"method"
],
"type": [
"null",
"object"
]
},
"map": {
"additionalProperties": false,
"properties": {
"active_count": {
"type": "integer"
},
"dimensions": {
"additionalProperties": false,
"properties": {
"height": {
"type": "integer"
},
"width": {
"type": "integer"
}
},
"required": [
"width",
"height"
],
"type": [
"null",
"object"
]
},
"expires_at": {
"type": "string"
},
"format": {
"type": "string"
},
"geo_scope": {
"type": "string"
},
"html_url": {
"type": "string"
},
"join_summary": {
"additionalProperties": false,
"properties": {
"matched": {
"type": "integer"
},
"total": {
"type": "integer"
},
"unmatched": {
"type": "integer"
}
},
"required": [
"matched",
"unmatched",
"total"
],
"type": [
"null",
"object"
]
},
"mime_type": {
"type": "string"
},
"preview_image_base64": {
"type": "string"
},
"render_id": {
"type": "string"
},
"subtitle": {
"type": "string"
},
"svg_url": {
"type": "string"
},
"title": {
"type": "string"
},
"total_count": {
"type": "integer"
},
"total_value": {
"type": "string"
},
"url": {
"type": "string"
},
"value_label": {
"type": "string"
}
},
"required": [
"url",
"format",
"render_id"
],
"type": [
"null",
"object"
]
},
"mode": {
"type": "string"
},
"points_plotted": {
"type": "integer"
},
"points_rejected": {
"type": "integer"
},
"rejected_rows": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"resolution_method": {
"type": "string"
},
"resolved_params": {
"additionalProperties": false,
"properties": {
"geo_column": {
"type": "string"
},
"geo_type": {
"type": "string"
},
"map_type": {
"type": "string"
},
"state_hint": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
},
"style": {
"additionalProperties": true,
"type": "object"
},
"value_column": {
"type": "string"
}
},
"required": [
"map_type",
"geo_type",
"geo_column",
"value_column"
],
"type": [
"null",
"object"
]
},
"usage": {
"additionalProperties": false,
"properties": {
"breakdown": {
"additionalProperties": {
"type": "integer"
},
"type": "object"
},
"month_limit": {
"type": "integer"
},
"month_remaining": {
"type": "integer"
},
"month_used": {
"type": "integer"
},
"this_call": {
"type": "integer"
}
},
"required": [
"this_call",
"breakdown",
"month_used",
"month_limit",
"month_remaining"
],
"type": [
"null",
"object"
]
},
"warnings": {
"items": {
"type": "string"
},
"type": [
"null",
"array"
]
}
},
"required": [
"mode"
],
"type": "object"
}
},
{
"description": "Turn latitude/longitude coordinates in an uploaded CSV or XLSX into addresses. Pass a file_key from upload_file.\n\nColumn selection: pass latitude_column and longitude_column, or latlong_column for a single combined column, or coordinate_pairs for several sets. Otherwise the server detects them. When the answer is not unambiguous — several coordinate columns, a weak match, coordinates outside the supported region, or coarse whole-number values — the response is status=clarification_required. Present the choice to the user and re-call with their answer.\n\nResults are written back into the uploaded file: the response carries file_key, a signed file_url, and a small preview. Each pair adds address, pincode, landmark and status columns.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"accept_low_precision": {
"type": "boolean"
},
"coordinate_pairs": {
"items": {
"additionalProperties": false,
"properties": {
"latitude_column": {
"type": "string"
},
"latlong_column": {
"type": "string"
},
"longitude_column": {
"type": "string"
}
},
"type": "object"
},
"type": [
"null",
"array"
]
},
"file_key": {
"type": "string"
},
"force_new": {
"type": "boolean"
},
"job_id": {
"type": "string"
},
"latitude_column": {
"type": "string"
},
"latlong_column": {
"type": "string"
},
"longitude_column": {
"type": "string"
},
"sheet": {
"type": "string"
}
},
"type": "object"
},
"name": "reverse_geocode",
"outputSchema": null
},
{
"description": "Upload a CSV or XLSX file for server-side ingestion under policy (auth, size cap, malware scan, injected-intent scan) and receive a file_key. This is the first step before calling question_to_map with your own data.\n\nStep 1: Call upload_file with file_name, file_size, and question. The response contains a signed upload_url and a curl command — run the curl command to POST the file bytes. The curl response contains file_key, columns, a row preview, and optionally 'intent' (geo-match service detected geo_column, geo_level, value_column, map_type, confidence) and 'guidance' (a ready-to-fire question_to_map action with all detected parameters pre-filled). Forward the intent fields into question_to_map to skip auto-detection and render immediately.\n\nFor multi-sheet XLSX: the curl response is 'sheet_selection_required' with a file_key and sheets list. Pass file_key and sheet to question_to_map (or any other tool that accepts file_key) — do not call upload_file again.\n\nAfter upload, pass the returned file_key to question_to_map to render a map from the full dataset. The file_key is reusable — for additional questions on the same file, pass the same file_key again without re-uploading. When the upload response includes 'guidance', use its next_actions directly for a zero-round-trip render.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"file_key": {
"type": "string"
},
"file_name": {
"type": "string"
},
"file_size": {
"type": "integer"
},
"question": {
"type": "string"
},
"sheet": {
"type": "string"
}
},
"required": [
"file_name",
"file_size"
],
"type": "object"
},
"name": "upload_file",
"outputSchema": null
}
]
}Verify it yourself
curl -s https://api.teppi.xyz/v1/evidence/sha256:c80e6bb2b0de5313fb4878fd71af62b2079c5cd77500904157556289287dc34a | sha256sum