Skip to main content
Glama
YASHUJOSHI
by YASHUJOSHI

geovector-3d-mcp

Downhole 3-D geochemical vectoring with honest uncertainty, plus an MCP server so AI agents can call the maths instead of improvising it.

You have six holes through a pegmatite, all sub-economic. The fractionation indices change from hole to hole: K/Rb falls, Nb/Ta falls, Cs rises. The question every exploration team asks next is which way, and how sure are we? This package answers it from collar, survey, assay and lithology tables:

  1. Desurvey every hole by minimum curvature, so sample positions are true 3-D points, not collar-plus-depth guesses.

  2. Clean the geochemistry. It parses below-detection values, uses log-ratios instead of raw ratios, and computes indices only in the rock they are defined for.

  3. Fit a local 3-D gradient of the index, aligned to the host structure, with a 95 % confidence cone on its direction and a significance test that it exists.

  4. Propose a step-out hole (collar, azimuth, dip, target depth), or decline to when the direction is not resolved.

Synthetic benchmark

The benchmark data in this repository are synthetic, generated by scripts/make_benchmark.py with a planted answer. Recovering that answer shows the code is correct. It does not show that real pegmatites zone this simply.


Quick start

git clone https://github.com/YASHUJOSHI/geovector-3d-mcp.git
cd geovector-3d-mcp
pip install -e ".[dev]"          # core + MCP + Streamlit + pyproj + pytest
pytest                           # 43 tests
streamlit run app/streamlit_viewer.py

From Python:

from geovector3d import run_vectoring

r = run_vectoring("data/benchmark_stuck_block", index="ln_K_Rb",
                  host_codes=("PEG",), strike=300, dip=50)
r["gradient"]["direction_trend_deg"], r["gradient"]["cone_half_angle_deg"]
r["proposal"]          # collar, azimuth, dip, target depth, confidence, caveats

Input tables

File

Required columns

Notes

collar.csv

BHID, X, Y, Z, TOTAL_DEPTH

local grid or projected CRS, metres

survey.csv

BHID, DEPTH, AZIMUTH, DIP

dip negative down; missing 0 m station is copied from the first shot

assay.csv

BHID, FROM, TO, <analytes…>

<0.5 or -0.5 both mean "below 0.5"

lithology.csv

BHID, FROM, TO, ROCK_CODE

optional but strongly recommended

units.json

{analyte: "ppm" | "ppb" | "pct" | "oxide_pct"}

optional; default is ppm

Related MCP server: GeoAgent MCP Server

Results on the benchmark

Six inclined holes cut a 20 m pegmatite dyke (strike 300°, dip 50° NE). K/Rb falls from 140 to 38 and Nb/Ta from 12 to 2.5 down a 34° plunge toward 335°. Planted truth: trend 335.0° / plunge 34.4°.

Configuration

Recovered trend / plunge

Error

95 % cone

Outcome

ln K/Rb, pegmatite only, structure-aligned

333.6° / 33.4°

1.5°

10.5°

step-out proposed, high confidence

ln Nb/Ta, same

7.5°

10.9°

proposed

ln Zr/Hf, same (weaker planted trend)

11.6°

37.3°

moderate

ln K/Rb, isotropic search (no structure)

38°

45°

borderline

ln K/Rb, no lithology filter

gradient not significant (Wald p = 0.43): no recommendation

The last two rows are the point of the package. Without structure, and without keeping wall rock out of the fit, the same data give a wrong or empty answer. A tool that reported a direction regardless would have sent a hole the wrong way.


Method

METHODOLOGY.md has the derivations. In short:

Minimum-curvature desurveying

Each survey station becomes a unit tangent t = (cos δ sin α, cos δ cos α, sin δ), with azimuth α and dip δ negative down. Between stations i and i+1, separated by ΔMD:

  • dogleg angle β = 2 arcsin(|tᵢ₊₁ − tᵢ| / 2)

  • ratio factor RF = (2/β) tan(β/2)

  • displacement Δx = (ΔMD/2) · RF · (tᵢ + tᵢ₊₁)

β is computed from the chord rather than arccos(tᵢ·tᵢ₊₁), which loses most of its precision for the nearly straight courses that dominate real surveys. RF is replaced by its limit 1 + β²/12 when β < 10⁻⁶. A sample midpoint between stations is placed on the arc, not the chord. The sub-arc to a fraction f ends at the slerp of the two tangents and is itself a minimum-curvature course of length f·ΔMD. The tests check this against a constant-build circular arc to 10⁻⁸ m.

Because everything is carried as vectors, a vertical hole is not a special case. At δ = −90° the azimuth multiplies zero and drops out, so there is no gimbal lock.

Compositional data

  • Non-detects are kept as censored values and replaced multiplicatively (Martín-Fernández et al., 2003) at 0.65 × LLD. This leaves ratios among detected parts unchanged. Analytes censored in more than 30 % of samples are reported as unusable, and a ratio of two censored values is set to missing.

  • Vectoring runs on log-ratios (ln K/Rb, ln Nb/Ta, …). A pairwise log-ratio is scale-invariant and subcompositionally coherent. Raw ratios are skewed, and their gradients are dominated by the high end. CLR and ILR are provided for multi-element work but are computed on a fixed, closed composition, because CLR scores change whenever the analyte suite changes.

  • Indices are host-restricted. LCT ratios are computed only in pegmatite and granite codes, and the Ishikawa AI and CCPI only in felsic volcanics.

Local gradient

A weighted least-squares fit of f(x) = a + g·(x − x₀) around x₀, with three safeguards for the way drillholes sample space:

Problem

Safeguard

Dense down-hole, sparse between holes, so the fit is driven by along-hole variation

at most 3 samples per hole per fit

Isotropic search crosses barren contacts

distances measured in a strike / dip / pole frame with separate ranges; optionally fit only the in-plane components

A direction is always returned, even from noise

a Wald test that g ≠ 0, and a 95 % cone half-angle from the parameter covariance

The cone is arctan(√(χ²₂,₀.₉₅ · λ⊥) / |g|), where λ⊥ is the largest variance perpendicular to g. It is a better guide than the design-matrix condition number, which is reported too, because it scales with the signal.

Step-out design

The target is placed along the in-plane fractionation direction, starting from the most-evolved decile of host samples. The default step is the data-support distance (median spacing of host intercepts). The hole is aimed down the host pole to cut the body at a high angle, with dip clipped to [−85°, −45°]. Longer steps are allowed but flagged beyond_support. A local gradient cannot tell you whether a trend continues for another 120 m: that is the hypothesis the hole tests.

Is a barren surface sample barren?

diagnose_false_surface_anomaly checks that immobile ratios (Zr/Hf, Nb/Ta, Ti/Zr) match the fresh parent, which rules out transported cover. It then computes tau mass-transfer coefficients (Brimhall & Dietrich, 1987) for mobile elements. It returns evidence and caveats, not a verdict, because Zr and Ti are only relatively immobile.


MCP server for AI agents

Agents should not do drillhole trigonometry or log-ratio algebra in their heads. The server exposes the engine as four deterministic tools. Every response states its sign conventions, and bad input returns an explicit error.

Tool

Does

validate_and_desurvey_drillholes

checks tables, desurveys, reports end-of-hole positions, dogleg severity and copied collar stations

compute_3d_fractionation_vector

host-filtered log-ratio gradient with cone and significance

propose_stepout_borehole

collar / azimuth / dip / depth, or no_recommendation

diagnose_false_surface_anomaly

immobile-ratio check + tau mass transfer

Built on the MCP Python SDK 2.x (MCPServer, formerly FastMCP). Add it to Claude Desktop's claude_desktop_config.json:

{
  "mcpServers": {
    "geovector3d": { "command": "geovector3d-mcp" }
  }
}

If the console script is not on your PATH, use "command": "python", "args": ["-m", "geovector3d.mcp_server"].

Repository layout

src/geovector3d/
  desurvey.py        minimum curvature, validation, interval mid-points
  compositional.py   censoring, units, CLR/ILR, LCT and alteration indices
  vector_field.py    structural frame, local gradient, cone, step-out design
  anomaly.py         immobile ratios and tau mass transfer
  workflow.py        load -> prepare -> gradient -> proposal
  export.py          CSV drill plan, GeoJSON (needs an EPSG code)
  mcp_server.py      MCP tools
app/streamlit_viewer.py
data/benchmark_stuck_block/   synthetic six-hole dataset + truth.json
scripts/                      benchmark and figure generators
tests/                        43 tests

Limitations

  • Linear local model: zoning that curves within the search radius is averaged.

  • One structural orientation per run. Folded hosts need domaining; unfolding is out of scope.

  • Fractionation indices assume a single magmatic system. Overprinting, alteration or multiple intrusive phases break the simple gradient picture.

  • GeoJSON export needs a real CRS; local mine grids export as CSV.

  • Validated only on the synthetic benchmark. Real-data case studies are the next step.

How this was built

I wrote this code with an AI coding assistant. The geological framing is mine: the choice of indices, host restriction, structure-aligned search, refusing to recommend without a significant gradient, and flagging step-outs beyond data support.

References

  • Brimhall, G.H. & Dietrich, W.E. (1987). Geochim. Cosmochim. Acta 51, 567–587.

  • Černý, P. (1991). Rare-element granitic pegmatites. Geoscience Canada 18, 49–67.

  • Egozcue, J.J. et al. (2003). Isometric logratio transformations. Math. Geol. 35, 279–300.

  • Ishikawa, Y. et al. (1976). Mining Geology 26, 105–117. Alteration index.

  • Large, R.R. et al. (2001). Econ. Geol. 96, 957–971. AI and CCPI box plot.

  • London, D. (2008). Pegmatites. Can. Mineral. Spec. Publ. 10.

  • Martín-Fernández, J.A. et al. (2003). Math. Geol. 35, 253–278. Zero replacement.

  • Sawaryn, S.J. & Thorogood, J.L. (2005). SPE Drill. Complet. 20, 77–86. Minimum curvature.

MIT licence.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Exposes tools and resources for human-supervised geological modelling from borehole data, including validation, 3D implicit model construction with GemPy, and uncertainty analysis, with a deterministic audit trail.
    MIT
  • F
    license
    B
    quality
    C
    maintenance
    Enables AI agents to query verifiable physical-world ground truth for any point on Earth — water availability, seismic and space-weather hazard, ground stability, and resource indications — with every answer backed by a Bitcoin-anchored provenance record that can be independently verified. It also lets agents check whether an Earth-science hypothesis has already been tested, list documented nulls and retractions, and run bounded controlled tests that return UNTESTABLE rather than fabricate a result.
    11
    -