EasyTerritory MCP
ai.easyterritory/ezt-mcpVersion 0.1.0Build, balance, realign and analyze sales/service territories; geocode, route, schedule, live map.
Status
Responds341 msAnswered our handshake without sign-in.- Last checked
- Nov 14, 2026, 13:29 UTC
- Latency
- 341 ms
- Remotes responding
- 1 of 1
- Sign-in
- API key
- Hosting
- Hosted outside the EU (detected)
- Registry data as of
- Nov 14, 2026, 22:14 UTC
Data from the official MCP Registry, checked by run.zero. How we check
Connect
Streamable HTTP
https://mcp.easyterritory.ai/Responds341 msNo sign-in
Claude Code
claude mcp add --transport http ezt-mcp https://mcp.easyterritory.ai/ --header 'Authorization: Bearer <YOUR_TOKEN>'Replace <YOUR_TOKEN> before running.
Claude Desktop and claude.ai
Settings > Connectors > Add custom connector
Name: ezt-mcp
Remote MCP server URL: https://mcp.easyterritory.ai/
This server expects the header Authorization.Cursor
{
"mcpServers": {
"ezt-mcp": {
"url": "https://mcp.easyterritory.ai/",
"headers": {
"Authorization": "Bearer <YOUR_TOKEN>"
}
}
}
}Replace <YOUR_TOKEN> before running.
VS Code
code --add-mcp '{"name":"ezt-mcp","type":"http","url":"https://mcp.easyterritory.ai/","headers":{"Authorization":"Bearer <YOUR_TOKEN>"}}'Replace <YOUR_TOKEN> before running.
Built your own server? run.zero hosts MCP servers on European infrastructure.
Tools
58 tools
Read-only | Idempotent | Open world | ||
|---|---|---|---|---|
account_buildBuilds territories that follow an account column, such as rep name or territory code from CRM: each part goes to the group holding most of its accounts (conflict_policy). Adds a new alignment (TAL). Needs an ingested point_layer, grouping_field, part_layer, and tal_label. Grouping values are labels, not balance metrics. part_scope: bbox_intersect (default; parts near the accounts) or explicit with part_filter, e.g. {state_abbr: TX}; in_tal: {tal_id} keeps only that TAL's parts, not_in_tal: {tal_id} only the parts it leaves uncovered. A declared visit-frequency column needs visit_frequency_field or ignore_visit_frequency (CLARIFICATION_REQUIRED otherwise). With map_session_id the open map is the input. Returns a task; the result carries tal_id and ts_handle. analyze reports the statistics. | No | No | No | No |
analyzeComputes territory statistics for one or more alignments, i.e. how balanced the territories are and how alignments compare: account counts, declared metric totals (e.g. Revenue), workload hours, balance scores, and cross-TAL comparison; hypothetical_moves previews a realign. Input: map_session_id (the open map as it is now), ts_handle, or a completed build job_id (pass tal_ids when several TALs exist). metrics: omit for every declared column, or name them; workload and account_count are always available. Workload needs dwell (dwell_time, the build's recorded dwell, or the layer's dwell_time_field); without it the result has every other statistic, no workload, and workload_omitted.ask_user to put to the user. analysis_panel=single with map_session_id fills the map dock (analysis_panel.status=pushed). Territory account_count, metric_totals, workload_total (minutes), and the dock grid cover accounts_point_layer (build point_layer), never seed, contractor, or visit layers; point_counts_by_layer counts every layer. Drive-time alignments count accounts inside each polygon. Returns a task. | No | No | No | No |
analyze_network_coverageFinds coverage gaps in a contractor (vendor, service provider, technician, repair shop) network: counts the contractors that reach each demand point (customer, claim, store, ZIP center). Reads contractor_layer (ingested with layer_role=contractors) and demand_layer. coverage: {rule: drive_time, max_minutes} (straight-line travel model, no provider calls), {rule: drive_time, source: isochrone_tal, isochrone_tal_id} (isochrone_build areas around the contractors), or {rule: zip_list} (declared service ZIPs). One trade per call ('*' for all). Missing layers, coverage, or trade return CLARIFICATION_REQUIRED with the question. Writes new layers, never the source: <demand>_coverage (contractor_count, single_source, coverage_class red none / amber one / green 2+ / blue saturated, nearest contractor and minutes, capacity_ratio, gap score) and <demand>_gaps; gap_territory=true adds the all-gap ZIPs as one territory. Assigns nothing; dividing work is auto_build. Returns a task; the result has coverage_pct, gap and single-source counts, top_gaps, and per-contractor reach. | No | No | No | No |
analyze_routesReturns the total hours for each of the routes calculate_route has drawn: drive hours, dwell hours, route_workload_hours (provider drive time plus dwell, no visit-frequency multiplier), stop coordinates, centroid, and bbox. Synchronous. Needs map_session_id or ts_handle, and dwell from dwell_time or the dwell recorded on the route; unresolved dwell returns CLARIFICATION_REQUIRED (needs_dwell). A circuit's stop_count includes the return to the start, so that stop's dwell counts twice. Facts only: no capacity, ranking, or overload flags. These hours are a different measure from territory and cluster workload; territory statistics come from analyze. | No | Yes | Yes | No |
auto_buildPartitions ingested account points into balanced sales territories with equal workload, metric, or count over a part layer (e.g. ZIPs) as a new alignment (TAL). Needs the user's choices: build_mode (fixed_territory_count + territory_count, fixed_workload_target + target_workload hours, or scoped_split), objective (workload_bias = drive + dwell, metric_bias = one column such as Revenue, count_bias = account count; sum 100), and dwell_time (a column or a stated scalar). A missing choice returns CLARIFICATION_REQUIRED with ask_user; a visit-frequency column also needs visit_frequency_field or ignore_visit_frequency. seed_point_layer seeds territories from provider points (any count). part_scope: bbox_intersect (default; can be national) or explicit with part_filter, e.g. {state_abbr: TX}; accounts outside stay unassigned (UNASSIGNED_ACCOUNTS). part_filter {in_tal: {tal_id}} keeps a TAL's parts; {not_in_tal: {tal_id}} its white space. With map_session_id the open map is the input. Returns a task; national builds take minutes. The result carries tal_id, ts_handle, and phase_timings_ms. | No | No | No | No |
calculate_routeSequences and drives a set of stops, e.g. a technician from home to the depot, then the day's calls, and back home: returns the order, road distance, drive time, per-leg timings, and geometry from TomTom or Azure Maps, and draws the path with numbered stops on the open map (map_session_id). Creates no territory and changes no assignment. route_type is the user's choice: circuit (returns to start), tour (ends at the required end stop), or open_tour (one way). stop_sets are visited in the order given and no stop moves between sets; order is optimize or as_given; group_by_field adds priority bands. Stops are inline coordinates or point-layer references (e.g. source.filter.territory_id); point_ids and stop_id are point_id values (visits: <account_id>#<n>). A new route_id adds a second route; recalculating an existing route_id replaces it, e.g. to drop a stop. dwell_time is stored for analyze_routes. Route drive time is a different measure from territory workload. No provider key returns ROUTING_NOT_CONFIGURED; past the monthly quota, PROVIDER_QUOTA_EXCEEDED. Returns a task. | No | No | No | Yes |
cluster_pointsGroups the points of one ingested layer into balanced clusters directly, with no ZIP or part layer and no territory alignment. Writes group_field (default group_id) on every point and colors the layer by it, replacing any prior color classification (size and shape channels stay). Needs build_mode (fixed_territory_count or fixed_workload_target), objective, and dwell_time, as in auto_build; a missing one returns CLARIFICATION_REQUIRED with the question. point_filter (e.g. {STATE: FL}) clusters a subset of the layer; unmatched points stay, ungrouped. Max 25,000 points after the filter. seed_point_layer, a second point layer such as technician homes, seeds the groups: with more seeds than groups the best-placed ones are used (seed_summary.unused lists the rest), with fewer the solver adds supplemental seeds in uncovered demand. seed_attraction 0-100 (default 70) is the pull of each seed on its group. Returns a task; the result lists groups with point_count, workload_hours, and point_ids. | No | No | No | No |
configure_mapUpdates map settings on the Territory Solution and refreshes the live map: project_name (map heading), theme (dark | light basemap and UI style), loaded_part_layers ([] hides ZIP/part outlines; builds never load them), active_part_layer, active_tal_id, center and zoom (default view; the live map jumps there), and point symbology. point_layer_classifications entries are {point_layer, field, method: quantile | equal_interval | categorical | manual, class_count 2-12, channel: color | size | shape, optional colors/sizes/shapes/style}; the server computes the breaks and returns per-class counts. One classification per channel per layer; clear:true removes one. Shapes cover role icons and all Designer symbols (circle, ring, square, triangle, triangle_down, diamond, star, star4, star6, star8, cross, house, pin, pin_solid, square_pin, flag, hexagon, pentagon, shield, arrow_up, building, tower, person, vehicle, gear, paint_swath, plus *_open variants). classification without point_layer is a project-level setting that does not color points. Input: map_session_id (the live map) or ts_handle. | No | No | No | No |
create_territory_from_partsCreates one leaf territory from a list of part_ids (e.g. a committed map selection), in a new alignment or an existing one (tal_id). With map_session_id the live map's Territory Solution is updated and repainted; otherwise ts_handle (a new ts_handle is returned). map_session_id wins when both are passed. territory_name is a display label; the result's created_territory.territory_id is the stable id for later edits, plus leaf_territories and selection_summary (duplicate_part_ids). Dwell is optional here and is not inherited from an earlier auto_build; dwell_time is recorded for later analyze. Without it, analyze reports every statistic except workload and returns workload_omitted.ask_user. Returns a task. | No | No | No | No |
delete_point_layerPoint-layer delete: removes one point layer and its account points from the Territory Solution and the open map, in one synchronous call. Needs point_layer (the layer id or its exact unique label), plus map_session_id or ts_handle. Territories, part overlays, and other point layers stay. A layer that is already gone returns ok with already_absent=true; an ambiguous label returns AMBIGUOUS_POINT_LAYER with matching_point_layers. ingest_accounts does not replace an existing layer; delete it here first. A visit layer derived from the deleted layer is reported and kept. | Yes | No | No | No |
delete_routeRoute delete: removes one whole route from the Territory Solution and the open map, in one synchronous call. Needs route_id or the route's exact unique label, plus map_session_id or ts_handle. A route that is already gone returns ok with already_absent=true; an ambiguous label returns AMBIGUOUS_ROUTE with matching_route_ids. A single stop is removed by recalculating the same route_id with calculate_route. | Yes | No | No | No |
delete_talDeletes one whole territory alignment (TAL: 'the territory layer', 'all territories') from the Territory Solution and the open map, in one synchronous call. Needs tal_id or the TAL's exact unique label, plus map_session_id or ts_handle. Points, part-layer overlays, and routes stay; the map switches to a remaining alignment or to points only. A TAL that is already gone returns ok with already_absent=true; an ambiguous label returns AMBIGUOUS_TAL. One territory is removed with delete_territory instead. | Yes | No | No | No |
delete_territoryDeletes one leaf territory from an alignment; its parts become unassigned. Needs tal_id, territory_id (the leaf id or its exact unique display name), and the Territory Solution from map_session_id or ts_handle. A territory that is already gone returns ok with already_absent=true and no task; otherwise returns a task and the open map repaints. Related: territory_merge hands a leaving rep's territory to its neighbors; delete_tal removes a whole alignment in one call. | Yes | No | No | No |
direct_buildBuilds territories from known part-to-territory assignments (a ZIP-to-territory sheet or file, including a three-level region/district/territory hierarchy via territory_path) and adds them to the Territory Solution as a new alignment (TAL). Assignments come only as an assignments_handle (aup_...) from request_assignment_upload (the file, csv_text, or assignment rows). Sheets with Postal Code plus Territory/Region/Division columns are mapped automatically. Duplicate part_ids follow duplicate_part_policy (default keep_first). Returns a task; the result carries tal_id and ts_handle and paints the open map. Location points load with ingest_accounts; balanced partitions come from auto_build; grouping by a column is account_build. | No | No | No | No |
discover_intentMaps a free-text territory request to a workflow. Read-only keyword routing; no compute. Returns intent_category, the recommended tool order, the main tool (tier1_tool, null when the request is ambiguous) and alternatives, required_inputs, clarifying_questions for missing inputs, and the workflow guide inline as guidance {uri, title, excerpt}. Covers building territories (auto_build, account_build, direct_build, cluster_points, seed_build), editing (realign, split, merge, rebalance), analyze, geocoding and ingest, showing a ZIP or part layer, routes, drive-time areas (isochrone_build), recurring visit schedules (schedule_visits), contractor coverage gaps (analyze_network_coverage), listing points in a territory (points_in_territory), and moving a Territory Solution to or from EasyTerritory Designer. | No | Yes | Yes | No |
ensure_map_viewerReports whether the person has the map open (viewer_status.connected) for a map_session_id from get_map_visualization, waiting up to wait_seconds (max 30 s per call; the result reports requested_wait_seconds and max_wait_seconds). Works the same for the in-chat map and the map_url tab. Returns VIEWER_NOT_CONNECTED while the map is still closed; the same call can be repeated while the person opens it. Build, analyze, and selection results paint live once the viewer is connected. | No | Yes | Yes | No |
ep_graph_traverseTraverses the EMEP knowledge graph from a topic file (e.g. 'workflows/realign-by-selection.md') to related guidance, up to `depth` hops. Returns no edges unless the pack ships a _graph.yaml. | No | Yes | Yes | No |
ep_list_topicsLists EMEP topics grouped by type (concept, workflow, interface, troubleshooting, decision). Optional `type` filter. | No | Yes | Yes | No |
ep_searchSemantic search over the EZT MCP Expert Pack (EMEP): workflow guidance, concepts, interfaces, and common mistakes. Returns ranked markdown chunks with source files; atoms pulled in via `requires` are flagged requires_expanded. Degrades to the ezt://guidance/... resources if retrieval is unavailable. Examples: 'build balanced territories from accounts', 'viewer not connected before compute', 'auto_build vs account_build'. | No | Yes | Yes | No |
export_geojsonExports the territory solution as one GeoJSON file to share, archive, or open in EasyTerritory Designer: territory polygons with part_ids, points, and routes with numbered stops, each carrying its displayed style. tal_ids, point_layers, and route_layers narrow it; include_points / include_routes omit a family. Input: map_session_id, ts_handle, or a completed build job_id. Returns a task whose result is geojson_artifact, share_url (key-less browser download for one hour; give the user share_with_user), and download_url (GET with the API key), never an inline body. Both serve a plain .geojson file. import_geojson reopens the file. | No | No | No | No |
extract_tal_branchExtracts one regional branch of a hierarchical alignment (by branch_rollup_territory_id or branch_territory_path) into its own Territory Solution, so a delegate can edit just that region. Returns the extract plus branch_metadata, which reintegrate_branch needs later. exclude_locked (default true) leaves locked territories out. | No | No | No | No |
eztPlain-language orchestrator: takes request (the goal) and runs the matching workflow in one call, optionally with csv_file (a host file parameter), accounts_handle, assignments_handle, map_session_id, or ts_handle. An uploaded CSV is parsed, staged, and ingested onto the open map. target_hours / workload_target map to a fixed-workload auto_build. Missing build inputs (part layer, alignment name, sizing, balance, dwell) return CLARIFICATION_REQUIRED with the questions. The granular tools do the same steps individually. | No | No | No | Yes |
geocode_addressGeocode-only pass: turns staged customer addresses into coordinates with match confidence, without loading a map layer. The rows are staged with request_account_upload (file, csv_text, or rows; up to 10,000 rows here) and passed as its upload_handle; the handle is not claimed, so ingest_accounts can load the same rows afterward. Accepts address/address_line1/street, city, state, and postal columns (common source headers are mapped). accept_suboptimal_geocodes=true accepts ZIP-centroid matches. Each address is billed once: cached no-match and suboptimal verdicts return free (failed_rows cached_verdict); a corrected address is a new lookup. Billable lookups count against a monthly per-key quota, and past it the result is PROVIDER_QUOTA_EXCEEDED with limit, used, remaining, and period_resets_at. Returns a task; the result has summary, sample_rows (10), failed_rows (first 50), a geocoded_rows_artifact with share_url for every row, and suggested_ingest. ingest_accounts alone also geocodes while it loads the map layer. | No | No | No | Yes |
get_guidanceReturns the EZT MCP operating guide: the cross-tool workflow order and shared rules (result.text, same text as the server instructions), result.server_version, and result.seat for the caller's key (plan standard|trial, key_expires_at, and quota_remaining for geocoding, routing, and isochrone requests). Read-only. Useful at the start of a session or for a host that does not show server instructions. | No | Yes | Yes | No |
get_map_selectionReturns the most recent committed selection on an open map session (map_session_id): part_layer, part_ids, and selection_task_id when the selection came from request_part_selection. Covers selections the person started from the map legend. realign takes these part_ids as moves with a leaf territory_id. | No | Yes | Yes | No |
get_map_visualizationOpens the interactive territory map (Map Component) and returns map_url and map_session_id. Opens a blank map, or shows the latest state of an existing Territory Solution (e.g. yesterday's work) from ts_handle or a completed job_id. Idempotent per user_id: a second call returns the same map. new_project=true replaces the open workspace with an empty project. theme: dark | light (basemap and UI style; default dark). presentation.view_name: empty | points_only | review | selection. Apps-capable hosts render the map in chat (ui://easyterritory/map-viewer); other clients open map_url in a browser. Later map tools take map_session_id. ensure_map_viewer reports when the person has the map open. | No | No | No | No |
get_part_selectionReturns the state of a map selection task (selection_task_id from request_part_selection, or active_selection_task_id in ezt://map-sessions/{id}/state): status awaiting_user_selection, committed, expired, or cancelled, and once committed the selected part_ids (with assigned and unassigned part_ids when a TAL is active). While awaiting, the response carries recommended_poll_delay_ms. Committed part_ids feed realign, create_territory_from_parts, or analyze. | No | Yes | Yes | No |
import_dataverse_viewMicrosoft Copilot only (Entra sign-in): reads a Dynamics 365 account view server to server, as the signed-in user, and stages it as an account upload. No rows pass through the agent. view_id (or an exact view_name) comes from list_dataverse_views. The server adds accountid, name, and the address1 location columns to the view; they arrive as latitude, longitude, address, city, state, postal_code, country. Returns a task (follow next_action / sleep_ms, fetch the result once); the result is the same shape as an account upload: upload_handle, row_count, csv_headers, preview, upload_warnings, geocode_plan, and suggested_ingest. Confirm the column roles with the user, then ingest_accounts(**suggested_ingest.args). Limit 100,000 accounts (DATAVERSE_VIEW_TOO_LARGE). Other clients get DATAVERSE_NOT_AVAILABLE: use request_account_upload instead. | No | No | No | Yes |
import_designer_projectOpens an EasyTerritory Designer project as a Territory Solution: the server exports it from Designer and imports it (part-based territories, non-part polygon areas such as radius buffers or hand-drawn shapes, point layers up to 250,000 features with Designer symbols/classifications, and routes). No file passes through the agent. Returns a task; the result has ts_handle and designer_warnings. With map_session_id the project replaces the open map's content. include_points / point_layers / include_routes / include_manual_polygons narrow it; part_layer forces the part layer. A Designer part layer is mapped to its EZT part layer id (listed in designer_warnings); one with no EZT match fails UNKNOWN_PART_LAYER with available_part_layers; retry with the user's choice as part_layer. Requires link_designer; project_id comes from list_designer_projects. | No | No | No | Yes |
import_geojsonOpens a GeoJSON FeatureCollection (points, or a territory file, plain or gzip/zip) as a Territory Solution; returns ts_handle and a summary. A file of any real size moves by reference, never inline: call with no file argument for an upload_url (give the user share_with_user, or POST it with curl_example), then poll import_geojson(upload_handle) every recommended_poll_delay_ms until upload_status=received. geojson_file takes a host file (download_url). Inline geojson / geojson_text / geojson_gzip take at most 256 KB; a larger one returns INLINE_PAYLOAD_TOO_LARGE with the upload_url call to make. Polygons without part_ids import as polygon areas with tal_kind="polygon" (measured by point-in-polygon), or convert to parts with part_layer + overlay_policy="centroid_within". For a Designer project, use import_designer_project. | No | No | No | Yes |
ingest_accountsAccount ingest: loads account rows (CRM records, a CSV, a spreadsheet) as point data on a named point layer of the Territory Solution, to add them to the map, geocoding rows without coordinates. Rows come only as accounts_handle from request_account_upload (a file, csv_text, or rows; 100,000-row cap); its suggested_ingest carries these args. latitude/lat and longitude/lon/lng pass through; other names need latitude_field/longitude_field, and unused coordinate-like columns return CLARIFICATION_REQUIRED (needs_coordinate_fields). id_field is a unique key (default row_id); duplicates return needs_unique_row_id. Only declared columns are kept: metric_fields, workload_fields, dwell_time_field, visit_frequency_field, grouping_fields, display_fields, search_fields; to load a contractor list, layer_role=contractors adds trade_field, tier_field, capacity_field, service_zip_field (analyze_network_coverage). Later use of an undeclared column returns UNDECLARED_FIELD. Over geocode quota fails it whole; a bad address bills once (fix it to retry). Returns a task with failed_rows and map_refresh. | No | No | No | Yes |
isochrone_buildDraws the area reachable by driving from one or more origins within a time or distance budget (drive-time area, service area, catchment) and adds each area as a territory in a drive-time alignment. origins: inline {latitude, longitude} or a point-layer reference. bands: [{time_budget_seconds} or {distance_budget_meters}], one unit per call (MIXED_BUDGET_TYPES otherwise); one band gives one area per origin, several give nested areas. Limits: 25 origins, 5 bands, 6 hours, 500 km; travel_mode car or truck; depart_at supported. Areas are the provider polygons and may overlap; analyze counts accounts in every area containing them. realign/split/merge/rebalance return ISOCHRONE_TAL_NOT_EDITABLE. A band budget is not territory workload or route time. No provider key returns ISOCHRONE_NOT_CONFIGURED; the full call count is checked against the monthly quota first (PROVIDER_QUOTA_EXCEEDED). Returns a task. | No | No | No | Yes |
link_designerConnects the customer's EasyTerritory Designer account so list_designer_projects, import_designer_project, and push_to_designer can call Designer from the server. Returns status linked (designer_origin, designer_user) or waiting_for_user with a link_url and share_with_user. The user pastes their Designer agent token (ezt_pat_...) on that page; the token is never a tool argument and never appears in a result. Repeated calls report the status; recommended_poll_delay_ms is the interval. unlink=true removes the stored link. | Yes | No | No | Yes |
list_dataverse_viewsMicrosoft Copilot only (Entra sign-in): lists the Dynamics 365 account views the signed-in user can read, so their accounts import without a file. Without environment_url it lists the user's environments; with one environment it goes straight to its views, with several it returns status choose_environment and an ask_user. Views carry view_id, name, kind (system | personal), and is_default; point_readiness samples active accounts for coordinates vs address-only (address rows are geocoded at ingest). Next: import_dataverse_view(environment_url, view_id). Other clients get DATAVERSE_NOT_AVAILABLE: use request_account_upload (a CSV file) or list_designer_projects instead. DATAVERSE_CONSENT_REQUIRED carries admin_consent_url for the user's Microsoft admin. | No | Yes | Yes | Yes |
list_designer_projectsLists the EasyTerritory Designer rolodex projects the linked Designer user can read: project_id, label, description, tags, saved_at, is_mine, and layers (point data present). q filters by text, tag by rolodex tag, mine=true to the user's own. project_id is the input to import_designer_project and push_to_designer. Without a link the error is DESIGNER_NOT_LINKED (see link_designer). | No | Yes | Yes | Yes |
list_part_layersReturns the available canonical part layers for territory construction (for example us_zips, us_counties, ca_fsa, and active country postal or administrative polygon layers), with the same metadata as ezt://part-layers: part_layer, label, description, country_codes, admin_levels, part_count, id_format, example_part_ids, capabilities, data_version, and updated_at. Optional part_layer returns detailed metadata for one layer (bbox, aliases, supported_admin1, source_name, source_vintage, id_format_notes) or UNKNOWN_PART_LAYER. Optional country_code filters by 2-letter ISO country code. Read-only. | No | Yes | Yes | No |
load_analysis_panelShows a completed analyze result in the open map's analysis dock (single or compare). Needs map_session_id and the analyze task_id/job_id or the full analyze result (with tal_analyses and ts_identity; a partial object returns INVALID_REQUEST). presentation_mode: single, compare, executive, or diagnostic. dismiss=true hides the dock and keeps the statistics on the session. Changes nothing in the Territory Solution. analyze with analysis_panel=single fills the dock in the same call. | No | No | No | No |
points_in_territoryLists which account points from one point layer fall inside a territory polygon or a drive-time (isochrone) area. Per territory: point_count, metric_sums (metrics, else the layer's declared metric fields), and a sample of sample_size points (default 25, max 200; 500 across all territories) with label and metric fields, or only the fields you name. Counts and sums cover every inside point. The full list is never inline: it is in points_artifact, via download_url (GET with the API key) or share_with_user (one-hour key-less link for the user). Synchronous, read-only; needs map_session_id or ts_handle. territory_id names one leaf (id or unique display name), territory_ids several; omit both for every leaf in the TAL (tal_id, else the active or sole TAL). point_layer defaults to the sole layer with points; point_filter (e.g. {tier: 'Gold'}) filters before counting. A point counts in every containing polygon; overlaps lists shared points. Unknown ids return UNKNOWN_TAL_ID / UNKNOWN_TERRITORY_ID / UNKNOWN_POINT_LAYER with the available values. | No | Yes | Yes | No |
publish_to_dataverseMicrosoft Copilot (Entra sign-in): writes stamped point-layer columns back to Dynamics 365 account records keyed by accountid (1:1 Account PATCH). Needs map_session_id or ts_handle. Point layers carry derived stamps from builds/realign (part_id, territory_id, territory_label), calculate_route (route_id, route_label, stop_sequence), schedule_visits (schedule_id, visit_count, schedule_days, schedule_dates, contractor_id, contractor_label), isochrone_build (isochrone_tal_id, isochrone_ids, isochrone_labels, isochrone_count), and cluster_points (group_id, group_label). A <point_layer>_visits layer resolves to its 1:1 parent account layer and maps schedule_day/date to schedule_days/dates. field_map maps point columns to Dynamics account logical attributes (primitive columns or territoryid / ownerid lookups resolved by name or GUID). With confirm=false (default) or no field_map, runs a read-only preflight returning status=confirmation_required, stamped_columns, candidate_target_attributes, preview_updates, and ask_user. With confirm=true, queues the batch PATCH task. | Yes | No | No | Yes |
push_to_designerSaves a Territory Solution in EasyTerritory Designer from the server. Without project_id it creates a new rolodex project named label (the user's choice; a missing label returns CLARIFICATION_REQUIRED). With project_id it overwrites that project's territories, points, and routes in place. Input: map_session_id, ts_handle, or a completed build job_id. Returns a task; the result has project_id, url, and share_with_user. part_layer_id binds the Designer catalog layer (default: the layer a pulled TAL came from); tal_id picks the alignment; include_points=false sends territories and routes only. Route stops link to point layers by point_id. run_plugin / push_power_bi (default false) run the project's post-save plugin / refresh Power BI. Requires link_designer. | Yes | No | No | Yes |
query_partsReturns attributes (no geometry) for parts of a part layer listed by list_part_layers or ezt://part-layers. Takes exactly one of filter (e.g. {state_abbr: TX}) or part_ids; neither or both returns INVALID_REQUEST. Paged with page_token. TAL membership (each needs map_session_id or ts_handle inside): filter.in_tal {tal_id, territory_ids?} keeps only the parts that TAL assigns (its whole footprint, however many separate regions; territory_ids narrows to those territories and everything under them); filter.not_in_tal {tal_id} drops that TAL's parts (white space), e.g. {state_abbr: TX, not_in_tal: {...}}. Both AND with other predicates. total_count is the set size. Build from it with the same part_filter. | No | Yes | Yes | No |
realignMoves ZIPs or other parts (typed ids or ones selected on the map) from one territory into another within one alignment (tal_id): a ZIP move. moves=[{part_id, to_territory_id}], or realign_operation with part_ids. The Territory Solution comes from map_session_id (the open map) or ts_handle; expected_revision adds optimistic concurrency (STALE_TS_REVISION when the map changed). to_territory_id is a leaf territory_id or that leaf's exact, unique display name; an unknown or ambiguous value returns UNKNOWN_TERRITORY_ID or AMBIGUOUS_TERRITORY with available_leaf_territories. A committed map selection is read with get_map_selection; request_part_selection lets the person pick parts on the map. remove_empty_territories drops leaves left with no parts. Returns a task; the open map repaints. analyze refreshes statistics when the map has account points. | Yes | No | No | No |
reintegrate_branchMerges an edited branch (proposal Territory Solution from extract_tal_branch) back into the master. Needs branch_metadata and expected_master_revision; returns STALE_TS_REVISION when the master changed since the extract, in which case a fresh extract is needed. Merges apply one at a time. | Yes | No | No | No |
request_account_uploadThe one way account or address rows enter the server: stages them for ingest_accounts (accounts_handle) or geocode_address (upload_handle) and returns upload_handle, csv_headers, and suggested_ingest args with a geocode_plan. Ways in: the returned upload_url (no API key; valid up to 1 hour), which the user opens in a browser to drop a CSV or .xlsx (result.share_with_user; the path for a file the client cannot read, e.g. a SharePoint link) or a shell POSTs to (curl_example); csv_file (a host file parameter); csv_text (raw CSV, up to 25 MB per call); or rows chunks appended with upload_handle. A call with only upload_handle polls: upload_status waiting_for_file (sleep recommended_poll_delay_ms) or received, with preview (sample rows, column profile) and upload_warnings whose ask_user goes to the user before ingest. A local path in csv_file returns UNREADABLE_FILE_REFERENCE; an expired URL returns UPLOAD_TOKEN_EXPIRED and a call with upload_handle issues a new one. One handle holds at most 100,000 rows and is single-use, claimed by ingest_accounts, for 1 hour. | No | No | No | No |
request_assignment_uploadThe one way part-to-territory assignment rows (e.g. a ZIP-to-territory spreadsheet with Postal Code plus Territory/Region/Division) enter the server: stages them for direct_build (assignments_handle) and returns upload_handle. Same ways in as request_account_upload: upload_url (no API key; up to 1 hour; the user opens it in a browser to drop a CSV or .xlsx, or a shell POSTs the file), csv_file, csv_text (newlines preserved), or assignment chunks appended with upload_handle; poll with only upload_handle until upload_status is received. Legacy columns map to part_id and territory_path automatically. A file of locations rather than assignments is redirected to request_account_upload. The handle is single-use and expires after 1 hour by default. | No | No | No | No |
request_part_selectionLets the person adjust boundaries by picking parts (e.g. ZIPs) on the map: puts the open map into select mode on a part_layer, for purpose realign, a new territory, or a plain list. Returns selection_task_id; get_part_selection reports status (awaiting_user_selection, then committed, expired, or cancelled) and the committed part_ids, and its response carries recommended_poll_delay_ms. The commit happens on the map, not in chat. destination_territory_id and realign_operation pre-set a realign. Works on the in-chat map and the map_url tab. map_session_id selects on the open map; ts_handle opens a stored Territory Solution first. initial_part_filter opens with a set pre-selected (e.g. in_tal or white space not_in_tal) for the person to trim; build from the committed set with part_filter {selection_task_id}. A selection the person started from the map legend is read with get_map_selection. | No | No | No | No |
schedule_visitsSchedules recurring visits: expands each cadence (e.g. every 7 days) across a horizon and packs visits into daily buckets under a technician-day cap. Decides which day each visit happens (auto_build and cluster_points divide accounts among people); creates no alignment. Needs point_layer (ingested with cadence declared, else UNDECLARED_FIELD), visit_frequency_field, dwell_time, and daily_capacity ({mode: not_to_exceed, hours: 8}); missing dwell or capacity returns CLARIFICATION_REQUIRED. Omitted max_buckets_per_day means one technician per day; when one does not fit, CLARIFICATION_REQUIRED carries capacity_plan. estimate_only=true returns capacity_plan. contractors (point_layer or list: start, pre_service_stops, route_type, end) anchors buckets; unanchored one-stop days warn SINGLE_STOP_DAYS. frequency_unit: interval_days or visits_per_horizon. bucket_workload_hours (drive plus dwell) is a different measure from territory workload and route_workload_hours. Returns a task. calculate_route on one bucket_id drives that day. Date limits: visit_constraints with horizon_start_date. | No | No | No | No |
seed_buildGrows one territory outward from a seed {longitude, latitude} over a part layer until it holds a target: {type: location_count, value: N} or {type: metric_sum, field: <declared metric>, value: X}, counted from an ingested point layer. Adds the territory as a leaf of tal_id, or as a new alignment. Fit is closest: target_status is reached, closest_under, closest_over, frontier_exhausted, or max_parts_reached, with SEED_TARGET_UNDERSHOT/OVERSHOT warnings and the difference. Parts already in that alignment are never taken; the territory grows around them (blocked_part_count, seed_offset_km), and a seed inside an assigned part returns SEED_PART_ASSIGNED. part_scope=explicit with part_filter confines growth to an area (not_in_tal: {tal_id} keeps it out of another TAL; in_tal: {tal_id} keeps it inside one, with no tal_id so it starts a new alignment). One seed per call. An undeclared metric field returns UNDECLARED_FIELD. Returns a task with created_territory and ts_handle; the open map repaints with map_session_id. | No | No | No | No |
set_map_stateChanges the open map's session state: mode, active alignment (active_tal_id), pending job reference, or camera (center [longitude, latitude] and zoom 0-24). Session only: the Territory Solution is not changed (configure_map sets a durable default view). The result's render_ack is read at publish time, so sent_unconfirmed one version behind is normal; render_ack_hint says whether to reread ezt://map-sessions/{map_session_id}/state or resend. camera reports the view in effect and its source (requested, session, map_config, or viewer_current). A set camera stays until changed; switching alignment does not refit. | No | Yes | Yes | No |
show_map_overlayShows or hides something on the open map from a plain request ('add US zip codes', 'hide the zips', 'show my accounts') or overlay_kind (part_layer, point_layer, tal, route) with overlay_id. Part layers load at a zoom where they are visible (visibility.camera_action); hiding a part layer leaves territories unchanged. Point layers must already be ingested; a layer in the Territory Solution but missing from the map is re-pushed (status=refreshed, with render_ack). Point layers have no hidden state: hide wording returns HIDE_NOT_SUPPORTED with do_this_next delete_point_layer, which removes the layer; the legend checkbox hides one in a single tab. route re-shows or hides routes calculate_route drew (route_id targets one); with no route yet it returns blocked_by=needs_route. When the user named a camera, do_this_next carries the configure_map call that sets it. Input: map_session_id (preferred) or ts_handle. | No | No | No | No |
submit_feedbackSends product feedback to EasyTerritory: a blocked or partial workflow, a workaround, a confusing response, or a missing capability. Returns an acknowledgement with feedback_id. Secrets, emails, Territory Solution JSON, GeoJSON, and account/CSV tables are stripped before storage; the text is meant for a description of what happened, not data. | No | No | No | No |
tasks_cancelTool equivalent of the native MCP tasks/cancel, listed for clients without the Tasks capability. Requests cooperative cancellation of a task_id and returns the Task status document. Whether the Territory Solution is unchanged or partially updated follows the originating tool. | Yes | No | No | No |
tasks_getTool equivalent of the native MCP tasks/get, listed for clients without the Tasks capability. Returns the Task status document for a task_id (holding up to wait_ms while the task is working). next_action is sleep_and_poll (wait sleep_ms, then one tasks_get), consume_result (one tasks_result call), or stop_error. status=cancelled means the user stopped it. While queued, _meta carries queue_position, queue_depth, queue_lane, and estimated_start_ms, which is advisory and not a wait time. Polling never starts work. | No | Yes | Yes | No |
tasks_resultTool equivalent of the native MCP tasks/result, listed for clients without the Tasks capability. Returns the originating tool's terminal result once the task status is completed (consume_result): ts_handle, counts, timings, and map binding, never an inline Territory Solution. A build's ts_handle or task_id (as job_id) is the input analyze takes. | No | Yes | Yes | No |
territory_mergeMerges a pair of adjacent territories (N to N-1 territories). By default, territory_id_b is folded into territory_id_a (or renamed to new_territory_label) and the rest of the alignment rebalances with minimal disruption, e.g. when a rep leaves and neighbors absorb the territory. Set preserve_other_territories=true for an exact two-territory union that combines only territory_id_a and territory_id_b (optionally named new_territory_label) and leaves every other territory unchanged with no rebalance. Non-adjacent ids return NON_ADJACENT_TERRITORIES. Needs source_tal_id and the Territory Solution from map_session_id or ts_handle; workload rebalance needs dwell_time (CLARIFICATION_REQUIRED otherwise). Writes a new derived alignment. Returns a task. | Yes | No | No | No |
territory_rebalanceRebalances an existing alignment after the account data changed, keeping it as close to the current alignment as possible. Needs source_tal_id and the Territory Solution from map_session_id or ts_handle. point_layer defaults to the alignment's build layer or the only point layer; otherwise CLARIFICATION_REQUIRED (ambiguous_point_layer, with details.point_layers). Workload balance needs dwell_time; zero_workload means no account maps to a part. The current alignment is the baseline: when nothing improves the objective the result is NO_IMPROVING_REBALANCE_FOUND and nothing changes. Writes a new derived alignment. Returns a task with retention_pct and solver_diagnostics. | Yes | No | No | No |
territory_splitTerritory split: divides one territory (e.g. an oversized one) into two while changing the rest of the alignment as little as possible (N to N+1 territories). Needs source_tal_id and target_territory_id, plus the Territory Solution from map_session_id (the open map) or ts_handle. Workload balance needs dwell_time; a missing id or dwell returns CLARIFICATION_REQUIRED with the question. Writes a new derived alignment; the source stays. Returns a task; the result carries disruption_summary (retention_pct). | Yes | No | No | No |
workflow_advisorReturns the next tool call for a multi-step workflow, given where the workflow stands. Read-only state machine; executes nothing. intent_category: build_from_accounts | account_grouping | known_assignments | realign_existing | restructure | load_part_layer | route_stops | reachable_area | periodic_scheduling | coverage_gap_analysis | points_in_territory. state: viewer_connected, point_layer, part_layer, tal_present, analysis_fresh, plus selection/realign or restructure flags. inputs: the values known so far (part_layer, territory_count, tal_id, operation, route_type, origins, visit_frequency_field, ...); missing_inputs names the keys still needed. Returns next_tool with drafted next_args, missing_inputs (reported, never invented), blocked_by, remaining_steps, and the workflow guide inline as guidance. Order rules applied: map before compute, viewer connected before compute, ingest before build, analyze after an edit when a point layer exists. Calling it after each step with the updated state walks the whole workflow. | No | Yes | Yes | No |
Details
- Registry status
- Active
- Published
- Sep 29, 2026
- Updated
- Sep 29, 2026
- Repository
- Not given
- Categories (suggested)
- Project managementData and analyticsSuggested categories are assigned automatically from the registry text and may be wrong. Verified operators can correct them.
- GDPR
- Not declared