QGIS MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| QGIS_MCP_HOST | No | Host for socket connection | localhost |
| QGIS_MCP_PORT | No | Port for socket connection | 9876 |
| QGIS_MCP_TRANSPORT | No | MCP transport: stdio or streamable-http | stdio |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| completions | {} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| pingA | Check connectivity to the QGIS plugin server. Returns pong if connected. |
| diagnoseA | Run diagnostic checks on the QGIS MCP stack. Reports QGIS version, plugin/server version match, processing providers, connected clients, and project status. |
| list_qgis_instancesA | List the configured QGIS instances: name, host, port, reachability, and - for each reachable one - which QGIS actually answered (version, process id, window title, profile). Use it to confirm a name maps to the window you mean before writing to it. Pass a name as the 'instance' argument of any other tool to target that QGIS window; omitting it targets the instance named 'default', or the first one listed when no instance is called 'default'. |
| get_qgis_infoA | Get QGIS version, profile path, and plugin count. |
| get_project_infoA | Get current project metadata: filename, title, CRS, layer count, and summary of layers. |
| load_projectA | Load a QGIS project from a .qgs/.qgz file path. Replaces the open project; unsaved changes to it are lost. Layers whose source is missing are kept as unavailable and listed in 'unavailable_layers'. |
| create_new_projectA | Create a new empty QGIS project and save it to the given path. Replaces the open project; unsaved changes to it are lost. |
| save_projectB | Save the current project. Optionally specify a new path. |
| create_checkpointA | Snapshot the whole project (layers, styles, labels, layouts, map themes, variables, and the features of memory layers) so restore_checkpoint can return to it. Take one before a sequence of changes you may want to undo. The user's project file is not touched. Data in files and databases is not copied, and uncommitted edits are listed under 'uncommitted_edits' because the checkpoint does not hold them. The last 20 are kept, until the plugin's server stops. |
| list_checkpointsA | List the project checkpoints: id, name, creation time, layer count. |
| restore_checkpointA | Put the project back as it was at a checkpoint: every change since, and any uncommitted edit, is discarded. The project keeps its file name and is left unsaved. Memory layer features come back with new feature ids. Layers whose source is missing are kept as unavailable and listed in 'unavailable_layers'. export_session afterwards replays the restored state, not the undone steps. |
| export_sessionA | Every command that changed something in this QGIS since the plugin's server started (read-only calls left out), as a Python script that replays them from the QGIS Python console. Layer ids are remapped on replay. Returns the script, or writes it to 'path' and returns the path. clear: start a new journal afterwards. Commands from every connected client are in it; a restore_checkpoint rewinds it. |
| get_layersA | List layers in the current project with IDs, names, types, visibility, and type-specific info. Use limit/offset for pagination. Response includes total_count. |
| add_vector_layerC | Add a vector layer (shapefile, GeoJSON, GeoPackage, etc.) to the project. |
| add_raster_layerC | Add a raster layer (GeoTIFF, etc.) to the project. |
| remove_layerA | Remove a layer from the project by its layer ID. This is irreversible. |
| find_layerA | Find layers by name pattern. Supports fnmatch wildcards (e.g. 'roads*') and substring matching. |
| create_memory_layerA | Create a new in-memory vector layer. geometry_type: Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon. fields: [{name, type}] where type is integer, double, string, date, datetime. |
| set_layer_visibilityB | Set a layer's visibility in the layer tree (show/hide on map). |
| zoom_to_layerA | Zoom the map canvas to the full extent of the specified layer. |
| get_layer_featuresA | Get features from a vector layer. Flat dicts: _fid + attributes at top level. expression filter (QGIS, e.g. "name = 'Berlin'", "population > 1000000"), limit (max 50, larger is refused; default 10), offset for paging, optional geometry in _geometry key. feature_count is the layer total; matched is the count after the expression filter. |
| get_field_statisticsA | Compute aggregate statistics (count, sum, mean, min, max, stdev) for a numeric field. For non-numeric fields returns count and distinct values. |
| add_featuresA | Add features to a vector layer. Each feature: {attributes: {field: value}, geometry_wkt: 'POINT(1 2)'}. geometry_wkt is in the layer's CRS, or in crs when given (it is then reprojected). A geometry type the layer cannot hold is refused; invalid geometry or 2D on a Z layer comes back in warnings. Returns count of added features. |
| update_featuresA | Update feature attributes. updates: [{fid: 1, attributes: {field: value}}]. Returns count of updated features. |
| delete_featuresA | Delete features by feature IDs or expression filter. Provide either fids (list of ints) or expression (string), not both. Returns requested and the measured deleted count. |
| update_feature_geometryA | Replace feature geometries. updates: [{fid: 1, geometry_wkt: 'POINT(1 2)'}]. WKT must be in the layer's CRS. Inside an edit session the change is undoable; otherwise it is written straight to the data source. |
| start_editingA | Open an edit session on a vector layer. Subsequent add/update/delete calls go to the undoable edit buffer instead of the data source, until commit_edits or rollback_edits. |
| commit_editsA | Commit the layer's edit buffer to the data source and close the edit session. |
| rollback_editsA | Discard every uncommitted change on a layer and close the edit session. |
| get_edit_statusA | Edit state of a layer: editable, modified, undo/redo availability, and the counts of pending added/deleted/changed features. |
| undo_editsB | Undo the last edit operations on a layer (its own undo stack). Returns how many steps were actually undone. |
| redo_editsB | Redo previously undone edit operations on a layer. |
| select_featuresB | Select features in a layer by expression or feature IDs. |
| get_selectionA | Get the current selection for a layer. Returns feature IDs and count. |
| clear_selectionC | Clear the selection on a layer. |
| set_layer_styleA | Set symbology. style_type: 'single' (one symbol), 'categorized' (unique values), 'graduated' (numeric ranges). field required for categorized/graduated. color_ramp: QGIS ramp name (e.g. 'Spectral', 'Viridis', 'Blues'). classes: graduated class count (default 5). |
| set_raster_styleA | Set raster symbology. style_type: 'singleband_pseudocolor' (color ramp over one band), 'singleband_gray', 'multiband_color' (RGB), 'hillshade'. min_value/max_value default to the band statistics. color_ramp: QGIS ramp name (e.g. 'Viridis', 'Spectral', 'RdYlGn'). classification: continuous|equal_interval|quantile. interpolation: interpolated|discrete|exact. gradient (gray): black_to_white|white_to_black. contrast: none|stretch|clip|stretch_clip. hillshade uses band, azimuth, altitude, z_factor. |
| get_canvas_extentA | Get the current map canvas extent and CRS. |
| set_canvas_extentA | Set the map canvas extent. Coordinates should be in the specified CRS (default: project CRS). |
| get_canvas_screenshotA | Grab a fast screenshot of the current map canvas widget (no re-render). Returns the image inline. Much faster than render_map. |
| get_3d_screenshotA | Capture an OPEN 3D Map View as an inline image. Reuses the open view's scene + camera, rendered via a print-layout 3D map item (the 2D get_canvas_screenshot cannot capture the OpenGL 3D view). Requires a 3D map view to be open in QGIS (View > 3D Map Views > New 3D Map View). view_index selects which view when several are open; dpi controls output resolution. Optional camera overrides (applied to the capture only, leaving the live view unchanged): pitch (0 = straight down/top-down, 90 = horizontal/edge-on; ~45 = balanced oblique), heading (compass degrees), distance (metres). |
| get_raster_infoA | Get raster layer info: band count, dimensions, CRS, extent, per-band statistics, nodata values. |
| execute_processingA | Execute a QGIS Processing algorithm. Use get_algorithm_help to discover parameters. Layer params accept layer IDs or file paths. Set OUTPUT to 'memory:' for temp layers. timeout: seconds before the algorithm is cancelled (default 55). Raise it for heavy raster work, or use start_processing_job, which runs in the background with no limit. load_results: add the algorithm's outputs to the project and list them in 'loaded_layers' (the processing.runAndLoadResults() behaviour). This is the only way to keep a 'TEMPORARY_OUTPUT'/'memory:' result, which is otherwise discarded when the run ends. Only vector and raster destinations are loaded, never file or folder ones. ellipsoid: ellipsoid for distance/area measurements (e.g. 'EPSG:7030' for WGS 84, 'NONE' for planimetric). Default is the open project's ellipsoid. |
| start_processing_jobA | Run a Processing algorithm as a QGIS background task, with no time limit, and return its job id at once. QGIS stays usable while it runs. Poll get_processing_job for progress and the result; cancel_processing_job stops it. Use it instead of execute_processing for anything that may take more than a minute. Same parameters as execute_processing. A 'TEMPORARY_OUTPUT'/'memory:' vector (feature sink) output needs load_results=True, since that memory layer ends with the job; temporary files stay on disk. Algorithms that must run on QGIS's main thread are refused: use execute_processing for those. |
| get_processing_jobA | State of a background job: 'running' (with progress 0-100), 'succeeded' (with result, loaded_layers and warnings, as execute_processing returns them), 'failed' (with error) or 'cancelled'. Omit job_id to list every job. |
| cancel_processing_jobA | Ask a running background job to stop. Its state turns 'cancelled' once QGIS has stopped it; outputs it already wrote stay on disk. |
| list_processing_algorithmsA | Search for processing algorithms by keyword and/or provider. Returns id, name, provider for each match. |
| get_algorithm_helpA | Get detailed help for a processing algorithm: parameters (name, type, optional, default), outputs, and description. |
| create_processing_modelA | Build QGIS Processing Model (.model3) from structured spec; save to user models folder, register in Processing Toolbox. Only call needed: algorithm discovery + param validation run in the plugin against the live registry, so do NOT call list_processing_algorithms or get_algorithm_help first. Pass keyword ('buffer') or full id ('native:buffer'); handler resolves it. Ambiguous hint returns candidate list to refine and retry. Bad param/output names reported with the valid set. Spec: inputs: [{name, type, description?, default?, optional?, parent_layer? (for field/distance), options? (for enum)}]. Types: vector, feature_source, raster, field, number, integer, distance, string, boolean, extent, crs, point, file, folder, enum, multiple_layers. steps: [{id, algorithm, description?, parameters: {ALG_PARAM: value}}]. algorithm = keyword or full id. Param values: '@input_name' = model input value '$step_id.OUTPUT' = earlier step output '=expression' = QGIS expression at run time else = static literal (number/bool/string/list) outputs: [{name, from_step, from_output, description?}] = exposed outputs; omit to expose the last step OUTPUT as 'Result'. Name collision appends a suffix (name_2.model3, ...). Response returns the actual 'name', the 'requested_name', and 'resolved_steps' (which algorithm each hint mapped to). |
| list_processing_modelsA | List registered Processing models (the 'model' provider). Returns id, name, group for each. Use run_model to execute one. |
| run_modelA | Run a Processing model by registered id (e.g. 'model:myflow') or by a .model3 file path. 'parameters' maps the model's input names to values (layer ids/paths, numbers, etc.). ellipsoid: ellipsoid for distance/area measurements (e.g. 'EPSG:7030' for WGS 84, 'NONE' for planimetric); default is the project's. |
| get_processing_providersA | List Processing providers (native, gdal, grass, saga, model, ...) with algorithm counts and active status. Use to diagnose missing algorithms. |
| execute_processing_batchA | Run one algorithm once per parameter dict in 'parameters_list'. Returns a per-run result with index and success/error status. Use for applying the same operation over many inputs in a single round-trip. timeout: seconds for the whole batch (default 55); runs that would start after it has elapsed come back as 'skipped' with the completed ones intact, so raise it or split the list for big batches. ellipsoid: measurement ellipsoid for every run (e.g. 'EPSG:7030'); default is the project's. |
| raster_calculatorA | Band math via the QGIS raster calculator. Reference loaded raster layers in the expression as 'LayerName@band' (e.g. '("dem@1" > 1000) * 1'). Writes a GeoTIFF to output_path. Output grid, extent and CRS taken from reference_layer (layer id or name), defaulting to the first loaded file-based raster. |
| zonal_statisticsB | Per-polygon stats from a raster (native:zonalstatisticsfb). stats int codes: 0=count 1=sum 2=mean 3=median 4=stdev 5=min 6=max 7=range 8=minority 9=majority 10=variety 11=variance (default [0,1,2]). New columns prefixed by 'prefix'. No output_path = in-memory layer. |
| sample_raster_valuesA | Sample raster pixel values at points. 'points' is a list of [x, y] in crs when given (reprojected to the raster), else in the raster's CRS. Omit 'band' to sample all bands. A null value is nodata when outside_extent is false; outside_extent true means the point is off the raster (often a CRS mix-up); transform_failed marks a point the raster's CRS cannot express. |
| export_layerA | Export vector/raster to disk; format from output_path extension (.gpkg, .shp, .geojson, .tif, ...). target_crs (e.g. 'EPSG:4326') reprojects on export. filter_expression (vector only) exports a subset matching a QGIS expression. |
| field_calculatorA | Add (if missing) + populate a field from a QGIS expression, per feature, in-place. field_type: string|int|double|bool|date|datetime (default double). Example: expression='$area', field_name='area'. $area/$length use the project's ellipsoid and units (reported back as 'measurement'), not necessarily m2/m; the area()/length() functions are planimetric in the layer CRS (measurement.planimetric_units, squared for area()); length() of a string counts characters and reports no units. Returns updated and failed counts; failed features keep their old value and first_error says why. Refused while the layer has an open edit session. |
| get_unique_valuesA | Return the distinct values of a field. Use 'limit' to cap results (-1 for all). Useful before building categorized symbology or filters. |
| spatial_joinA | Join attributes by location (native:joinattributesbylocation). predicates int list: 0=intersects 1=contains 2=equals 3=touches 4=overlaps 5=within 6=crosses (default [0]). method: 0=one-to-many 1=first match (default) 2=largest overlap. First match keeps one arbitrary match per target feature and drops the others; use 0 when several can match. join_fields = copied columns (default all). No output_path = in-memory layer. Returns joined_count (target features that found a match, whatever the method) next to target_features. warnings/warning_count report features QGIS skipped, e.g. invalid geometries under the Processing setting that skips them; fix them first (native:fixgeometries) or those features never match. |
| render_mapB | Render the current map canvas to an image. Returns the image inline so you can see it. Optionally saves to a file path on disk. |
| execute_codeA | Execute arbitrary PyQGIS code. Use for operations not covered by other tools. Has access to QgsProject, iface, and core QGIS classes. Returns stdout/stderr and elapsed seconds. timeout: seconds before the script is cancelled (default 55); a script that runs past it comes back with timed_out=True and the output printed so far, and its side effects stand. Raise timeout or split bulk work into several calls; QGIS is unresponsive while a script runs. A single blocking call (time.sleep, GDAL) cannot be interrupted before it returns. A script that raises or times out is a tool error carrying the traceback and output so far. |
| get_active_layerA | Get the currently active (selected) layer in the QGIS layer panel. |
| set_active_layerB | Set the active layer in the QGIS layer panel by layer ID. |
| get_canvas_scaleA | Get the current map canvas scale, rotation, and magnification factor. |
| set_canvas_scaleA | Set the map canvas scale and/or rotation. Provide scale as denominator (e.g. 50000 for 1:50000). Rotation in degrees (0-360). |
| get_layer_labelingA | Get the labeling configuration of a vector layer: enabled state, field, font size, color. |
| set_layer_labelingA | Configure labeling for a vector layer. Set enabled=false to disable labels. Set field_name to the attribute field to label with. Optional: font_size (float), color (hex like '#000000'). |
| get_layer_crsA | Get the coordinate reference system (CRS) of a layer: EPSG code, description, whether geographic, and PROJ4 string. |
| set_layer_crsA | Set the CRS of a layer (e.g. 'EPSG:4326'). This does NOT reproject data - it only changes how the layer's coordinates are interpreted. |
| get_bookmarksA | Get spatial bookmarks from the project. Each bookmark has a name, group, extent (xmin/ymin/xmax/ymax), and CRS. |
| add_bookmarkA | Add a spatial bookmark to the project for quick navigation. Provide a name and extent (xmin/ymin/xmax/ymax), in crs when given, else the project CRS. |
| remove_bookmarkA | Remove a spatial bookmark by its ID. |
| get_map_themesA | Get map themes (visibility presets). Each theme stores which layers are visible. |
| add_map_themeA | Create a map theme from the current layer visibility state. If a theme with this name exists, it will be updated. |
| remove_map_themeB | Remove a map theme by name. |
| apply_map_themeA | Apply a map theme - restores the layer visibility state saved in the theme. |
| set_project_crsA | Set the project coordinate reference system (e.g. 'EPSG:4326', 'EPSG:3857'). This changes how layers are projected on the map canvas. |
| batch_commandsA | Execute multiple commands in a single round-trip. Each command is {"type": "", "params": {...}}. Destructive commands (batch, delete_features, execute_code, execute_connection_sql, import_layer_to_connection, reload_plugin, remove_layer, rollback_edits, set_setting) are not allowed in batch, call them individually. |
| list_layoutsA | List all print layouts in the current project with names and page counts. |
| export_layoutA | Export a print layout to file. format: 'pdf', 'png', 'jpg', 'svg'. dpi: resolution (default 300). |
| get_message_logA | Get QGIS message log entries. Filter by level ('info', 'warning', 'critical', 'success', 'none') and/or tag (e.g. 'QGIS MCP'). Returns newest first. |
| list_pluginsA | List installed QGIS plugins with name, enabled status, and version. Set enabled_only=true to list only active plugins. |
| get_plugin_infoA | Get detailed info for a specific plugin: name, enabled, version, description, author, path. |
| reload_pluginA | Reload a QGIS plugin by name. Cannot reload the MCP plugin itself. Useful during plugin development. |
| get_layer_treeA | Get the full layer tree structure with groups and layers. Returns recursive tree with type, name, visibility, and children. |
| create_layer_groupC | Create a new layer group in the layer tree. Optionally specify a parent group name. |
| move_layer_to_groupB | Move a layer into a layer group by group name. |
| set_layer_propertyA | Set a layer property. Supported properties: opacity (0.0-1.0), name (string), min_scale, max_scale (float), scale_visibility (bool). |
| get_layer_extentA | Get the spatial extent (bounding box) and CRS of a layer. |
| get_project_variablesA | Get all project-level variables (key-value pairs set in Project Properties). |
| set_project_variableB | Set a project-level variable. Variables are accessible in expressions as @key. |
| validate_expressionA | Validate a QGIS expression. Returns whether it's valid, any parse errors, and referenced column names. Optionally test against a layer's fields. |
| get_settingA | Read a QGIS setting by key path (e.g. 'qgis/sketching/sketching_enabled'). |
| set_settingC | Write a QGIS setting. Use with care - incorrect settings can affect QGIS behavior. |
| transform_coordinatesA | Transform coordinates between CRS. Accepts a point {x, y}, a point list [{x, y}, ...], or a bbox {xmin, ymin, xmax, ymax}. Returns the same format. x is always longitude/easting and y latitude/northing, including for EPSG:4326. A bbox that crosses the antimeridian comes back with xmin > xmax and crosses_antimeridian: true. |
| list_connectionsA | List the data source connections saved in QGIS (PostgreSQL, GeoPackage, SpatiaLite, MS SQL, Oracle, ...) - the Browser panel entries. Optionally filter by provider (e.g. 'postgres', 'ogr', 'spatialite'). Passwords are redacted from the URIs. |
| create_postgresql_connectionA | Validate and save a new PostgreSQL Browser-panel connection. Passwords are never accepted: credentials come from a QGIS Authentication Manager configuration, from the libpq service file (pg_service.conf), or both. connection_mode selects which parameters are required; when the user's intent is unclear, ask which mode applies before calling. endpoint_using_auth_manager: host, port, database, auth_config_id (port must be the actual database port supplied by the caller or user, this tool never assumes 5432). service_using_auth_manager: service (the name defined in pg_service.conf) and auth_config_id; database optionally overrides the service file's dbname. service_only: service; database optionally overrides dbname; do not pass auth_config_id. Parameters a mode does not use are rejected. Fails if name already exists or the database cannot be reached. ssl_mode is one of prefer (default), disable, allow, require, verify-ca, or verify-full. |
| list_connection_tablesA | List tables reachable through a saved connection. On providers with schemas (PostgreSQL), omit schema to get the schema list first, then pass one. Returns each table's geometry column, CRS, primary key and kind. |
| add_layer_from_connectionA | Load a table from a saved connection as a project layer. Pass table (+ schema), or sql to build a query layer executed by the database. For a SQL layer, geometry_column and primary_key may be needed for QGIS to map/identify the result. |
| import_layer_to_connectionA | Write a loaded vector layer into a saved connection as a new table (PostgreSQL, GeoPackage, ...). Fails if the table exists unless overwrite=true. |
| execute_connection_sqlA | Run SQL directly on the database behind a saved connection (server-side, not a virtual layer - use execute_sql for that). Can modify the database: DDL/DML run as issued. limit caps returned rows (-1 for all). |
| add_web_layerA | Add a web layer (XYZ, WMS, WFS) to the project. service: 'xyz', 'wms', 'wfs'. crs is optional and only meaningful for wms ('crs=' in the uri) and wfs ('srsname='): leave it unset to take whatever the service serves natively. XYZ tiles are always EPSG:3857, so requesting another CRS for them is an error rather than a silent no-op. The response reports the CRS the layer actually got. |
| add_table_joinC | Add a table join to a vector layer. |
| add_fieldC | Add a new field to a vector layer. field_type: 'string', 'int', 'double', 'bool', 'date', 'datetime'. |
| delete_fieldC | Delete a field from a vector layer. |
| rename_fieldC | Rename a field in a vector layer. |
| apply_style_qmlA | Apply a QGIS QML style to a layer, from a file (path) or inline QML text (qml); pass exactly one. Use it for styles the other styling tools do not model (rule-based renderers, data-defined properties, SVG fills, blend modes). Rejected, with the previous style restored, if the XML is malformed, targets the other layer kind, or QGIS loads a different renderer than the QML declares. Tip: save_style_qml on a similar layer gives a template in this QGIS version's format. |
| save_style_qmlC | Save a layer's style to a QGIS QML file. |
| create_layoutD | Create a new print layout. |
| add_layout_mapB | Add a map item to a print layout at specified position and size (in millimeters). |
| get_layout_infoB | List items in a print layout (type, id, uuid, position, size) and page count. |
| add_layout_labelC | Add a text label to a print layout (mm). text may contain [% expression %] for dynamic content. color is hex (e.g. '#000000'). |
| add_layout_legendA | Add a legend to a print layout, linked to a map item (defaults to the first map item). Position/size in mm. |
| add_layout_scalebarC | Add a scale bar to a print layout, linked to a map item. style e.g. 'Single Box', 'Double Box', 'Line Ticks Up', 'Numeric'. |
| add_layout_pictureB | Add a picture or SVG (logo, north arrow) to a print layout. path is an image or SVG file path. Position/size in mm. |
| add_layout_tableC | Add an attribute table for a vector layer to a print layout. max_rows caps the number of features shown. Position/size in mm. |
| configure_atlasA | Configure a print layout's atlas: coverage_layer (vector layer id) drives one page per feature. Optional page_name_expression, filter_expression, sort_expression. |
| export_atlasA | Export a configured atlas. format 'pdf' writes a single multi-page file at output_path; image formats ('png','jpg','tif') write one file per feature into the output_path directory. Call configure_atlas first. |
| remove_layoutB | Remove a print layout from the project. |
| execute_sqlA | SQL across loaded layers via a virtual layer; reference layers by name in FROM/JOIN. as_layer=True registers the result as a new layer (set geometry_field for spatial output); else returns rows inline, capped by limit (default 1000, negative for all) with a truncated flag. layers limits sources by layer id. |
| evaluate_expressionA | Evaluate a standalone QGIS expression to a scalar value (e.g. aggregate('layer','sum','field'), @project_var, now()). Optional layer_id adds layer scope. Distinct from validate_expression (validate only) and field_calculator (per-feature). |
| identify_featuresA | Identify features at a point [x, y] across layers (map-click analogue). The point and tolerance are in crs when given, else the project CRS; layers in another CRS are reprojected. tolerance (in those units) expands the search; 0 = exact hit. layer_ids limits the search (default: visible vector layers). limit caps features per layer. Layers the point cannot be transformed into are listed in skipped_layers. |
| duplicate_layerC | Duplicate a layer (including its style) under a new name. |
| set_layer_orderA | Reorder layer tree nodes; tree order is draw order. layer_ids is the ordered list of layer ids from top (drawn last) to bottom; unlisted layers keep their slots. Clears any custom draw order (it freezes a snapshot list - layers added later would silently draw behind everything). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| analyze_layer | Deeply inspect a layer's schema, sample data, and compute detailed field statistics |
| spatial_analysis | Run a spatial operation between two layers with CRS validation |
| create_processing_model | Translate a natural-language workflow description into a saved QGIS Processing Model |
| style_map | Create a thematic map with categorized or graduated symbology |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| qgis_info | QGIS version, profile, and plugin count (implicit instance - use the equivalent tool with instance= for another) |
| project_info | Current project metadata, CRS, layer count, layer summary (implicit instance - use the equivalent tool with instance= for another) |
| layer_list | All layers with IDs, names, types, visibility (implicit instance - use the equivalent tool with instance= for another) |
| llms_context | Capabilities summary for LLM context - lists all tools, resources, and usage tips |
TDQS
Scored across 125 tools
Most tools target a distinct resource and action, and descriptions actively disambiguate near-pairs like render_map vs get_canvas_screenshot and execute_sql vs execute_connection_sql. The sheer 125-tool surface still creates some selection friction, e.g. get_layers/find_layer/get_layer_tree and several expression-related tools, though each is arguably distinct.
The dominant pattern is verb_noun in snake_case (add_raster_layer, set_canvas_extent, list_processing_algorithms), which is highly consistent across the set. Minor deviations like ping, diagnose, raster_calculator, field_calculator, and zonal_statistics break the pattern, but they are readable and do not cause confusion.
At 125 tools, this is far beyond the well-scoped 3-15 tool range and falls into the 50+ extreme category. Even for a broad GIS desktop application, this many MCP tools creates a heavy selection and discovery burden for agents.
The tool surface is remarkably comprehensive: project lifecycle, vector/raster editing, styling, processing algorithms/background jobs/models, print layouts, SQL connections, expressions, bookmarks, and themes are all covered. Minor lifecycle gaps exist (e.g. no remove_layout_item, no delete_connection, no delete_processing_model), but execute_code and the general breadth make these workarounds rather than dead ends.