plantcv-mcp
plantcv-mcp is an MCP server that lets AI agents run PlantCV plant phenotyping. It returns trait numbers and the segmentation overlay they were measured from, and refuses to return numbers when the segmentation is degenerate.
Left, channel="a", object_type="dark": the mask covers 3.1% of the frame, 9 components,
area=32427. Right, channel="s", object_type="dark": the mask covers 96.1%; it is the
background, area=1007829.
Why you get the overlay
Both images come from the same file and the same threshold method; only the channel differs. Without the picture, both runs return 17 traits with correct units and believable magnitudes. The one on the right is measuring the wall behind the plants. Red marks the measured pixels; a cyan line traces the mask's edge.
So segment() returns the overlay and diagnostics but no traits, and measure() needs the
session_id that segment() mints: no single image is measured before you are shown it. The
exception is measure_images(), which applies one recipe to up to 200 images without overlays.
Settle the recipe on one image's overlay first (the server does not check); every image still
passes the segment() guards, and one that trips a blocking guard gets no traits.
Measured with PlantCV 4.11.3 on a synthetic render (first row:
tests/fixtures/multi_specimen.png) and on photographs, each of these returns believable
numbers with correct units:
| Failure | What you get without the overlay |
|---|---|
| four-view render, whole-image ROI | 17 plausible traits describing four merged plants |
| plant clipped by the frame | size traits that are silently lower bounds |
| empty mask | 17 traits of zeros, with PlantCV reporting in_bounds=True |
Install
With uv nothing needs installing: uvx --python 3.13 plantcv-mcp fetches and
runs the current release. Otherwise:
pip install plantcv-mcp
Requires Python 3.11 to 3.13: PlantCV 4.11.3 needs SciPy below 1.16, which has no Python 3.14
wheels, so --python 3.13 keeps uvx off a 3.14 default. PlantCV and its scientific stack make the first install (or first uvx
run) slow. From a checkout: uv add /path/to/plantcv-mcp. The one optional tool,
segment_leaves_sam(), needs pip install "plantcv-mcp[sam]" (torch, torchvision,
segment-anything); without it, that tool refuses with that command and every other tool works.
Configure your MCP client
claude mcp add plantcv -- uvx --python 3.13 plantcv-mcp
Claude Desktop and other stdio hosts:
{ "mcpServers": { "plantcv": { "command": "uvx", "args": ["--python", "3.13", "plantcv-mcp"] } } }
With a pip install the command is plantcv-mcp (checkout config).
Verify with list_methods().
Flags: --root DIR (repeatable, or PLANTCV_MCP_ROOTS) confines every read, and every file
the server keeps, to your imagery: plantcv-mcp --root /data/phenotyping. --no-isolate (or
PLANTCV_MCP_ISOLATE=0) runs analyses in-process instead of in the crash-containing worker.
What the benchmark shows
Claude with the server was compared with Claude writing its own code (mostly OpenCV) in a Python environment we set up with the same PlantCV and OpenCV, on 46 measurement questions about rendered plant images, 3 runs each. A tie means the server matches that result without you building the environment. Questions right in every run, server against Claude's own code: Claude Haiku 5.5 38 against 32, Sonnet 5.5 33 against 28, Opus 5.5 42 against 44. None is separated (pre-registered; exact McNemar p = 0.15, 0.23 and 0.63), and Claude's own code was cheaper on all three models.
The chart is the Opus 5.5 re-run on 2026-10-18, against an unreleased commit (051aff0) that adds
several-channel segmentation rules and zoom_image: right on 97.1% of answers with its own code
and 95.7% with the server. Its own code cost $0.038 against $0.066 per answer (medians; the
intervals do not overlap). On release 1.16.1 the server was right on 86.2% against 95.7%
(p = 0.18). The images have crisp edges, so a single color cut with no model answers 28 of the
46.
We wrote the questions and ran the benchmark ourselves; an outside re-run is welcome. Method, controls and limitations: benchmarks/agent_qa; the Haiku and Sonnet runs: 2026-10-20 re-run.
Tools
| Tool | Returns |
|---|---|
suggest_segmentation |
contact sheets, and what each object_type would yield |
segment |
overlay + diagnostics + warnings, no traits |
refine |
a new session with a cleaned-up mask, plus its overlay |
measure |
traits, or a raised error on a degenerate mask |
measure_images |
one recipe across many images; traits only where valid |
measure_regions |
one row per plant in a tray, plus the numbered overlay |
measure_morphology |
leaf/stem skeleton traits + the numbered-segment overlay |
count_leaves |
an estimated leaf count by watershed + the numbered overlay |
segment_leaves_sam |
the same count from Segment Anything (optional sam extra) |
calibrate_scale_from_marker |
px_per_mm from a marker of known real size |
correct_lens_distortion |
a fisheye or wide-angle image undistorted from checkerboards |
segment_hyperspectral, measure_spectral |
an HSI session from an index threshold; index statistics |
segment_thermal, measure_thermal |
a thermal session from a °C band; °C statistics under the mask |
zoom_image |
part of an image, enlarged to look closely (not a measurement) |
list_methods |
channels, methods, object types, pinned PlantCV version |
Typical loop: suggest_segmentation → segment → look at the overlay → segment again
with another channel, method or polarity if it is wrong (or refine if it is nearly right) →
measure. With a ColorChecker in the frame, color_correct=true corrects colors before
segmenting and excludes the card from the mask. Parameters, an example response and the
measured facts behind each tool:
docs/GUIDE.md.
What it refuses
Each guard was added after a specific failure and names the next action. Blocking guards withhold numbers; advisories travel with them.
- Inverted mask (
implausible_coverage): the right-hand image above, 17 believable traits describing the wall. - Nothing selected, or
fill_sizedeleted the specimen (empty_mask,fill_erased_mask): PlantCV returns 17 zeros within_bounds=True. - Background texture (
noisy_segmentation): specks of chamber wall measured as one plant. - Several plants in one mask (
multi_specimen): usemeasure_regions(). - Wrong scale, wrong session kind, a file changed after segmentation: refused, naming the right tool.
- A lens calibration the boards do not determine, or no color card when one was asked for: refused.
Why each guard exists, and every warning code: docs/GUIDE.md#warnings-and-refusals.
Security
With no --root, the server reads any image file the host user can read and returns it to the
model. It writes only the lens-corrected image, the Segment Anything checkpoint when asked to
download it, and short-lived temporary copies of hyperspectral and thermal inputs. Run it as a
non-root user with --root set. Analyses run in a worker subprocess, so a native crash is a
tool error, not a dead server. Details:
docs/GUIDE.md#security-and-trust-boundary.
Attribution and license
MIT licensed. It depends on PlantCV, which is licensed under the Mozilla Public License 2.0. No PlantCV source is vendored or redistributed here; it is an ordinary runtime dependency, so the MIT license applies to this project's own files. Unofficial: not affiliated with, endorsed by, or sponsored by the Donald Danforth Plant Science Center or the PlantCV maintainers. See NOTICE.
Cite it with CITATION.cff (archived at doi:10.5281/zenodo.21713516). Changes: CHANGELOG.md.
Metadata
Release files for plantcv-mcp 1.17.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 |
|---|---|---|---|---|
| plantcv_mcp-1.17.2.tar.gz | 3.5 MB | Without provenance | Details for plantcv_mcp-1.17.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| plantcv_mcp-1.17.2-py3-none-any.whl | Python 3 | none | any | Details for plantcv_mcp-1.17.2-py3-none-any.whl |
Total release size: 3.7 MB
Release files / plantcv_mcp-1.17.2.tar.gz
| Download URL | plantcv_mcp-1.17.2.tar.gz |
|---|---|
| Size | 3.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7ce228075dfe44defe2d090f3379350754d9fbc1e2bc5a45e0fbe01fddf632ab
|
|
BLAKE2b-256 checksum How to use checksums |
51efb1370a121f5b53b50deb52b67df80f262ba2f2f47963ecde2eb54f3642ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|
Release files / plantcv_mcp-1.17.2-py3-none-any.whl
| Download URL | plantcv_mcp-1.17.2-py3-none-any.whl |
|---|---|
| Size | 160.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e7abb20718e474f9c89eb9bd6f37661076f3efe04beab1cb8bdfd3ecfab9113c
|
|
BLAKE2b-256 checksum How to use checksums |
edfbf01022f2639b30d9c4b93bf1b3aa967d2e294ae2abe665f4a0511b608bcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|
Security for plantcv-mcp 1.17.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.