<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammed Enes Duran</title>
    <description>The latest articles on DEV Community by Muhammed Enes Duran (@muend).</description>
    <link>https://dev.to/muend</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3955086%2F5f1cd487-ae94-40cd-9672-3f78bf4408ad.jpeg</url>
      <title>DEV Community: Muhammed Enes Duran</title>
      <link>https://dev.to/muend</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/muend"/>
    <language>en</language>
    <item>
      <title>Building a Secure MCP Bridge for ArcGIS Pro and ArcPy</title>
      <dc:creator>Muhammed Enes Duran</dc:creator>
      <pubDate>Wed, 01 Jul 2026 15:44:07 +0000</pubDate>
      <link>https://dev.to/muend/building-a-secure-mcp-bridge-for-arcgis-pro-and-arcpy-511g</link>
      <guid>https://dev.to/muend/building-a-secure-mcp-bridge-for-arcgis-pro-and-arcpy-511g</guid>
      <description>&lt;p&gt;ArcGIS Pro has a powerful Python runtime through ArcPy, but it is not a lightweight dependency. It is native, licensed, Windows-bound, and tightly coupled to the ArcGIS Pro environment.&lt;/p&gt;

&lt;p&gt;That makes it awkward to connect directly to AI tooling.&lt;/p&gt;

&lt;p&gt;I built &lt;code&gt;arcgis-mcp-bridge&lt;/code&gt; as an independent open-source experiment to solve this problem through the Model Context Protocol (MCP).&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/muend/arcgis-mcp-bridge" rel="noopener noreferrer"&gt;https://github.com/muend/arcgis-mcp-bridge&lt;/a&gt;&lt;br&gt;&lt;br&gt;
PyPI: &lt;a href="https://pypi.org/project/arcgis-mcp-bridge/" rel="noopener noreferrer"&gt;https://pypi.org/project/arcgis-mcp-bridge/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
MCP Registry: &lt;code&gt;io.github.muend/arcgis-mcp-bridge&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;ArcPy is extremely useful for GIS automation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;geoprocessing&lt;/li&gt;
&lt;li&gt;feature class and geodatabase operations&lt;/li&gt;
&lt;li&gt;raster workflows&lt;/li&gt;
&lt;li&gt;map and layer management&lt;/li&gt;
&lt;li&gt;coordinate reference operations&lt;/li&gt;
&lt;li&gt;spatial statistics&lt;/li&gt;
&lt;li&gt;network analysis&lt;/li&gt;
&lt;li&gt;export and layout workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But ArcPy is not a normal pure-Python library. It depends on the licensed ArcGIS Pro Python environment and native Esri runtime components.&lt;/p&gt;

&lt;p&gt;For AI/MCP workflows, importing ArcPy directly into the host process is not a clean architecture. If the native runtime crashes, blocks, logs to stdout, or touches the wrong local path, the AI host process is affected too.&lt;/p&gt;

&lt;p&gt;So the main design goal was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep the AI/MCP host process lightweight, controlled, and separate from the licensed ArcPy execution runtime.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What arcgis-mcp-bridge does
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;arcgis-mcp-bridge&lt;/code&gt; is a local-first MCP server that exposes ArcGIS Pro’s ArcPy engine over stdio JSON-RPC.&lt;/p&gt;

&lt;p&gt;It allows MCP-compatible clients to call a controlled set of ArcPy/geoprocessing tools without importing ArcPy directly into the MCP server process.&lt;/p&gt;

&lt;p&gt;The project currently includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 declarative geoprocessing tools&lt;/li&gt;
&lt;li&gt;10 GIS verticals&lt;/li&gt;
&lt;li&gt;a two-process architecture&lt;/li&gt;
&lt;li&gt;ArcPy worker-process isolation&lt;/li&gt;
&lt;li&gt;PathGuard filesystem boundaries&lt;/li&gt;
&lt;li&gt;confirmation gates for destructive operations&lt;/li&gt;
&lt;li&gt;mocked ArcPy tests for CI without an ArcGIS license&lt;/li&gt;
&lt;li&gt;optional Sketch-to-GIS / OpenCV pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not an official Esri project and not an official Anthropic project. It is an independent open-source bridge for ArcGIS Pro, ArcPy automation, and MCP-based GIS workflows.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;The project is split into two layers.&lt;/p&gt;
&lt;h3&gt;
  
  
  Layer A: MCP server
&lt;/h3&gt;

&lt;p&gt;Layer A is the MCP protocol host.&lt;/p&gt;

&lt;p&gt;It handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stdio JSON-RPC transport&lt;/li&gt;
&lt;li&gt;MCP tool registration&lt;/li&gt;
&lt;li&gt;Pydantic validation&lt;/li&gt;
&lt;li&gt;path validation before worker execution&lt;/li&gt;
&lt;li&gt;dispatching jobs to the worker process&lt;/li&gt;
&lt;li&gt;returning structured MCP tool results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layer A does not import ArcPy.&lt;/p&gt;

&lt;p&gt;That is intentional. The MCP server should remain lightweight and should not depend on ArcGIS Pro’s native runtime being importable in the same process.&lt;/p&gt;
&lt;h3&gt;
  
  
  Layer B: ArcPy worker
&lt;/h3&gt;

&lt;p&gt;Layer B is a separate Python process running inside the licensed ArcGIS Pro Python environment.&lt;/p&gt;

&lt;p&gt;It handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;importing ArcPy&lt;/li&gt;
&lt;li&gt;executing geoprocessing tools&lt;/li&gt;
&lt;li&gt;collecting ArcPy messages&lt;/li&gt;
&lt;li&gt;returning one structured JSON result frame&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation matters because ArcPy can be slow to import, can depend on license state, and can interact with native runtime components. Keeping it in a worker process protects the MCP server process from crashes and native runtime instability.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why two processes?
&lt;/h2&gt;

&lt;p&gt;The two-process model gives the project a clean failure boundary.&lt;/p&gt;

&lt;p&gt;If the ArcPy worker fails, times out, or crashes, the MCP server can return a structured error instead of dying with it.&lt;/p&gt;

&lt;p&gt;The basic flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MCP client
   ↓ stdio JSON-RPC
Layer A: MCP server
   ↓ NDJSON subprocess bridge
Layer B: ArcPy worker
   ↓
ArcGIS Pro / ArcPy runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is slower than keeping ArcPy warm in the same process, but it is much safer as a first production boundary.&lt;/p&gt;

&lt;p&gt;A future version could add a warm worker pool behind the same execution interface, but the isolation model should remain explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filesystem safety: PathGuard
&lt;/h2&gt;

&lt;p&gt;GIS workflows often touch sensitive local data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;file geodatabases&lt;/li&gt;
&lt;li&gt;enterprise connection files&lt;/li&gt;
&lt;li&gt;infrastructure datasets&lt;/li&gt;
&lt;li&gt;cadastral data&lt;/li&gt;
&lt;li&gt;client project folders&lt;/li&gt;
&lt;li&gt;personal or proprietary spatial datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of that, the bridge uses a PathGuard boundary.&lt;/p&gt;

&lt;p&gt;Each filesystem-touching tool declares whether a path is used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;read&lt;/li&gt;
&lt;li&gt;write&lt;/li&gt;
&lt;li&gt;read list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server validates paths before spawning a worker, and the worker validates again before execution.&lt;/p&gt;

&lt;p&gt;The goal is not to make arbitrary AI file access convenient. The goal is to make the allowed local execution boundary narrow, explicit, and auditable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Destructive operation gates
&lt;/h2&gt;

&lt;p&gt;Some ArcPy operations mutate data.&lt;/p&gt;

&lt;p&gt;Examples include append, delete, repair geometry, calculate field, projection definition, and other state-changing workflows.&lt;/p&gt;

&lt;p&gt;For those operations, the project requires explicit confirmation in the tool input.&lt;/p&gt;

&lt;p&gt;The rule is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Destructive tools must require &lt;code&gt;confirm=true&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This gives both the MCP host and the user a clear point where mutation is intentional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing without ArcGIS Pro in CI
&lt;/h2&gt;

&lt;p&gt;A major practical issue with ArcPy projects is CI.&lt;/p&gt;

&lt;p&gt;Hosted CI runners usually do not have ArcGIS Pro installed, and they do not have a licensed ArcPy runtime available.&lt;/p&gt;

&lt;p&gt;To keep the project testable, the automated test suite mocks ArcPy and focuses on the parts that can be verified without Esri runtime access:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pydantic contracts&lt;/li&gt;
&lt;li&gt;PathGuard behavior&lt;/li&gt;
&lt;li&gt;registry invariants&lt;/li&gt;
&lt;li&gt;destructive operation gates&lt;/li&gt;
&lt;li&gt;worker error mapping&lt;/li&gt;
&lt;li&gt;configuration validation&lt;/li&gt;
&lt;li&gt;import boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current suite contains 81 unit tests and runs without ArcGIS Pro.&lt;/p&gt;

&lt;p&gt;Real geoprocessing execution still requires a licensed ArcGIS Pro environment on Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current tool surface
&lt;/h2&gt;

&lt;p&gt;The project currently exposes 100 tools across 10 GIS verticals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;map and layer management&lt;/li&gt;
&lt;li&gt;data management&lt;/li&gt;
&lt;li&gt;geometry analysis&lt;/li&gt;
&lt;li&gt;coordinate reference and projection&lt;/li&gt;
&lt;li&gt;raster operations&lt;/li&gt;
&lt;li&gt;vision analytics&lt;/li&gt;
&lt;li&gt;export and layout&lt;/li&gt;
&lt;li&gt;editing and topology&lt;/li&gt;
&lt;li&gt;network analysis&lt;/li&gt;
&lt;li&gt;spatial statistics&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The optional vision component includes a Sketch-to-GIS pipeline using OpenCV. The idea is to extract hand-drawn boundaries from an image and commit them into a geodatabase workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;The package is available on PyPI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;arcgis-mcp-bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project also includes a setup command for preparing an ArcGIS Pro worker environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;arcgis-mcp-setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For vision-related functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"arcgis-mcp-bridge[vision]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real ArcPy execution requires a licensed ArcGIS Pro Python environment. The server uses &lt;code&gt;ARCPY_PYTHON_PATH&lt;/code&gt; to locate the worker interpreter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example MCP use cases
&lt;/h2&gt;

&lt;p&gt;Potential workflows include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;list feature classes inside a file geodatabase&lt;/li&gt;
&lt;li&gt;buffer parcels and write outputs to a scratch geodatabase&lt;/li&gt;
&lt;li&gt;dissolve features by attribute&lt;/li&gt;
&lt;li&gt;run raster slope/aspect analysis&lt;/li&gt;
&lt;li&gt;export layouts&lt;/li&gt;
&lt;li&gt;inspect geometry errors&lt;/li&gt;
&lt;li&gt;run spatial statistics tools&lt;/li&gt;
&lt;li&gt;prepare repeatable GIS automation tasks from natural language requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is not to let an AI agent freely mutate GIS projects. The point is to expose a controlled, typed, auditable tool surface around common ArcPy workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/muend/arcgis-mcp-bridge" rel="noopener noreferrer"&gt;https://github.com/muend/arcgis-mcp-bridge&lt;/a&gt;&lt;br&gt;&lt;br&gt;
PyPI: &lt;a href="https://pypi.org/project/arcgis-mcp-bridge/" rel="noopener noreferrer"&gt;https://pypi.org/project/arcgis-mcp-bridge/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
MCP Registry: &lt;code&gt;io.github.muend/arcgis-mcp-bridge&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Esri Community discussion:&lt;br&gt;&lt;br&gt;
&lt;a href="https://community.esri.com/t5/python-questions/open-source-mcp-bridge-for-arcgis-pro-arcpy/m-p/1711533#M75310" rel="noopener noreferrer"&gt;https://community.esri.com/t5/python-questions/open-source-mcp-bridge-for-arcgis-pro-arcpy/m-p/1711533#M75310&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback wanted
&lt;/h2&gt;

&lt;p&gt;I am especially interested in feedback from GIS developers, ArcPy users, and people building MCP servers.&lt;/p&gt;

&lt;p&gt;The main questions are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does this architecture make sense for a local licensed runtime like ArcGIS Pro?&lt;/li&gt;
&lt;li&gt;Which ArcPy tools or workflows should be prioritized next?&lt;/li&gt;
&lt;li&gt;What safety boundaries would be required before using this with real project data?&lt;/li&gt;
&lt;li&gt;Which ArcGIS Pro versions should be tested first?&lt;/li&gt;
&lt;li&gt;Would a warm worker pool be worth the added complexity, or is spawn-per-call isolation the better default?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The project is open source, and feedback is welcome.&lt;/p&gt;

</description>
      <category>python</category>
      <category>gis</category>
      <category>opensource</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
