EasyTerritory MCP
by easyterritory.ai · remote · no sign-in to list tools · v0.1.0 · published by ai.easyterritory
Build, balance, realign and analyze sales/service territories; geocode, route, schedule, live map.
51 tools: 23 can delete or cancel things, 1 do something that can't be undone, 16 change things and 11 only read.
Scanned Oct 21, 2026
- Deletes or cancels23Claude Code: deny: see these tools
- Can't be undone1Claude Code: ask: see these tools
- Changes things16Claude Code: ask: see these tools
- Only reads11Claude Code: allow: see these tools
6 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http ezt https://mcp.easyterritory.ai/ --header 'Authorization: <your-authorization>'Findings
Matches of fixed checks, with the text they matched.
The server marks "get_map_visualization" destructive (destructiveHint: true), and its name says "get", a word for reading.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}; The name "get_map_visualization" says "get": a word for reading.
- Warnsubmit_feedback
The input schema at $defs.FeedbackCategoryParam.enum[1] names a tool "gap" that this server does not list.
What this check looks forMatched text
inputSchema.$defs.FeedbackCategoryParam.enum[1]: "mcp_tool_gap"
The server marks "analyze_network_coverage" destructive (destructiveHint: true), and its name says "analyze", a word for reading.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}; The name "analyze_network_coverage" says "analyze": a word for reading.
- Warnanalyze
The server marks "analyze" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "analyze" says "analyze": a word for reading.
The server marks "load_analysis_panel" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The description's first verb is "show": a word for reading.
- Warnshow_map_overlay
The server marks "show_map_overlay" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "show_map_overlay" says "show": a word for reading.
Tools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
51 tools
Deletes or cancels 23Claude Code: deny
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).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Builds 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}. 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Build Territories by Account Field
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 ce…1 finding
Why it is in this group
- The name "analyze_network_coverage" says "analyze": a word for reading.
- The server marks it destructive (destructiveHint: true).
Findings
- Warn
The server marks "analyze_network_coverage" destructive (destructiveHint: true), and its name says "analyze", a word for reading.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}; The name "analyze_network_coverage" says "analyze": a word for reading.
Description, as the server wrote it Finds 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Analyze Contractor Network Coverage
auto_buildPartitions ingested account points into balanced sales territories with equal workload, metric, or count over a part layer (e.g.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Partitions 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 for drive time + dwell; metric + metric_bias for a column such as Revenue; biases sum to 100), and dwell_time (a column or a stated scalar). Each missing choice returns CLARIFICATION_REQUIRED with ask_user; a declared visit-frequency column also needs visit_frequency_field or ignore_visit_frequency. part_scope: bbox_intersect (default; parts near the accounts, can reach national scale) or explicit with part_filter, e.g. {state_abbr: TX}. The filter limits parts; accounts outside it stay on the layer, unassigned (UNASSIGNED_ACCOUNTS). With map_session_id the open map is the input. Returns a task; national builds take minutes and estimated_remaining_ms is capped, not a forecast. The result carries tal_id, ts_handle, and phase_timings_ms; analyze has statistics.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Auto-Build Territories
cluster_pointsGroups the points of one ingested layer into balanced clusters directly, with no ZIP or part layer and no territory alignment.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Groups 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 10,000 points after the filter. seed_point_layer, a second point layer such as technician homes, anchors one group per seed (the seed count matches the group count, else seed_count_mismatch); 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Cluster Points
configure_mapUpdates map settings on the Territory Solution and refreshes the live map: project_name (map heading), loaded_part_layers ([] hides ZIP/part outlines; builds never load them), acti…No findings
Why it is in this group
- The description's first verb is "update": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Updates map settings on the Territory Solution and refreshes the live map: project_name (map heading), 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 include circle, square, triangle, diamond, star, cross, house, pin, flag, hexagon, pentagon, shield, arrow_up, building, person. classification without point_layer is a project-level setting that does not color points. Input: map_session_id (the live map), ts_handle, or ts.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Configure Map
create_territory_from_partsCreates one leaf territory from a list of part_ids (e.g.No findings
Why it is in this group
- The name "create_territory_from_parts" says "create": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Creates 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Create Territory from Parts
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.No findings
Why it is in this group
- The name "delete_point_layer" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Point-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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Delete Point Layer
delete_routeRoute delete: removes one whole route from the Territory Solution and the open map, in one synchronous call.No findings
Why it is in this group
- The name "delete_route" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Route 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Delete Route
delete_talDeletes one whole territory alignment (TAL: 'the territory layer', 'all territories') from the Territory Solution and the open map, in one synchronous call.No findings
Why it is in this group
- The name "delete_tal" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Deletes 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Delete Alignment
delete_territoryDeletes one leaf territory from an alignment; its parts become unassigned.No findings
Why it is in this group
- The name "delete_territory" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Deletes 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, ts_handle, or ts. 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Delete Territory
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 a…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Builds 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 inline or as an assignments_handle (aup_...) from request_assignment_upload. 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Build Territories from Assignments
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 …No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Extracts 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Extract Alignment Branch
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_han…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Plain-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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: true
- readOnlyHint: false
- title: EasyTerritory Assistant
get_map_visualizationOpens the interactive territory map (Map Component) and returns map_url and map_session_id.1 finding
Why it is in this group
- The name "get_map_visualization" says "get": a word for reading.
- The description's first verb is "open": a word for a change.
- The server marks it destructive (destructiveHint: true).
Findings
- Warn
The server marks "get_map_visualization" destructive (destructiveHint: true), and its name says "get", a word for reading.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}; The name "get_map_visualization" says "get": a word for reading.
Description, as the server wrote it Opens 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, 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. 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Open Map
import_geojsonOpens a GeoJSON FeatureCollection (plain points, or a territory file this server produced, plain or gzip/zip) as a Territory Solution and returns ts_handle and a summary.No findings
Why it is in this group
- The name "import_geojson" says "import": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Opens a GeoJSON FeatureCollection (plain points, or a territory file this server produced, plain or gzip/zip) as a Territory Solution and returns ts_handle and a summary. Input: geojson (object), geojson_text, or geojson_gzip (base64). Territory polygons without part_ids return TERRITORY_POLYGONS_WITHOUT_PART_IDS unless part_layer plus overlay_policy=centroid_within assigns parts by centroid. point_layer names imported points; tal_label names the alignment. EasyTerritory Designer projects (REST/Agent/Projects/{projectId}/TerritorySolution) import as geojson_gzip.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Import GeoJSON
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.No findings
Why it is in this group
- The description's first verb is "move": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Moves 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), ts_handle, or ts; 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Realign Parts
reintegrate_branchMerges an edited branch (proposal Territory Solution from extract_tal_branch) back into the master.No findings
Why it is in this group
- The description's first verb is "merge": a word for a change that another call does not undo.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Merges 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Reintegrate Alignment Branch
schedule_visitsSchedules recurring visits: expands each account's cadence (e.g.No findings
Why it is in this group
- The name "schedule_visits" says "schedule": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Schedules recurring visits: expands each account's cadence (e.g. every 7 days, twice a month) across a horizon and packs the visits into daily work clusters (buckets) under a technician-day cap. Decides which day each visit happens (auto_build and cluster_points divide accounts among people instead); creates no alignment. Needs point_layer (ingested, with the cadence column declared, else UNDECLARED_FIELD), visit_frequency_field, dwell_time, and daily_capacity (e.g. {mode: not_to_exceed, hours: 8}); missing dwell or capacity returns CLARIFICATION_REQUIRED with the question. Optional contractors (point_layer or list with start, pre_service_stops, route_type, end) anchors each bucket to a contractor and includes stem travel. frequency_unit: interval_days or visits_per_horizon. never_visit_values are excluded. bucket_workload_hours is bucket drive plus dwell, a different measure from territory workload and route_workload_hours. Returns a task. calculate_route over one bucket_id drives that day. Date limits use visit_constraints with horizon_start_date.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Schedule Visits
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 met…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Grows 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. 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Grow Territory from Seed
tasks_cancelTool equivalent of the native MCP tasks/cancel, listed for clients without the Tasks capability.No findings
Why it is in this group
- The name "tasks_cancel" says "cancel": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Tool 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Cancel Task
territory_mergeMerges a pair of adjacent territories and rebalances the rest of the alignment with minimal disruption (N to N-1 territories), e.g.No findings
Why it is in this group
- The name "territory_merge" says "merge": a word for a change that another call does not undo.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Merges a pair of adjacent territories and rebalances the rest of the alignment with minimal disruption (N to N-1 territories), e.g. when a rep leaves and the neighbors absorb the territory. territory_id_b is the territory that goes away; territory_id_a is an adjacent neighbor that keeps its id. The same job rebalances every remaining territory. One call removes one territory; non-adjacent ids return NON_ADJACENT_TERRITORIES. Needs source_tal_id and the Territory Solution from map_session_id, ts_handle, or ts; workload balance needs dwell_time (CLARIFICATION_REQUIRED otherwise). Writes a new derived alignment. Returns a task.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Merge Territories
territory_rebalanceRebalances an existing alignment after the account data changed, keeping it as close to the current alignment as possible.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Rebalances 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, ts_handle, or ts. 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.
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Rebalance Territories
territory_splitTerritory split: divides one territory (e.g.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Territory 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), ts_handle, or ts. 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).
Annotations the server declares
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Split Territory
Can't be undone 1Claude Code: ask
submit_feedbackSends product feedback to EasyTerritory: a blocked or partial workflow, a workaround, a confusing response, or a missing capability.1 finding
Why it is in this group
- The name "submit_feedback" says "submit": a word for a change.
- The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
Findings
- Warn
The input schema at $defs.FeedbackCategoryParam.enum[1] names a tool "gap" that this server does not list.
What this check looks forMatched text
inputSchema.$defs.FeedbackCategoryParam.enum[1]: "mcp_tool_gap"
Description, as the server wrote it Sends 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Submit Feedback
Changes things 16Claude Code: ask
analyzeComputes territory statistics for one or more alignments, i.e.1 finding
Why it is in this group
- The name "analyze" says "analyze": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Warn
The server marks "analyze" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "analyze" says "analyze": a word for reading.
Description, as the server wrote it Computes 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, ts, 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, the question for the user. analysis_panel=single with map_session_id fills the map's analysis dock (analysis_panel.status=pushed). territories[].workload_total is minutes; hours are in territory_metric_grids. Drive-time alignments count accounts inside each polygon. Returns a task.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Analyze Territories
calculate_routeSequences and drives a set of stops, e.g.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Sequences 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). 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
- readOnlyHint: false
- title: Calculate Route
discover_intentMaps a free-text territory request to a workflow.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Maps 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Discover Workflow Intent
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 rep…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Reports 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Wait for Map Viewer
ep_graph_traverseTraverses the EMEP knowledge graph from a topic file (e.g.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Traverses 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Traverse Expert Pack Links
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, e…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Exports 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 plus a download_url (GET with the API key; gzip unless zip=false), not an inline body. import_geojson reopens the file.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Export GeoJSON
geocode_addressGeocodes a list of customer addresses to coordinates with match confidence, without loading them as a point layer.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Geocodes a list of customer addresses to coordinates with match confidence, without loading them as a point layer. Accepts address/address_line1/street, city, state, and postal columns (common CRM headers are mapped). accept_suboptimal_geocodes=true accepts ZIP-centroid matches. Cached addresses are free; 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 geocoded_rows, which ingest_accounts can load. ingest_accounts also geocodes on its own.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
- readOnlyHint: false
- title: Geocode Addresses
ingest_accountsAccount ingest: loads account or location 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…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Account ingest: loads account or location 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 inline (rows) or as accounts_handle from request_account_upload for large files; a client file path is unreadable. 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. label defaults to the point_layer id in title case. Returns a task; the result reports failed_rows, map_refresh, and geocode quota shortfall.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
- readOnlyHint: false
- title: Ingest Accounts
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 driv…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Draws 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
- readOnlyHint: false
- title: Build Drive-Time Area
load_analysis_panelShows a completed analyze result in the open map's analysis dock (single or compare).1 finding
Why it is in this group
- The description's first verb is "show": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Warn
The server marks "load_analysis_panel" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The description's first verb is "show": a word for reading.
Description, as the server wrote it Shows 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Load Analysis Panel
request_account_uploadStages account rows for ingest_accounts and returns upload_handle, csv_headers, and suggested_ingest args with a geocode_plan.No findings
Why it is in this group
- The name "request_account_upload" says "request": a word for a change.
Description, as the server wrote it Stages account rows for ingest_accounts and returns upload_handle, csv_headers, and suggested_ingest args with a geocode_plan. Four ways in: POST the CSV file to the returned upload_url (no API key; expires in 15 minutes; fastest for large files), csv_file (a host file parameter), csv_text (raw CSV, up to 16 MB, newlines preserved), or rows chunks appended with upload_handle. 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. The handle is single-use (claimed by ingest_accounts) and expires after 1 hour by default.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Request Account Upload
request_assignment_uploadStages part-to-territory assignment rows (e.g.No findings
Why it is in this group
- The name "request_assignment_upload" says "request": a word for a change.
Description, as the server wrote it Stages part-to-territory assignment rows (e.g. a ZIP-to-territory spreadsheet with Postal Code plus Territory/Region/Division) for direct_build and returns upload_handle. Same four ways in as request_account_upload: POST the file to upload_url (no API key; 15 minutes), csv_file, csv_text (newlines preserved), or assignment chunks appended with upload_handle. 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Request Assignment Upload
request_part_selectionLets the person adjust boundaries by picking parts (e.g.No findings
Why it is in this group
- The name "request_part_selection" says "request": a word for a change.
Description, as the server wrote it Lets 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. A selection the person started from the map legend is read with get_map_selection.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Request Part Selection
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).No findings
Why it is in this group
- The name "set_map_state" says "set": a word for a change.
Description, as the server wrote it Changes 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Set Map State
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 o…1 finding
Why it is in this group
- The name "show_map_overlay" says "show": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Warn
The server marks "show_map_overlay" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "show_map_overlay" says "show": a word for reading.
Description, as the server wrote it Shows 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), ts_handle, or ts.
Annotations the server declares
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
- readOnlyHint: false
- title: Show Map Overlay
tasks_resultTool equivalent of the native MCP tasks/result, listed for clients without the Tasks capability.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Tool 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 when a handle exists. A build's ts_handle or task_id (as job_id) is the input analyze takes.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Get Task Result
Only reads 11Claude Code: allow
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 multipl…No findings
Why it is in this group
- The name "analyze_routes" says "analyze": a word for reading.
Description, as the server wrote it Returns 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Analyze Routes
ep_list_topicsLists EMEP topics grouped by type (concept, workflow, interface, troubleshooting, decision).No findings
Why it is in this group
- The name "ep_list_topics" says "list": a word for reading.
Description, as the server wrote it Lists EMEP topics grouped by type (concept, workflow, interface, troubleshooting, decision). Optional `type` filter.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: List Expert Pack Topics
ep_searchSemantic search over the EZT MCP Expert Pack (EMEP): workflow guidance, concepts, interfaces, and common mistakes.No findings
Why it is in this group
- The name "ep_search" says "search": a word for reading.
Description, as the server wrote it Semantic 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'.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Search Expert Pack
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 …No findings
Why it is in this group
- The name "get_guidance" says "get": a word for reading.
Description, as the server wrote it Returns 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Get Startup Guidance
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…No findings
Why it is in this group
- The name "get_map_selection" says "get": a word for reading.
Description, as the server wrote it Returns 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Get Map Selection
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_select…No findings
Why it is in this group
- The name "get_part_selection" says "get": a word for reading.
Description, as the server wrote it Returns 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Get Part Selection
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 …No findings
Why it is in this group
- The name "list_part_layers" says "list": a word for reading.
Description, as the server wrote it Returns 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: List Part Layers
points_in_territoryLists which account points from one point layer fall inside a territory polygon or a drive-time (isochrone) area: per territory, the point ids, full properties, point_count, and me…No findings
Why it is in this group
- The description's first verb is "list": a word for reading.
Description, as the server wrote it Lists which account points from one point layer fall inside a territory polygon or a drive-time (isochrone) area: per territory, the point ids, full properties, point_count, and metric sums (metrics, else the layer's declared metric fields). Synchronous and read-only. Needs map_session_id or ts_handle. territory_id names one leaf (a stable territory_id or its exact unique display name); territory_ids names several; both omitted means every leaf in the TAL (tal_id, else the active or sole TAL). point_layer omitted uses the sole layer with points; point_filter (e.g. {tier: 'Gold'}) filters points by attribute before counting and listing. A point counts in every containing polygon, and overlaps lists points in more than one. max_points caps the points listed per territory (default 1000, max 10000); counts and sums always cover every inside point. Unknown ids return UNKNOWN_TAL_ID / UNKNOWN_TERRITORY_ID / UNKNOWN_POINT_LAYER with the available values. Territory statistics without the point list come from analyze.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Points in Territory
query_partsReturns attributes (no geometry) for parts of a part layer listed by list_part_layers or ezt://part-layers.No findings
Why it is in this group
- The name "query_parts" says "query": a word for reading.
Description, as the server wrote it Returns 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Query Territory Parts
tasks_getTool equivalent of the native MCP tasks/get, listed for clients without the Tasks capability.No findings
Why it is in this group
- The name "tasks_get" says "get": a word for reading.
Description, as the server wrote it Tool equivalent of the native MCP tasks/get, listed for clients without the Tasks capability. Returns the Task status document for a task_id. 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Get Task Status
workflow_advisorReturns the next tool call for a multi-step workflow, given where the workflow stands.No findings
Why it is in this group
- The description's first verb is "return": a word for reading.
Description, as the server wrote it Returns 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.
Annotations the server declares
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
- readOnlyHint: true
- title: Get Next Workflow Step
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Install
Pinned to version 0.1.0. Values in angle brackets are yours to fill in.
claude mcp add --transport http ezt https://mcp.easyterritory.ai/ --header 'Authorization: <your-authorization>'Run in a terminal.
Claude Code permissions
Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__ezt__get_guidance",
"mcp__ezt__workflow_advisor",
"mcp__ezt__ep_search",
"mcp__ezt__ep_list_topics",
"mcp__ezt__list_part_layers",
"mcp__ezt__query_parts",
"mcp__ezt__get_part_selection",
"mcp__ezt__analyze_routes",
"mcp__ezt__points_in_territory",
"mcp__ezt__tasks_get",
"mcp__ezt__get_map_selection"
],
"ask": [
"mcp__ezt__discover_intent",
"mcp__ezt__ep_graph_traverse",
"mcp__ezt__ensure_map_viewer",
"mcp__ezt__submit_feedback",
"mcp__ezt__request_part_selection",
"mcp__ezt__analyze",
"mcp__ezt__ingest_accounts",
"mcp__ezt__request_account_upload",
"mcp__ezt__request_assignment_upload",
"mcp__ezt__geocode_address",
"mcp__ezt__calculate_route",
"mcp__ezt__isochrone_build",
"mcp__ezt__tasks_result",
"mcp__ezt__set_map_state",
"mcp__ezt__load_analysis_panel",
"mcp__ezt__show_map_overlay",
"mcp__ezt__export_geojson"
],
"deny": [
"mcp__ezt__get_map_visualization",
"mcp__ezt__direct_build",
"mcp__ezt__auto_build",
"mcp__ezt__cluster_points",
"mcp__ezt__analyze_network_coverage",
"mcp__ezt__schedule_visits",
"mcp__ezt__account_build",
"mcp__ezt__realign",
"mcp__ezt__delete_tal",
"mcp__ezt__delete_territory",
"mcp__ezt__territory_split",
"mcp__ezt__territory_merge",
"mcp__ezt__territory_rebalance",
"mcp__ezt__extract_tal_branch",
"mcp__ezt__reintegrate_branch",
"mcp__ezt__create_territory_from_parts",
"mcp__ezt__seed_build",
"mcp__ezt__delete_route",
"mcp__ezt__delete_point_layer",
"mcp__ezt__tasks_cancel",
"mcp__ezt__configure_map",
"mcp__ezt__import_geojson",
"mcp__ezt__ezt"
]
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as ezt. Review it before you use it.