Install
$ agentstack add mcp-pedropaulovc-meshprobe ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
MeshProbe
MeshProbe gives AI agents a small, typed interface for inspecting 3D assemblies without editing the source model. Agents can identify components, move a camera, switch between orthographic and perspective projection, control lens and lighting, hide occluders, mark parts, and request evidence renders or contact sheets.
MeshProbe starts a persistent, factory-clean Blender worker. It imports GLB, glTF, OBJ, or STL files and returns a validated scene manifest without changing the source file. It can render the current inspection state with Eevee or CUDA-backed Cycles, produce private component and highlight masks plus a Depth/Normal EXR for evaluators, rank line-of-sight occluders, and build a focused 3×3 contact sheet with perspective context and six orthographic detail views.
The Playwright CLI model, for 3D
If you have used Playwright CLI, MeshProbe's interaction model should feel familiar. Playwright opens a named browser session, applies small operations such as navigation and clicks, and keeps a compact page snapshot that an agent can query. MeshProbe does the same for a 3D model: it opens a named inspection session, applies camera, lighting, display, and marking operations, and writes compact state under .meshprobe.
That makes MeshProbe useful when an agent needs to investigate a model over several turns. The model is imported once. Later commands reuse the same Blender worker, and a daemon restart reconstructs the session from its last acknowledged checkpoint. The agent usually reads components.yml and state.yml with rg or yq; the complete manifest remains in scene.json for jq queries.
uv run meshprobe --session gearbox open models/gearbox.glb
uv run meshprobe --session gearbox find '**/idler*'
yq '.components[] | select(.name | test("idler"; "i"))' \
.meshprobe/sessions/gearbox/components.yml
uv run meshprobe --session gearbox display c7 --mode isolated
uv run meshprobe --session gearbox illumination-set raking_left
uv run meshprobe --session gearbox render-sheet c7
uv run meshprobe --session gearbox view-frame c7
uv run meshprobe --session gearbox render-image --output idler.png
view-frame computes the camera that tightly fits a component's bounds and persists it like view-orbit, so a following render-image fills the frame with an isolated part instead of inheriting a camera framed for the whole assembly. The --focus option on the view-* commands is a projection diagnostic (it reports where components land in the image); it never moves the camera.
Normal output is a short receipt containing the result and state paths. Add --json or --yaml for a machine-readable receipt, or --raw when the full operation result is actually needed. meshprobe schema --kind state gives a compact field map for every durable file; add --full for formal JSON Schemas, and --yaml (before or after the subcommand) for YAML output. Visual mutations (open, display, mark, illumination-set, view-*, and reset) accept --render when the next step is to inspect an image. The mutation and render stay as separate journaled operations but run in one CLI invocation. Leave it off while chaining setup commands. Use meshprobe undo [COUNT] to reverse recent visual mutations, including after a daemon restart. Queries and renders do not consume history; reset starts a new undo boundary.
LLM-readable CLI help
MeshProbe supports cmdhelp v0.1. Use it when an agent needs the full command tree and invocation schema:
meshprobe help --format md --depth 99
meshprobe help --format json --depth 99
meshprobe help view-orbit --format md
meshprobe help --capabilities
text is the default and preserves the ordinary concise Click help. md includes command synopses, arguments, flags, examples, stream behavior, exit codes, and session context. json uses the same command metadata and examples for programmatic dispatch; llm is an alias for md. --depth 0 emits a summary tree, while each additional depth expands one more level.
find auto-detects plain component names, exact hierarchy paths, and wildcard globs. A slash-free glob searches component names at any hierarchy depth; use --name NAME for an exact display name and --kind regex only when regular-expression matching is intentional. The same auto-detection resolves the component arguments of display, mark, render-sheet, and occlusion, so a glob there fans out to every match just as find does (occlusion '**/*' measures the whole scene). Component paths remain authoritative when scene.json reports hierarchy: flattened; intermediate non-mesh source nodes stay encoded in the path even though they are not separately addressable components.
Install
MeshProbe uses Python 3.12 or newer, uv, and Blender 5.2 LTS on Linux and Windows. The qualification harness uses Bubblewrap on Linux. On Ubuntu 24.04 or newer, load the distro's AppArmor profile. It grants Bubblewrap the namespace permissions needed by the harness and keeps user-namespace hardening enabled:
sudo apt-get install apparmor-profiles bubblewrap
sudo cp \
/usr/share/apparmor/extra-profiles/bwrap-userns-restrict \
/etc/apparmor.d/bwrap-userns-restrict
sudo apparmor_parser -r /etc/apparmor.d/bwrap-userns-restrict
Windows needs no additional sandbox package. MeshProbe creates a fresh AppContainer profile for each episode and puts the agent in a constrained Job Object. Install the pinned Blender release from an elevated PowerShell prompt:
choco install blender --version=5.2.0 --yes
Install the locked Python environment and run the test suite:
uv sync
uv run meshprobe schema
uv run pytest
Sessions and lifecycle commands
MeshProbe stores session data in the current project's .meshprobe directory by default. Use --workspace to choose another project root and -s/--session to switch sessions.
The lifecycle commands have deliberately different failure and persistence semantics:
| Command | Renderer shutdown | Checkpoint retained | Daemon | | --- | --- | --- | --- | | close | Graceful, selected session | Yes | Keeps running | | close --all | Graceful, every session | Yes | Stops gracefully | | kill | Immediate, selected session | Last acknowledged state | Keeps running | | kill --all | Immediate process-tree stop | Last acknowledged state | Force-stops | | delete-data | Requires a stopped daemon | Deletes all .meshprobe data | Stays stopped |
Use close at the end of ordinary work. Use kill to test recovery or escape a wedged renderer. Neither command deletes the session: the next inspection operation reopens the source, verifies its hash, and replays the checkpoint. delete-data is the explicit cleanup operation.
Each session contains:
.meshprobe/sessions//
metadata.json # source, status, worker PID
scene.json # complete scene manifest
components.yml # deterministic c1, c2, ... reference index
state.yml # camera, lighting, sparse display/mark overrides
checkpoint.json # acknowledged replay log
events.jsonl # accepted and rejected operations
results/ snapshots/ artifacts/
The CLI and MCP adapter share the same Pydantic operation contracts. Blender remains a separate factory-clean worker, and source files stay untouched. Renders, manifests, traces, and normalized cache entries are derived artifacts.
MCP clients get the same discriminated command schema and result envelope through one meshprobe tool. Start the stdio server with:
uv run meshprobe-mcp
Qualification harness
The evaluation harness runs each agent without network access, with a read-only assigned model, a writable artifact directory, and evaluator-owned traces and render passes. It uses Bubblewrap on Linux and AppContainer plus Job Object limits on Windows. It supports a JSONL command-line protocol and an MCP stdio protocol. Both adapters use the same prompt, command schema, budgets, broker, and answer contract.
Build the released 512-model procedural corpus and the 160-model curated track, then combine and pin them:
uv run meshprobe eval generate .corpora --version procedural-v7
uv run meshprobe eval curated-generate \
evals/curated/catalog.json .cache/meshprobe-curated .corpora \
--build-version curated-v2 --corpus-version curated-tasks-v7
uv run meshprobe eval merge .corpora \
.corpora/procedural-v7 .corpora/curated-tasks-v7 \
--version qualification-v8
uv run meshprobe eval pin \
.corpora/qualification-v8 .corpora/manifests-v8
The resulting release corpus has 672 models, 2,528 episodes, and 672 full-stack investigations. The nested smoke, pull-request, nightly, and release manifests committed under evals/manifests/public/ pin every episode, model, corpus, MeshProbe version, Blender version, importer, and render engine. The curated catalog pins the source commit, download hash, topology hash, license, and attribution for 20 CC0 assets; the build creates eight controlled variants of each three-source inspection assembly.
The manifests committed under evals/manifests/public/ pin qualification-v8, built under the current 2576²/1200² render-resolution defaults; running the commands above reproduces it exactly.
Run a pinned tier with either agent transport:
uv run meshprobe eval run-tier \
.corpora/qualification-v8 evals/manifests/public/smoke.json .runs \
--adapter cli \
--blender /path/to/blender \
--agent-command-json '["/path/to/agent"]'
The CLI agent reads one episode envelope, sends tool_call lines, and finishes with a structured submission. With --adapter mcp, the agent speaks MCP as a client over its standard streams and calls the meshprobe and submit tools. Runs checkpoint after each episode and publish JSON plus Markdown reports split by operation, task family, difficulty, projection, focal-length band, illumination, model source, and failure gate. On Linux the episode envelope uses /workspace/input and /workspace/artifacts paths; on Windows it uses the assigned absolute paths granted to the AppContainer.
To test the packaged wheel instead of the checkout, run the pinned smoke tier through a clean uv environment:
uv run python tools/clean_install_smoke.py \
.corpora/qualification-v8 evals/manifests/public/smoke.json \
.runs/clean-install-smoke
The command records the wheel hash, runtime versions, manifest hash, and qualification report hash in clean-install-report.json.
To migrate existing local datasets without regenerating geometry or task identities:
uv run meshprobe eval migrate .corpora/procedural-v5 .corpora --version procedural-v6
uv run meshprobe eval migrate .corpora/curated-tasks-v5 .corpora \
--version curated-tasks-v6
uv run meshprobe eval migrate .corpora/qualification-v6 .corpora \
--version qualification-v7
uv run meshprobe eval migrate .corpora/private-v7 .corpora \
--version private-v8 --opaque-family opaque_family_v8
eval migrate only accepts a schema-1 or schema-2 source (it upgrades the manifest shape itself); qualification-v7 and its inputs are already schema-3, so migrating past them into the new -v7/-v8 names above is not this command's job. To land on procedural-v7, curated-tasks-v7, or qualification-v8 instead, regenerate a fresh corpus with eval generate/eval curated-generate/eval merge/eval pin (the release-corpus commands earlier in this section) rather than eval migrate.
eval audit-migration verifies that model hashes, episode IDs, evaluator truth, and the full-investigation operation contract survived the migration. Schema-v1 corpora are rejected by the qualification runtime instead of being translated silently.
Every qualification agent runs in the platform sandbox and retains its exact prompt, live protocol stream, and stderr under episodes//evaluator/agent-run/. The same audit artifacts are retained by the ergonomics pilot.
The separate CLI ergonomics pilot pairs 12 basic and 12 intermediate episodes across Claude Opus and Codex Luna (gpt-5.6-luna). It records exposed command trajectories and token accounting; it does not claim access to hidden chain of thought and does not replace release qualification. The harness silently enforces a 768,000-token ceiling on each attempt in addition to its wall-clock limit. On Linux, agents run inside Bubblewrap with only the assigned public model, a clean MeshProbe install, credentials, and their writable attempt directory mounted. Blender is mounted read-only as a runtime dependency. The repository and private evaluator data stay outside the sandbox:
uv run meshprobe eval ergonomics \
.corpora/qualification-v7 .runs/ergonomics-v1
Live provider streams and stderr are saved beneath .runs/ergonomics-v1/attempts///attempt-/; the exact prompt is saved there as prompt.txt. The ergonomics pilot currently runs on Linux; Windows support will use AppContainer isolation and will not fall back to an unsandboxed agent.
The approved session and migration design is in [docs/session-cli-plan.md](docs/session-cli-plan.md). The broader qualification design remains in [docs/plan.md](docs/plan.md).
Release notes are recorded in [CHANGELOG.md](CHANGELOG.md).
License
Apache-2.0.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: pedropaulovc
- Source: pedropaulovc/meshprobe
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.