Skip to main content
Glama

AgentSUMO

An Agentic Framework for Interactive Simulation Scenario Generation in SUMO via Large Language Models

PyPI tests arXiv Docs License: MIT Python 3.10+ MCP Registry

Documentation · Installation · Tools · Schema · Tutorials


Overview

AgentSUMO lets non-expert stakeholders design, execute, and analyze SUMO traffic simulations through natural-language interaction. The Planner Agent translates abstract policy questions into executable simulation plans, drives them via the Model Context Protocol (MCP), and surfaces results through a web dashboard.

  • Conversational scenario design — describe a policy question, get a runnable simulation

  • Policy experiments — road closures, lane reductions, signal optimization, demand changes

  • Cross-scenario analysis — SQL-based comparison across runs, with auto-generated HTML reports

  • Web dashboard — geospatial visualization, time-series charts, and trip replay

Related MCP server: SUMO-MCP-Server

Demo

Web interface: conversational planning panel, scenario list, and live simulation status.

Geospatial visualization: per-edge metrics, congestion overlays, and trip replay on the 2.5D basemap.

Architecture

User (natural language)
    |
    v
Planner Agent (Claude LLM, Interactive Planning Protocol)
    |
    +--> AgentSUMO MCP Client --> AgentSUMO MCP Server (PyPI: agentsumo-mcp) --> SUMO
    |
    +--> SQLite MCP Client    --> SQLite MCP Server (Anthropic, open source)  --> simulations.db
    |
    +--> Filesystem MCP Client --> Filesystem MCP Server (Anthropic, open source) --> additional XML files

The reasoning layer (Planner Agent) lives in this repository. The execution layer (agentsumo-mcp) is published to PyPI and installed automatically as a dependency.

Tool Layer

The AgentSUMO MCP Server exposes 26 tools grouped into five capability categories that follow the simulation workflow. Full reference at agentsumo.readthedocs.io/.../tools.

Category

Purpose

Representative tools

Scenario Generation

Build a baseline SUMO simulation: OSM → network → trips → routes → run

osm_extract, net_convert, trip_generate, route_generate, sumo_runner

Policy Experimentation

Apply infrastructure, demand, and signal-control interventions

edge_edit_tool, reduce_lanes_tool, vehicle_generation_tool, flow_generation_tool, tls_offset_tool, tls_adaptation_tool

Result Analysis

Convert SUMO XML output to SQLite and render HTML reports

xml_to_sqlite_tool, simulation_report_tool

Visualization

Render networks, highlighted edges, and per-edge metric heatmaps

visualize_net_tool, visualize_edge_tool, visualize_policy_target_tool, visualize_edgedata_tool

Utility Functions

Network statistics, routing, road-name ↔ edge-id resolution, OD-coordinate validation, web-search grounding

network_summary_tool, route_analysis_tool, validate_od_coordinates_tool, web_search_tool

Installation

Requirements

  • Python 3.10 or later

  • SUMO 1.24 or later (locally installed, with SUMO_HOME set)

  • Anthropic Claude API key (bring-your-own-key)

  • Mapbox access token (used by the web map renderer)

1. Install SUMO

macOS

brew install sumo

Or download the installer from the Eclipse SUMO downloads page.

Windows — Download the installer from the Eclipse SUMO downloads page.

Linux (Ubuntu/Debian)

sudo add-apt-repository ppa:sumo/stable
sudo apt-get update
sudo apt-get install sumo sumo-tools sumo-doc

2. Set up the Python environment

Install uv:

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

Clone the repository, create a virtual environment, and install AgentSUMO:

git clone https://github.com/mw-jeong/AgentSUMO
cd AgentSUMO

# Create a Python 3.12 venv
uv venv --python 3.12

# Activate the venv
source .venv/bin/activate              # macOS / Linux
# .venv\Scripts\activate               # Windows

# Install AgentSUMO and all dependencies
# (this also pulls agentsumo-mcp from PyPI as a dependency)
uv pip install -e .

3. Configure environment variables

AgentSUMO reads API keys and the SUMO path from environment variables. The easiest way is a .env file at the project root:

cp .env.example .env

Open .env in your editor and fill in:

ANTHROPIC_API_KEY (required) — Claude API key that drives the Planner Agent. Get one at the Anthropic Console.

ANTHROPIC_API_KEY=sk-ant-api03-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

MAPBOX_TOKEN (required for the web UI) — used to render the basemap. Get one at the Mapbox access tokens page.

MAPBOX_TOKEN=pk.eyJ1Ijoixxxxxxxxxxxxxxxxxx

SUMO_HOME (required) — absolute path to your local SUMO installation. The directory must contain bin/sumo (or bin/sumo.exe on Windows).

# macOS (Homebrew)
SUMO_HOME=/opt/homebrew/share/sumo

# macOS (Eclipse SUMO installer)
SUMO_HOME=/Library/Frameworks/EclipseSUMO.framework/Versions/<version>/EclipseSUMO  # e.g. 1.24.0; use the directory name installed under Versions/

# Windows
SUMO_HOME=C:\Program Files (x86)\Eclipse\Sumo

# Linux
SUMO_HOME=/usr/share/sumo

AGENTSUMO_MCP_OUTPUT_BASE (optional) — override the base directory where the MCP server writes simulation outputs (networks, trips, results). Defaults to the current working directory.

AGENTSUMO_MCP_OUTPUT_BASE=/path/to/your/output/dir

4. Run

# Web interface (opens at http://localhost:8000)
python web.py

# CLI mode
python chat.py

# Clean up simulation outputs
python clean.py

Project Structure

AgentSUMO/
├── agentsumo/
│   ├── agent/        # Planner Agent (Claude orchestrator + prompts)
│   ├── client/       # MCP clients (AgentSUMO, SQLite, Filesystem)
│   └── core/         # Configuration
├── agentsumo_mcp/    # AgentSUMO MCP Server source (also published to PyPI)
│   └── defaults/     # Packaged fixtures (e.g., vehicle_types.add.xml)
├── packaging/mcp/    # PyPI build configuration for agentsumo-mcp
├── web/              # Web interface (FastAPI + Jinja2 templates)
├── docs/             # Sphinx documentation source
├── tests/            # Unit tests
├── assets/           # README images
├── output/           # Runtime artifacts (auto-populated; 8 categories tracked
│                     #   via .gitkeep — simulations/, networks/, trips/,
│                     #   analysis/, reports/, uploads/, visualizations/, additional/)
├── chat.py           # CLI entry point
├── web.py            # Web server entry point
└── .env.example      # Environment variable template

Use the MCP Server Standalone

The AgentSUMO MCP Server can be used independently from this framework with any MCP-compatible LLM client (Claude Desktop, OpenAI tool clients, Gemini, local LLMs):

pip install agentsumo-mcp

Or via uvx without installing:

uvx agentsumo-mcp

The server is registered in the official MCP Registry under io.github.mw-jeong/agentsumo-mcp.

Troubleshooting

SUMO path error — Verify SUMO_HOME in your .env. The directory must contain bin/sumo (or bin/sumo.exe on Windows).

API key error — Verify ANTHROPIC_API_KEY in your .env is set to a valid Claude API key. The Planner Agent will refuse to start without it.

Dependency error — Re-resolve dependencies:

uv pip install -e . --upgrade

Legacy token files (deprecated, scheduled for removal in 0.2.0) — AgentSUMO still falls back to claude_api.txt and mapbox_token.txt at the project root when the corresponding environment variables are missing, but those code paths now emit a DeprecationWarning at import time. Use the .env workflow for new installations.

Documentation

Full documentation lives at agentsumo.readthedocs.io.

  • Installation — SUMO, Python 3.10+, environment setup

  • Tools — reference for all MCP tools

  • Schema — simulations.db ER diagram and column reference

  • Tutorials — walkthroughs of the paper case studies

Citation

If you use AgentSUMO in academic work, please cite:

@article{jeong2025agentsumo,
  title         = {AgentSUMO: An Agentic Framework for Interactive Simulation Scenario Generation in SUMO via Large Language Models},
  author        = {Jeong, Minwoo and Chang, Jeeyun and Yoon, Yoonjin},
  journal       = {arXiv preprint arXiv:2511.06804},
  year          = {2025},
  url           = {https://arxiv.org/abs/2511.06804}
}

License

MIT. See LICENSE.


Developed at

&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;

Available Tools

26 tools
analyze_road_details_toolA
Analyze detailed road information (lanes, speed limits, length, etc.).

This tool provides comprehensive analysis of road segments including:
- Number of lanes per segment
- Speed limits (km/h)
- Road length and width
- Statistical summary (averages, min/max)

USE CASES:
1. "Show lane count and speed limit for the 500m segment of Teheran-ro near Gangnam Station"
2. "Analyze current road state to compare before and after policy application"
3. "Road capacity analysis (lane count x length)"

Args:
    net_file: Network file path
    target_road_name: Road name (e.g., "테헤란로", "Teheran-ro")
    reference_location: Reference point (e.g., "강남역", "Gangnam Station")
    radius_km: Radius in km (e.g., 0.5 for 500m)
    include_lane_details: Whether to include per-lane information

Returns:
    Dict with detailed road analysis including:
    - segments: List of segment details
    - statistics: Overall statistics (avg lanes, speed, length)
    - summary: Human-readable summary
    - filtering: Location filtering info (if applied)

EXAMPLE:
analyze_road_details_tool(
    net_file="gangnam_station.net.xml",
    target_road_name="테헤란로",
    reference_location="강남역",
    radius_km=0.5
)
-> Returns: Detailed analysis of Teheran-ro segments within 500m of Gangnam Station

Inputs: net_file (required), target_road_name (required), radius_km, reference_location, +1 more.

edge_edit_toolA
Delete specific road segments from the network file.

⚠️🚨 CRITICAL: After using this tool, you MUST regenerate trips and routes!
Route files contain explicit edge lists - if those edges are deleted, the route file becomes INVALID!
Workflow: edge_edit → trip_generate → route_generate → sumo_runner (REQUIRED!)

🌟 REALISTIC USAGE: Specify reference_location + radius_km for partial road closure!

Three modes (priority order):
1. edge_ids: Delete exact edges (most precise, but requires knowing edge IDs)
2. target_road_name + reference_location + radius_km: Delete road segments near a location (REALISTIC!)
3. target_road_name only: Delete entire road (extreme scenario, use with caution!)

Examples:
    # REALISTIC: Block 300m of Teheran-ro near Gangnam Station (construction scenario)
    edge_edit_tool(
        net_file="gangnam_station.net.xml",
        target_road_name="테헤란로",
        reference_location="강남역",
        radius_km=0.3
    )
    # Then: trip_generate → sumo_runner (MUST regenerate trip!)

    # EXTREME: Block entire Teheran-ro (unrealistic!)
    edge_edit_tool(
        net_file="gangnam_station.net.xml",
        target_road_name="테헤란로"
    )
    # Then: trip_generate → sumo_runner (MUST regenerate trip!)

Args:
    net_file: Network file path
    route_file: Route file path (optional, but will be invalidated after edge deletion)
    output_dir: Output directory for results
    target_road_name: Road name to delete from network (e.g., '테헤란로')
    edge_ids: Specific edge IDs to delete (list, optional)
    reference_location: Reference point for partial deletion (str, optional, e.g., "강남역")
    radius_km: Radius in km around reference (float, optional, e.g., 0.3)

Returns:
    Dict with status, net_file, and requires_reroute=True (indicating trip regeneration needed)

Inputs: net_file (required), edge_ids, radius_km, output_dir, +3 more.

flow_generation_toolA
Generate a SUMO flow from source to destination.

Two ways to specify locations:
1. Place names (source/dest) — uses geocoding to find coordinates
2. Direct coordinates (source_lat/lon, dest_lat/lon) — skips geocoding.
   Use this when coordinates are already known (e.g., from map O/D selection).

Two ways to specify vehicle count (exactly one required):
1. vehs_per_hour — rate-based generation (SUMO <flow vehsPerHour="N">)
2. number — total vehicle count over [begin,end] (SUMO <flow number="N">)

Safety parameters applied: departLane="free", departPos="random_free", departSpeed="random"

IMPORTANT: When calling multiple times for multi-OD scenarios, pass the previous call's
route_file output as the next call's route_file input to accumulate all flows in one file.

Args:
    route_file: Route file path (pass previous output for chained calls)
    net_file: Network file path
    source: Source location place name (e.g., "Madison Square Garden")
    dest: Destination location place name (e.g., "Lincoln Tunnel")
    begin: Start time in seconds (default: 0.0)
    end: End time in seconds (default: 3600.0)
    vehs_per_hour: Vehicles per hour — mutually exclusive with number
    number: Total vehicle count — mutually exclusive with vehs_per_hour
    flow_id: Flow ID (auto-generated if None)
    output_dir: Output directory for results
    use_geocoding: Use geocoding for place name resolution (default: True)
    search_radius: Search radius in km for nearest edge (default: 0.3)
    source_lat: Source latitude (WGS84) — use with source_lon for coordinate mode
    source_lon: Source longitude (WGS84) — use with source_lat for coordinate mode
    dest_lat: Destination latitude (WGS84) — use with dest_lon for coordinate mode
    dest_lon: Destination longitude (WGS84) — use with dest_lat for coordinate mode

Examples:
    Place name mode (geocoding):
    flow_generation_tool(route_file="r.rou.xml", net_file="n.net.xml",
        source="Madison Square Garden", dest="Lincoln Tunnel",
        begin=0, end=1800, vehs_per_hour=260)

    Coordinate mode (from map selection):
    flow_generation_tool(route_file="r.rou.xml", net_file="n.net.xml",
        source_lat=40.7505, source_lon=-73.9934,
        dest_lat=40.7580, dest_lon=-73.9855,
        begin=0, end=3600, number=200)

Inputs: net_file (required), route_file (required), end, dest, +12 more.

get_edge_ids_from_road_name_toolA
Convert road name to SUMO edge IDs using edge.getName().

IMPORTANT: Use this when user asks questions with road names (e.g., "What is the density of Teheran-ro?")

This tool maps human-readable road names to SUMO's technical edge IDs,
enabling SQL queries based on road names.

Args:
    road_name: Road name (e.g., "테헤란로", "강남대로", "9th Avenue")
    net_file: Network file path used in simulation.
              When working with DB data, get this from:
              SELECT net_file FROM simulations WHERE simulation_id = '<your_sim_id>'

Returns:
    List[str]: List of edge IDs matching the road name

Example workflow:
    1. User asks: "What is the density of Teheran-ro?"

    2. Get net_file from DB (if using DB data):
       read_query("SELECT net_file FROM simulations WHERE simulation_id = 'baseline'")
       → "/path/to/network.net.xml"

    3. Convert road name to edge IDs:
       get_edge_ids_from_road_name_tool(
           road_name="테헤란로",
           net_file="/path/to/network.net.xml"  # Use actual path from step 2
       )
       → ["375049565#11", "375049565#12", "375049565#13", ...]

    4. Use in SQL query:
       read_query("SELECT AVG(density) FROM edge_metrics WHERE edge_id IN ('375049565#11', '375049565#12', ...)")

    5. Present results with road name (not edge IDs)

Note:
    - Returns all edge segments for the given road name
    - Raises ValueError if road name not found

Inputs: net_file (required), road_name (required).

get_road_names_toolA
Convert SUMO edge IDs to actual road names using edge.getName().

IMPORTANT: Use this after congestion analysis to show human-readable road names!

This tool maps SUMO's technical edge IDs to real-world street names,
making analysis results much more understandable and actionable.

Args:
    edge_ids: List of SUMO edge IDs to convert (e.g., ["194926855#1", "420901920#0"])
    net_file: Network file path used in simulation.
              When working with DB data, get this from:
              SELECT net_file FROM simulations WHERE simulation_id = '<your_sim_id>'

Returns:
    Dict mapping edge_id → road_name

Example workflow:
    1. SQL query for Top 10 density:
       read_query("SELECT edge_id, avg_density FROM edge_metrics ORDER BY avg_density DESC LIMIT 10")
       → ["194926855#1", "1030139836#1", ...]

    2. Get net_file from DB (if using DB data):
       read_query("SELECT net_file FROM simulations WHERE simulation_id = 'baseline'")
       → "/path/to/network.net.xml"

    3. Convert to road names:
       get_road_names_tool(
           edge_ids=["194926855#1", "1030139836#1", ...],
           net_file="/path/to/network.net.xml"  # Use actual path from step 2 or user-provided
       )
       → {"194926855#1": "9th Avenue", "1030139836#1": "Broadway", ...}

    4. Present results:
       "Top 10 Congested Roads:
        1. 9th Avenue: 800 veh/km
        2. Broadway: 731 veh/km
        ..."

Note:
    - Returns "Unnamed Road" if road name not set in network

Inputs: edge_ids (required), net_file (required).

net_convertA
[Step 2/5] Convert OSM data to SUMO network format (.net.xml).

Converts the raw .osm file from osm_extract() into a SUMO-compatible
road network using netconvert. Applies road type filtering and UTM projection.

Previous step: osm_extract() to get .osm file and bbox.
Next step: trip_generate() to create traffic demand on this network.

=== PARAMETERS ===
- osm_file (REQUIRED): Path to .osm file (from osm_extract result)
- city_en: English name for output file naming (auto-derived from osm_file if omitted)
- bbox: Bounding box [west, south, east, north] for boundary trimming.
  Pass the bbox from osm_extract result to trim roads at area boundaries.
  If omitted, roads may extend beyond the intended area.

=== RETURNS ===
- net_file: Path to generated .net.xml file (pass to trip_generate and sumo_runner)

Inputs: osm_file (required), bbox, city_en, output_dir. Returns: result

network_summary_toolA
Get a comprehensive summary of a SUMO network.

Use when user asks about the network, its size, or what roads are included.
Returns edge count, junction count, total road length, bounding box, and road name list.

Args:
    net_file: Path to the SUMO network file (.net.xml)

Returns:
    Dict with network statistics and road names

Inputs: net_file (required).

osm_extractA
[Step 1/5] Extract OpenStreetMap (OSM) road network data for a given area.

This is the FIRST step in the simulation pipeline. It downloads or extracts
raw OSM data (.osm file) for the specified geographic area.

Next step: Use net_convert() to convert the .osm file to SUMO .net.xml format.

=== AREA SPECIFICATION (priority order) ===
1. bbox: Direct coordinates [west, south, east, north]
   Example: [127.015, 37.490, 127.040, 37.506]
2. od_data_file: Auto-compute bbox from OD CSV coordinate columns
   (use column_mapping if columns are not named O_lon, O_lat, D_lon, D_lat)
3. zone_shp_file: Auto-compute bbox from shapefile geometry bounds
4. city + radius: Geocode city name and use radius in KILOMETERS (not meters!)
   Example: city="Gangnam Station", radius=1.5

=== PARAMETERS ===
- city_en (REQUIRED): English name for file naming. Example: "gangnam", "manhattan_midtown"
- bbox: [west, south, east, north] bounding box coordinates
- city: City/location name for geocoding (e.g., "강남역", "Times Square")
- radius: Radius in km (used with city parameter)
- od_data_file: Path to OD CSV file (bbox auto-computed from coordinate ranges)
- zone_shp_file: Path to zone shapefile (bbox auto-computed from geometry)
- column_mapping: Column name mapping for non-standard OD CSV files.
  Keys are standard names, values are actual column names in the CSV.
  Example: {"O_lon": "pickup_lng", "O_lat": "pickup_lat", "D_lon": "dropoff_lng", "D_lat": "dropoff_lat"}

=== PIPELINE CONTEXT ===
RandomOD:     osm_extract(bbox/city+radius) → net_convert → trip_generate → route_generate → sumo_runner
RealOD-coord: osm_extract(od_data_file, column_mapping) → net_convert → trip_generate → route_generate → sumo_runner
RealOD-zone:  osm_extract(zone_shp_file) → net_convert → trip_generate → route_generate → sumo_runner

=== RETURNS ===
- osm_file: Path to extracted .osm file (pass to net_convert)
- bbox: Computed bounding box (pass to net_convert for boundary trimming)
- tag: File naming tag derived from city_en

Inputs: city_en (required), bbox, city, radius, +4 more. Returns: result

reduce_lanes_toolA
Reduce lanes on road segments with two modes.

✅ Trip file can be reused - edges still exist, only lane count changed.
Workflow: reduce_lanes → sumo_runner (reuse existing trip file)

**MODE 1: Relative Reduction (RECOMMENDED for most policies)**
- reduce_by: Reduce N lanes from each segment
- Example: reduce_by=1 → 5→4, 3→2, 2→1, 1→1 (balanced reduction)

**MODE 2: Absolute Reduction (for special cases)**
- remain_lanes: Set all segments to N lanes
- Example: remain_lanes=1 → 5→1, 3→1, 2→1, 1→1 (extreme reduction)

REALISTIC USAGE: Use reference_location + radius_km for localized lane reduction!

Examples:
    # BALANCED POLICY: Reduce 1 lane from each segment
    reduce_lanes_tool(
        net_file="gangnam_station.net.xml",
        target_road_name="테헤란로",
        reference_location="강남역",
        radius_km=0.5,
        reduce_by=1  # Each segment: 5→4, 3→2, 2→1, 1→1
    )
    # Then: sumo_runner (reuse trip file - no trip_generate needed!)

    # EXTREME POLICY: Set all segments to 1 lane
    reduce_lanes_tool(
        net_file="gangnam_station.net.xml",
        target_road_name="테헤란로",
        reference_location="강남역",
        radius_km=0.5,
        remain_lanes=1  # All segments: 5→1, 3→1, 2→1, 1→1
    )
    # Then: sumo_runner (reuse trip file - no trip_generate needed!)

Args:
    net_file: Network file path
    route_file: Route file path (optional, can be reused after this tool)
    output_dir: Output directory for results
    target_road_name: Road name to reduce lanes (e.g., '테헤란로')
    edge_ids: Specific edge IDs (optional)
    reference_location: Reference point (optional, e.g., "강남역")
    radius_km: Radius in km (optional, e.g., 0.5)
    reduce_by: Number of lanes to reduce from each segment (RECOMMENDED!)
    remain_lanes: Number of lanes to remain (ABSOLUTE - use with caution)

Inputs: net_file (required), edge_ids, radius_km, reduce_by, +5 more.

route_analysis_toolA
Analyze the optimal route between two locations in the network.

Accepts place names (e.g., "강남역", "Gangnam Station") or road names (e.g., "테헤란로").

TWO ROUTING MODES:
1. "distance" (default): Shortest path by edge length. Works without simulation data.
2. "traveltime": Optimal path using actual simulation results (edgedata XML) as edge weights.
   Requires weight_file (edgedata XML from a previous simulation).
   Can also use other attributes: "density", "CO2_abs", etc.

Use cases:
- "What is the shortest path from Gangnam Station to Samseong Station?" -> routing_mode="distance"
- "What is the optimal path based on actual travel time?" -> routing_mode="traveltime", weight_file=edgedata.xml
- "What is the lowest-CO2 path?" -> routing_mode="traveltime", weight_attribute="CO2_abs"
- "How does the path change after a road closure?" -> compare_net_file + compare_weight_file

In web mode, use [SHOW_ROUTE:edges|color|net_file_name] marker to visualize the result.
Always include net_file_name from the result so routes render on the correct network.

Args:
    net_file: Network file path
    origin: Origin location (place name, landmark, or road name)
    destination: Destination location (place name, landmark, or road name)
    routing_mode: "distance" (default, edge length) or "traveltime" (simulation-weighted)
    weight_file: Edgedata XML file for weighted routing (required when routing_mode="traveltime").
                 Use the netstate/edgedata file from simulation output.
    weight_attribute: Attribute to use as edge weight (default: "traveltime").
                     Other options: "density", "CO2_abs", "fuel_abs", etc.
    compare_net_file: Optional second network for before/after route comparison
    compare_weight_file: Optional edgedata for the comparison network

Returns:
    Dict with route edges, distance, time, road names.
    If comparison provided, includes both routes and diff.

Inputs: origin (required), net_file (required), destination (required), weight_file, +4 more.

route_generateA
[Step 4/5] Generate routes from trips using SUMO's duarouter.

Assigns shortest-path routes to each trip based on the road network.
Converts trips.xml → routes.rou.xml which is required for simulation.

Previous step: trip_generate() to get .trips.xml file.
Next step: sumo_runner() to run the simulation with net_file and route_file.

=== PARAMETERS ===
- net_file (REQUIRED): Path to SUMO network file (.net.xml, from net_convert)
- trip_file (REQUIRED): Path to trip file (.trips.xml, from trip_generate)

=== RETURNS ===
- route_file: Path to generated .rou.xml file (pass to sumo_runner)

Inputs: net_file (required), trip_file (required), output_dir. Returns: result

simulation_report_toolA
Generate a comprehensive HTML simulation analysis report from SQLite database.

This is the FINAL deliverable of a simulation analysis session.
It summarizes ALL scenarios in the database with KPIs, comparisons, congestion analysis, and emissions.

The report is a standalone dark-themed HTML file that can be:
- Viewed in the web interface (click from file tree)
- Opened in any browser
- Shared as a file

IMPORTANT — Before calling this tool:
1. Query the database (read_query) to understand the simulation results
2. Write an executive_summary (1-2 paragraphs, English, professional tone) that covers:
   - Context: what area was studied and what problem was investigated
   - Key findings: most significant results from scenario comparison
   - Risks/concerns: any metrics that worsened or areas of concern
   - Recommendation: what action should urban stakeholders take based on the analysis
   Focus on insights useful for urban decision-makers (policymakers, planners, city officials).
   Do NOT list raw numbers — interpret them.

Args:
    db_path: Path to SQLite database file
    executive_summary: LLM-generated executive summary for urban stakeholders (English, 1-2 paragraphs)
    output_dir: Output directory for report files

Returns:
    Dict with report_file path and metadata

Inputs: db_path (required), output_dir, executive_summary.

speed_limit_edit_toolA
Modify speed limits on specific road segments (supports partial application).

✅ Trip file can be reused - edges still exist, only speed limit changed.
Workflow: speed_limit_edit → sumo_runner (reuse existing trip file)

REALISTIC USAGE: Use reference_location + radius_km for localized speed limit changes!

Examples:
    # REALISTIC: Reduce speed to 40km/h on 500m of Teheran-ro near Gangnam Station
    speed_limit_edit_tool(
        net_file="gangnam_station.net.xml",
        target_road_name="테헤란로",
        reference_location="강남역",
        radius_km=0.5,
        new_speed_kmph=40.0
    )
    # Then: sumo_runner (reuse trip file - no trip_generate needed!)

Args:
    net_file: Network file path
    route_file: Route file path (optional, can be reused after this tool)
    output_dir: Output directory for results
    target_road_name: Road name (e.g., '테헤란로')
    edge_ids: Specific edge IDs (optional)
    reference_location: Reference point (optional, e.g., "강남역")
    radius_km: Radius in km (optional, e.g., 0.5)
    new_speed_kmph: New speed limit in km/h (e.g., 40.0)

Inputs: net_file (required), edge_ids, radius_km, output_dir, +4 more.

sumo_runnerA
[Step 5/5] Run SUMO traffic simulation using TraCI.

Executes the simulation with the generated network and routes.
Captures vehicle position frames for post-simulation replay visualization.

Previous step: route_generate() to get .rou.xml file.

=== PARAMETERS ===
- net_file (REQUIRED): SUMO network file (.net.xml, from net_convert)
- route_file: Route file (.rou.xml, from route_generate) — preferred over trip_file
- trip_file: Trip file (.trips.xml) — use only if route_file is unavailable
- duration: Simulation duration in seconds (default: 3600 = 1 hour)
- additional_files: List of additional XML files (e.g., traffic light programs)
- policy_type: Set to "baseline" to exclude additional files

=== RETURNS ===
- output_files: List of result file paths [tripinfo, edgedata, edgedata_emission]
- summary_xml: Path to summary.xml file. ALWAYS pass this to xml_to_sqlite_tool(summary_xml=...) for dashboard time-series charts.
- replay_file: JSON file for web visualization replay
- simulation_time: Wall-clock execution time in seconds

Inputs: net_file (required), duration, trip_file, output_dir, +3 more.

tls_adaptation_toolB
Run SUMO tlsCycleAdaptation.py to optimize traffic light cycles and generate an additional XML file.

Args:
    net_file: Network file path (tag will be extracted from filename)
    route_file: Route file path
    output_dir: Output directory for results

Inputs: net_file (required), route_file (required), output_dir.

tls_offset_toolC
Run SUMO tlsCoordinator.py to optimize traffic light offsets and generate an additional XML file.

Args:
    net_file: Network file path (tag will be extracted from filename)
    route_file: Route file path
    output_dir: Output directory for results

Inputs: net_file (required), route_file (required), output_dir.

trip_generateA
[Step 3/5] Generate trip demand (trips.xml) for SUMO simulation.

Creates origin-destination trip definitions. This tool ONLY generates trips —
route assignment is done separately by route_generate().

Previous step: net_convert() to get .net.xml file.
Next step: route_generate() to assign routes to trips.

=== THREE MODES ===

1. RandomOD — Random trip generation:
   - trip_type: "RandomOD"
   - traffic_condition (REQUIRED): "light" | "medium" | "heavy"
     * light: ~20% of edge count (rural, off-peak)
     * medium: ~80% of edge count (typical urban)
     * heavy: ~150% of edge count (rush hour, dense urban)

2. RealOD-coordinate — Real OD from coordinate CSV:
   - trip_type: "RealOD", od_type: "coordinate"
   - od_data_file: Path to CSV file
   - Default columns: O_lon, O_lat, D_lon, D_lat, O_time_relative
   - Use column_mapping if your CSV has different column names

3. RealOD-zone — Real OD from zone CSV + shapefile:
   - trip_type: "RealOD", od_type: "zone"
   - od_data_file: Path to OD CSV file
   - zone_shp_file: Path to zone shapefile (.shp)
   - Default columns: h3_lv9_O, h3_lv9_D, O_time_relative
   - Default shapefile ID column: h3_indx
   - Use column_mapping to override any of these

=== COLUMN MAPPING ===
For non-standard CSV files, provide column_mapping to map standard names to actual column names.

Coordinate mode mapping keys:
  "O_lon", "O_lat", "D_lon", "D_lat", "O_time_relative"
Zone mode mapping keys:
  "zone_O", "zone_D", "O_time_relative", "zone_id_column"

Example: {"O_lon": "pickup_lng", "O_lat": "pickup_lat", "D_lon": "dropoff_lng", "D_lat": "dropoff_lat", "O_time_relative": "start_sec"}

=== RETURNS ===
- trip_file: Path to generated .trips.xml file (pass to route_generate)
- trip_count: Number of trips generated

Inputs: net_file (required), trip_type (required), od_type, output_dir, +4 more. Returns: result

validate_od_coordinates_toolA
Validate a list of coordinates against the SUMO network.

Use this BEFORE generating flows to check which coordinates are within the network
and find the nearest edges. Essential for agentic OD planning — lets you verify
destinations are reachable before proposing them to the user.

Args:
    net_file: SUMO network file path (.net.xml)
    coordinates: List of coordinate dicts, each with:
        - lat (float): Latitude (WGS84)
        - lon (float): Longitude (WGS84)
        - label (str, optional): Human-readable label (e.g., "Lincoln Tunnel")
    search_radius: Search radius in km for nearest edge (default: 0.5)

Returns:
    Dict with:
        - network_bbox: [min_lon, min_lat, max_lon, max_lat]
        - results: List of validation results per coordinate:
            - label, lat, lon
            - in_network: bool
            - nearest_edge: edge ID (or null)
            - distance_m: distance to nearest edge in meters (or null)
            - status: "ok" | "out_of_network" | "no_edge_found"

Example:
    validate_od_coordinates_tool(
        net_file="manhattan.net.xml",
        coordinates=[
            {"lat": 40.7505, "lon": -73.9934, "label": "MSG"},
            {"lat": 40.7425, "lon": -74.0099, "label": "Holland Tunnel"},
            {"lat": 40.7060, "lon": -73.9969, "label": "Brooklyn Bridge"}
        ]
    )

Inputs: net_file (required), coordinates (required), search_radius.

vehicle_generation_toolA
Add vehicles from source to destination with optimal path calculation.

SUPPORTS TWO MODES:

1. Road Name Mode:
   - Use exact road names (e.g., '테헤란로', '강남대로')
   - Set use_geocoding=False (default)

2. Location Mode (Recommended):
   - Use any location name or place (e.g., '강남역', '코엑스', 'Gangnam Station, Seoul')
   - Uses geocoding to find coordinates, then finds nearest edges
   - Set use_geocoding=True
   - Automatically validates if location is within network bounds

IMPORTANT NOTES:
- Location Mode validates coordinates against network bounds (1km buffer)
- If location is outside network, you'll get a clear error with network bbox info
- Search radius is 300m by default (sufficient for most cases)

Args:
    route_file: Route file path
    net_file: Network file path
    source_location: Source location (road name OR place name)
    destination_location: Destination location (road name OR place name)
    vehicle_id: Vehicle ID prefix (default: "genveh_0")
    depart_time: Departure time in seconds (default: 0.0)
    depart_time_range: Departure time range [min, max] in seconds (optional)
    vehicle_count: Number of vehicles to generate (default: 1)
    output_dir: Output directory for results
    use_geocoding: If True, use location-based mode with geocoding (default: False)
    search_radius: Search radius in km for nearest edge (default: 0.3 = 300m)

Examples:
    Road name mode:
    vehicle_generation_tool(
        route_file="routes.rou.xml",
        net_file="gangnam.net.xml",
        source_location="테헤란로",
        destination_location="강남대로",
        use_geocoding=False
    )

    Location mode (RECOMMENDED):
    vehicle_generation_tool(
        route_file="routes.rou.xml",
        net_file="gangnam.net.xml",
        source_location="강남역",
        destination_location="코엑스",
        use_geocoding=True,
        vehicle_count=20
    )

Inputs: net_file (required), route_file (required), source_location (required), destination_location (required), +7 more.

vehicle_type_edit_toolC
Reassign vehicle types in the route file according to the electric_ratio.

Args:
    route_file: Route file path
    electric_ratio: Ratio of electric vehicles (0.0 to 1.0)
    output_dir: Output directory for results

Inputs: route_file (required), electric_ratio (required), output_dir.

visualize_edgedata_toolA
🎨 Visualize SUMO edgedata with flexible scaling modes for comparison.

⚠️ IMPORTANT: Only use when user EXPLICITLY requests heatmap/visualization!
- User says "show heatmap", "visualize density", "show congestion map" → Use this
- User asks "which road is congested?" -> Do NOT use; answer with text from SQL query

**SCALE MODES:**

1. **'auto'** (default): Dynamic scale from current file
   - Best for: Single simulation analysis
   - Scale: Optimized for current data range

2. **'unified'**: Consistent scale across multiple files
   - Best for: Policy comparison (before/after)
   - Requires: comparison_files parameter
   - Example: Compare baseline vs policy A vs policy B

3. **'fixed'**: User-defined fixed scale
   - Best for: Standardized reports, academic papers
   - Requires: min_value and max_value parameters
   - Example: Always use [0, 100] for all simulations

**USE CASES:**

# Single simulation analysis (auto scale)
visualize_edgedata_tool(..., scale_mode="auto")
→ Optimized color contrast for this simulation

# Policy comparison (unified scale)
visualize_edgedata_tool(
    edgedata_file="after.xml",
    scale_mode="unified",
    comparison_files=["before.xml"]
)
→ Same colors mean same values across both

# Standardized scale (fixed)
visualize_edgedata_tool(..., scale_mode="fixed", min_value=0, max_value=100)
→ All simulations use [0, 100] scale

Args:
    net_file: Path to the SUMO network file (.net.xml)
    edgedata_file: Path to the SUMO edgeData output file (.xml)
    attribute: Attribute to visualize (e.g., 'density', 'speed', 'CO2_abs')
    output_dir: Output directory for visualization files
    scale_mode: Scale mode ('auto' | 'unified' | 'fixed')
    comparison_files: List of files for unified scale (for 'unified' mode)
    min_value: Minimum value for fixed scale (for 'fixed' mode)
    max_value: Maximum value for fixed scale (for 'fixed' mode)

Inputs: net_file (required), edgedata_file (required), attribute, max_value, +4 more.

visualize_edge_toolA
Visualize a SUMO network file with selected edges highlighted and save as PNG image.

Only use when user EXPLICITLY requests edge visualization!
- User says "show edge details", "visualize this road" → Use this
- User asks "which road is congested?" → Do NOT use, answer with text

Args:
    net_file: Path to the SUMO network file (.net.xml)
    road_name: Name of the road to highlight
    output_dir: Output directory for visualization files

Inputs: net_file (required), road_name (required), output_dir.

visualize_net_toolA
Visualize a SUMO network file and save as PNG image.

⚠️ IMPORTANT: Only use when user EXPLICITLY requests visualization!
- User says "show network map", "visualize network" → Use this
- User asks about simulation results → Do NOT use, answer with text

Args:
    net_file: Path to the SUMO network file (.net.xml)
    output_dir: Output directory for visualization files

Inputs: net_file (required), output_dir.

visualize_policy_target_toolA
Visualize policy target area using SUMO's built-in visualization.

Only use when user EXPLICITLY requests to preview policy area!
- User says "show me which roads will be affected" → Use this
- User just wants to apply policy → Do NOT use, proceed with policy tool

This tool helps visualize which road segments will be affected by a policy
before actually applying it. Essential for confirming policy target area!

VISUALIZATION:
- Shows ONLY the selected road segments within the specified radius
- Uses SUMO's standard plot_net_selection.py for consistent styling
- Clean, focused view of the policy target area

USE CASES:
1. "Show me which part of 테헤란로 near 강남역 within 300m will be affected"
2. "Visualize policy target before deleting road segments"
3. "Preview lane reduction area before applying"

REALISTIC WORKFLOW:
Step 1: Use this tool to visualize policy area
Step 2: Confirm the target area is correct
Step 3: Apply policy using edge_edit_tool/reduce_lanes_tool/speed_limit_edit_tool

Args:
    net_file: Network file path
    target_road_name: Road name (e.g., "테헤란로", "Teheran-ro")
    reference_location: Reference point (e.g., "강남역", "Gangnam Station")
    radius_km: Radius in km (e.g., 0.3 for 300m)
    output_dir: Output directory

Returns:
    PNG file showing selected road segments only

EXAMPLE:
visualize_policy_target_tool(
    net_file="gangnam_station.net.xml",
    target_road_name="테헤란로",
    reference_location="강남역 교차로",
    radius_km=0.3
)
-> Shows: Only the 300m segment of Teheran-ro near Gangnam Station (selected segments)

Inputs: net_file (required), target_road_name (required), radius_km, output_dir, +1 more.

web_search_toolA
Search the web using DuckDuckGo. Use this to look up real-world information
that helps with simulation scenario design.

Useful for:
- Venue/facility capacity (e.g., "Madison Square Garden capacity")
- Geographic/infrastructure info (e.g., "bridges connecting Manhattan to Brooklyn")
- Traffic patterns and event schedules
- Road/highway specifications
- Any factual information needed to set realistic simulation parameters

Args:
    query: Search query string. Be specific for better results.
    max_results: Number of results to return (default: 5, max: 10)

Returns:
    List of search results, each with title, url, and snippet.

Inputs: query (required), max_results.

xml_to_sqlite_toolA
Convert SUMO XML results to SQLite database for advanced SQL-based analysis.

IMPORTANT: This enables detailed queries that summary statistics cannot answer:
- Top N queries (e.g., "What are the top 10 roads by density?")
- Specific edge analysis (e.g., "What is the congestion level at the Gangnam Station intersection?")
- Comparative analysis (e.g., "How did density change before and after the policy?")
- Temporal analysis (e.g., "How does speed vary across times of day?")
- Road-level aggregation (e.g., "What is the average congestion across all of Teheran-ro?")

DATABASE SCHEMA (IMPORTANT):
- simulations: (simulation_id, created_at, vehicle_count, net_file, route_file, description)
- edge_info: (simulation_id, edge_id, road_name, length, num_lanes, speed_limit)
  * Network topology from .net.xml — enables road-level analysis
  * road_name: Human-readable street name (e.g., "테헤란로", "9th Avenue")
  * length: Edge length in meters
  * num_lanes: Number of lanes
  * speed_limit: Speed limit in km/h
- vehicle_info: (simulation_id, vehicle_id, vehicle_type, fuel_type, origin_edge, destination_edge, origin_road, destination_road)
  * Per-vehicle metadata from tripinfo + network — enables OD and fleet analysis
  * vehicle_type: SUMO vType (e.g., "passenger", "truck")
  * fuel_type: Classified from emissionClass — "gasoline", "diesel", "electric", "unknown"
  * origin_edge / destination_edge: First/last edge IDs
  * origin_road / destination_road: Human-readable road names (from edge_info)
- trips: (simulation_id, trip_id, duration, routeLength, waitingTime, timeLoss, depart, arrival, ...)
- edge_metrics: (simulation_id, edge_id, interval_begin, interval_end, speed, density, waitingTime,
                 timeLoss, occupancy, entered, left, ...)
  * PRIMARY KEY: (simulation_id, edge_id, interval_begin)
- network_state: (simulation_id, time, running, halting, waiting, meanSpeed, meanSpeedRelative, ...)
  * Network-wide time-series from summary.xml — 1 row per simulation second
  * Enables temporal analysis: congestion onset, performance curves, before/after comparison
  * PRIMARY KEY: (simulation_id, time)

KEY: Table name is 'edge_metrics', NOT 'edgedata'!

=== ROAD-LEVEL ANALYSIS WITH edge_info ===
For road-level congestion analysis (instead of edge-level), JOIN edge_info:

-- Road-level weighted density (RECOMMENDED for congestion ranking)
SELECT ei.road_name,
       ROUND(SUM(em.density * ei.length) / SUM(ei.length), 2) AS weighted_density,
       ROUND(SUM(ei.length), 1) AS total_length_m
FROM edge_metrics em
JOIN edge_info ei ON em.simulation_id = ei.simulation_id AND em.edge_id = ei.edge_id
WHERE em.simulation_id = '1_baseline' AND ei.road_name IS NOT NULL
GROUP BY ei.road_name
ORDER BY weighted_density DESC LIMIT 10;

-- Filter out micro-segments (< 10m)
WHERE ei.length > 10

-- Query by road name (NO need for get_edge_ids_from_road_name_tool!)
WHERE ei.road_name = '테헤란로'

DESIGN: Single unified DB with simulation_id for comparative studies
- Same network's simulations → Same DB file
- Different simulations → Different simulation_ids in same DB
- Enables SQL JOIN for before/after comparison

Args:
    tripinfo_xml: Path to tripinfo XML file
    edgedata_xml: Path to edgedata XML file
    edgedata_emission_xml: Path to edgedata emission XML file
    output_dir: Output directory for database (default: output/analysis)
    simulation_id: REQUIRED — NEVER leave as None!
        Format: "{N}_{scenario_name}" where N is the sequential number.
        - Check current simulations in context to determine N.
        - Use short, descriptive English names.
        - Examples: "1_baseline", "2_road_closure_teheran", "3_lane_reduction_gangnam",
          "4_tls_optimize_seocho", "5_speed_limit_gangnam"
    net_file: Path to network (.net.xml) file used in this simulation
    route_file: Path to route (.rou.xml) file used in this simulation
    description: REQUIRED — NEVER leave as None!
        Human-readable English description of the scenario.
        Displayed in the UI for scenario comparison.
        Always describe WHAT was changed and WHERE.
        Examples:
        - "Baseline simulation (Gangnam Station 1km)"
        - "Road closure on Teheran-ro near Gangnam Station (500m)"
        - "Lane reduction on Gangnam-daero (3 to 2 lanes)"
        - "Signal timing optimization at Seocho-daero intersection"
        - "Speed limit reduced to 30km/h on Teheran-ro"
    summary_xml: Path to summary XML file from sumo_runner result's top-level "summary_xml" field.
        IMPORTANT: Always provide this! Without it, dashboard time-series charts will be empty.

Returns:
    Dict with db_file, simulation_id, and metadata

Examples:
    # After sumo_runner returns result with metadata.absolute_summary:
    xml_to_sqlite_tool(
        tripinfo_xml="gangnam_tripinfo.xml",
        edgedata_xml="gangnam_edgedata.xml",
        edgedata_emission_xml="gangnam_emission.xml",
        simulation_id="1_baseline",
        description="Baseline simulation (Gangnam Station 1km)",
        summary_xml="/path/to/gangnam_summary.xml"
    )

Inputs: edgedata_xml (required), tripinfo_xml (required), edgedata_emission_xml (required), net_file, +5 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

    TDQS

    A3.7/5.0

    Scored across 26 tools

    Disambiguation4/5

    Most tools have distinct purposes, especially the pipeline steps (osm_extract, net_convert, etc.) and editing tools (edge_edit_tool, reduce_lanes_tool). However, multiple visualization tools (visualize_net_tool, visualize_edge_tool, visualize_policy_target_tool, visualize_edgedata_tool) and two vehicle generation tools (vehicle_generation_tool, flow_generation_tool) could cause some confusion despite clear usage instructions.

    Naming Consistency3/5

    The naming is mostly snake_case, but there is inconsistency: core pipeline tools omit the '_tool' suffix (e.g., net_convert, trip_generate) while many utility and editing tools include it (e.g., edge_edit_tool, xml_to_sqlite_tool). This mix of naming conventions slightly reduces predictability.

    Tool Count3/5

    With 26 tools, the server is quite extensive for a single domain. While each tool has a clear role, the count feels high for an MCP server, potentially overwhelming agents. A more focused set (e.g., 15-20 tools) might be more manageable.

    Completeness5/5

    The tool set covers the entire simulation workflow: data extraction, network conversion, demand generation (with multiple modes), routing, simulation execution, network editing (edges, lanes, speed, TLS), vehicle type editing, analysis (route, road details, SQL database), visualization, reporting, and web search. There are no obvious gaps for the stated purpose of traffic simulation with SUMO.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Connects LLMs to Eclipse SUMO traffic simulation, enabling AI agents to automate traffic network generation, demand modeling, signal optimization, simulation execution, and real-time TraCI control through natural language.
      59
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Enables natural language-driven creation and execution of autonomous-vehicle scenarios in the CARLA simulator, with validated primitives and replay support.
      7
      1
      MIT
    • F
      license
      Not graded
      quality
      A
      maintenance
      Enables natural language interaction with OpenStudio building energy simulation, allowing creation, querying, and modification of models, running EnergyPlus simulations, and analyzing results.
      58
      -