Skip to main content
Glama
3DCityDB MCP Server

3DCityDB MCP Server

Official
by tum-gis

A Model Context Protocol (MCP) server giving AI assistants direct, natural language access to semantic 3D city models in CityGML managed within a 3DCityDB v5 geodatabase.

It dynamically resolves CityGML object classes, properties, codelists, and generic attributes from the database so the AI can answer both spatial and semantic queries stated in natural language, write and execute SQL queries, and reason about CityGML data — without any manual prompt engineering. By including the MCP server in agentic coding environments, it becomes easy to create software that can read and write complex structured 3D city models compliant to the OGC CityGML standard (and using 3DCityDB V5 as the data repository).

Furthermore, a Chat Assistant is included offering a simple GUI for interactive query asking, reasoning, and answering. It is an agentic AI tool based on LangChain utilising the ReAct pattern for carrying out multi-step reasoning and automated error corrections. The Chat Assistant currently can be configured to work with OpenAI and Anthropic commercial LLMs, any OpenAI-compatible endpoint, as well as with locally running Ollama LLMs. For example, when using the qwen3.8:27b LLM running in Ollama, the Chat Assistant is capable of performing very complex analyses on any kind of stored 3D city model, including multi-step SQL workflows with live reasoning traces, rendered diagrams, and PDF export.

The evaluation of the MCP Server for the accompanying paper was done using 100 queries of 4 different complexity levels. The complete list of the queries can be found here.


Features

The project has two layers with their own feature sets: the MCP server (the model-facing tool provider, usable from any MCP client) and the Chatbot (the browser GUI that wraps the MCP server with a multi-LLM agentic loop, an optional 3D viewer and per-user state).

MCP Server Features

  • Dynamic schema resolution — walks the CityGML class hierarchy to discover available object classes and their properties

  • Property filtering — only includes properties that actually exist in the database

  • Country-aware codelist resolution — qualified <namespace>:<Class>.<attribute> keys, country selected via the database EPSG code; only codes actually present in the data are exposed

  • Generic attribute enrichment — automatic categorical detection for generic attributes

  • Read-only query execution — run_query enforces SELECT-only; writes are blocked at the application layer and the database layer, where every pooled connection runs in a read-only transaction (default_transaction_read_only = on) so even a crafted CTE hiding a write is rejected by PostgreSQL

  • Prompt assembly — assemble_prompt orchestrates all tools into a complete system prompt in one call

  • Per-user context into tool calls — every tool call can carry a server-side _ctx (user / session / turn) that is stripped before dispatch, so per-user tools such as the scratchpad know which user is calling without ever trusting the model

Chatbot Features

  • Gradio chat UI — browser-based interface with multi-LLM support (Anthropic, OpenAI, Ollama), thinking-level control, live reasoning trace, mermaid/LaTeX rendering, and PDF export

  • Multi-user, per-tab sessions — each browser tab is an independent session with its own Stop button and its own user identity (a uuid in the browser's localStorage, no login), so several users — and several tabs of the same user — can chat in parallel without interfering (session layer)

  • Integrated 3D viewer (optional) — embeds the 3DCityDB Web Map Client into the chat UI (fullstack Docker mode, see Option 3b); the model is streamed as 3D Tiles generated on demand by a separate citydb-3dtiler container. Features from an answer are highlighted in 3D and the camera flies to them, and selected viewer objects are passed to the chatbot so questions can refer to them ("these buildings", "the selected ones")

  • Spatial scratchpad (optional) — a per-user "staging area" the chatbot fills with saved, reusable results: featuresets (named sets of buildings, e.g. "the buildings built between 1945 and 1980") and geometries (pins, lines, draped 2D areas, extruded 3D solids, convex hulls) with per-item name, color and opacity. Items appear as a labelled list in the 3D viewer, can be shown, hidden, re-styled, re-flown-to and deleted — and re-queried later with ordinary SQL against a per-user my_scratchpad view. Enabled by CITYDB_SCRATCHPAD=true; see Spatial scratchpad and scratchpad.md

  • Flood scene (optional) — a quick "bathtub" flood visualization: a query result with a flood_level_m column draws a water surface at that height and colours every building red (flooded), green (held back by a protection_m barrier) or grey (dry), with an on-screen water-level slider and gauge. Enabled by FLOOD_SCENE=true; see flood-scene.md

  • CityGML 1.0-3.0/CityJSON/IFC import — one-click import via the Gradio UI (fullstack Docker mode only); .ifc files are converted to CityGML 3.0 first


Related MCP server: GraphJin

Deployment Options

There are four ways to run the 3DCityDB MCP Server (Option 3b is a 3D-viewer variant of Option 3):

Option 1: PyPI

Option 2: Docker BYOD

Option 3: Docker Fullstack

Option 3b: Fullstack + 3D Viewer

Best for

Claude Code / Claude Desktop power users

Existing 3DCityDB instances

Starting from a .gml/.json/.ifc file

3D exploration & highlighting of query results

Requires

Python 3.10+, running 3DCityDB

Docker, running 3DCityDB

Docker only

Docker only (same as Option 3)

Gradio UI

No (uses your AI client directly)

Yes (localhost:7860)

Yes (localhost:7860)

Yes (localhost:7860) with embedded 3D viewer

CityGML/CityJSON/IFC import

Manual

Manual

Via Gradio UI

Via Gradio UI

Database

Your own

Your own

Bundled (PostgreSQL + PostGIS + SFCGAL)

Bundled (same as Option 3)


Chat CLI

The WebGUI-equivalent 3dcitydb-chat CLI is included in the chatbot image used by Docker Options 2, 3, and 3b. Start one of those stacks first, then run the CLI in its chatbot container. For example, with the fullstack stack:

docker exec -it production-citydb-agent-1 3dcitydb-chat chat

The same CLI can run without Docker from a source checkout, but it is not part of the standard PyPI package. Install the project and WebGUI dependencies, configure the database/provider environment as described under Option 1, then run these commands from the production directory:

python -m pip install -e ..
python -m pip install -r webui/requirements.txt
python -m webui.cli chat

The local MCP server executable (3dcitydb-mcp) must be on PATH, and the configured database must be reachable from the machine running the CLI. Unlike the Docker CLI, a local CLI process uses that machine's environment and filesystem.

Choose a provider and model explicitly when desired. For example:

docker exec -it production-citydb-agent-1 3dcitydb-chat chat \
  --provider ollama --model qwen3.8:27b \
  --temperature 0.1 --thinking high --prompt-mode auto --num-ctx 131072

Available options also include --base-url, --keep-story / --no-keep-story, --full-lists / --no-full-lists (also for benchmark; see Show every row in result tables below; with --no-full-lists the full result is printed as CSV after the answer), --include-reasoning, and --show-reasoning. By default, provider reasoning is not displayed; --show-reasoning adds a clearly labeled reasoning/activity section on stderr. Use /new to clear conversation history and /bye or /exit to leave the session. Prompt assembly reports each database-context step and its duration on stdout. Status and context-size estimates also go to stdout. INFO logs and generation/tool diagnostics between submitting a question and receiving its answer go to stderr. Pass --quiet-stderr to suppress stderr output, including INFO logs.

Benchmarking and Validation

Work on support for systematic result quality validation and benchmarking is work in progress. Documentation and usage of the already existing tools are documented in docs/benchmarking.md.


Option 1: PyPI Package

Install the MCP server as a Python package and connect it to Claude Code, Claude Desktop, or any MCP-compatible client.

Prerequisites

  • Python 3.10 or later

  • A running 3DCityDB v5 PostgreSQL instance with PostGIS

Installation

pip install 3dcitydb-mcp-server

Or install from source for development:

git clone https://github.com/tum-gis/3dcitydb-mcp-server.git
cd 3dcitydb-mcp-server
pip install -e .

Configuration

Copy the example environment file and edit it:

# Linux / macOS
cp .env.example .env

# Windows (PowerShell)
Copy-Item .env.example .env

Then fill in your connection details:

# 3DCityDB PostgreSQL connection
CITYDB_HOST=localhost
CITYDB_PORT=5432
CITYDB_NAME=citydb
CITYDB_USER=postgres
CITYDB_PASSWORD=your_password_here
CITYDB_SCHEMA=citydb

# Query behaviour (optional)
CATEGORICAL_THRESHOLD=20
SAMPLE_VALUES_COUNT=5

# LLM API keys (only needed for the LangChain agent CLI, not for Claude Code/Desktop)
ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=sk-...
# OLLAMA_BASE_URL=http://localhost:11434

The server loads .env automatically by searching upward from the working directory.

Verify your installation

3dcitydb-doctor

Checks Python version, required packages, database connectivity, PostGIS/SFCGAL extensions, and the 3DCityDB v5 schema. Exits 0 if all critical checks pass.

From the directory containing your .env:

claude mcp add 3dcitydb -- 3dcitydb-mcp
claude

The MCP server starts automatically when you open a Claude session. Use /mcp inside the session to confirm it is connected.

Connect to Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "3dcitydb": {
      "command": "3dcitydb-mcp",
      "cwd": "/path/to/your/project"
    }
  }
}

Restart Claude Desktop. The MCP server will be listed in Settings → Developer → MCP Servers.

SSE transport (remote / production)

Run the server over HTTP for remote clients:

3dcitydb-mcp-sse --host 0.0.0.0 --port 8080
  • Clients connect via: http://your-server:8080/sse

  • Modern clients (e.g. VS Code) prefer the Streamable HTTP transport: http://your-server:8080/mcp

  • Health check: http://your-server:8080/health

The repository ships a ready-made .mcp.json that points an MCP client (e.g. VS Code) at http://localhost:8080/mcp/. With the fullstack stack running locally, it enables the 3dcitydb-* tools in your editor without any manual configuration. Adjust the URL if you run the SSE server on a different host or port.

LangChain agent CLI (optional)

A standalone CLI agent that uses the MCP tools directly:

3dcitydb-agent

Requires ANTHROPIC_API_KEY, OPENAI_API_KEY, or OLLAMA_BASE_URL in your .env.


Option 2: Docker — BYOD (Bring Your Own Database)

Run the Gradio chat UI as a Docker container, connected to your existing 3DCityDB instance.

Prerequisites

  • Docker with Compose (V2)

  • A running 3DCityDB v5 PostgreSQL instance accessible from the Docker host

⚠️ Spatial function support: The AI agent uses SFCGAL functions (CG_Volume, CG_3DArea, CG_MakeSolid) for geometry calculations. These require PostGIS to be compiled with SFCGAL support.

If your database lacks SFCGAL, volume and 3D area queries will fail silently or return errors. To get full spatial support, use Option 3 (Fullstack) instead — it ships a 3dcitydb-pg image with PostGIS + pre-patched SFCGAL already enabled. The SFCGAL patch circumvents the much too strict geometry planarity checks normally compiled into SFCGAL (checking for nano meter planarity), so working with 3D geometry works e.g. with volume calculation, 3D surface area calculation as well as 3D boolean operations.

You can verify SFCGAL availability on your instance with:

SELECT postgis_sfcgal_version();

If this returns an error, many spatial queries will not work.

Quick Start

# 1. Clone the repository (or just download docker-compose.byod.yml + .env.example)
git clone https://github.com/tum-gis/3dcitydb-mcp-server.git
cd 3dcitydb-mcp-server/production

# 2. Copy and edit the environment file
cp .env.example .env   # Linux / macOS
# Copy-Item .env.example .env   # Windows PowerShell

Edit .env with your database connection and at least one LLM API key:

# Your existing 3DCityDB instance
CITYDB_HOST=your-db-host
CITYDB_PORT=5432
CITYDB_NAME=citydb
CITYDB_USER=citydb
CITYDB_PASSWORD=your_password
CITYDB_SCHEMA=citydb

# At least one LLM provider (the UI auto-selects based on what is available)
ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=sk-...
# OLLAMA_BASE_URL=http://host.docker.internal:11434
# 3. Pull the pre-built image and start (works on all platforms, no build needed)
docker compose -f docker-compose.byod.yml up -d

# 4. Open the UI
# http://localhost:7860

The pre-built image (ghcr.io/tum-gis/3dcitydb-mcp-agent:latest) is pulled automatically from the GitHub Container Registry on first run.

What it includes

  • Gradio chat UI — natural-language interface to your 3DCityDB

  • MCP server — spawned automatically as a subprocess inside the container

  • Auto provider detection — the UI selects Anthropic, OpenAI, or Ollama based on which keys are present in .env

Gradio UI overview

Tab

What it does

Chat

Send natural-language questions; the agent writes and executes SQL automatically

MCP Inspector

Shows the MCP server's self-description and lists all active MCP tools

System Prompt

Displays the full assembled system prompt sent to the LLM and offers Re-assemble system prompt to rebuild it from the current database contents — useful for debugging

Note: the Import CityGML / CityJSON / IFC tab is only shown in the fullstack variant (Option 3); BYOD connects to an existing database and has no import tab (see Import CityGML/CityJSON/IFC under Option 3).

While the agent is working, the chat bubble shows live status: Thinking… → Running query… → Interpreting results…. Right next to the chat log, the Agent activity panel streams the full ReAct trace — each thought, tool call, and observation — with per-step timing.

Chat settings (above the input field):

Setting

Options

Description

Provider / API

anthropic / openai / ollama

Auto-selected from .env; can be overridden per session

Model

(populated per provider)

Dropdown with free-text entry possibility; Refresh models re-discovers models from the Ollama endpoint

Set temperature

checkbox + value (0.0–1.0, default 0.1)

Unchecked = provider default; enable to pin a fixed temperature

Thinking

off / low / medium / high (+ max for OpenAI)

Reasoning level for thinking-capable models. Ollama uses native think; OpenAI-compatible endpoints use reasoning_effort. Higher levels are slower but more thorough

Prompt mode

auto / compact / full

auto picks compact for small local models; override for complex queries

Keep a distilled summary of how the answer was found

on / off (default on; Ollama + OpenAI)

After each DB turn, distills the successful path (purpose + working SQL + short result) into a compact story carried into later turns. Adds one extra blocking generation per tool-using turn

Show every row in result tables

on / off (default on; all providers)

On: the answer's table lists every row the query returned (e.g. all building IDs). Off: results with more than 10 rows show 5 example rows and the sentence "5 of N", which answers faster for long lists. Above 10 rows the complete result is attached below the answer as collapsible CSV and JSON in both modes (not sent back to the model). Prompt rules: _LIST_RULES / chat_instructions() in webui/llm_utils.py

Include all reasoning steps in context

on / off (default off; Ollama + OpenAI)

Feeds each turn's full reasoning trace back into context on later turns. Off by default: the full trace consumes a large share of the context window, and the distilled summary (above) already carries the essential path

Context window (Ollama)

8K / 32K / 64K / 128K / 256K (default 128K)

Tokens available to the model; a smaller window uses less memory but is too small for complex queries

Rendering and export:

  • Mermaid diagrams are rendered inline in the chat, with a copy toolbar (SVG / PNG / source code) and a visible fallback box if a diagram fails to parse

  • Inline LaTeX is rendered in chat messages; the agent activity panel shows the unrendered source

  • PDF export (🖨 button next to the send button) prints the current conversation to a multi-page PDF via the browser's print dialog

Local (Ollama) model support

The Chat Assistant is deliberately built to work with small local models, not just commercial APIs:

  • Robust tool-call parser — local models frequently emit ReAct actions in non-standard formats (e.g. a full sentence as the action name, extra whitespace, missing arguments). The parser normalises these automatically and repairs common malformations instead of aborting the run.

  • Model profiling — a built-in registry (webui/model_profiles.py) classifies known models by empirically observed behaviour (works, sentence-as-tool, wrong-sql, thinking-then-empty, unknown). The class drives a warning line under the model dropdown (e.g. a model known to emit broken SQL is forced into full prompt mode with an explanatory note), so you get an honest assessment of what a model can do before the first query.

  • Endpoint & model discovery — the Refresh models button queries the Ollama endpoint and repopulates the model dropdown, including custom or fine-tuned models.

  • Native thinking — for Ollama models with a thinking capability (e.g. qwen3.8:27b, gpt-oss:20b), the Thinking dropdown controls the native think parameter; no prompt engineering needed. However, it seems that many Ollama models do not consider this parameter properly.

See production/docs/local-model-probing.md for the full probing methodology, the per-model results, and how to add a new model profile.

Building locally (optional)

If you want to build the image from source instead of pulling it:

# Linux / macOS
docker compose -f docker-compose.byod.yml up -d --build

# Windows — Docker BuildKit has a known ordering bug on Windows/NTFS.
# Disable it for local builds:
$env:DOCKER_BUILDKIT=0; docker compose -f docker-compose.byod.yml up -d --build

Windows note: The DOCKER_BUILDKIT=0 flag is only needed when building locally. Pulling the pre-built image (docker compose up -d without --build) works on Windows without any workaround.

Useful commands

# View logs
docker compose -f docker-compose.byod.yml logs -f

# Stop
docker compose -f docker-compose.byod.yml down

Option 3: Docker — Fullstack (Bundled PostgreSQL)

Run everything — PostgreSQL (with PostGIS and SFCGAL), the 3DCityDB schema, the MCP server, and the Gradio UI — in a single Docker Compose stack. No pre-existing database needed. If you also want to see the model in 3D, continue with Option 3b — the 3D viewer after the quick start below.

Prerequisites

  • Docker with Compose (V2)

  • A CityGML, CityJSON, or IFC file to import (optional — the database starts empty)

Quick Start

# 1. Clone the repository (or just download docker-compose.fullstack.yml + .env.example)
git clone https://github.com/tum-gis/3dcitydb-mcp-server.git
cd 3dcitydb-mcp-server/production

# 2. Copy and edit the environment file
cp .env.example .env   # Linux / macOS
# Copy-Item .env.example .env   # Windows PowerShell

Edit .env:

# PostgreSQL settings for the bundled database
POSTGRES_DB=citydb
POSTGRES_USER=citydb
POSTGRES_PASSWORD=citydb
SRID=25832          # choose the right EPSG code of the coordinate reference system for the dataset you want to import

# At least one LLM provider
ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=sk-...
# OLLAMA_BASE_URL=http://host.docker.internal:11434
# 3. (Optional) Place your CityGML file in the data directory
mkdir -p data
cp /path/to/your/city.gml data/

# 4. Pull the pre-built image and start (works on all platforms, no build needed)
docker compose -f docker-compose.fullstack.yml up -d

# 5. Open the UI
# http://localhost:7860

Both images are pulled automatically from the GitHub Container Registry on first run. The first start takes ~60 seconds while PostgreSQL initialises.

Recommended: pre-pull the importer's helper images so the first import doesn't silently block for several minutes:

# citydb-tool (~350 MB) — used for every CityGML/CityJSON import
docker compose -f docker-compose.fullstack.yml --profile importer pull

# ifc-to-citygml3 (~2 GB) — only needed if you plan to import .ifc files
docker compose -f docker-compose.fullstack.yml --profile ifc pull

# citydb-3dtiler (~1.7 GB) — generates the 3D tiles for the optional 3D view (see below)
docker compose -f docker-compose.fullstack.yml -f docker-compose.fullstack.viz.yml --profile tiler pull

These are pulled on demand anyway on first use if you skip this step — it just moves the wait earlier and shows normal docker pull progress instead of Gradio's import log.

Option 3b: add the 3D viewer (optional)

Add the viewer to the fullstack stack by layering docker-compose.fullstack.viz.yml on top of it:

docker compose -f docker-compose.fullstack.yml -f docker-compose.fullstack.viz.yml up -d

The Chat tab then shows the 3DCityDB Web Map Client next to the chat. The client streams the model as 3D Tiles: they are generated on demand by the citydb-3dtiler container (ghcr.io/3dcitydb/citydb-3dtiler), which the stack starts as a sibling of the agent and writes into a shared tiles_data volume served at /tiles. After an import, tick Generate 3D tiles after import, or press 🔄 Refresh 3D tiles above the viewer at any time (e.g. after editing the database directly). When an answer lists objectids, those features are highlighted and the camera flies to them; features without geometry of their own, such as a Room, are expanded to the surfaces they contain (see resolve_highlight_targets below).

Selecting objects for the chatbot. The viewer also supports selection: turn on the ON/OFF toggle in the viewer's selection panel and click features in the 3D scene — a click on a boundary surface, e.g. a wall, opens a small panel offering the picked surface, its containing feature such as the building, and its siblings, so you can add the level you actually mean (Add to selection). The selected features are listed in the panel (removable with −) and appear live as a 🖱 … features selected badge in the chat UI. Press ✓ Finish selecting when done. The chatbot receives the selection as a [VIEWER SELECTION] context block, so questions like "What is the total floor area of these buildings?" or "Wie alt sind die ausgewählten Objekte?" are scoped to exactly the selected objectids — no coordinate or address filtering needed.

The viewer is baked into the citydb-mcp-agent image, so until the published image is updated rebuild it locally with docker compose -f docker-compose.fullstack.yml build citydb-agent.

Spatial scratchpad (optional)

The spatial scratchpad gives the chatbot a place to park intermediate and final results so they survive beyond a single answer and can be inspected in 3D and queried again. Each saved item is either:

  • a featureset — a named set of objectids, e.g. "the buildings in Bräugasse" or "the buildings taller than 30 m", shown as coloured buildings in the tiles; or

  • a geometry — a pin, point, line, draped 2D polygon or extruded 3D solid, e.g. "a pin on my house", "a 3D convex hull around these two buildings", or "a 25 m solid from this polygon".

What it is useful for. It turns a chat into a little scratch workspace: ask the chatbot to save the result of a query ("store the affected buildings in a variable affected_2013"), then in a later turn reuse it ("how many of affected_2013 are residential?", "show me the buildings within 100 m of my marker my_house"). Because the saved items are a per-user SQL view (my_scratchpad), you can also join them against the CityGML schema in ordinary run_query queries — set differences, proximity, aggregates — without re-running the original, possibly expensive, query. Typical uses:

  • stage and compare the results of several analysis steps (set A minus set B, A ∩ B, …);

  • drop labelled pins / markers / areas / solids into the 3D view to annotate the scene;

  • give the user a persistent, clickable, fly-to-able list of "my objects" (bottom-right panel) that survives across turns and across page reloads of the same browser.

How it works. The chatbot creates and manages items through four dedicated MCP tools (save_to_scratchpad, update_scratchpad_item, scratchpad_action, list_scratchpad), which also work from external MCP clients (Claude Desktop, VS Code). Saving a featureset re-runs the user's SELECT read-only in the server — the geometry / objectids never pass through the model. Items are isolated per user (a read-only database role plus a security_barrier view filtered to the user's id from the session layer, not from the model), capped (100 items, 20k vertices, 100k objectids per user), and every change is written to a JSONL audit log. The 3D viewer renders each item according to its class: pins with labels, Point3D spheres, 3D lines as pipes, filled / draped polygons and solids, and floating markers with a stem down to the terrain.

Note: the scratchpad is stored in the database, so it is available in all Docker options (BYOD included); the 3D display additionally needs the viewer (ENABLE_VIZ=true, Option 3b). Enabling CITYDB_SCRATCHPAD=true needs a bootstrap role with CREATEROLE (the bundled fullstack superuser has it; with a restricted BYOD account a fallback guard is used instead).

Enable it in production/.env:

CITYDB_SCRATCHPAD=true
# Optional: shared scratchpad id for external MCP clients without a web UI session
# CITYDB_SCRATCHPAD_MCP_USER=<default: a fixed uuid>
# Optional: one JSON line per change; empty switches the audit log off
# CITYDB_MCP_AUDIT_LOG=/app/data/audit/scratchpad.jsonl

Full reference — data model, class vocabulary (15 geometry classes + FeatureSet), the 2D↔3D/height/extrusion rules, isolation details, and the viewer behaviour — is in production/docs/scratchpad.md.

Flood scene (optional)

The 3D viewer can also render a quick bathtub flood scenario, triggered from an ordinary run_query — so it works with any model (including local Ollama) and needs no extra tool. When an answer contains a constant column flood_level_m (the water level in the data's height system), the viewer draws a flat water surface at that height and colours every building: red = flooded (lowest point below the water), green = held back by a protection_m barrier, grey = dry. A panel offers the affected count, the current level, a level slider, a gauge widget and a "Hide flood" button. It is a fast first estimate (no flow, no connectivity, no defences), not a hydraulic model. Requires the viewer (ENABLE_VIZ=true) and buildings with absolute heights.

FLOOD_SCENE=true

See production/docs/flood-scene.md for the full mechanics, the gauge/warning-level settings, and the limitations.

Building locally (optional)

# Linux / macOS
docker compose -f docker-compose.fullstack.yml up -d --build

# Windows — disable BuildKit to avoid a known NTFS ordering bug:
$env:DOCKER_BUILDKIT=0; docker compose -f docker-compose.fullstack.yml up -d --build

Windows note: Only needed when building locally with --build. The default docker compose up -d (pull from the GitHub Container Registry) works on Windows without any workaround.

Import CityGML/CityJSON/IFC

Once the UI is open:

  1. Go to the Import CityGML / CityJSON / IFC tab

  2. Click Refresh to see files in ./production/data/, or use Upload file to add one from your computer

  3. Select your file and click Import

  4. Watch the live log — the import runs using the Docker container ghcr.io/3dcitydb/citydb-tool. Note, this container is pulled automatically, if it is not available in your Docker environment so far. In this case, please be patient as it might take 30 seconds before the import process really starts.

The data directory is mounted at ./production/data/ on the host and /app/data/ inside the container.

Importing IFC files: selecting an .ifc file (or overriding the Format selector to ifc) reveals three conversion options before import:

Option

Effect

Georeference to Oktoberfest / Munich

Use when the IFC model carries no real-world georeferencing of its own. It will be translated to the Theresienwiese in Munich, which is the place where the annual Oktoberfest takes place.

Skip storeys

Don't create Storey features from the IFC building structure

Group unrelated doors/windows into a dummy BuildingConstructiveElement

For IFC models where door/window openings aren't properly related to a wall

The file is first converted to CityGML 3.0 via ghcr.io/tum-gis/ifc-to-citygml3 (written next to the .ifc file as <name>.gml), then imported the same way as any other CityGML file. Like citydb-tool, this image (~2 GB) is pulled automatically on first use if not already present — see the pre-pull commands above to avoid that wait during the import itself.

Coordinate reference system

Set SRID to the EPSG code for your data before the first start. Common values:

Region

CRS

SRID

Dimensionality

Units of measure

Germany (UTM Zone 32N)

ETRS89 / UTM Zone 32N

25832

2D

(m, m)

Germany (UTM Zone 33N)

ETRS89 / UTM Zone 33N

25833

2D

(m, m)

USA (NAD83 / UTM Zone 14N)

NAD83

26914

2D

(m, m)

USA (NAD83 / UTM Zone 14N)

NAD83 (US survey feet)

32614

2D

(ft, ft)

Japan (PLATEAU)

JGD2011 (JGD2024) + JGD2011 vertical (compound)

6697

3D

(°, °, m)

Global (WGS84)

WGS 84

4326

2D

(°, °)

The Netherlands (RD New + NAP height)

RD + NAP height (compound)

7415

3D

(m, m, m)

Dimensionality is how many coordinates the CRS defines: the German, US and global rows above are 2D (planar easting/northing, or longitude/latitude, with no vertical axis in the CRS definition). A 3D CRS carries heights as part of the coordinate system, and the two 3D rows here are compound CRS — a horizontal part joined to a separate vertical part:

  • The Netherlands 7415 = the planimetric RD New grid (Amersfoort, EPSG:28992) + NAP height (Normaal Amsterdams Peil, EPSG:5709).

  • Japan (PLATEAU) 6697 = JGD2011 / JGD2024 geographic lat/lon in degrees (EPSG:6668) + JGD2011 (vertical) gravity-related height in metres (EPSG:6695).

In both, the data already carries x, y and a height.

The US is not automatically in feet. The standard NAD83 / UTM CRS (such as 26914) is in metres — 26914 uses metre units for both easting and northing. The US survey foot version is a separate EPSG code: 32614 is NAD83 / UTM zone 14N in US survey feet (a different zone-numbering scheme, 326xx, and the 1.000000226 US-survey-foot length). US CityGML data is commonly published in either form, so read the CRS from the file header: if it says 26914 / 269xx the units are metres, if it says 326xx the units are US survey feet. (Geographic WGS 84 / NAD83, 4326 / 4269, are in degrees regardless.)

You should name a 3D SRID whenever one is available for your data. However, many CityGML datasets use a compound CRS with separate SRIDs for planimetry and height, and for these combinations a predefined SRID is often not available in PostGIS. In that case, name the SRID of the planimetric coordinates (2D) instead, as in the 2D rows above.

Useful commands

# View logs
docker compose -f docker-compose.fullstack.yml logs -f

# Stop (preserves database volume)
docker compose -f docker-compose.fullstack.yml down

# Stop and delete all data
docker compose -f docker-compose.fullstack.yml down -v

Configuration Reference

All options are set via environment variables (.env file or Docker Compose environment block).

Database connection

Variable

Default

Description

CITYDB_HOST

localhost

PostgreSQL host

CITYDB_PORT

5432

PostgreSQL port

CITYDB_NAME

citydb

Database name

CITYDB_USER

citydb

Database user

CITYDB_PASSWORD

(required)

Database password

CITYDB_SCHEMA

citydb

3DCityDB schema name

DATABASE_URL

(auto-built)

Full PostgreSQL URL (overrides individual vars)

Fullstack only

Variable

Default

Description

POSTGRES_DB

citydb

Database name for bundled PostgreSQL

POSTGRES_USER

citydb

Database user for bundled PostgreSQL

POSTGRES_PASSWORD

citydb

Database password for bundled PostgreSQL

SRID

25832

EPSG code for the 3DCityDB spatial reference

POSTGIS_SFCGAL

true

Enable SFCGAL extension (required for, e.g., CG_Volume, CG_3DArea)

3D viewer (only used when ENABLE_VIZ=true)

Default terrain and base map for the 3D view. Both default to Germany-wide, freely licensed sources (basemap.de) and are applied unconditionally — not gated to one region's SRID. Set a *_URL to an empty string to disable that layer, or override all of these for another country.

Variable

Default

Description

VIEWER_TERRAIN_URL

https://web3d.basemap.de/cesium/dgm5-mesh/

Cesium quantized-mesh terrain endpoint

VIEWER_TERRAIN_NAME

DGM5 (basemap.de)

Shown in the terrain picker

VIEWER_TERRAIN_TOOLTIP

basemap.de - DGM5 (Germany)

Tooltip for the terrain picker entry

VIEWER_WMS_URL

https://sgx.geodatenzentrum.de/wms_basemapde?

OGC WMS endpoint added as a selectable base map

VIEWER_WMS_LAYER

de_basemapde_web_raster_farbe

WMS layer name

VIEWER_WMS_NAME

WMS basemap.de

Shown in the base-layer picker

VIEWER_WMS_TOOLTIP

(C) basemap.de

Tooltip for the base-layer picker entry

VIEWER_WMS_PROXY_URL

(empty)

Only needed for a WMS without CORS — this image does not ship the vendored client's own /proxy/ endpoint; basemap.de sends Access-Control-Allow-Origin: * so the default (no proxy) works

LLM providers

At least one must be configured for the Docker variants. The Gradio UI auto-selects the provider based on what is available (Anthropic → OpenAI → Ollama, in that priority order).

Variable

Description

ANTHROPIC_API_KEY

Anthropic API key (sk-ant-...)

OPENAI_API_KEY

OpenAI API key (sk-...); when using Ollama via the OpenAI-compatible endpoint this value must be ollama

OPENAI_BASE_URL

Base URL for the OpenAI provider. Leave empty for models offered by OpenAI. When using a locally running LLM or a remote LLM (not hosted by OpenAI) via its OpenAI-compatible API (e.g., provided by llama.cpp, vLLM, or Ollama) provide the corresponding endpoint URL (e.g. http://host.docker.internal:11434/v1/)

OLLAMA_BASE_URL

Ollama base URL (e.g. http://host.docker.internal:11434)

LITELLM_TIMEOUT

120

LITELLM_TIMEOUT_LOCAL

300

Query behaviour

Variable

Default

Description

CATEGORICAL_THRESHOLD

20

Max distinct values for CityGML feature attributes before the attribute is considered not as an enumeration but as free text (only applied when no known codelist exists). The values of enumeration attributes are prefetched and added to the system prompt.

SAMPLE_VALUES_COUNT

5

Number of sample values shown per non-categorical attribute

Country-specific codelists

Code-type properties (core:Code) are resolved against country-specific codelist definitions. The country is auto-selected from the database EPSG code (database_srs), falling back to a generic DEFAULT block for unknown countries:

  • DE (EPSG 25831–25833, 31466–31469, 5650) — ALKIS/AdV: function (31 codes), usage, roofType (roof form)

  • JP (EPSG 6668–6692, 2443–2461) — J-PLATEAU/MLIT: class, roofType (29 codes), usage

  • DEFAULT — SIG3D-standard roofType

Each codelist is keyed by a qualified composite key of the form <namespace-alias>:<Classname>.<attribute> — e.g. bldg:Building.function. The alias comes from the 3DCityDB namespace.alias column and the class name is the concrete feature class. Lookup is exact (case-insensitive); there is no fallback to bare attribute names, so same-named attributes in different classes (e.g. bldg:Building.function vs. brid:Bridge.function) never collide. Only codes that actually occur in the imported data are exposed to the LLM, with no artificial cap.

Codelists are defined in src/citydb_mcp/tools/dynamic_tools.py (COUNTRY_CODELISTS). Adding a class or country later (e.g. bldg:BuildingPart.*) is a pure data change — no code changes required.

Ollama tuning (optional)

Variable

Default

Description

OLLAMA_NUM_CTX

131072

Context window size (tokens) passed to the Ollama model

LOCAL_MAX_TOKENS

16000

Maximum tokens the local model may generate per response

OLLAMA_TIMEOUT

300

Timeout in seconds for Ollama requests

AGENT_MAX_ITERATIONS

10

Maximum ReAct tool-call iterations per question

WebUI story distillation (optional)

The "Keep a distilled summary" feature (chat WebUI) distills each turn's reasoning trace into a compact story. Both knobs apply to the distillation call regardless of provider (Ollama or OpenAI-compatible).

Variable

Default

Description

STORY_TRANSCRIPT_MAX_CHARS

30000

Maximum characters of the reasoning transcript fed into the distillation prompt. Tail-preserving: if the trace is longer, the beginning is cut (early exploration) so the final successful queries are always kept

STORY_MAX_TOKENS

2000

Maximum tokens the story itself may contain (OpenAI-compatible provider; the Ollama path is fixed at 700)

Sessions / multiple users (WebUI)

Per-user state (user identity, per-tab Stop, parallel chats) — see session-layer.md.

Variable

Default

Description

WEBUI_CONCURRENCY

4

How many chat turns may run at the same time (Gradio's default would be 1)

Spatial scratchpad (only used when CITYDB_SCRATCHPAD=true)

Variable

Default

Description

CITYDB_SCRATCHPAD

false

Master switch for the per-user spatial scratchpad (table + four MCP tools + my_scratchpad view + [SCRATCHPAD] prompt block)

CITYDB_QUERY_USER

citydb_query

Name of the dedicated read-only role used for run_query and the scratchpad

CITYDB_QUERY_PASSWORD

derived

Password for that role; if unset it is derived deterministically from CITYDB_PASSWORD and CITYDB_NAME so the web UI and every MCP subprocess agree

CITYDB_SCRATCHPAD_MCP_USER

fixed uuid

Shared scratchpad user id for external MCP clients that have no web UI session

CITYDB_MCP_AUDIT_LOG

(empty)

Path to a JSONL audit log, one line per scratchpad change; empty switches it off

Flood scene (only used when FLOOD_SCENE=true)

Variable

Default

Description

FLOOD_SCENE

false

Adds a short [FLOOD SCENE] prompt block: a result with a flood_level_m column draws the water surface and coloured buildings

FLOOD_EXCLUDE_FUNCTIONS

(empty)

Comma-separated CityGML function codes that are not buildings, excluded from the flood count and named in the prompt

FLOOD_GAUGE_NAME / FLOOD_GAUGE_ZERO_M

(empty)

Viewer gauge widget: gauge name and its zero in the data's height system

FLOOD_STAGES

(empty)

Comma-separated warning levels (cm above gauge zero) marked on the gauge

FLOOD_REFERENCE_CM / FLOOD_REFERENCE_LABEL

(empty)

A historic flood reading (cm) and its label, shown on the gauge


Available MCP Tools

Static (cached per session)

Tool

Description

get_server_version

Version of the 3DCityDB MCP server package

get_database_schema

3DCityDB v5 table structures and foreign key relationships

get_query_guidelines

SQL best practices and optimisation tips for 3DCityDB

Dynamic (called at session start)

Tool

Description

scan_objectclasses

Discover available object classes with full CityGML hierarchy

resolve_properties(objectclass_id)

Resolve properties with codelists for a given class

get_generic_attributes

Generic attributes with categorical detection

get_db_context_snapshot

SRS, bounding box, feature counts, database statistics

get_lod_config

Available Levels of Detail in the database

get_examples(objectclass_ids)

SQL examples filtered to existing object classes

resolve_highlight_targets(objectids)

Expands GML ids (e.g. a Room) to the geometry-owning features a 3D viewer can highlight, plus a WGS84 camera target

get_feature_tree(objectid)

Containment tree around one picked feature: its ancestors, children, and siblings

describe_selection(objectids)

Summarizes a multi-feature viewer selection: resolved features, per-class counts, tileable ids

Runtime (per query)

Tool

Description

run_query(sql)

Execute read-only SQL (SELECT/WITH only) against 3DCityDB

get_session_context

Session management and state

update_module_selection

Narrow scope to specific object classes

get_history

Conversation history for a session

submit_feedback

Log query feedback

Assembly

Tool

Description

assemble_prompt

Orchestrates all tools into a complete system prompt in one call

Spatial scratchpad (only when CITYDB_SCRATCHPAD=true)

Tool

Description

save_to_scratchpad

Save a result as a named item — a featureset (SELECT with an objectid column) or a geometry (SELECT with a geom column, or GeoJSON) — with optional label, colour, class and 2D/3D height/extrusion settings. Replaces an existing name

update_scratchpad_item

Change a saved item in place: style (label, colour, opacity, size), class, and height/extrusion (which may rewrite the geometry to match)

scratchpad_action

Act on named items — show, hide, delete (deleting more than one needs confirm: true), or goto (fly the camera to them)

list_scratchpad

List the user's items: name, label, kind, class, colour, visibility and count/geometry type

Note: The 3D viewer tools — resolve_highlight_targets, get_feature_tree, and describe_selection — are only offered when the stack runs with the viewer enabled (ENABLE_VIZ=true, see Option 3b). The four scratchpad tools are only offered when CITYDB_SCRATCHPAD=true. In deployments where a feature is off, its tools are omitted from the tool list entirely, so they never appear to clients such as the MCP Inspector. The scratchpad additionally exposes a per-user my_scratchpad SQL view that can be queried with ordinary run_query calls. See Spatial scratchpad.


Architecture

  Claude Code / Claude Desktop / any MCP client
                      │
               MCP Protocol (stdio / SSE)
                      │
       ┌──────────────┴──────────────┐
       │   3DCityDB MCP Server       │
       │   assemble_prompt()         │
       │   scan_objectclasses()      │
       │   run_query()               │
       └──────────────┬──────────────┘
                      │
                 3DCityDB v5
               (PostgreSQL + PostGIS)


      Browser ──► Gradio UI (port 7860)       [Docker variants only]
                                │
          ┌─────────────────────┴────────────────────┐
          │                                          │
   Anthropic / OpenAI                        Ollama (local)
   LiteLLM cloud backend                     LangChain ReAct (langchain-ollama)
   (incl. OpenAI-compatible endpoints         robust tool-call parser
    via OPENAI_BASE_URL)                      model profiles + native thinking
          │                                          │
          └─────────────────────┬────────────────────┘
                                │
              MCP Client (spawns citydb-mcp subprocess)
                                │
                          3DCityDB MCP Server
                                │
                           3DCityDB v5

Citation

This work was developed at the Chair of Geoinformatics, Technical University of Munich (TUM). Main developer: Khaoula Kanna; additional testing and programming: Thomas H. Kolbe.

The accompanying paper, Enabling AI Agents for Semantic 3D City Models through Automated Domain Context Generation, was published in the ISPRS Annals of the Photogrammetry, Remote Sensing and Spatial Information Sciences (Volume XII-4/W1-2026, 21st ISPRS 3D GeoInfo Conference) and can be cited as:

@inproceedings{kanna2026enabling,
    author    = {Kanna, Khaoula and Kolbe, Thomas H.},
    title     = {Enabling AI Agents for Semantic 3D City Models through Automated Domain Context Generation},
    booktitle = {ISPRS 21st 3D GeoInfo Conference, ISPRS Ann. Photogramm. Remote Sens. Spatial Inf. Sci.},
    volume    = {XII-4/W1-2026},
    pages     = {211--218},
    year      = {2026},
    doi       = {10.5194/isprs-annals-XII-4-W1-2026-211-2026},
    url       = {https://isprs-annals.copernicus.org/articles/XII-4-W1-2026/211/2026/isprs-annals-XII-4-W1-2026-211-2026.html},
}

Further documentation of implemented web UI internals:

  • session-layer.md — users, browser tabs and turns: per-tab Stop, parallel chats, a user context passed to MCP tool calls, and per-user data folders with expiry.

  • scratchpad.md — the spatial scratchpad: per-user saved results (building sets, pins, hulls) that the chatbot creates with MCP tools and the 3D viewer shows, isolated by a read-only database role and a per-user view.

  • flood-scene.md — the 3D flood scene: a flood_level_m column in a query result draws a water surface and colours every building red / green / grey, with a level slider and gauge.

Ideas for Future Developments

We (the developers) have a number of ideas for future improvements and extensions of the ChatBot and the MCP server. They are described in these documents:

  • idea-for-future-multiple-MCP-servers.md — turning the WebUI into a general-purpose agent shell that can connect to several MCP servers configured via .env.

  • idea-for-future-websearch.md — giving the ChatBot the ability to do web searches and to download & inspect files (e.g. specifications) using a self-hosted SearXNG metasearch engine.

  • idea-for-future-Openstreetmap-interface.md — querying OpenStreetMap geodata (Nominatim / Overpass) to enrich 3DCityDB queries with real-world context.

  • idea-for-future-write-access.md — opt-in write access (DML / DDL) to the database for experimentation, off by default.

  • idea-for-future-memory-rag.md — persistent chat memory (question / answer / distilled story) with RAG retrieval of similar past turns via pgvector, off by default.

  • idea-for-future-speech-interaction.md — let users talk to the ChatBot: voice input/output and a wake word ("Hello CityBot") via an optional local citydb-voice sidecar (offline STT/TTS, English + German, no API keys), off by default.

  • idea-for-future-viewer-hide-objects.md — MCP tools to hide and unhide 3D objects by their objectid in the Webmap Client, so the agent can visually declutter the scene (e.g. hide a building's roof while inspecting its walls).

  • idea-for-future-viewer-screenshot.md — MCP tools to fly the 3D viewer camera and capture screenshots of the viewer, embedded in the generated answer (and the PDF export) while keeping the image bytes out of the LLM context — e.g. "fly to the three tallest buildings one after another and make a screenshot of each".

These new features are already implemented (to full extent or partially):


License

The 3DCityDB MCP server is distributed under the Apache License 2.0. See LICENCE for details.

Available Tools

14 tools
assemble_promptA

Assembles the complete system prompt by orchestrating all static and dynamic tools. Returns a structured prompt string containing database schema, object classes with resolved properties and codelists, generic attributes, spatial context, and optionally SQL examples and query guidelines. Set include_query_agent_extras=false for non-query agents.

NameRequiredDescriptionDefault
include_query_agent_extrasNoInclude SQL examples and query guidelines (default: true)
compactNoCompact rendering for local models with small context windows (default: false)

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description must carry the full burden. It describes the return value and orchestration but does not disclose side effects, safety, or performance characteristics. The read-only nature is implied but not explicit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no fluff. First sentence defines purpose and output; second sentence provides key parameter usage. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description thoroughly lists the components of the returned prompt and handles both parameters. It covers the essential information for an agent to understand what the tool returns and when to use parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the description adds meaningful context beyond the schema: include_query_agent_extras is linked to non-query agents, compact is for local models. This adds semantic value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool 'Assembles the complete system prompt by orchestrating all static and dynamic tools', specifying verb, resource, and scope. It distinguishes from sibling tools (which provide individual components) by being an orchestrator.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on parameter usage ('Set include_query_agent_extras=false for non-query agents'), but does not explicitly state when to use this tool versus alternatives like get_database_schema. Context implies usage for full prompt assembly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_database_schemaA

Returns the 3DCityDB v5 table structures, column details, and foreign key relationships. Called once and cached.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite no annotations, the description conveys essential behavior: it is a read operation with caching. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that efficiently communicates the action and caching behavior. No extraneous information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and no output schema, the description fully explains the tool's purpose and return content, making it complete for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, and schema coverage is 100%. The description adds context on what is returned, exceeding the baseline expectation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description specifies the exact resource ('3DCityDB v5 table structures, column details, and foreign key relationships') and action ('returns'), clearly distinguishing it from siblings like 'get_db_context_snapshot'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states 'Called once and cached,' guiding the agent to avoid repeated calls, though no alternative tools or when-not scenarios are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_db_context_snapshotA

Returns database-level context: coordinate system, EPSG code, bounding box, feature counts per class, available LoDs, null value percentages, and supported spatial operations.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description must carry the full burden. It correctly implies a read operation by naming return items, but does not explicitly state read-only behavior, side effects, performance, or authorization needs. It adds some value beyond the name by detailing outputs, but not enough to fully compensate for missing annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence with no wasted words. It front-loads the purpose ('Returns database-level context') followed by a colon and a succinct list of returned items. Every part is necessary and clearly communicates the tool's output.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has no output schema, the description lists all significant return fields, making it relatively complete for a simple retrieval tool. However, it does not mention the format of the returned data (e.g., JSON object) or any edge cases (e.g., when context is unavailable). It provides sufficient information for most scenarios.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has no parameters, and the input schema is fully covered (100%). The description does not need to explain parameters. The baseline of 4 applies because there are no parameters to document.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns 'database-level context' and lists specific items (coordinate system, EPSG code, etc.), making the purpose unambiguous. The verb 'returns' and the resource 'database-level context' are specific and distinct from siblings like 'get_database_schema' which returns different information.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives such as 'get_database_schema' or 'get_session_context'. There is no mention of prerequisites, limitations, or typical use cases. The agent must infer usage from the tool name and list of return items.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_examplesA

Returns SQL query examples filtered to only include examples for object classes that exist in the database.

NameRequiredDescriptionDefault
objectclass_idsYesList of available objectclass IDs to filter examples

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully convey behavior. It only mentions filtering, but fails to disclose whether the operation is read-only, what happens with invalid IDs, the output format, or any side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence, front-loaded with the action, and contains no unnecessary words. Every word contributes to understanding the tool's purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter tool, the description is minimally complete. However, it lacks details about the return format, error handling, and any constraints on the objectclass_ids, which would be necessary for an agent to invoke it confidently without relying on prior knowledge.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully documents the only parameter (objectclass_ids) with a description similar to the tool's description. The tool description adds no additional meaning beyond what the schema already provides, matching the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns SQL query examples, and specifies a filtering condition to only include examples for existing object classes. This distinguishes it from sibling tools like get_database_schema or run_query.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use: when you need filtered SQL examples. However, it does not provide explicit guidance on when not to use this tool or mention alternatives among the siblings, leaving it to the agent to infer.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_generic_attributesA

Fetches generic attributes (namespace_id=3) with categorical detection. String attributes with few distinct values include all possible values. Numeric attributes include min/max range.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description discloses key behaviors: categorical detection includes all possible values for strings, and numeric attributes show min/max range. However, it does not mention read-only nature or side effects, which could be inferred but not explicit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core purpose, concise and no redundant information. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and low complexity, the description sufficiently explains what is returned (all possible values for categorical, min/max for numeric). No missing critical information for the tool's purpose.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has no parameters (0 count, 100% coverage), so the baseline is high. The description adds no parameter-level details but that's fine since none exist. It explains output behavior which compensates.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Fetches generic attributes') and specifies the resource with a unique identifier (namespace_id=3), distinguishing it from sibling tools like run_query or get_database_schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use or alternatives. The specialized namespace and categorical detection imply a specific use case, but lack of explicit context or when-not-to-use reduces clarity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_historyC

Returns the conversation history for a session.

NameRequiredDescriptionDefault
session_idYes

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description must cover behavior. It only states the output type but omits details like ordering, pagination, or performance implications. Does not disclose if it's read-only, which is implied but unconfirmed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no filler, directly states purpose. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple retrieval tool with no output schema, the description is minimally adequate. However, it lacks contextual details like whether history is ordered chronologically or how limits/errors are handled.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter session_id has no description in the schema (0% coverage) and the tool description adds no semantic meaning beyond the parameter name. An agent cannot infer format or constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns conversation history for a session, matching the name. It distinguishes from siblings like get_session_context or get_examples by focusing on history. However, it could be more specific about what 'history' includes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool vs. alternatives like get_session_context. No context about prerequisites or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_lod_configA

Returns available Levels of Detail in the database, with the most common LoD set as default.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description must cover behavioral traits. It only states the tool returns data, which implies a read-only operation, but provides no additional disclosure about side effects, caching, or performance characteristics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that is concise and front-loaded, containing no unnecessary information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description lacks detail on the return format or structure of the LoD data. It mentions a default but does not elaborate, leaving the agent with incomplete information for a simple tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has no parameters, so the description does not add parameter meaning. According to guidelines, baseline is 4 for zero parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns available Levels of Detail and indicates a default is set. It uses a specific verb 'returns' and a specific resource 'available Levels of Detail', distinguishing it from sibling tools like get_database_schema which focus on different aspects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. The description simply states what it does without offering context on selection criteria, prerequisites, or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_query_guidelinesA

Returns SQL best practices, indexed columns, optimization tips, and expensive operations to avoid for 3DCityDB queries.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description bears full responsibility for behavioral disclosure. It does not mention whether the tool is read-only, requires any authentication, or has side effects. The description only lists what is returned, omitting important behavioral traits like cost or data source.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence of 16 words that directly states the tool's purpose. It is concise and front-loaded with the main action, with no unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and no parameters, the description is the sole source of information. It lists the types of information returned but does not specify format (e.g., text, JSON) or provide example content. For a simple reference tool, this is minimally adequate but could be more complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and schema coverage is 100%. The description does not need to add parameter info since there are none. Baseline of 4 is appropriate as no additional meaning is required beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it returns SQL best practices, indexed columns, optimization tips, and expensive operations to avoid for 3DCityDB queries. The verb 'Returns' and specific resource names make the purpose unambiguous, and it is distinct from siblings like get_database_schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives. While the purpose implies consulting it for SQL guidelines, there is no guidance on when not to use it or which sibling tools to consider instead. The context is implied but not articulated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_session_contextB

Returns or creates the current user session context.

NameRequiredDescriptionDefault
session_idNoOptional session ID. Creates new session if not provided.

TDQS

B3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states the tool 'returns or creates', implying both read and write behavior, but does not disclose side effects, required permissions, or whether creation is idempotent. Since no annotations are provided, the description carries the full burden of transparency, which it fails to meet.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that efficiently conveys the core function. However, it lacks structural elements like separate sections for behavior or examples, and could benefit from front-loading the primary action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that the tool can both return and create session context, the description omits important information such as the return value format, any error conditions, or how the session context is represented. No output schema exists to fill this gap, so completeness is insufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds context: 'Optional session ID. Creates new session if not provided.' This explains the parameter's effect beyond the schema's basic description, aiding in correct usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: returning or creating the current user session context. However, it does not differentiate this tool from siblings like get_db_context_snapshot or get_history, which might also involve session or context retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. The description does not mention prerequisites, when a session is created versus returned, or how this tool compares to other context-related siblings like get_db_context_snapshot.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_propertiesC

For a given objectclass_id, walks the superclass hierarchy, collects all schema-defined properties, filters against the property table to keep only existing properties, determines value columns and join info, and resolves codelists for Code-type properties. Returns fully enriched PropertyDefinitions.

NameRequiredDescriptionDefault
objectclass_idYesThe objectclass ID to resolve properties for (e.g. 901 for Building)

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description must disclose behavioral traits. It outlines internal steps (walk hierarchy, filter, resolve codelists) but omits side effects, error conditions, or performance implications.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single lengthy sentence that packs many steps. It is not optimally concise or front-loaded; restructuring would improve clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description only vaguely mentions 'Returns fully enriched PropertyDefinitions.' Missing details on return format, errors, and edge cases for invalid inputs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter, so baseline is 3. The description does not add additional meaning beyond the schema's parameter description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool resolves properties for a given objectclass_id by walking the superclass hierarchy and enriching. It is specific and distinguishes from general query tools, though no explicit sibling differentiation is provided.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool vs alternatives like get_generic_attributes or scan_objectclasses. No when-not or prerequisites mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_queryA

Executes a read-only SQL query against 3DCityDB. Only SELECT and WITH (CTE) statements are allowed. Results are automatically limited to 500 rows.

NameRequiredDescriptionDefault
sqlYesSQL SELECT query to execute

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses read-only nature, allowed statements, and the automatic 500-row limit, covering key behavioral traits. It could mention error handling or performance, but the given details are sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the main action, and every word serves a purpose. No redundancy or verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (1 param, no output schema, no annotations), the description covers essential aspects: what it does, allowed queries, result limit. It could mention that queries are executed against a specific database, but that is already stated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter 'sql', and the description adds valuable constraints: only SELECT/WITH queries are allowed and results are limited to 500 rows, enhancing the schema's basic description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it executes read-only SQL queries against 3DCityDB, specifying allowed statement types (SELECT and WITH), which distinguishes it from sibling tools that perform other database operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description specifies allowed statements and implicitly guides against using it for mutations or unsupported queries. However, it doesn't explicitly compare to sibling tools or provide when-not-to-use scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scan_objectclassesA

Scans the database for existing object classes (e.g. Building, Vegetation, LandUse). Returns the full class hierarchy with superclass chain, namespace IDs, and schema definitions.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must carry full behavioral burden. It describes the output but does not disclose performance, authorization requirements, or that it is a read-only operation. Lacks details on side effects or error conditions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with no redundant words. Front-loaded with verb and examples, immediate clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with no output schema, the description adequately covers purpose and output. Lacks detail on output format or structure, but sufficient given simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0 parameters (100% coverage automatically). Description adds value by explaining what the tool returns beyond the schema, which only states no parameters. Baseline 4 applies as per guidelines.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description uses clear verb 'Scans' with specific resource 'existing object classes', provides examples (Building, Vegetation, LandUse), and specifies the return value (full class hierarchy with superclass chain, namespace IDs, schema definitions). Distinguishable from sibling tools like get_database_schema which returns broader schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description implies usage for retrieving object class hierarchy but does not explicitly state when to use this tool versus alternatives like get_database_schema or get_generic_attributes. No guidance on prerequisites or exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_feedbackC

Logs feedback for a query execution (rating, errors).

NameRequiredDescriptionDefault
session_idYes
queryYes
ratingYes
execution_time_msNo
result_countNo
errorNo

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the entire burden falls on the description. It only says 'Logs feedback,' which implies a write operation but lacks details on side effects, permissions, rate limits, or data persistence. The description does not clarify whether the operation is reversible or what happens on failure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The single-sentence description is concise and front-loaded with the primary action. However, it could include more context without becoming verbose, but remains appropriately sized for a simple tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 6 parameters, no output schema, and no annotations, the description is incomplete. It does not explain return values, success/failure signals, or how the feedback is used. The minimal information leaves gaps for an AI agent to correctly invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 6 parameters with 0% description coverage. The description mentions 'rating' and 'errors,' but omits session_id, query, execution_time_ms, and result_count. It adds some meaning for the mentioned params but fails to explain the purpose of the others, which is insufficient given the low schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Logs feedback for a query execution (rating, errors).' It uses a specific verb ('Logs') and resource ('feedback for a query execution'), and distinguishes itself from sibling tools (no other tool logs feedback).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. While it implies use after a query execution, it does not specify prerequisites, exclusions, or mention related tools like 'run_query' for context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_module_selectionB

Narrows the user's scope to specific object classes or modules. Affects which properties, examples, and codelists are relevant.

NameRequiredDescriptionDefault
session_idYes
objectclass_idsYesObject class IDs to focus on
modulesNoModule names to focus on (e.g. ['building', 'vegetation'])

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description bears full responsibility for disclosing behavioral traits. It states the tool 'narrows scope' and 'affects relevancy', but does not clarify whether the selection is additive or overwriting, whether the change is persistent, or what side effects occur. The absence of output schema also leaves return behavior unclear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences are concise and front-loaded; the first states the core function, the second elaborates on the effect. No unnecessary words or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a mutation tool with no annotations, no output schema, and a required session_id parameter lacking description, the description is incomplete. It does not explain error handling, parameter constraints, or how the tool fits into the broader workflow with siblings like get_session_context or run_query.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 67% (two of three parameters have descriptions). The description echoes the schema by mentioning 'object classes or modules' but adds no new semantic detail beyond that. The baseline score of 3 is appropriate given moderate coverage and marginal added value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'narrows the user's scope to specific object classes or modules' with a specific verb ('narrows') and resource ('object classes or modules'). It is clear but does not explicitly differentiate from sibling tools like get_session_context that also handle session state, though the action (update vs. retrieve) is implied.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when needing to focus on relevant properties, examples, and codelists, but provides no explicit when-to-use, when-not-to-use, or alternatives among sibling tools. No prerequisites (e.g., session must exist) are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 14 tool updatesv0.2.0
    • First observedassemble_prompt
    • First observedget_database_schema
    • First observedget_db_context_snapshot
    • First observedget_examples
    • First observedget_generic_attributes
    • First observedget_history
    • First observedget_lod_config
    • First observedget_query_guidelines
    • First observedget_session_context
    • First observedresolve_properties
    • First observedrun_query
    • First observedscan_objectclasses
    • First observedsubmit_feedback
    • First observedupdate_module_selection

TDQS

A3.8/5.0

Scored across 14 tools

Disambiguation5/5

All 14 tools have clearly distinct purposes—retrieving different types of metadata (schema, context, examples, attributes, etc.), executing queries, scanning object classes, updating module selections, and submitting feedback. No two tools overlap in functionality.

Naming Consistency5/5

Every tool follows the consistent verb_noun pattern using snake_case (e.g., get_database_schema, run_query, submit_feedback). Minor abbreviation ('db' vs 'database') is common and does not break consistency.

Tool Count5/5

14 tools is well-suited for a 3DCityDB query agent—covering metadata retrieval, query execution, configuration, and feedback without excess or deficiency. The count feels appropriate for the domain.

Completeness5/5

The tool set covers all necessary operations for a read-only query agent: database introspection (schema, context, classes, attributes), query building guidance (examples, guidelines), query execution, session management, and feedback logging. No obvious gaps exist for the stated purpose.

Maintenance

ActivityNo data
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables natural language and geospatial queries on PostGIS databases, with 32 tools for spatial analysis, geometry operations, and database management.
    5
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI assistants to query databases using natural language, with automatic schema discovery and SQL compilation.
    865 npm
    3,227
    Apache 2.0
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to interact with Autodesk Civil 3D through natural language, supporting tools for surfaces, alignments, profiles, corridors, pipe networks, COGO points, and AutoCAD geometry.
    9
    3
    MIT