Vulcan MCP
Model Context Protocol (MCP) server connecting Maptek Vulcan 12 Desktop with AI Agents
Quick Start • Capabilities • MCP Tools • Practical Examples • Tutorial • How-To Guides • Documentation • Contributing
Connect **Vulcan 12 ** directly to Artificial Intelligence assistants (Google Antigravity, Claude Desktop, Claude Code, Cursor, VS Code) via the open Model Context Protocol (MCP) standard.
Seamlessly query block models (.bmf), audit 3D triangulations and solids (.00t), explore ISIS drillhole databases (.dhd.isis), interact with CAD design layers (.dgd.isis), inspect color legends (.scd), capture the Envisage 3D viewport, and execute native PyVulcan automation scripts using natural language.
Key Capabilities
Block Models (
|
Triangulations & Surfaces (
|
ISIS Exploration Drillholes (
|
CAD Design & 3D Viewport (
|
Communication Architecture
Maptek Vulcan 12 Desktop embeds Python 3.5.2 tightly linked to its C++/SWIG graphics engine (maptek.vulcan). Modern MCP servers require Python 3.11+.
The system bridges both worlds across two processes using a local TCP loopback socket on 127.0.0.1:9877:
flowchart LR
A["AI Agent<br/>(Claude / Cursor / Antigravity)"] <-->|"MCP (Stdio)<br/>uvx luiccian-vulcan-mcp"| B["MCP Server<br/>(src/vulcan_mcp)"]
B <-->|"TCP 127.0.0.1:9877<br/>uint32 framing + JSON"| C["Vulcan Plugin<br/>(plugin/server.py)"]
C <-->|"C++ / SWIG Bindings"| D["Maptek Vulcan 12 Desktop<br/>(maptek.vulcan & vulcan_gui)"]
Quick Start (in 2 Steps)
You don't need to manually create or configure virtual environments if you have uv / uvx installed.
Step 1: Start the Plugin inside Maptek Vulcan 12
- Open your mining project in Maptek Vulcan 12 Desktop (Envisage).
- In Vulcan's top menu, go to File > Python Script (or type
pyin Vulcan's command window). - Select the file
plugin/server.py. - Check the box "Run in shell window" and click OK.
- A Windows console window will open confirming the listener is running:
==============================================================
[Vulcan MCP] Vulcan MCP Listener started on 127.0.0.1:9877
[Vulcan MCP] Working directory: C:\your_mining_project
[Vulcan MCP] Registered domains: block_model, canvas, design, drillholes, execute_code, legend, system, triangulation
[Vulcan MCP] Token authentication: DISABLED (localhost open mode)
[Vulcan MCP] Keep this window open while using your AI client. Ctrl+C to stop.
==============================================================
Step 2: Connect your AI Client
Choose the mode that best fits your workflow:
Mode A: For End Users (Zero-Install via uvx)
No repository cloning required. The AI client pulls and runs the MCP server on the fly:
-
In Claude Desktop / Cursor / VS Code: Add this block to your MCP config file (
claude_desktop_config.json,.cursor/mcp.json, etc.):{ "mcpServers": { "vulcan": { "command": "uvx", "args": [ "luiccian-vulcan-mcp" ] } } }
-
In Claude Code (CLI):
claude mcp add -s user vulcan -- uvx luiccian-vulcan-mcp
Mode B: For Developers (with uv run on a local clone)
If you are developing or modifying the codebase and want hot-reloading:
-
In Google Antigravity: The plugin in
.agents/plugins/vulcan-mcp/is already preconfigured dynamically with${workspaceFolder}. -
Manual Local Configuration:
{ "mcpServers": { "vulcan": { "command": "uv", "args": [ "run", "--directory", "C:\\path\\to\\vulcan-mcp", "vulcan-mcp-server" ] } } }
The 9 Master Tools Catalog
See complete parameter specifications and JSON schemas in docs/MCP_TOOLS_REFERENCE.md.
| # | MCP Tool | Mining Domain | Actions (action=) |
Description |
|---|---|---|---|---|
| 1 | vulcan_system |
System & Project | ping, project_info, capabilities |
Connection health, complete active project file inventory, and available SDK modules. |
| 2 | vulcan_block_model |
Block Models (.bmf) |
list, info, query_xyz, stats |
Block model schema, $(X,Y,Z)$ point query, tonnage, volume, and volume-weighted mean grade with cutoffs. |
| 3 | vulcan_triangulation |
Triangulations (.00t/.tri) |
list, info, elevation, point_inside, load, unload |
Nodes, faces, volume, topological consistency, centroid, $Z$ elevation, and point-in-solid test. |
| 4 | vulcan_design |
3D CAD Design (.dgd.isis) |
list_dbs, list_layers, layer_info, load_layer, clear_temp, create_polyline |
CAD layer inspection, planar area ($m^2$), centroid, 3D layer loading, and polyline creation. |
| 5 | vulcan_drillholes |
ISIS Drillholes (.dhd.isis) |
list_dbs, schema, holes, hole, high_grade, display, clear_display |
Drillhole database exploration, high-grade intercept search, and desurveyed 3D colored display. |
| 6 | vulcan_legend |
Legends (.scd) |
list, inspect, update, restore |
Color scheme inspection and interval color updates with automatic .scd.bak backup. |
| 7 | vulcan_screenshot |
Visual 3D Viewport | (Direct: max_width, quality) |
Viewport screenshot of Envisage compressed as JPEG for multimodal vision analysis. |
| 8 | vulcan_canvas |
UI & Macros | macro, report |
Envisage Workbench macro execution and writing messages to Vulcan's report window. |
| 9 | vulcan_execute_code |
PyVulcan Scripting | (Direct: code) |
Direct execution of Python scripts inside Maptek Vulcan (vulcan, vulcan_gui, project_dir). |
Practical & Simple Examples
Here are 4 representative mining workflows demonstrating the natural language user prompt, the resulting MCP tool call in JSON, and the returned data.
1. Project Health Diagnostic & File Inventory
-
Natural Language Prompt:
"What mining files and block models are available in the open Vulcan project?"
-
MCP Tool Call:
{ "tool": "vulcan_system", "arguments": { "action": "project_info" } }
-
Returned Response:
{ "connected": true, "project_dir": "C:\\MiningProjects\\Deposit_Cu_Au", "inventory": { "block_models": { "count": 2, "files": ["global_deposit.bmf", "phase1.bmf"] }, "triangulations": { "count": 4, "files": ["topo_2026.00t", "final_pit.00t"] }, "drillhole_dbs": { "count": 1, "files": ["rc_drilling.dhd.isis"] } } }
2. Mineral Resource Estimation with Cutoff Grade
-
Natural Language Prompt:
"Calculate the tonnage and mean copper grade (CUT) in 'phase1.bmf' using a cutoff >= 0.40% and density of 2.7 t/m³."
-
MCP Tool Call:
{ "tool": "vulcan_block_model", "arguments": { "action": "stats", "name": "phase1.bmf", "variable": "CUT", "cutoff": 0.40, "default_density": 2.7 } }
-
Returned Response:
{ "total_blocks": 120500, "blocks_above_cutoff": 35210, "total_volume": 2816800.0, "tonnage": 7605360.0, "mean_grade": 0.785, "variable": "CUT", "cutoff": 0.4 }
3. High-Grade Intercept Detection & 3D Display
-
Natural Language Prompt:
"Find the top 5 gold intercepts in the ASSAYS table of 'rc_drilling.dhd.isis' and display them in Envisage."
-
MCP Tool Call:
{ "tool": "vulcan_drillholes", "arguments": { "action": "high_grade", "name": "rc_drilling.dhd.isis", "table": "ASSAYS", "field": "AU", "top_n": 5 } }
-
Returned Response:
{ "database": "rc_drilling.dhd.isis", "table": "ASSAYS", "field": "AU", "intercepts": [ { "hole_id": "RC-104", "from": 84.0, "to": 88.0, "grade": 12.45, "length": 4.0 }, { "hole_id": "RC-112", "from": 120.0, "to": 126.0, "grade": 8.70, "length": 6.0 } ] }
4. Direct Automation with PyVulcan Scripting
-
Natural Language Prompt:
"Run a script inside Vulcan that reports the active window title in the report console."
-
MCP Tool Call:
{ "tool": "vulcan_execute_code", "arguments": { "code": "import maptek.vulcan_gui as vg\nresult = {'window_name': vg.get_window_name() if hasattr(vg, 'get_window_name') else 'Envisage'}" } }
-
Returned Response:
{ "success": true, "result": { "window_name": "Envisage - [C:\\MiningProjects\\Deposit_Cu_Au]" } }
Configuration & Environment Variables
Both the plugin inside Maptek Vulcan and the external MCP server automatically read operating system environment variables (os.environ):
| Variable | Default | Type | Description | When is it used? |
|---|---|---|---|---|
VULCAN_MCP_HOST |
127.0.0.1 |
String | IP address where the plugin listens and the MCP server connects. | Optional. Change if running Vulcan on a separate VM or container. |
VULCAN_MCP_PORT |
9877 |
Integer | TCP port for binary uint32 message transport. |
Optional. Change if port 9877 is used by another application. |
VULCAN_MCP_TOKEN |
"" (Disabled) |
String | Shared secret authenticated via constant-time HMAC. | Required if VULCAN_MCP_HOST is non-loopback (!= 127.0.0.1). Optional on localhost. |
Authentication & Security
Zero .env Philosophy
You do not need to create or manage insecure .env files containing plain text passwords that might accidentally be committed to Git. Tokens are managed at the Windows OS environment level:
# 1. Generate and save a token permanently in your Windows user account:
$token = python -c "import secrets; print(secrets.token_urlsafe(32))"
[System.Environment]::SetEnvironmentVariable('VULCAN_MCP_TOKEN', $token, 'User')
# 2. Verify that it was stored correctly:
[System.Environment]::GetEnvironmentVariable('VULCAN_MCP_TOKEN', 'User')
# 3. (Optional) To revoke and revert to open mode:
[System.Environment]::SetEnvironmentVariable('VULCAN_MCP_TOKEN', $null, 'User')
Strict Non-Loopback Network Rule
- If you bind
VULCAN_MCP_HOSTto a non-loopback interface (e.g.,0.0.0.0or a LAN IP), the plugin strictly refuses to start (RuntimeError) unlessVULCAN_MCP_TOKENis set, preventing unauthorized remote script execution.
🛠️ Diagnostics & FAQ
3-Layer Automated Testing Harness
The project includes automated testing infrastructure organized across 3 validation tiers:
| Layer | Test Level | Command | Scope & Target |
|---|---|---|---|
| Layer 1 | Unit & AST | uv run --no-sync pytest tests/test_vulcan_mcp.py -v |
Validates strict Python 3.5.2 compatibility (f-string prohibition in plugin/), domain registration, and token isolation. |
| Layer 2 | Mock Harness & Agent Eval | uv run --no-sync pytest tests/test_mcp_tools.py tests/test_agent_eval.py -v |
Emulates Vulcan's socket listener in-memory using MockVulcanServer. Tests all 9 FastMCP tools and multi-step geologist workflows without opening Vulcan. |
| Layer 3 | Live Integration | uv run --no-sync pytest tests/test_live.py -v |
Live end-to-end tests against a running Maptek Vulcan 12 Desktop session with active Envisage. |
🔄 CI/CD & Automated Workflows
The repository uses coordinated, path-filtered GitHub Actions to ensure maximum speed, security, and reproducibility on Windows:
| Workflow | Trigger | Runner | Responsibilities |
|---|---|---|---|
CI & Code Quality (ci.yml) |
Pull requests & pushes targeting src/**, plugin/**, tests/**, pyproject.toml, uv.lock |
windows-latest |
• Ruff linter & format enforcement • Mypy strict type checking • AST check ensuring 100% Python 3.5.2 compatibility in plugin/• Pytest matrix on Python 3.11 & 3.12 |
Security Analysis (security.yml) |
Weekly schedule & PRs touching core dependencies | ubuntu-latest |
• GitHub CodeQL semantic security scan • pip-audit vulnerability scanning on frozen production dependencies |
Release Pipeline (release.yml) |
Tag creation (v*) |
ubuntu-latest |
• Builds sdist and wheel with uv build• Generates SHA-256 cryptographic checksums ( checksums.txt)• Creates official GitHub Release with release notes and binary assets |
Publish to PyPI (publish-pypi.yml) |
Release published (release: [published]) or manual dispatch |
ubuntu-latest |
• OIDC Trusted Publishing (keyless, zero static tokens) • PEP 740 Cryptographic Build Provenance Attestation • Direct publish to PyPI ( luiccian-vulcan-mcp) |
🏷️ Release Cadence, Versioning & Tag Creation
We strictly adhere to Semantic Versioning (SemVer 2.0.0):
- MAJOR (
X.0.0): Incompatible API breaks or major protocol overhaul. - MINOR (
0.X.0): Backwards-compatible new MCP tools, handlers, or capabilities. - PATCH (
0.0.X): Bug fixes, dependency bumps, performance optimizations, and documentation updates.
5-Target Synchronized Versioning (scripts/bump_version.py)
To prevent version discrepancies between metadata files, use the unified version bumper:
# Preview changes without modifying files:
python scripts/bump_version.py patch --dry-run
# Execute version bump (patch, minor, major, or explicit version):
python scripts/bump_version.py patch
python scripts/bump_version.py minor
python scripts/bump_version.py 0.3.1
The script automatically synchronizes all 5 points in a single atomic pass:
pyproject.toml([project] version = "...")src/vulcan_mcp/__init__.py(__version__ = "...").agents/plugins/vulcan-mcp/plugin.json("version": "...")uv.lock(root package version updated)CHANGELOG.md(moves[Unreleased]into[X.Y.Z] - YYYY-MM-DDand creates a fresh empty[Unreleased]section).
How to Cut a Release & Publish to PyPI
# 1. Update version and changelog
python scripts/bump_version.py 0.3.1
# 2. Commit the version bump
git add .
git commit -m "chore(release): bump version to 0.3.1"
# 3. Create an annotated Git tag
git tag -a v0.3.1 -m "Release v0.3.1: Windows CI, PyPI packaging & English docs"
# 4. Push branch and tag to GitHub
git push origin master
git push origin v0.3.1
🤝 Contributing
Contributions, bug reports, and suggestions are warmly welcomed! Please read our Contributing Guide (CONTRIBUTING.md) to learn about:
- Setting up the local development environment with
uv. - Feature branch workflows (
feat/*,fix/*) to keepmasterstable. - Strict Python 3.5.2 compatibility in
plugin/(no f-strings). - Conventional Commits and submitting Pull Requests with GitHub CLI (
gh).
Metadata
Release files for luiccian-vulcan-mcp 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| luiccian_vulcan_mcp-0.3.2.tar.gz | 405.7 kB | Without provenance | Details for luiccian_vulcan_mcp-0.3.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| luiccian_vulcan_mcp-0.3.2-py3-none-any.whl | Python 3 | none | any | Details for luiccian_vulcan_mcp-0.3.2-py3-none-any.whl |
Total release size: 429.9 kB
Release files / luiccian_vulcan_mcp-0.3.2.tar.gz
| Download URL | luiccian_vulcan_mcp-0.3.2.tar.gz |
|---|---|
| Size | 405.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f9047f78d01ec7929cd13a6f249fe3c60aed59f3aaee8ed8f8c2a5c89fedc289
|
|
BLAKE2b-256 checksum How to use checksums |
9d28fe143fdb1df5f531a19edce5d0d2befd4336bcb7e82c71433aa6fd544cfc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / luiccian_vulcan_mcp-0.3.2-py3-none-any.whl
| Download URL | luiccian_vulcan_mcp-0.3.2-py3-none-any.whl |
|---|---|
| Size | 24.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bcbf5e953ca3ba4f2cd8d3a1a57bfdcb741cf62704c65ff1fe5aea81992b0ea1
|
|
BLAKE2b-256 checksum How to use checksums |
978cfea536f4bbf947f03749169e42cbd635e0828583c88bffd2c73ef2554262
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for luiccian-vulcan-mcp 0.3.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.