Skip to main content

sodir-mcp

A read-only MCP server for the public Sodir (Norwegian Offshore Directorate) FactPages. It answers two questions with sourced, unit-labelled data:

Tool What it returns
wellbore_facts Official facts of one wellbore: status, purpose, content, operator, field, spud (entered) and completion dates, total depth (MD), Sodir final vertical depth (TVD), kelly bushing elevation, water depth, drilling facility, surface location.
field_production_monthly Sodir's monthly saleable production of a whole field (oil, gas, NGL, condensate, oil equivalents, produced water) with totals over a window.

The package contains no Sodir data. You fetch the public tables once into a local cache, and the tools read that cache (read-only). Nothing is sent anywhere else.

Data licence: the Sodir data is published under the Norwegian Licence for Open Government Data (NLOD) 2.0. Every tool response carries the NLOD attribution; keep it if you pass the data on. See NOTICE-DATA.md. The code of this package is MIT-licensed.

Install and first run

uvx sodir-mcp refresh          # downloads about 8 MB of CSV from factpages.sodir.no into the cache
uvx sodir-mcp status           # what the cache holds, and when it was fetched
uvx sodir-mcp                  # serve over stdio (same as `sodir-mcp serve`)

(uvx runs the published package. Before it is published, install from a built wheel: pip install dist/sodir_mcp-0.1.0-py3-none-any.whl.)

Claude Desktop (claude_desktop_config.json):

{"mcpServers": {"sodir": {"command": "uvx", "args": ["sodir-mcp"]}}}

Until refresh has run, each tool answers data_not_loaded with the hint run: sodir-mcp refresh. Set SODIR_MCP_AUTO_REFRESH=1 to let the first tool call download the data (off by default, so nothing downloads without being asked).

Commands

Command Does
sodir-mcp refresh [--force] [--from-dir DIR] Downloads field, wellbore_development_all, wellbore_exploration_all and field_production_monthly, checks that each is CSV with the expected columns, normalises, and replaces the cache atomically. A failed refresh keeps the previous cache. At most once per 24 hours unless --force. --from-dir reads the four <table>.csv files from a folder you downloaded yourself (offline path; only this command reads files).
sodir-mcp status Shows the cache path, the tables, fetch time and SHA-256.
sodir-mcp serve [--http --host H --port P] MCP over stdio (default) or streamable HTTP.

Environment: SODIR_MCP_CACHE (cache folder; default is the platform cache folder, for example ~/Library/Caches/sodir-mcp on macOS or ~/.cache/sodir-mcp on Linux), SODIR_MCP_AUTO_REFRESH=1, SODIR_MCP_BACKEND=postgres (see below). The only host the package contacts is factpages.sodir.no; redirects to other hosts are refused. A cache older than 90 days adds a note to every answer.

Example

wellbore_facts(wellbore="F-12") (a Volve alias; any exact Sodir name such as 15/9-F-12 works, for other fields only exact Sodir names). Trimmed output with values from the fixture used in the tests (hand-made, not a Sodir extract):

{"wellbore": "15/9-F-12", "npd_wellbore_id": 5599, "category": "development",
 "status": "P&A", "purpose": "PRODUCTION", "spud_date": "2007-06-14",
 "completion_date": "2007-08-27", "total_depth_md_m": 3520.0,
 "final_vertical_depth_tvd_m": 3107.0, "kb_elevation_m": 54.0,
 "drilling_facility": {"name": "MÆRSK INSPIRER", "type": "JACK-UP 3 LEGS", "fixed_or_move": "FIXED"},
 "data_as_of": {"table": "wellbore_development_all", "exported_at_utc": "…", "sha256_16": "…"},
 "source": {"type": "sodir", "server": "sodir-mcp", "tool": "wellbore_facts",
            "query_id": "sodir_wellbore_v1", "params": {"wellbore": "15/9-F-12"}, "rows": 1, "…": "…"}}

field_production_monthly(field="VOLVE", start="2014-01", end="2014-12") returns rows[{month, oil_msm3, gas_bsm3, ngl_msm3, condensate_msm3, oe_msm3, water_msm3}] as JSON numbers, units (million Sm3, billion Sm3), totals summed in decimal, data_coverage and notes.

What the answers will and will not say

  • Values are exactly as Sodir publishes them; nothing is converted, completed or corrected.
  • The completion date is Sodir's end of drilling for a development wellbore and rig release for an exploration wellbore drilled from a moveable facility; never the production start-up date. For a sidetrack the entered date is the first drilling after kick-off, not a spud (date_notes).
  • final_vertical_depth_tvd_m null means "not published", never zero.
  • The surface location is the wellhead, not the bottom hole.
  • Facility names are quoted verbatim and may be cut at 16 characters by Sodir.
  • Field volumes are whole-field saleable volumes; do not compare them with per-wellbore allocated volumes without stating both bases.
  • Errors are structured: {"error", "detail", "hint"} with invalid_input, unknown_wellbore, unknown_field, out_of_coverage, data_not_loaded, backend_unavailable, timeout, internal_error. A name that is not an exact Sodir name or alias is never replaced by a similar one.

Safety

Read-only tools; the cache is opened with mode=ro. No tool takes a path, a URL, SQL or a free-form query. Names are validated (letters, digits, space and / . _ # : -, 64 characters). Output is capped at 500 rows and 20,000 characters. No credentials are involved.

Postgres backend (optional, for the Volve Well Ops Copilot stack)

pip install "sodir-mcp[postgres]" and SODIR_MCP_BACKEND=postgres read the stack's sodir_* tables as the read-only role (POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_READONLY_USER, POSTGRES_READONLY_PASSWORD). Same tools, same output.

Development

cd mcp_servers/sodir
uv run --group dev pytest          # package tests (fixtures are hand-made CSVs)
uv build && uvx twine check dist/* # wheel and sdist; nothing is uploaded

From the repository root, make test and make ci-full run the package tests too (the root pyproject.toml adds mcp_servers/sodir/tests to testpaths and mcp_servers/sodir/src to pythonpath). The repository's tests/mcp_servers/test_sodir_package.py fails if the copied helpers drift from mcp_servers/common.py or the output leaves contracts/mcp-tools.md.

Metadata

Release files for sodir-mcp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sodir-mcp 0.1.0
File Size Uploaded
sodir_mcp-0.1.0.tar.gz 35.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sodir-mcp 0.1.0
File Interpreter ABI Platform
sodir_mcp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.2 kB

Release files / sodir_mcp-0.1.0.tar.gz

Download URL sodir_mcp-0.1.0.tar.gz
Size 35.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a4d305a6d4904e77884db94a17647a78821acb285eac406747a68740e0b385a3
BLAKE2b-256 checksum
How to use checksums
8a5888c5eb2e8f460b4f3db30d6c1ca3941a6a4790a3bf8c442dbb377f7f91d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.0

Release files / sodir_mcp-0.1.0-py3-none-any.whl

Download URL sodir_mcp-0.1.0-py3-none-any.whl
Size 33.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
90ed1aa017cdfa210ea308a436dae989abe9c401fe1e7785bf75fd4cdce3485e
BLAKE2b-256 checksum
How to use checksums
b5ebd96b1bbe55b364ea923c62e820757a87a582836348b0a4f900cd70a443e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.0

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page