MCP guide

Drive meshcheck from Claude Code, Claude Desktop, Cursor, or any MCP client.

meshcheck-mcp is a local-first Model Context Protocol server. It lets any MCP client validate, render, and inspect GLB/glTF models through the meshcheck API. It reads models straight off disk by path — an agent that just generated a model hands over a filename, not bytes. All analysis runs server-side; the package is a thin, faithful client that passes reports through verbatim and adds zero telemetry.

Register

The server needs a meshcheck API key (mc_live_...) in its environment.

Claude Code

claude mcp add meshcheck -s project \
  -e MESHCHECK_API_KEY=mc_live_... \
  -- npx -y meshcheck-mcp

Any MCP config

{
  "mcpServers": {
    "meshcheck": {
      "command": "npx",
      "args": ["-y", "meshcheck-mcp"],
      "env": { "MESHCHECK_API_KEY": "mc_live_..." }
    }
  }
}

Configuration

Env var Required Default Purpose
MESHCHECK_API_KEY yes Your key. The server exits with a clear message if it is missing.
MESHCHECK_API_URL no https://api.meshcheck.dev/v1 Override for staging or self-hosted.

Tools

Tool Deterministic What it does
validate_model yes Runs the checks and returns the full report JSON with a pass/warn/fail rollup.
render_model yes Renders stills with the fixed studio rig; returns the render JSON plus the first few stills inline.
inspect_model no Asks a vision model a semantic question. An opinion surface, priced and isolated separately.
get_report yes Re-fetches a stored report by id (free).

Every tool takes either a local path or a public url (exactly one). Large files (≥ ~4.4 MB) go through the presigned upload flow automatically; async jobs (turntables, very large models) are polled internally, so you always get the finished report, never a job envelope.

validate_model

validate_model({
  path?: string,            // local file path (read + uploaded for you)
  url?: string,             // or a public URL
  profile?: "web" | "mobile" | "pc" | "hero",
  overrides?: { [param: string]: number },
  checks_only?: boolean     // skip rendering for faster results
})

Returns the full report JSON: verdict, per-check measured/threshold/status, stats, and (unless checks_only) screenshots.

render_model

render_model({
  path?: string, url?: string,
  angles?: { rv: number, rh: number }[],
  size?: number,
  turntable?: { frames?: number, size?: number, format?: "gif" }
})

Returns the render JSON (signed screenshot URLs + stats) and, inline, the first up to three stills so the agent can look at the model immediately.

inspect_model

inspect_model({
  path?: string, url?: string,
  check: "VIS-001" | "VIS-002" | "VIS-003",
  prompt?: string,     // VIS-001
  question?: string    // VIS-003
})

Non-deterministic — a vision model’s opinion, not a measurement. Use validate_model for anything measurable.

Errors

Errors pass through from the API verbatim as structured JSON, with the tool result flagged isError. The MCP layer adds no interpretation:

{ "error": { "code": "INSUFFICIENT_CREDITS", "message": "...", "detail": { "balance": 0, "needed": 2 } } }

Client-side failures (a missing file, a file larger than your plan allows) use the same envelope shape with codes like FILE_NOT_FOUND and FILE_TOO_LARGE.

The loop

1. Your agent generates model.glb on disk.
2. validate_model({ path: "model.glb", profile: "web" })
   → verdict "fail", PERF-001 fail: 48,231 triangles exceeds budget of 25,000.
3. Your agent regenerates with a lower triangle target.
4. validate_model({ path: "model.glb", profile: "web" })
   → verdict "pass".

See the Meshy and Tripo cookbooks for full generate → validate → fix transcripts.