Skip to content

Commit e4f84df

Browse files
committed
Merge branch 'fix/text-editor/improve-error-handling' into develop
2 parents 23eef44 + 6dcc5de commit e4f84df

8 files changed

+184
-748
lines changed

src/mcp_text_editor/errors.py

-99
This file was deleted.

src/mcp_text_editor/handlers/base.py

+2-69
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,11 @@
11
"""Base handler for MCP Text Editor."""
22

3-
from functools import wraps
4-
from typing import Any, Dict, Sequence, TypeVar
3+
from typing import Any, Dict, Sequence
54

65
from mcp.types import TextContent, Tool
76

8-
from ..errors import MCPError, InternalError, ValidationError
97
from ..text_editor import TextEditor
108

11-
T = TypeVar("T")
12-
13-
14-
def handle_errors(func):
15-
"""Decorator to handle errors in handler methods."""
16-
17-
@wraps(func)
18-
async def wrapper(*args, **kwargs) -> Sequence[TextContent]:
19-
try:
20-
return await func(*args, **kwargs)
21-
except MCPError as e:
22-
# Known application errors
23-
return [TextContent(text=str(e.to_dict()))]
24-
except Exception as e:
25-
# Unexpected errors
26-
internal_error = InternalError(
27-
message="An unexpected error occurred",
28-
details={"error": str(e), "type": e.__class__.__name__},
29-
)
30-
return [TextContent(text=str(internal_error.to_dict()))]
31-
32-
return wrapper
33-
349

3510
class BaseHandler:
3611
"""Base class for handlers."""
@@ -42,52 +17,10 @@ def __init__(self, editor: TextEditor | None = None):
4217
"""Initialize the handler."""
4318
self.editor = editor if editor is not None else TextEditor()
4419

45-
def validate_arguments(self, arguments: Dict[str, Any]) -> None:
46-
"""Validate the input arguments.
47-
48-
Args:
49-
arguments: The arguments to validate
50-
51-
Raises:
52-
ValidationError: If the arguments are invalid
53-
"""
54-
raise NotImplementedError
55-
5620
def get_tool_description(self) -> Tool:
5721
"""Get the tool description."""
5822
raise NotImplementedError
5923

60-
@handle_errors
6124
async def run_tool(self, arguments: Dict[str, Any]) -> Sequence[TextContent]:
62-
"""Execute the tool with given arguments.
63-
64-
This method is decorated with handle_errors to provide consistent
65-
error handling across all handlers.
66-
67-
Args:
68-
arguments: The arguments for the tool
69-
70-
Returns:
71-
Sequence[TextContent]: The tool's output
72-
73-
Raises:
74-
MCPError: For known application errors
75-
Exception: For unexpected errors
76-
"""
77-
# Validate arguments before execution
78-
self.validate_arguments(arguments)
79-
return await self._execute_tool(arguments)
80-
81-
async def _execute_tool(self, arguments: Dict[str, Any]) -> Sequence[TextContent]:
82-
"""Internal method to execute the tool.
83-
84-
This should be implemented by each handler to provide the actual
85-
tool functionality.
86-
87-
Args:
88-
arguments: The validated arguments for the tool
89-
90-
Returns:
91-
Sequence[TextContent]: The tool's output
92-
"""
25+
"""Execute the tool with given arguments."""
9326
raise NotImplementedError

src/mcp_text_editor/handlers/delete_text_file_contents.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class DeleteTextFileContentsHandler(BaseHandler):
1818
"""Handler for deleting content from a text file."""
1919

2020
name = "delete_text_file_contents"
21-
description = "Delete specified content ranges from a text file. The file must exist. File paths must be absolute. You need to provide the file_hash comes from get_text_file_contents." # noqa: E501
21+
description = "Delete specified content ranges from a text file. The file must exist. File paths must be absolute. You need to provide the file_hash comes from get_text_file_contents."
2222

2323
def get_tool_description(self) -> Tool:
2424
"""Get the tool description."""
@@ -34,7 +34,7 @@ def get_tool_description(self) -> Tool:
3434
},
3535
"file_hash": {
3636
"type": "string",
37-
"description": "Hash of the file contents for concurrency control. it should be matched with the file_hash when get_text_file_contents is called.", # noqa: E501
37+
"description": "Hash of the file contents for concurrency control. it should be matched with the file_hash when get_text_file_contents is called.",
3838
},
3939
"ranges": {
4040
"type": "array",
@@ -52,7 +52,7 @@ def get_tool_description(self) -> Tool:
5252
},
5353
"range_hash": {
5454
"type": "string",
55-
"description": "Hash of the content being deleted. it should be matched with the range_hash when get_text_file_contents is called with the same range.", # noqa: E501
55+
"description": "Hash of the content being deleted. it should be matched with the range_hash when get_text_file_contents is called with the same range.",
5656
},
5757
},
5858
"required": ["start", "range_hash"],

src/mcp_text_editor/handlers/insert_text_file_contents.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class InsertTextFileContentsHandler(BaseHandler):
1717
"""Handler for inserting content before or after a specific line in a text file."""
1818

1919
name = "insert_text_file_contents"
20-
description = "Insert content before or after a specific line in a text file. Uses hash-based validation for concurrency control. You need to provide the file_hash comes from get_text_file_contents." # noqa: E501
20+
description = "Insert content before or after a specific line in a text file. Uses hash-based validation for concurrency control. You need to provide the file_hash comes from get_text_file_contents."
2121

2222
def get_tool_description(self) -> Tool:
2323
"""Get the tool description."""
@@ -33,7 +33,7 @@ def get_tool_description(self) -> Tool:
3333
},
3434
"file_hash": {
3535
"type": "string",
36-
"description": "Hash of the file contents for concurrency control. it should be matched with the file_hash when get_text_file_contents is called.", # noqa: E501
36+
"description": "Hash of the file contents for concurrency control. it should be matched with the file_hash when get_text_file_contents is called.",
3737
},
3838
"contents": {
3939
"type": "string",

0 commit comments

Comments
 (0)