feat: Add tool annotations for improved LLM tool understanding#166
feat: Add tool annotations for improved LLM tool understanding#166bryankthompson wants to merge 3 commits intoahujasid:mainfrom
Conversation
📝 WalkthroughWalkthroughUpdated the Changes
Sequence Diagram(s)(Skipped — changes are metadata-only decorator updates without new multi-component control flow.) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Compliance Guide 🔍Below is a summary of compliance checks for this PR:
Compliance status legend🟢 - Fully Compliant🟡 - Partial Compliant 🔴 - Not Compliant ⚪ - Requires Further Human Verification 🏷️ - Compliance label |
|||||||||||||||||||||||
PR Code Suggestions ✨Explore these optional code suggestions:
|
|||||||||
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/blender_mcp/server.py (1)
881-881: Pre-existing bug: incorrect variable reference in URL validation.Line 881 validates
input_image_pathsinstead ofinput_image_urls. This causes the URL validation logic to incorrectly reference the wrong parameter, which would fail wheninput_image_urlsis provided andinput_image_pathsis None.🔎 Proposed fix
- if not all(urlparse(i) for i in input_image_paths): + if not all(urlparse(i) for i in input_image_urls): return "Error: not all image URLs are valid!"Note: This is a pre-existing bug, not introduced by this PR, but should be addressed.
🧹 Nitpick comments (1)
src/blender_mcp/server.py (1)
991-996: Consider adding telemetry decorators for consistency.The four Hunyuan3D tools (
get_hunyuan3d_status,generate_hunyuan3d_model,poll_hunyuan_job_status,import_generated_asset_hunyuan) are missing the@telemetry_tooldecorator that all other 17 tools have. Adding these decorators would provide consistent usage tracking across all tools.🔎 Proposed additions
Add the telemetry decorators before the MCP tool decorators:
+@telemetry_tool("get_hunyuan3d_status") @mcp.tool( annotations=ToolAnnotations(+@telemetry_tool("generate_hunyuan3d_model") @mcp.tool( annotations=ToolAnnotations(+@telemetry_tool("poll_hunyuan_job_status") @mcp.tool( annotations=ToolAnnotations(+@telemetry_tool("import_generated_asset_hunyuan") @mcp.tool( annotations=ToolAnnotations(Also applies to: 1013-1018, 1055-1060, 1089-1094
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (2)
pyproject.toml(1 hunks)src/blender_mcp/server.py(22 hunks)
🧰 Additional context used
🪛 Ruff (0.14.8)
src/blender_mcp/server.py
997-997: Unused function argument: ctx
(ARG001)
1020-1020: Unused function argument: ctx
(ARG001)
1021-1021: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
1022-1022: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
🔇 Additional comments (3)
src/blender_mcp/server.py (2)
3-3: LGTM!The import of
ToolAnnotationsfrommcp.typesis correct and necessary for adding tool annotations.
256-261: LGTM! Annotations correctly classify tool behavior.All 21 tool annotations are correctly applied:
- 12 read-only tools properly marked with
readOnlyHint=True(query operations)- 9 destructive tools properly marked with
destructiveHint=True(modification operations)- Titles provide clear, human-readable descriptions
The semantic distinction between read-only and destructive operations will help LLMs make safer tool execution decisions.
Also applies to: 275-280, 299-304, 348-353, 371-376, 409-414, 464-469, 521-526, 586-591, 610-615, 636-641, 660-665, 742-747, 800-805, 842-847, 904-909, 953-958, 991-996, 1013-1018, 1055-1060, 1089-1094
pyproject.toml (1)
17-17: The dependency constraint is justified.MCP version 1.8.0 was released on May 8, 2025 and ToolAnnotations is supported in mcp.types and can be used with the @mcp.tool decorator. The version bump from >=1.3.0 to >=1.8.0 is appropriate for this feature requirement.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/blender_mcp/server.py (1)
880-883: Critical bug: wrong variable in URL validation.Line 881 validates URLs but incorrectly iterates over
input_image_pathsinstead ofinput_image_urls. This bug exists in the current code and is not introduced by this PR, but should be fixed.🔎 Proposed fix
elif input_image_urls is not None: - if not all(urlparse(i) for i in input_image_paths): + if not all(urlparse(i) for i in input_image_urls): return "Error: not all image URLs are valid!" images = input_image_urls.copy()
🧹 Nitpick comments (1)
src/blender_mcp/server.py (1)
1023-1024: Consider explicit Optional type annotations.Per PEP 484, parameters with
Nonedefaults should use explicit union syntax:str | Nonerather than implicitOptional.🔎 Proposed fix
- text_prompt: str = None, - input_image_url: str = None + text_prompt: str | None = None, + input_image_url: str | None = None
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/blender_mcp/server.py(22 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: cuericlee
Repo: ahujasid/blender-mcp PR: 102
File: src/blender_mcp/server.py:527-534
Timestamp: 2025-04-16T11:49:00.500Z
Learning: For the Blender MCP codebase, parameters with mutable default values that aren't actively used don't need immediate refactoring and can be marked with TODOs for future improvement.
🧬 Code graph analysis (1)
src/blender_mcp/server.py (2)
src/blender_mcp/telemetry_decorator.py (1)
telemetry_tool(16-65)addon.py (1)
get_hunyuan3d_status(1707-1751)
🪛 Ruff (0.14.8)
src/blender_mcp/server.py
998-998: Unused function argument: ctx
(ARG001)
1022-1022: Unused function argument: ctx
(ARG001)
1023-1023: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
1024-1024: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
🔇 Additional comments (6)
src/blender_mcp/server.py (6)
3-3: LGTM!The import is clean and necessary for the ToolAnnotations used throughout the file.
256-261: LGTM! Read-only hints are correctly applied.All 12 tools marked with
readOnlyHint=Trueare appropriately classified—they perform read operations (status checks, queries, searches, polling) without modifying the Blender scene or external state.Also applies to: 275-280, 299-304, 371-376, 409-414, 586-591, 610-615, 636-641, 660-665, 904-909, 992-997, 1058-1063
348-353: LGTM! Destructive hints are correctly applied.All 9 tools marked with
destructiveHint=Trueare appropriately classified—they perform state-changing operations (executing code, importing assets, modifying scene objects, generating models).Also applies to: 464-469, 521-526, 742-747, 800-805, 842-847, 953-958, 1015-1020, 1093-1098
1003-1003: LGTM! Typo corrected.Good catch fixing "sliently" to "silently" in the docstring.
1027-1030: LGTM! Docstring improved.The clarification that the function accepts "either text description, image reference, or both" better documents the function's capabilities.
3-3: ToolAnnotations is supported in MCP SDK 1.8.0+.The
readOnlyHintproperty is available in ToolAnnotations, and thedestructiveHintproperty is also present. The import ofToolAnnotationsfrommcp.typesis correct and compatible with the dependency bump to >=1.8.0.
|
After further testing, I noticed This tool modifies the Blender scene in memory, but changes aren't persisted until the .blend file is explicitly saved. Per the MCP spec, Suggested change: @mcp.tool(
annotations=ToolAnnotations(
title="Set Texture",
),
)The download/import/generate tools are correctly marked as destructive since they write to disk or call external APIs.
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/blender_mcp/server.py (1)
1022-1023: Fix implicitOptionaltype hints.The parameters use implicit
Optional(= None without| None), which is deprecated per PEP 484. Use explicit union syntax for proper type checking.🔎 Proposed fix
def generate_hunyuan3d_model( ctx: Context, - text_prompt: str = None, - input_image_url: str = None + text_prompt: str | None = None, + input_image_url: str | None = None ) -> str:
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/blender_mcp/server.py
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: cuericlee
Repo: ahujasid/blender-mcp PR: 102
File: src/blender_mcp/server.py:527-534
Timestamp: 2025-04-16T11:49:00.500Z
Learning: For the Blender MCP codebase, parameters with mutable default values that aren't actively used don't need immediate refactoring and can be marked with TODOs for future improvement.
🧬 Code graph analysis (1)
src/blender_mcp/server.py (2)
src/blender_mcp/telemetry_decorator.py (1)
telemetry_tool(16-65)addon.py (1)
get_hunyuan3d_status(1707-1751)
🪛 Ruff (0.14.10)
src/blender_mcp/server.py
997-997: Unused function argument: ctx
(ARG001)
1021-1021: Unused function argument: ctx
(ARG001)
1022-1022: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
1023-1023: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
🔇 Additional comments (5)
src/blender_mcp/server.py (5)
3-3: LGTM: Import addition is correct.The ToolAnnotations import is properly placed and necessary for the annotation functionality added throughout the file.
256-261: LGTM: Read-only annotations are correctly applied.All 12 tools marked with
readOnlyHint=Trueare query or status-check operations that don't modify state. The annotations accurately reflect the non-destructive nature of these operations.Also applies to: 275-280, 299-304, 371-376, 409-414, 585-590, 609-614, 635-640, 659-664, 903-908, 990-996, 1056-1062
348-353: LGTM: Destructive annotations are semantically correct.All 8 tools marked with
destructiveHint=Trueperform operations that write to persistent storage (downloading assets, importing models, executing arbitrary code). Theexecute_blender_codetool is appropriately marked destructive as a defensive default since it can execute arbitrary Python code.Also applies to: 464-469, 741-746, 799-804, 841-846, 952-957, 1013-1019, 1091-1097
521-525: LGTM: Correct annotation for in-memory operation.The title-only annotation for
set_textureis correct. Per the MCP spec,destructiveHintshould be reserved for operations that write to persistent storage. Sinceset_textureonly modifies the Blender scene in memory and doesn't persist changes to disk, the absence of hints is appropriate.
1002-1002: LGTM: Documentation improvements.The typo fix ("sliently" → "silently") and docstring formatting improvements enhance code quality without affecting functionality.
Also applies to: 1026-1034
Add readOnlyHint and destructiveHint annotations to all 21 tools to help LLMs better understand tool behavior and make safer decisions. Changes: - Added readOnlyHint: true to 12 read-only tools (get_*, search_*, poll_*) - Added destructiveHint: true to 9 tools that modify data (download_*, execute_*, generate_*, import_*, set_*) - Added title annotations for human-readable display - Bump MCP SDK from >=1.3.0 to >=1.8.0 for annotation support - Import ToolAnnotations from mcp.types This improves tool safety metadata for MCP clients. Co-Authored-By: Claude <[email protected]>
Add @telemetry_tool decorator to all 4 Hunyuan3D tools for consistent usage tracking: - get_hunyuan3d_status - generate_hunyuan3d_model - poll_hunyuan_job_status - import_generated_asset_hunyuan Addresses code review feedback from qodo-code-review and coderabbitai. Co-Authored-By: Claude <[email protected]>
set_texture modifies the Blender scene in memory but changes aren't persisted until the .blend file is explicitly saved. Per the MCP spec, destructiveHint is specifically for operations that write to persistent storage. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
f99b635 to
3f6a8c9
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI Agents
In @src/blender_mcp/server.py:
- Around line 788-793: The download_sketchfab_model tool is missing the
@telemetry_tool decorator; add @telemetry_tool("download_sketchfab_model")
immediately above the @mcp.tool(...) decorator on the download_sketchfab_model
function to enable telemetry, and ensure telemetry_tool is imported (or
exported) from the telemetry module where other tools use it so the decorator
resolves correctly.
🧹 Nitpick comments (1)
src/blender_mcp/server.py (1)
1099-1100: Consider using explicit optional type annotations.The function parameters use implicit
Optional(e.g.,text_prompt: str = None). PEP 484 recommends explicit optional types:text_prompt: str | None = None.🔎 Proposed refinement
def generate_hunyuan3d_model( ctx: Context, - text_prompt: str = None, - input_image_url: str = None + text_prompt: str | None = None, + input_image_url: str | None = None ) -> str:
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (2)
pyproject.tomlsrc/blender_mcp/server.py
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: cuericlee
Repo: ahujasid/blender-mcp PR: 102
File: src/blender_mcp/server.py:527-534
Timestamp: 2025-04-16T11:49:00.500Z
Learning: For the Blender MCP codebase, parameters with mutable default values that aren't actively used don't need immediate refactoring and can be marked with TODOs for future improvement.
🧬 Code graph analysis (1)
src/blender_mcp/server.py (2)
src/blender_mcp/telemetry_decorator.py (1)
telemetry_tool(16-65)addon.py (1)
get_hunyuan3d_status(1897-1941)
🪛 Ruff (0.14.10)
src/blender_mcp/server.py
1074-1074: Unused function argument: ctx
(ARG001)
1098-1098: Unused function argument: ctx
(ARG001)
1099-1099: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
1100-1100: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
🔇 Additional comments (5)
src/blender_mcp/server.py (4)
3-3: LGTM!The
ToolAnnotationsimport is correctly added to support the tool metadata annotations applied throughout the file.
256-261: LGTM! Annotations correctly applied.The
ToolAnnotationsmetadata is correctly applied across the tools:
- Read-only tools (
get_scene_info,get_object_info,get_viewport_screenshot) appropriately marked withreadOnlyHint=True- Destructive tools (
execute_blender_code,download_polyhaven_asset) appropriately marked withdestructiveHint=Trueset_texturecorrectly uses title-only annotation since it modifies scene state in memory but doesn't persist to storageThe annotations provide clear semantic hints for LLM tool understanding without changing function behavior.
Also applies to: 275-280, 299-304, 348-353, 464-469, 521-525
1079-1079: LGTM! Documentation improvements.The typo fix ("sliently" → "silently") and docstring formatting improvements enhance code quality.
Also applies to: 1103-1103
371-376: LGTM! All remaining tool annotations correctly applied.The annotations for all remaining tools are consistent and semantically correct:
- Query/search/status/poll operations appropriately marked with
readOnlyHint=True- Download/generate/import operations appropriately marked with
destructiveHint=TrueThe annotations align with the tool behaviors and follow the pattern established throughout the codebase.
Also applies to: 409-414, 585-590, 609-614, 635-640, 659-664, 740-746, 876-881, 918-923, 980-985, 1029-1034, 1067-1073, 1090-1096, 1133-1139, 1168-1174
pyproject.toml (1)
17-17: The dependency constraint correctly requiresmcp[cli]>=1.8.0, which introducedToolAnnotationssupport.
| @mcp.tool( | ||
| annotations=ToolAnnotations( | ||
| title="Download Sketchfab Model", | ||
| destructiveHint=True, | ||
| ), | ||
| ) |
There was a problem hiding this comment.
Missing telemetry decorator.
The download_sketchfab_model function is missing the @telemetry_tool("download_sketchfab_model") decorator that all other tool functions have. This means telemetry tracking won't be recorded for this tool, creating an inconsistency.
🔎 Proposed fix
+@telemetry_tool("download_sketchfab_model")
@mcp.tool(
annotations=ToolAnnotations(
title="Download Sketchfab Model",🤖 Prompt for AI Agents
In @src/blender_mcp/server.py around lines 788 - 793, The
download_sketchfab_model tool is missing the @telemetry_tool decorator; add
@telemetry_tool("download_sketchfab_model") immediately above the @mcp.tool(...)
decorator on the download_sketchfab_model function to enable telemetry, and
ensure telemetry_tool is imported (or exported) from the telemetry module where
other tools use it so the decorator resolves correctly.
User description
Summary
Adds MCP tool annotations (
readOnlyHint,destructiveHint,title) to all 21 tools to help LLMs better understand tool behavior and make safer decisions about tool execution.Changes
Added
readOnlyHint: trueto 12 read-only tools:get_scene_info,get_object_info,get_viewport_screenshotget_polyhaven_categories,search_polyhaven_assets,get_polyhaven_statusget_hyper3d_status,get_sketchfab_status,search_sketchfab_modelspoll_rodin_job_status,get_hunyuan3d_status,poll_hunyuan_job_statusAdded
destructiveHint: trueto 9 tools that modify scene/data:execute_blender_code,download_polyhaven_asset,set_texturedownload_sketchfab_modelgenerate_hyper3d_model_via_text,generate_hyper3d_model_via_images,import_generated_assetgenerate_hunyuan3d_model,import_generated_asset_hunyuanAdded
titleannotations for human-readable displayBump MCP SDK dependency from
>=1.3.0to>=1.8.0for annotation supportImport
ToolAnnotationsfrommcp.typesWhy This Matters
readOnlyHint: truetells the LLM a tool is safe to call without side effectsdestructiveHint: truesignals the LLM should be more careful before executingTesting
uv syncfrom blender_mcp.server import mcpmcp._tool_manager._toolsBefore/After
Before:
After:
🤖 Generated with Claude Code
PR Type
Enhancement
Description
Add
ToolAnnotationsto all 21 MCP tools with semantic metadatareadOnlyHint=TruedestructiveHint=TruetitleannotationsBump MCP SDK dependency from
>=1.3.0to>=1.8.0for annotation supportImprove LLM tool understanding and enable safer execution decisions
Diagram Walkthrough
File Walkthrough
server.py
Add ToolAnnotations to all 21 MCP toolssrc/blender_mcp/server.py
ToolAnnotationsfrommcp.typesmoduleToolAnnotationswithtitleandreadOnlyHint=Trueto 12 read-onlytools:
get_scene_info,get_object_info,get_viewport_screenshot,get_polyhaven_categories,search_polyhaven_assets,get_polyhaven_status,get_hyper3d_status,get_sketchfab_status,search_sketchfab_models,poll_rodin_job_status,get_hunyuan3d_status,poll_hunyuan_job_statusToolAnnotationswithtitleanddestructiveHint=Trueto 9destructive tools:
execute_blender_code,download_polyhaven_asset,set_texture,download_sketchfab_model,generate_hyper3d_model_via_text,generate_hyper3d_model_via_images,import_generated_asset,generate_hunyuan3d_model,import_generated_asset_hunyuanpyproject.toml
Bump MCP SDK dependency versionpyproject.toml
>=1.3.0to>=1.8.0to support toolannotations feature
Summary by CodeRabbit
Chores
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.