feat: Add tool annotations for improved LLM tool understanding

Add readOnlyHint, destructiveHint, and title annotations to all tools
to help LLMs better understand tool behavior and make safer decisions.

Changes:
- Added destructiveHint: true to tools that modify data
- Added title annotations for human-readable display (e.g., "Find Symbol")
- Fixed memory tools (WriteMemoryTool, DeleteMemoryTool, EditMemoryTool)
  to correctly inherit ToolMarkerCanEdit, ensuring they get destructiveHint: true

This improves tool safety metadata for MCP clients by:
- Helping LLMs distinguish read-only from destructive operations
- Providing human-readable titles for tool display
- Correctly categorizing all memory-modifying tools as destructive

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
triepod-aiandClaude committed 2025-12-21 13:09:40 -06:00
1 parent 5b730baf07
commit 61bb9b85ee
2 files changed
+15 -6

No files matched your search

+11 -2
View File
@@ -215,7 +215,16 @@ class SerenaMCPFactory:
def execute_fn(**kwargs) -> str: # type: ignore def execute_fn(**kwargs) -> str: # type: ignore
return tool.apply_ex(log_call=True, catch_exceptions=True, **kwargs) return tool.apply_ex(log_call=True, catch_exceptions=True, **kwargs)
annotations = ToolAnnotations(readOnlyHint=not tool.can_edit()) # Generate human-readable title from snake_case tool name
tool_title = " ".join(word.capitalize() for word in func_name.split("_"))
# Create annotations with appropriate hints based on tool capabilities
can_edit = tool.can_edit()
annotations = ToolAnnotations(
title=tool_title,
readOnlyHint=not can_edit,
destructiveHint=can_edit,
)
return MCPTool( return MCPTool(
fn=execute_fn, fn=execute_fn,
@@ -226,7 +235,7 @@ class SerenaMCPFactory:
is_async=is_async, is_async=is_async,
context_kwarg=None, context_kwarg=None,
annotations=annotations, annotations=annotations,
title=None, title=tool_title,
) )
@abstractmethod @abstractmethod
+4 -4
View File
@@ -1,9 +1,9 @@
from typing import Literal from typing import Literal
from serena.tools import ReplaceContentTool, Tool from serena.tools import ReplaceContentTool, Tool, ToolMarkerCanEdit
class WriteMemoryTool(Tool): class WriteMemoryTool(Tool, ToolMarkerCanEdit):
""" """
Writes a named memory (for future reference) to Serena's project-specific memory store. Writes a named memory (for future reference) to Serena's project-specific memory store.
""" """
@@ -52,7 +52,7 @@ class ListMemoriesTool(Tool):
return self._to_json(self.memories_manager.list_memories()) return self._to_json(self.memories_manager.list_memories())
class DeleteMemoryTool(Tool): class DeleteMemoryTool(Tool, ToolMarkerCanEdit):
""" """
Deletes a memory from Serena's project-specific memory store. Deletes a memory from Serena's project-specific memory store.
""" """
@@ -66,7 +66,7 @@ class DeleteMemoryTool(Tool):
return self.memories_manager.delete_memory(memory_file_name) return self.memories_manager.delete_memory(memory_file_name)
class EditMemoryTool(Tool): class EditMemoryTool(Tool, ToolMarkerCanEdit):
def apply( def apply(
self, self,
memory_file_name: str, memory_file_name: str,