ogr-slip2d-mcp is the official Model Context Protocol (MCP) server of OGR Slip2D. With it, an AI agent can build a slope model, run the analysis and read and draw the results, either on models of the server's own or on the model open in the program window, where the user sees each edit and can undo it. This page is the technical reference (options, transports, the 74 tools, resources and the security model); how to connect a particular client is explained on the AI page.
5.1.1What it is#
- A thin layer over the operations layer. Each tool is one operation of
ogr_api(73 operations), plusserver_info, which only the server has. The tools are written by hand, because a tool's description and parameter types are the whole interface a language model sees; a test keeps the two in step: every operation has a tool, every tool calls an operation and every tool parameter is a parameter of its operation. The same operations can be called from Python (Section 5.3). - The official SDK. The server is built on the MCP SDK for Python (
mcp≥ 2.1 and < 3, MIT licence), installed by the[mcp]extra. The desktop program does not need it. - Two transports. Standard input/output (the default) and streamable HTTP, with a bearer token and, for clients that reach it over the Internet, OAuth 2.1.
- SI units everywhere (m, kN, kPa, kN/m³, degrees), x to the right and y up, whatever unit system the window displays.
- Analyses are jobs. An analysis runs in a child process that can be cancelled; every edit of a model is one undo step.
- The open window first. If OGR Slip2D is open, calls work on its window (Section 5.1.6).
5.1.2Installation#
From a clone of the repository, with Python 3.11 or later:
pip install -e ".[mcp]"
ogr-slip2d-mcp --version # ogr-slip2d-mcp 0.1.235, on standard error
python -m ogr_mcp --version # the same program, if the command is not on PATHWithout the SDK the server stops with exit code 3 and asks for the extra (pip install "ogr-slip2d[mcp]"). ogr-slip2d-mcp --help lists every option. Client configuration files, for desktop chat applications, local models and HTTP clients, are on the AI page.
5.1.3Command-line options#
ogr-slip2d-mcp.| Option | Default | Meaning |
|---|---|---|
--transport {stdio,http} | stdio | Transport (Section 5.1.4). |
--host HOST | 127.0.0.1 | HTTP: interface to listen on. A host that is not a loopback address needs an explicit token. |
--port PORT | 8765 | HTTP: port. |
--token TOKEN | — | HTTP: bearer token. On the command line it is visible to other users of the machine: prefer --token-file or OGR_MCP_TOKEN. |
--token-file FILE | — | HTTP: file holding the bearer token (UTF-8; surrounding white space is ignored). |
--no-auth | off | HTTP on a loopback host only: no token. Since python_exec is always available, any local program can then run code as you. Refused with any other host and with --public-url. |
--allow-origin ORIGIN | — | HTTP: one more allowed Origin; repeatable. |
--public-url URL | — | HTTP: the https:// address the server is reached at from outside, through a tunnel or reverse proxy. Turns on OAuth 2.1; access is approved with the server's token. An http:// address is accepted only on a loopback host, for testing. |
--oauth-redirect URI | — | With --public-url: one more allowed OAuth redirect URI; repeatable. |
--tls-cert FILE | — | HTTP: serve HTTPS directly with this certificate (PEM). Goes with --tls-key. |
--tls-key FILE | — | HTTP: the private key of --tls-cert (PEM). |
--profile {full,compact} | full | Tool set (Section 5.1.5); also read from OGR_MCP_PROFILE. |
--toolsets LIST | — | Comma-separated toolsets instead of a profile. |
--attach [PID] | — | Work only on an open program window, never on a model of the server's own; with a process id, on that window. |
--headless | off | Never use an open window: always work on the server's own models (the behaviour before v0.1.207). |
--workdir DIR | — | Folder that relative paths are resolved against (opening and saving .ogr files, images, reports). Without it, paths must be absolute. |
--max-wait SECONDS | 50 | Longest a tool waits for a job before returning its job_id. |
--max-jobs N | 1 | Jobs allowed to run at the same time; one more is refused with E_BUSY. |
--log-file FILE | standard error | Where log messages go. |
--version | — | Print the version on standard error and exit. |
| Variable | Meaning |
|---|---|
OGR_MCP_TOKEN | HTTP bearer token, used when neither --token nor --token-file is given. |
OGR_MCP_PROFILE | Profile, used when --profile is not given. |
OGR_BRIDGE_DIR | Folder where open windows announce their agent bridge (default ~/.ogr-slip2d/bridges). The program and the server must see the same value. |
ogr-slip2d-mcp.| Code | Meaning |
|---|---|
| 0 | Normal end. |
| 2 | A configuration the server refuses to run with: a non-loopback host without a token; --no-auth with a non-loopback host or with --public-url; an HTTP-only option (--public-url, --tls-cert, --tls-key, --oauth-redirect) with stdio; --oauth-redirect without --public-url; --tls-cert without --tls-key or a file that does not exist; a public URL that is not https://; a token shorter than 32 characters with --public-url; --attach together with --headless or with a process id that is not a number; an unknown profile or toolset. |
| 3 | The MCP SDK is not installed. |
Nothing is written on standard output, because over stdio that stream carries the protocol. Messages go to standard error, or to --log-file.
The options, the exposure rules and the exit codes are checked in one place before anything listens. The default --max-wait of 50 s is kept below the 60 s at which many clients cut a request.
5.1.4Transports#
Standard input/output#
The client starts the server as a child process and talks to it through its standard streams; no port is opened. This is the transport of desktop chat applications, coding agents and local-model clients.
ogr-slip2d-mcp --workdir "C:\models"
ogr-slip2d-mcp --profile compact --workdir "C:\models" # small local modelsStreamable HTTP#
With --transport http the server answers at http://HOST:PORT/mcp, stateless and with JSON responses. Every request needs Authorization: Bearer <token>; a missing or wrong token is answered 401. The token comes from --token, --token-file or OGR_MCP_TOKEN, in that order. When none is given on a loopback host, the server generates one (43 characters) and prints it on standard error when it starts.
ogr-slip2d-mcp --transport http --port 8765 --token-file token.txt --workdir "C:\models"The Host and Origin headers are checked even when the token is right: a Host that is not this server's is answered 421 and a foreign Origin 403. Allowed hosts are 127.0.0.1, localhost, [::1] and --host, at the port; allowed origins are 127.0.0.1 and localhost at the port, plus each --allow-origin. With --tls-cert and --tls-key the same endpoint is served over HTTPS.
OAuth 2.1 for clients on the Internet#
Some hosted clients connect only to a public HTTPS server and only through OAuth. For them, the server keeps listening on 127.0.0.1, a tunnel or reverse proxy that terminates HTTPS is placed in front of it, and the server is told its public address with --public-url. It then acts as its own OAuth 2.1 authorization server: PKCE with S256, dynamic client registration and tokens bound to the resource <public-url>/mcp. Access is granted by typing the server's token on its page <public-url>/approve; whoever knows the token is taken to be the owner. The static token keeps working as a bearer header for clients that can send one. The limits are listed under Section 5.1.11.
ogr-slip2d-mcp --transport http --port 8765 --token-file token.txt \
--public-url https://your-tunnel.example --workdir "C:\models"A server reachable from the Internet exposes python_exec, that is, the machine. Expose it only when a client needs it, and stop the tunnel and the server when finished. The server opens no tunnel by itself.
5.1.5Profiles and toolsets#
A small local model loses its way among many tools, and every tool's description costs context on every request. The server therefore offers two profiles:
full(default): all 74 tools.compact: the 14 tools a complete build–run–read cycle needs:server_info,catalog,project_new,project_open,project_save,project_summary,model_define,analysis_configure,analysis_run,job_get,job_cancel,results_get,model_renderandpython_exec.model_definebuilds the whole geometry in one call andpython_execcovers the rest. They are marked C in the tables of Section 5.1.7.
--toolsets replaces the profile by a list of toolsets: core (10 tools), model (9), settings (3), analysis (7), loads (5), supports (6), search (5), annotations (4), files (5), groundwater (11), statistics (6), view (1), history (1) and python (1). server_info is always included. Tools are published in a fixed order, so a client can cache the list.
ogr-slip2d-mcp --toolsets core,model,settings,analysis,view --workdir "C:\models"5.1.6Working on the open program window#
Since v0.1.207 the program opens its agent bridge when it starts (Tools → Agent bridge (MCP), ticked by default). If OGR Slip2D is open, a call goes to its window; if it is not, to models of the server's own. The order in which the program and the client are opened does not matter, and a window that is closed and opened again is found again.
- Which call goes where. A call that names a
project_id,job_idorresult_idthe server holds stays with the server, so a model begun before the window was opened is not lost. Any other call goes to the window if one answers (the most recently started one when several are open) and otherwise to the server's own models.server_infosays where the next call goes (attached_to_window: mode, whether a window is open, its process id and title,next_call_goes_to), and each entry ofopen_modelssaysin_window. - It is the user's model. The user sees every edit; each edit of the agent is one step of Edit → Undo, and the user's own steps can be undone by the agent; the canvas is redrawn after each edit. An analysis the agent runs appears in the results panel and on the canvas, as a Compute would.
model_render(source="window")returns a capture of the canvas as it is on screen. - Unsaved work is protected.
project_newandproject_openopen in the window and refuse (E_CONFLICT) while it has unsaved changes: the agent has to save them withproject_saveor ask the user.project_closenever closes the window's model. - Busy. While the window is computing (its own Compute or drawdown sweep, which use the live model on another thread), an edit answers
E_BUSY, to be retried when the window has finished. - Relative paths are resolved against the server's
--workdir, which the server sends to the window when it connects (the last server to connect sets it). - A window that closes mid-call. A call the window was answering when it closed is not repeated, because whether it ran cannot be known: it answers
E_CONFLICT, and the model should be checked withproject_summarybefore repeating it.
| Mode | Window open | No window open |
|---|---|---|
| default | calls go to the window (the most recent one) | calls go to the server's own models |
--attach | calls go to the window | calls answer E_NOT_CONFIGURED, saying what to open |
--attach PID | calls go to the window of that process | as --attach |
--headless | the window is never used | calls go to the server's own models |
The bridge listens only on 127.0.0.1, at a port chosen by the system, with a new random token each time it starts. The window announces both in ~/.ogr-slip2d/bridges/<pid>.json (port, token, process id and window title); on POSIX systems only the user can read that file. It is deleted when the bridge is switched off or the window closes, and a file whose port no longer answers is removed by the next server that looks. A connection whose first line does not carry the right token is answered E_UNAUTHORIZED and closed. To keep the bridge off, untick Tools → Agent bridge (MCP) or start the program with python -m ogr_gui --no-agent-bridge (Section 5.2).
The bridge carries the same operations as the headless server, as JSON lines (protocol ogr-slip2d-bridge/1), and runs them on the window's thread, so an edit of the agent and one of the user never race. The window's model is read at each call, so File → New and File → Open in the window are seen at once.
5.1.7Tools#
The 74 tools of the full profile, grouped as in the program's own tool list. C marks the 14 tools of the compact profile. Hint is the MCP annotation the server declares for the tool (read-only, edit or destructive), which clients that ask for confirmation can use. The exact parameters and their descriptions are published by the server itself (tools/list).
Project (core)#
| Tool | C | Hint | What it does |
|---|---|---|---|
server_info | C | read-only | Version, units, modelling rules, open models and coverage of the program. The first call. |
catalog | C | read-only | What the program offers: strength models with their parameters, methods, searches, boundary types, settings with their options. |
project_new | C | edit | Creates an empty model or the demo slope; returns its project_id. |
project_open | C | edit | Opens a .ogr file. |
project_save | C | edit | Saves to .ogr, the format the desktop program opens. |
project_close | destructive | Closes a model; refuses to lose unsaved changes unless told to. | |
project_list | read-only | The open models. | |
project_summary | C | read-only | The model: boundaries, materials, which material occupies each region and how (assigned, inherited or the first by default), state, history and results. |
project_validate | read-only | What an analysis would check, without computing. | |
project_get | read-only | One section of the model as the .ogr file stores it (Section 5.4). |
Model (model)#
| Tool | C | Hint | What it does |
|---|---|---|---|
model_define | C | edit | The whole model in one call: boundaries, materials, a point inside the region of each, water table and settings. |
boundary_add | edit | One boundary: external, material, water table, piezometric line, drawdown line, tension crack, Block Search object, weak layer or anisotropic surface (details below). | |
boundary_edit | destructive | Edits or deletes a boundary: vertices, translation, type, name; op=block_object changes the kind of a Block Search object. It also copies, scales, rotates and simplifies. | |
material_set | edit | Creates or modifies a material, also its rapid-drawdown envelope (drawdown_envelope, since v0.1.200); hydraulic properties go through hydraulic_set. A range of a Generalized Anisotropic material takes a material of the model by name ("material": "Clay", since v0.1.228), and the analysis uses that material's strength as it is when it runs. | |
material_delete | destructive | Deletes a material; refused while regions, weak layers or ranges of a Generalized Anisotropic material use it, unless reassign_to or force is given. | |
material_assign | edit | Assigns a material to the region that contains a point. | |
external_reshape | edit | Expands or shrinks the external boundary: a parallel offset, or a fill or excavation polyline with both ends on it. | |
slope_angle_change | edit | Changes the overall angle of the slope face between two vertices of the external boundary (toe and crest). Only the face moves, projecting horizontally (default), vertically or by rotation; keep_benches keeps the width of the benches. Boundaries that end on the face follow it; supports and loads do not move, and a warning says so. | |
geometry_cleanup | edit | Reports duplicate vertices, self-intersections and crossings between boundaries; with apply, corrects them. |
boundary_add details. A closed material boundary (closed=true) is a lens: a region of its own and a hole in the region around it (since v0.1.197). A Block Search object carries its kind in block_object (since v0.1.232): window, line, point or polyline. A polyline gives each trial surface two points and the stretch of polyline between them, and accepts left_point and right_point (any, segment, end_point); two open points without a kind are a line, not a polyline. Since v0.1.233 an object also carries a group_id (an integer, 0 by default) that is read only with search.block_multiple_groups on: each group is then searched separately, the number of surfaces is shared among the groups, and polylines of different groups may overlap in x.
Loads (loads)#
| Tool | C | Hint | What it does |
|---|---|---|---|
load_set | edit | Adds or changes a distributed load (kPa between two points) or a line load (kN/m at a point). | |
load_delete | destructive | Deletes loads. | |
seismic_set | edit | Pseudo-static seismic load: , and whether it applies. Both forces act on the static weight of the soil (loads and ponded water carry no seismic force); is positive downwards (the soil weighs ); is a magnitude that always acts in the direction of failure; and . | |
seismic_record_set | edit | Adds an acceleration record (file, text or values) for the Newmark analysis, or renames it. | |
seismic_record_delete | destructive | Deletes an acceleration record. |
A line load normal to the boundary or at an angle to the boundary takes its direction from the ground surface at its point (since v0.1.199): the normal points into the ground (at a vertex, along the bisector), and the angle is measured anticlockwise from the ground surface traversed from left to right, so −90° is the normal. Off the ground surface such a load is refused.
Supports (supports)#
| Tool | C | Hint | What it does |
|---|---|---|---|
support_type_set | edit | Defines or changes a support type (the set of properties of one class). | |
support_type_delete | destructive | Deletes a type; refused while supports use it. | |
support_set | edit | Places a support (head on the slope face, tail inside the ground), or moves, stretches or edits one. | |
support_pattern_add | edit | A row of supports along a segment. | |
support_delete | destructive | Deletes supports or a whole pattern. | |
support_ungroup | edit | Ungroups a pattern. |
Search (search)#
| Tool | C | Hint | What it does |
|---|---|---|---|
tension_crack_set | edit | Water in the tension crack. | |
focus_set | edit | Focus objects (window, line, point, tangent) that restrict the search. | |
focus_delete | destructive | Deletes focus objects. | |
user_surface_add | edit | A circle of the user's own, analysed together with the search. | |
user_surface_delete | destructive | Deletes such circles. |
Annotations (annotations)#
| Tool | C | Hint | What it does |
|---|---|---|---|
annotation_set | edit | Draws lines, arrows, texts, dimensions, axes and images, or changes or hides them. The analysis never reads them. | |
annotation_delete | destructive | Deletes annotations. | |
annotation_to_boundary | edit | The only bridge, and an explicit one, from a drawing to the model. | |
properties_table | read-only | Tables of materials, supports or hydraulic properties. |
Files (files)#
| Tool | C | Hint | What it does |
|---|---|---|---|
dxf_inspect | read-only | Reads a DXF file without importing it: layers, proposed type, unit and problems. | |
dxf_import | edit | Imports its geometry (one undo step). | |
dxf_export | edit | Exports the model and the critical surfaces of a result. | |
report_generate | edit | PDF report of an analysis. | |
properties_import | edit | Copies materials or support types from another .ogr file. A range of a Generalized Anisotropic material that took a material is linked to its imported copy or to the material of the same name; if there is neither, it keeps its strength without a link and a note says so. |
Groundwater (groundwater, since v0.1.200)#
| Tool | C | Hint | What it does |
|---|---|---|---|
hydraulic_set | edit | Hydraulic properties of a material: saturated permeability and anisotropy, model of the unsaturated zone (with its soil library), water contents and storage. A parameter of another model is refused. | |
mesh_generate | destructive | Finite-element mesh. It replaces the previous one and deletes its boundary conditions and fields, also those of the transient stages, because they are keyed by node number. | |
mesh_reset | destructive | Removes the mesh and everything computed on it. | |
seepage_bc_set | edit | A boundary condition on a side (left, right, bottom, ground), at nodes, along a polyline of the boundary, or a reservoir at an elevation. | |
seepage_bc_clear | destructive | Returns to the default conditions (unknown on the ground surface, no flow elsewhere), which prescribe no head. | |
transient_set | edit | The staged transient analysis: times, conditions of each stage, Calculate SF and initial state. | |
water_grid_set | edit | Water pressure grid (points or a CSV file) and its interpolation options. | |
water_grid_delete | destructive | Removes the water pressure grid. | |
groundwater_run | edit | Solves the groundwater (steady state, or the transient stages with their factor of safety) in the background. The field is written back into the model as one undo step, unless the model has changed in the meantime. | |
groundwater_results | edit | Reads the field: summary, values at a point, flow through a section, free surface, stages with their factors, or every node as CSV. Also works after the project has been reopened. | |
drawdown_sweep_run | edit | Rapid drawdown to several reservoir levels, because total drawdown is not always the worst case; through the same door as an analysis (design factors and checks). |
Units: hydraulic heads in m and pore pressure in kPa; permeability, infiltration and nodal flow in one consistent unit (m/s). Since v0.1.200 each permeability model takes suction in the unit of its own definition: van Genuchten and Gardner in suction head (α in 1/m); Brooks–Corey, Fredlund–Xing, Simple and the user-defined curve in matric suction (kPa).
Statistics, back analysis and optimisation (statistics, since v0.1.201)#
| Tool | C | Hint | What it does |
|---|---|---|---|
random_variable_list | read-only | The inputs of the model that can be random variables, with their key and value, and those already defined. | |
random_variable_set | edit | Makes an input random or changes it: distribution, standard deviation, range, correlation. The mean is always the model's value. | |
random_variable_delete | destructive | Removes a variable; correlations that pointed to it are cleared. | |
statistics_run | edit | Compute Statistics in the background: the deterministic run, then the probabilistic analysis (probability of failure, reliability index) or the sensitivity analysis, with the design factors and the seed of the model. | |
back_analysis_run | edit | The horizontal support force needed for a target factor of safety, over the configured search. | |
optimize_run | edit | Optimises the non-circular critical surface of a result with the model's settings and seed; the outcome is a new result. |
The three runs go through the same door as analysis_run: without a design standard they give the same results as before; with one, they analyse the factored model.
Settings (settings)#
| Tool | C | Hint | What it does |
|---|---|---|---|
settings_get | read-only | Every setting with its value, type and options. | |
settings_set | edit | Any setting by its path (search.search_method); all or nothing. | |
analysis_configure | C | edit | The most common analysis settings in one call: methods, surface type, search, slices, grid, failure direction, design standard. |
Analysis (analysis)#
| Tool | C | Hint | What it does |
|---|---|---|---|
analysis_run | C | edit | Starts the analysis in the background; returns the result or a job_id. |
job_get | C | read-only | State and progress of a job; its result once it has finished. |
job_cancel | C | destructive | Stops an analysis and every process it started. |
job_list | read-only | The jobs of the session. | |
results_get | C | read-only | Reads a result: summary, critical surface with its slices, best surfaces, minima, warnings. |
results_query | edit | What the Interpret window asks (since v0.1.201): error codes (−120 tensile, −112 m-alpha, −111 not converged, −101 other) and the census of rejected surfaces, raw data, surfaces through a point (measured on the surface that was computed, not on the whole circle), minimum per centre, factor along the slope, slices with the method's numbers, filters; and, of a statistics result, histogram, convergence, samples with their index and sensitivity. | |
surface_evaluate | read-only | The factor of safety of one given surface (circle, three points or polyline), without a search. |
View, history and Python (view, history, python)#
| Tool | C | Hint | What it does |
|---|---|---|---|
model_render | C | read-only | PNG image of the model, with the critical surfaces of a result, or with contours of the groundwater field (field) and its free surface; with the program open, source="window" captures the canvas of the window. |
project_history | edit | Undoes, redoes or lists the edits. | |
python_exec | C | destructive | Python against the model, for what has no tool yet (Section 5.1.11). |
server_info also reports how much of the program an agent can reach (program_coverage): in v0.1.235, 116 of the 140 actions of the main window are mapped to an operation, none is pending, and the other 24 only make sense in the interface (zoom, pan, printing, preferences and the like), each with its reason written down.
5.1.8Resources#
| URI | Type | Content |
|---|---|---|
ogr://guide | Markdown | The complete modelling guide the agent reads: units and axes, geometry, water, finite-element groundwater, statistics, materials, search and methods, running and reading results, undo and scripts, work on the window, files. |
ogr://catalog/{kind} | JSON | catalog(kind) as a resource. Kinds: strength_models, methods, search_methods, surface_types, boundary_types, pore_pressure_types, groundwater_methods, interslice_functions, failure_directions, unit_systems, design_standards, settings. |
Many clients never read resources. A short version of the guide therefore travels with every connection as the server's instructions, and every rule that changes a number is in it and repeated in the tool descriptions where it applies.
5.1.9Modelling workflow#
project_new → model_define → project_validate → analysis_configure
→ analysis_run → results_get / model_render → project_save- Each call returns or takes a
project_id; it may be omitted while only one model is open. analysis_runruns every enabled method as a background job and waits up towait_seconds(30 s by default, capped at--max-wait). If it answersstate: "running"with ajob_id, polljob_get(with a wait) untildone;job_cancelkills the job's whole process tree. A job isqueued,running,done,failed,cancelledorcrashed.- A finished job carries a
result_id:results_get(result_id, view=…)withsummary,critical(with slices),top,minimaorwarnings, andmodel_render(result_id=…)draws its critical surfaces. The server keeps the last five results of each model. - Warnings are how the program reports a problem it has noticed, so they should be read before a result is relied on.
Rules that change the number#
The rules the server gives every agent, because each of them changes a factor of safety without an error:
- A region nobody assigned takes the first material of the list. The convention is silent:
project_summarysays for each region whether its material wasassigned,inheritedor thedefault_first_material. - A water table or piezometric line does nothing until materials point at it (
model_definewater_table.materials, orboundary_addassign_to). - The grid search
nxandnyare intervals: points =nx+ 1;radius_increment10 means 11 radii per centre. Total circles = (nx+ 1)(ny+ 1)(radius_increment+ 1). analysis_runmay returnstate: "running"with ajob_id: polljob_get.- A result marked
stalewas computed on a model that has changed since. - A finite-element groundwater field (
groundwater_run) reaches only the materials whosepore_pressureisfem.
The full guide adds that, with a design standard on, the number reported is an over-design factor, which must exceed 1, not a factor of safety (results say which in caption); that failure_direction is left_to_right when the slope goes down to the right; and that the unit system in the settings only changes what the interface displays.
5.1.10Errors#
A tool that fails answers with a coded message, [E_CODE] message Hint: …; an unknown name comes with the closest known names (Did you mean …?). The codes are listed in Section 5.5.4. A setting that the analysis would not read is refused with the reason instead of being stored, and a failed or crashed job is reported as E_JOB_FAILED with its error.
5.1.11Security model#
python_exec: arbitrary code execution#
The server always publishes python_exec, which runs arbitrary Python in the server process with the permissions of the user who started it; through the bridge, it runs inside the program window's process. It is the owner's decision (2026-09-24), to cover whatever has no tool yet. As a result, whoever can talk to the server can run code on the machine, and everything below follows from that.
- The script sees
project(the live model),api(every operation:api.material_set(...)),np,ogr_core,ogr_slip2dandresult(result_id); the value of its last expression is returned. - The whole script is one undo step, rolled back if it raises. Output is cut at 20 000 characters, and the returned value at 5 000.
- A script cannot be stopped: one that never ends holds its model's lock until the process exits. That is why analyses are jobs and scripts are not.
Over stdio#
The server is a child process of the client and opens no port. The remaining risk is prompt injection: a text the model reads (a file, a web page) can ask it to run something. Clients that ask for confirmation before each tool are the defence; it should stay on for python_exec, which the server declares destructive.
Over HTTP#
- A token always, also on 127.0.0.1. "Only local" is not a boundary: any web page can make the browser send requests to
localhost. The token is compared in constant time. - Host and Origin are checked (the SDK's DNS-rebinding protection, switched on): 421 for a foreign
Host, 403 for a foreignOrigin, even with the token. - An explicit token off loopback. On a host that is not loopback the server requires an explicit token (
--token,--token-fileorOGR_MCP_TOKEN) and refuses to start without one (exit code 2).--no-authis accepted only on loopback. - A token on the command line is visible to other users of the machine:
--token-fileorOGR_MCP_TOKENare preferable.
The bridge to the window#
The bridge listens only on 127.0.0.1, with a new random token at each start, written to a file in the user's home folder. Whoever has the bridge drives the window, python_exec included. It opens no new access, because reading that file already requires being that user on that machine; it can still be switched off in Tools → Agent bridge (MCP) or with --no-agent-bridge. The program's tests run with an empty discovery folder of their own, so a test that starts a server cannot edit a model the user has open.
On the Internet (--public-url)#
- The server opens no tunnel by itself; a tunnel or proxy that terminates HTTPS goes in front of it, or
--tls-certand--tls-keyserve HTTPS directly. - Approval is granted by typing the server's token on
/approve, a page that names the client asking and where it will be sent back, and warns that approving lets it run every tool,python_execincluded. A wrong token is answered after a delay of one second; after 5 wrong tokens a request is locked; after 20 wrong tokens within 10 minutes, counting every request, all approvals stop for a while (anyone can open a new request, so a per-request limit alone would not bound the guessing). - For the same reason the token must have at least 32 characters with
--public-url; a generated one has 43. - No other site can frame the approval page (
X-Frame-Options: DENY,frame-ancestors 'none'), and neither the page nor where it came from is kept (no-store,no-referrer). - An approval yields an authorization code (PKCE S256, single use, valid for 5 minutes); a pending request expires after 10 minutes. Tokens issued are opaque and live in memory, so restarting the server revokes them all: access tokens last one hour, refresh tokens thirty days and are rotated at each use. Revocation is enabled; identity-assertion grants are refused.
- The server's own token keeps working as
Authorization: Bearerfor clients that send headers. - Clients register dynamically (RFC 7591), and only with redirect URIs on an allowlist: the callback addresses of the hosted clients listed in
ogr_mcp/oauth.py, loopback addresses, and those added with--oauth-redirect. - Client ID metadata documents are not offered: they would make the server fetch a document from another site, and the server makes no network calls.
--no-authnever goes with--public-url, and anhttp://public URL is accepted only on loopback, for testing. The publicHostandOriginjoin the allowed ones; any other still gets 421 or 403.
Files, network and telemetry#
- Relative paths are resolved against
--workdir. Saving never overwrites an existing file withoutoverwrite=true, except the model's own file, which is what saving means. - The server makes no network call of its own. The
opentelemetry-apidependency that the SDK brings is only the API: without a telemetry SDK configured, it exports nothing.
The security rules are written in the program's own documentation and enforced in the code listed here; this section follows them.
Source: docs/mcp/seguridad.md · ogr_mcp/security.py · ogr_mcp/oauth.py · ogr_api/pyexec.pyAn agent can build and run a model quickly, and can also get it wrong quickly. Before relying on a number, check the geometry, the materials of each region and the pore pressures it set. The responsibility for a design stays with the engineer who signs it.