From metashape-mcp
Scaffolds new Metashape MCP tool modules with correct imports, registration, progress tracking, auto-save, and prerequisite checks. Use when adding tools to metashape-mcp server.
npx claudepluginhub jenkinsm13/claude-plugins --plugin metashape-mcpThis skill uses the workspace's default tool permissions.
Generate a new Metashape MCP tool module or add a tool to an existing module, following all project conventions.
Looks up Metashape Python API parameters, enums, types, and defaults from local reference files when building or fixing MCP tools.
Generates complete Python MCP server project with uv init, mcp[cli], FastMCP, typed tools/resources/prompts, stdio/HTTP transport options, error handling, and testing setup.
Scaffolds complete, runnable MCP servers in TypeScript or Python from tool specifications, with transport config, handlers, and test harness. Use for new projects, migrations to MCP, or prototyping tool surfaces.
Share bugs, ideas, or general feedback.
Generate a new Metashape MCP tool module or add a tool to an existing module, following all project conventions.
Every tool module follows this exact pattern:
"""[Module description] tools."""
import Metashape
from metashape_mcp.utils.bridge import auto_save, get_chunk, get_document
from metashape_mcp.utils.enums import resolve_enum
from metashape_mcp.utils.progress import make_tracking_callback
def register(mcp) -> None:
"""Register [module] tools."""
@mcp.tool()
def tool_name(
param1: str = "default",
param2: int = 1,
) -> dict:
"""One-line description of what this tool does.
Longer explanation if needed. Mention prerequisites
(e.g., "Run match_photos first.").
Args:
param1: Description of param1.
param2: Description of param2.
Returns:
Description of return dict fields.
"""
chunk = get_chunk()
# Or: doc = get_document()
# Prerequisite checks (import from bridge as needed):
# require_tie_points(chunk)
# require_model(chunk)
# require_depth_maps(chunk)
# require_point_cloud(chunk)
# Resolve enums for Metashape API parameters:
# resolved = resolve_enum("category", param1)
# Progress callback for long operations:
cb = make_tracking_callback("Operation name")
# Call Metashape API:
chunk.someMethod(
param1=param1,
param2=param2,
progress=cb,
)
# Always auto-save after state-mutating operations:
auto_save()
return {
"status": "operation_complete",
"key_metric": some_value,
}
Before writing a tool, verify ALL of these:
async def. All tools are plain def. Metashape API is not thread-safe.Context parameter — Never import or use from mcp.server.fastmcp import Context.get_chunk() / get_document() — Never access Metashape.app.document directly.resolve_enum() — For all Metashape enum parameters. Check utils/enums.py for existing mappings, add new ones there.make_tracking_callback() — For any operation that takes a progress parameter.auto_save() — After every state-mutating operation. Import from utils.bridge.require_tie_points(), require_model(), require_depth_maps(), require_point_cloud() before operations that need them.dict (or list[dict]). Include actionable metrics.keep_keypoints=True overrides Metashape's False).src/metashape_mcp/tools/@mcp.tool() function inside the existing register(mcp) functionsrc/metashape_mcp/tools/new_module.pysrc/metashape_mcp/tools/__init__.py:
from . import new_module
# In the register_all function:
new_module.register(mcp)
If the tool needs a new enum category, add it to src/metashape_mcp/utils/enums.py:
"new_category": {
"option_a": Metashape.SomeEnum.OptionA,
"option_b": Metashape.SomeEnum.OptionB,
},
Then use: resolved = resolve_enum("new_category", user_string)
Read-only tool (no auto_save needed):
@mcp.tool()
def get_something_stats() -> dict:
chunk = get_chunk()
require_model(chunk)
return {"faces": len(chunk.model.faces)}
Tool with optional filtering by class:
@mcp.tool()
def build_something(classes: list[int] | None = None) -> dict:
kwargs = {"progress": cb}
if classes is not None:
kwargs["classes"] = classes
chunk.buildSomething(**kwargs)
Tool that wraps a long operation:
cb = make_tracking_callback("Building thing")
chunk.buildThing(progress=cb)
auto_save()