{"name":"io.github.musharna/plantcv-mcp","slug":"musharna-plantcv-mcp","title":"plantcv-mcp","description":"Plant phenotyping via PlantCV — returns traits plus the segmentation overlay they came from","url":"https://mcp.market/server/musharna-plantcv-mcp","rating":null,"grade":"A","score":85,"certified":false,"status":"active","category":"other","tags":[],"presence":{"score":30,"stars":0,"forks":0,"downloads_week":261,"last_push_at":"2026-09-19T08:15:49.000Z","license":"MIT"},"uptime":null,"claimed":false,"transport":"pypi","callable_via_gateway":false,"default_price_micros":0,"repository":"https://github.com/musharna/plantcv-mcp","website":"https://github.com/musharna/plantcv-mcp","version":"1.15.0","remotes":[],"packages":[{"registryType":"pypi","registryBaseUrl":"https://pypi.org","identifier":"plantcv-mcp","version":"1.15.0","runtimeHint":"uvx","transport":{"type":"stdio"}}],"tools":[{"name":"calibrate_scale_from_marker","description":"Measure a size marker of known real length and return px_per_mm, which you then pass to measure() to get traits in mm instead of pixels.","write_action":false,"price_micros":0,"input_schema":null},{"name":"correct_lens_distortion","description":"Correct lens/fisheye distortion using checkerboard calibration photos, write the corrected image next to the input as <image>_undistorted.png (or to output_path, refused if it exists), and return its path plus a preview. Segment, calibrate scale, and measure the CORRECTED file. The correction is never written INTO checkerboard_dir: everything there is read as a calibration frame, so pass output_pa","write_action":false,"price_micros":0,"input_schema":null},{"name":"count_leaves","description":"Split ONE top-view plant mask into leaf instances with PlantCV's distance-transform watershed and return the count, each instance's area, centroid [x, y] and bbox [x, y, w, h] (full-frame pixels), and the overlay with every instance outlined and numbered — instance `id` is the number drawn on the picture.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_methods","description":"List available segmentation channels, methods, object types, analyses, and the pinned PlantCV version.","write_action":false,"price_micros":0,"input_schema":null},{"name":"measure","description":"Return plant traits for a segmentation produced by segment(). Raises if the mask is degenerate rather than returning zeros.","write_action":false,"price_micros":0,"input_schema":null},{"name":"measure_images","description":"Run one fixed segmentation recipe across many images.","write_action":true,"price_micros":0,"input_schema":null},{"name":"measure_morphology","description":"Skeleton-based traits for ONE plant: per-segment path and euclidean length, curvature, angle, tangent angle and insertion angle, plus stem height/length/angle, tip and branch-point counts, cycles and widths. Returns the numbered-segment overlay with the table — segment `id` is the number drawn on the picture.","write_action":false,"price_micros":0,"input_schema":null},{"name":"measure_regions","description":"Measure EACH plant in a multi-plant image separately.","write_action":false,"price_micros":0,"input_schema":null},{"name":"measure_spectral","description":"Per requested index: mean, median, std, min, max over the session's mask, computed on the calibrated (or float-cast) cube exactly as segment_hyperspectral() prepared it. indices defaults to the index the session was segmented with. include_spectrum adds the per-band mean/ max/min/std reflectance — hundreds of numbers per list, off by default; band_count is always reported. Refuses RGB and thermal","write_action":false,"price_micros":0,"input_schema":null},{"name":"measure_thermal","description":"max, min, mean and median degrees Celsius over the session's mask, via PlantCV's analyze.thermal, plus the pixel count and the frame's range. include_histograms adds the 100-bin temperature histogram. Refuses RGB and hyperspectral sessions.","write_action":false,"price_micros":0,"input_schema":null},{"name":"refine","description":"Apply morphological cleanup to a session's mask and get a NEW session.","write_action":false,"price_micros":0,"input_schema":null},{"name":"segment","description":"Segment an image. Returns the overlay image and mask diagnostics — NOT traits. Use the returned session_id with measure() to get traits.","write_action":false,"price_micros":0,"input_schema":null},{"name":"segment_hyperspectral","description":"Compute one spectral index over an ENVI cube (.raw/.hdr pair; give either path) and threshold it into a mask, returning the overlay on the cube's pseudo-RGB plus diagnostics — NOT numbers. Use the session_id with measure_spectral().","write_action":false,"price_micros":0,"input_schema":null},{"name":"segment_leaves_sam","description":"Split ONE top-view plant mask into leaf instances with Segment Anything (ViT-B, Apache-2.0) and return the count, each instance's area, centroid [x, y] and bbox [x, y, w, h] (full-frame pixels), and the overlay with every instance outlined and numbered, as count_leaves() does. The model is prompted on a 32x32 point grid restricted to the mask; masks are kept when leaf-sized (0.2%-40% of the plant)","write_action":false,"price_micros":0,"input_schema":null},{"name":"segment_thermal","description":"Read a FLIR radiometric .jpg (via flyr), a .csv, or a .npz of degrees Celsius and select the pixels between min_c and max_c (give at least one) as the plant. Returns the overlay on a grey rendering of the frame, the frame's temperature range and diagnostics — NOT numbers; use the session_id with measure_thermal(). A thermal frame is a different sensor from the RGB camera, so a mask is never borrow","write_action":false,"price_micros":0,"input_schema":null},{"name":"suggest_segmentation","description":"Return colourspace and threshold contact sheets, plus what each object_type would yield on this image, so the channel/method/polarity choice is informed rather than blind. Call this before segment(). polarity.warnings carries `noisy_segmentation` when the recommended polarity is many components with no dominant one — background texture, not a plant — which the `ambiguous` flag alone cannot tell yo","write_action":false,"price_micros":0,"input_schema":null}],"scan":{"score":85,"grade":"A","scanned_at":"2026-09-19T19:28:40.328Z","report":{"scannerVersion":"0.1.5","scannedAt":"2026-09-19T19:28:40.281Z","components":{"code":{"score":20,"max":25,"notes":["23 source files scanned"]},"reliability":{"score":-1,"max":20,"notes":["no gateway calls yet and no remote to probe"]},"poisoning":{"score":-1,"max":15,"notes":["tools not inspected (local package is not executed); not counted"]},"auth":{"score":12,"max":15,"notes":["local package, no credentials required"]},"maintenance":{"score":15,"max":15,"notes":["last push 0 days ago"]},"identity":{"score":8,"max":10,"notes":["registry namespace matches repository owner","GitHub account older than a year"]}},"findings":[{"id":"exec.eval","severity":"medium","component":"code","title":"eval / new Function used","evidence":"plantcv_mcp-1.15.0/src/plantcv_mcp/sam_leaves.py: …te_dict(state) model.to(device).eval() _loaded.clear() # one model i…"}],"inputs":{"packages":[{"registryType":"pypi","identifier":"plantcv-mcp","version":"1.15.0","found":true,"license":"MIT","dependencyCount":8,"publishedAt":"2026-09-19T08:14:52.500338Z","repositoryUrl":"https://github.com/musharna/plantcv-mcp"}],"repo":{"found":true,"owner":"musharna","repo":"plantcv-mcp","archived":false,"pushedAt":"2026-09-19T08:15:49Z","stars":0,"forks":0,"openIssues":2,"ownerType":"User","ownerAvatarUrl":"https://avatars.githubusercontent.com/u/96366172?v=4","ownerCreatedAt":"2021-12-19T05:59:46Z","license":"MIT"},"icon":{"url":"https://avatars.githubusercontent.com/u/96366172?v=4&s=128","source":"registry","width":128,"height":128},"presence":{"stars":0,"forks":0,"downloadsWeek":261,"license":"MIT","lastPushAt":"2026-09-19T08:15:49.000Z","score":30}}}},"grade_history":[],"reviews":[]}