pomera-ai-commander 0.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +105 -680
- package/bin/pomera-ai-commander.js +62 -62
- package/core/__init__.py +65 -65
- package/core/app_context.py +482 -482
- package/core/async_text_processor.py +421 -421
- package/core/backup_manager.py +655 -655
- package/core/backup_recovery_manager.py +1033 -1033
- package/core/content_hash_cache.py +508 -508
- package/core/context_menu.py +313 -313
- package/core/data_validator.py +1066 -1066
- package/core/database_connection_manager.py +744 -744
- package/core/database_curl_settings_manager.py +608 -608
- package/core/database_promera_ai_settings_manager.py +446 -446
- package/core/database_schema.py +411 -411
- package/core/database_schema_manager.py +395 -395
- package/core/database_settings_manager.py +1507 -1507
- package/core/database_settings_manager_interface.py +456 -456
- package/core/dialog_manager.py +734 -734
- package/core/efficient_line_numbers.py +510 -510
- package/core/error_handler.py +746 -746
- package/core/error_service.py +431 -431
- package/core/event_consolidator.py +511 -511
- package/core/mcp/__init__.py +43 -43
- package/core/mcp/protocol.py +288 -288
- package/core/mcp/schema.py +251 -251
- package/core/mcp/server_stdio.py +299 -299
- package/core/mcp/tool_registry.py +2372 -2345
- package/core/memory_efficient_text_widget.py +711 -711
- package/core/migration_manager.py +914 -914
- package/core/migration_test_suite.py +1085 -1085
- package/core/migration_validator.py +1143 -1143
- package/core/optimized_find_replace.py +714 -714
- package/core/optimized_pattern_engine.py +424 -424
- package/core/optimized_search_highlighter.py +552 -552
- package/core/performance_monitor.py +674 -674
- package/core/persistence_manager.py +712 -712
- package/core/progressive_stats_calculator.py +632 -632
- package/core/regex_pattern_cache.py +529 -529
- package/core/regex_pattern_library.py +350 -350
- package/core/search_operation_manager.py +434 -434
- package/core/settings_defaults_registry.py +1087 -1087
- package/core/settings_integrity_validator.py +1111 -1111
- package/core/settings_serializer.py +557 -557
- package/core/settings_validator.py +1823 -1823
- package/core/smart_stats_calculator.py +709 -709
- package/core/statistics_update_manager.py +619 -619
- package/core/stats_config_manager.py +858 -858
- package/core/streaming_text_handler.py +723 -723
- package/core/task_scheduler.py +596 -596
- package/core/update_pattern_library.py +168 -168
- package/core/visibility_monitor.py +596 -596
- package/core/widget_cache.py +498 -498
- package/mcp.json +51 -61
- package/package.json +61 -57
- package/pomera.py +7482 -7482
- package/pomera_mcp_server.py +183 -144
- package/requirements.txt +32 -0
- package/tools/__init__.py +4 -4
- package/tools/ai_tools.py +2891 -2891
- package/tools/ascii_art_generator.py +352 -352
- package/tools/base64_tools.py +183 -183
- package/tools/base_tool.py +511 -511
- package/tools/case_tool.py +308 -308
- package/tools/column_tools.py +395 -395
- package/tools/cron_tool.py +884 -884
- package/tools/curl_history.py +600 -600
- package/tools/curl_processor.py +1207 -1207
- package/tools/curl_settings.py +502 -502
- package/tools/curl_tool.py +5467 -5467
- package/tools/diff_viewer.py +1071 -1071
- package/tools/email_extraction_tool.py +248 -248
- package/tools/email_header_analyzer.py +425 -425
- package/tools/extraction_tools.py +250 -250
- package/tools/find_replace.py +1750 -1750
- package/tools/folder_file_reporter.py +1463 -1463
- package/tools/folder_file_reporter_adapter.py +480 -480
- package/tools/generator_tools.py +1216 -1216
- package/tools/hash_generator.py +255 -255
- package/tools/html_tool.py +656 -656
- package/tools/jsonxml_tool.py +729 -729
- package/tools/line_tools.py +419 -419
- package/tools/markdown_tools.py +561 -561
- package/tools/mcp_widget.py +1417 -1417
- package/tools/notes_widget.py +973 -973
- package/tools/number_base_converter.py +372 -372
- package/tools/regex_extractor.py +571 -571
- package/tools/slug_generator.py +310 -310
- package/tools/sorter_tools.py +458 -458
- package/tools/string_escape_tool.py +392 -392
- package/tools/text_statistics_tool.py +365 -365
- package/tools/text_wrapper.py +430 -430
- package/tools/timestamp_converter.py +421 -421
- package/tools/tool_loader.py +710 -710
- package/tools/translator_tools.py +522 -522
- package/tools/url_link_extractor.py +261 -261
- package/tools/url_parser.py +204 -204
- package/tools/whitespace_tools.py +355 -355
- package/tools/word_frequency_counter.py +146 -146
- package/core/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/__pycache__/app_context.cpython-313.pyc +0 -0
- package/core/__pycache__/async_text_processor.cpython-313.pyc +0 -0
- package/core/__pycache__/backup_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/backup_recovery_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/content_hash_cache.cpython-313.pyc +0 -0
- package/core/__pycache__/context_menu.cpython-313.pyc +0 -0
- package/core/__pycache__/data_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/database_connection_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_curl_settings_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_promera_ai_settings_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_schema.cpython-313.pyc +0 -0
- package/core/__pycache__/database_schema_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_settings_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_settings_manager_interface.cpython-313.pyc +0 -0
- package/core/__pycache__/dialog_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/efficient_line_numbers.cpython-313.pyc +0 -0
- package/core/__pycache__/error_handler.cpython-313.pyc +0 -0
- package/core/__pycache__/error_service.cpython-313.pyc +0 -0
- package/core/__pycache__/event_consolidator.cpython-313.pyc +0 -0
- package/core/__pycache__/memory_efficient_text_widget.cpython-313.pyc +0 -0
- package/core/__pycache__/migration_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/migration_test_suite.cpython-313.pyc +0 -0
- package/core/__pycache__/migration_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/optimized_find_replace.cpython-313.pyc +0 -0
- package/core/__pycache__/optimized_pattern_engine.cpython-313.pyc +0 -0
- package/core/__pycache__/optimized_search_highlighter.cpython-313.pyc +0 -0
- package/core/__pycache__/performance_monitor.cpython-313.pyc +0 -0
- package/core/__pycache__/persistence_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/progressive_stats_calculator.cpython-313.pyc +0 -0
- package/core/__pycache__/regex_pattern_cache.cpython-313.pyc +0 -0
- package/core/__pycache__/regex_pattern_library.cpython-313.pyc +0 -0
- package/core/__pycache__/search_operation_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_defaults_registry.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_integrity_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_serializer.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/smart_stats_calculator.cpython-313.pyc +0 -0
- package/core/__pycache__/statistics_update_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/stats_config_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/streaming_text_handler.cpython-313.pyc +0 -0
- package/core/__pycache__/task_scheduler.cpython-313.pyc +0 -0
- package/core/__pycache__/visibility_monitor.cpython-313.pyc +0 -0
- package/core/__pycache__/widget_cache.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/protocol.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/server_stdio.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/tool_registry.cpython-313.pyc +0 -0
- package/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- package/tools/__pycache__/ai_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/ascii_art_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/base64_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/base_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/case_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/column_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/cron_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_history.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_processor.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_settings.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/diff_viewer.cpython-313.pyc +0 -0
- package/tools/__pycache__/email_extraction_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/email_header_analyzer.cpython-313.pyc +0 -0
- package/tools/__pycache__/extraction_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/find_replace.cpython-313.pyc +0 -0
- package/tools/__pycache__/folder_file_reporter.cpython-313.pyc +0 -0
- package/tools/__pycache__/folder_file_reporter_adapter.cpython-313.pyc +0 -0
- package/tools/__pycache__/generator_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/hash_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/html_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/huggingface_helper.cpython-313.pyc +0 -0
- package/tools/__pycache__/jsonxml_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/line_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/list_comparator.cpython-313.pyc +0 -0
- package/tools/__pycache__/markdown_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/mcp_widget.cpython-313.pyc +0 -0
- package/tools/__pycache__/notes_widget.cpython-313.pyc +0 -0
- package/tools/__pycache__/number_base_converter.cpython-313.pyc +0 -0
- package/tools/__pycache__/regex_extractor.cpython-313.pyc +0 -0
- package/tools/__pycache__/slug_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/sorter_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/string_escape_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/text_statistics_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/text_wrapper.cpython-313.pyc +0 -0
- package/tools/__pycache__/timestamp_converter.cpython-313.pyc +0 -0
- package/tools/__pycache__/tool_loader.cpython-313.pyc +0 -0
- package/tools/__pycache__/translator_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/url_link_extractor.cpython-313.pyc +0 -0
- package/tools/__pycache__/url_parser.cpython-313.pyc +0 -0
- package/tools/__pycache__/whitespace_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/word_frequency_counter.cpython-313.pyc +0 -0
package/core/mcp/__init__.py
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
"""
|
|
2
|
-
MCP (Model Context Protocol) Module for Pomera AI Commander
|
|
3
|
-
|
|
4
|
-
This module provides bidirectional MCP functionality:
|
|
5
|
-
1. MCP Client - Connect to external MCP servers (filesystem, GitHub, etc.)
|
|
6
|
-
2. MCP Server - Expose Pomera's text tools to external AI assistants
|
|
7
|
-
|
|
8
|
-
Submodules:
|
|
9
|
-
- schema: Data classes for MCP types (Tool, Resource, Message)
|
|
10
|
-
- protocol: JSON-RPC 2.0 message handling
|
|
11
|
-
- tool_registry: Maps Pomera tools to MCP tool definitions
|
|
12
|
-
- server_stdio: stdio transport for MCP server
|
|
13
|
-
- resource_provider: Exposes tab contents as MCP resources
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
from .schema import (
|
|
17
|
-
MCPMessage,
|
|
18
|
-
MCPTool,
|
|
19
|
-
MCPResource,
|
|
20
|
-
MCPError,
|
|
21
|
-
MCPErrorCode,
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
from .protocol import MCPProtocol
|
|
25
|
-
|
|
26
|
-
from .tool_registry import ToolRegistry, MCPToolAdapter
|
|
27
|
-
|
|
28
|
-
__all__ = [
|
|
29
|
-
# Schema
|
|
30
|
-
"MCPMessage",
|
|
31
|
-
"MCPTool",
|
|
32
|
-
"MCPResource",
|
|
33
|
-
"MCPError",
|
|
34
|
-
"MCPErrorCode",
|
|
35
|
-
# Protocol
|
|
36
|
-
"MCPProtocol",
|
|
37
|
-
# Tool Registry
|
|
38
|
-
"ToolRegistry",
|
|
39
|
-
"MCPToolAdapter",
|
|
40
|
-
]
|
|
41
|
-
|
|
42
|
-
__version__ = "0.1.0"
|
|
43
|
-
|
|
1
|
+
"""
|
|
2
|
+
MCP (Model Context Protocol) Module for Pomera AI Commander
|
|
3
|
+
|
|
4
|
+
This module provides bidirectional MCP functionality:
|
|
5
|
+
1. MCP Client - Connect to external MCP servers (filesystem, GitHub, etc.)
|
|
6
|
+
2. MCP Server - Expose Pomera's text tools to external AI assistants
|
|
7
|
+
|
|
8
|
+
Submodules:
|
|
9
|
+
- schema: Data classes for MCP types (Tool, Resource, Message)
|
|
10
|
+
- protocol: JSON-RPC 2.0 message handling
|
|
11
|
+
- tool_registry: Maps Pomera tools to MCP tool definitions
|
|
12
|
+
- server_stdio: stdio transport for MCP server
|
|
13
|
+
- resource_provider: Exposes tab contents as MCP resources
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from .schema import (
|
|
17
|
+
MCPMessage,
|
|
18
|
+
MCPTool,
|
|
19
|
+
MCPResource,
|
|
20
|
+
MCPError,
|
|
21
|
+
MCPErrorCode,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from .protocol import MCPProtocol
|
|
25
|
+
|
|
26
|
+
from .tool_registry import ToolRegistry, MCPToolAdapter
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
# Schema
|
|
30
|
+
"MCPMessage",
|
|
31
|
+
"MCPTool",
|
|
32
|
+
"MCPResource",
|
|
33
|
+
"MCPError",
|
|
34
|
+
"MCPErrorCode",
|
|
35
|
+
# Protocol
|
|
36
|
+
"MCPProtocol",
|
|
37
|
+
# Tool Registry
|
|
38
|
+
"ToolRegistry",
|
|
39
|
+
"MCPToolAdapter",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
__version__ = "0.1.0"
|
|
43
|
+
|
package/core/mcp/protocol.py
CHANGED
|
@@ -1,288 +1,288 @@
|
|
|
1
|
-
"""
|
|
2
|
-
MCP Protocol Module - JSON-RPC 2.0 message handling
|
|
3
|
-
|
|
4
|
-
This module provides utilities for parsing and creating MCP messages
|
|
5
|
-
following the JSON-RPC 2.0 specification.
|
|
6
|
-
|
|
7
|
-
Features:
|
|
8
|
-
- Parse incoming JSON-RPC messages
|
|
9
|
-
- Create response/error messages
|
|
10
|
-
- Validate message structure
|
|
11
|
-
- Handle message batching
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import json
|
|
15
|
-
import logging
|
|
16
|
-
from typing import Optional, Any, Dict, List, Union
|
|
17
|
-
|
|
18
|
-
from .schema import (
|
|
19
|
-
MCPMessage,
|
|
20
|
-
MCPError,
|
|
21
|
-
MCPErrorCode,
|
|
22
|
-
MCPTool,
|
|
23
|
-
MCPResource,
|
|
24
|
-
MCPToolResult,
|
|
25
|
-
MCPServerCapabilities,
|
|
26
|
-
MCPServerInfo,
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
logger = logging.getLogger(__name__)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class MCPProtocolError(Exception):
|
|
34
|
-
"""Exception raised for protocol-level errors."""
|
|
35
|
-
def __init__(self, code: int, message: str, data: Any = None):
|
|
36
|
-
super().__init__(message)
|
|
37
|
-
self.code = code
|
|
38
|
-
self.message = message
|
|
39
|
-
self.data = data
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class MCPProtocol:
|
|
43
|
-
"""
|
|
44
|
-
MCP Protocol handler for JSON-RPC 2.0 communication.
|
|
45
|
-
|
|
46
|
-
Provides static methods for message parsing, creation, and validation.
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
# Protocol version
|
|
50
|
-
JSONRPC_VERSION = "2.0"
|
|
51
|
-
MCP_PROTOCOL_VERSION = "2024-11-05"
|
|
52
|
-
|
|
53
|
-
@staticmethod
|
|
54
|
-
def parse(data: str) -> MCPMessage:
|
|
55
|
-
"""
|
|
56
|
-
Parse a JSON-RPC message from string.
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
data: JSON string to parse
|
|
60
|
-
|
|
61
|
-
Returns:
|
|
62
|
-
MCPMessage object
|
|
63
|
-
|
|
64
|
-
Raises:
|
|
65
|
-
MCPProtocolError: If parsing fails or message is invalid
|
|
66
|
-
"""
|
|
67
|
-
try:
|
|
68
|
-
obj = json.loads(data)
|
|
69
|
-
except json.JSONDecodeError as e:
|
|
70
|
-
raise MCPProtocolError(
|
|
71
|
-
MCPErrorCode.PARSE_ERROR,
|
|
72
|
-
f"Invalid JSON: {str(e)}"
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
# Validate basic structure
|
|
76
|
-
if not isinstance(obj, dict):
|
|
77
|
-
raise MCPProtocolError(
|
|
78
|
-
MCPErrorCode.INVALID_REQUEST,
|
|
79
|
-
"Message must be a JSON object"
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
# Check JSON-RPC version
|
|
83
|
-
if obj.get("jsonrpc") != MCPProtocol.JSONRPC_VERSION:
|
|
84
|
-
raise MCPProtocolError(
|
|
85
|
-
MCPErrorCode.INVALID_REQUEST,
|
|
86
|
-
f"Invalid JSON-RPC version: {obj.get('jsonrpc')}"
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
return MCPMessage.from_dict(obj)
|
|
90
|
-
|
|
91
|
-
@staticmethod
|
|
92
|
-
def serialize(msg: MCPMessage) -> str:
|
|
93
|
-
"""
|
|
94
|
-
Serialize an MCPMessage to JSON string.
|
|
95
|
-
|
|
96
|
-
Args:
|
|
97
|
-
msg: MCPMessage to serialize
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
JSON string
|
|
101
|
-
"""
|
|
102
|
-
return msg.to_json()
|
|
103
|
-
|
|
104
|
-
@staticmethod
|
|
105
|
-
def create_response(id: int, result: Any) -> MCPMessage:
|
|
106
|
-
"""
|
|
107
|
-
Create a success response message.
|
|
108
|
-
|
|
109
|
-
Args:
|
|
110
|
-
id: Request ID to respond to
|
|
111
|
-
result: Result data
|
|
112
|
-
|
|
113
|
-
Returns:
|
|
114
|
-
MCPMessage response
|
|
115
|
-
"""
|
|
116
|
-
return MCPMessage(id=id, result=result)
|
|
117
|
-
|
|
118
|
-
@staticmethod
|
|
119
|
-
def create_error(id: Optional[int], code: int, message: str, data: Any = None) -> MCPMessage:
|
|
120
|
-
"""
|
|
121
|
-
Create an error response message.
|
|
122
|
-
|
|
123
|
-
Args:
|
|
124
|
-
id: Request ID (can be None for parse errors)
|
|
125
|
-
code: Error code
|
|
126
|
-
message: Error message
|
|
127
|
-
data: Optional additional error data
|
|
128
|
-
|
|
129
|
-
Returns:
|
|
130
|
-
MCPMessage error response
|
|
131
|
-
"""
|
|
132
|
-
return MCPMessage(
|
|
133
|
-
id=id,
|
|
134
|
-
error=MCPError(code=code, message=message, data=data)
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
@staticmethod
|
|
138
|
-
def create_notification(method: str, params: Optional[Dict] = None) -> MCPMessage:
|
|
139
|
-
"""
|
|
140
|
-
Create a notification message (no response expected).
|
|
141
|
-
|
|
142
|
-
Args:
|
|
143
|
-
method: Method name
|
|
144
|
-
params: Optional parameters
|
|
145
|
-
|
|
146
|
-
Returns:
|
|
147
|
-
MCPMessage notification
|
|
148
|
-
"""
|
|
149
|
-
return MCPMessage(method=method, params=params)
|
|
150
|
-
|
|
151
|
-
# =========================================================================
|
|
152
|
-
# MCP-specific response creators
|
|
153
|
-
# =========================================================================
|
|
154
|
-
|
|
155
|
-
@staticmethod
|
|
156
|
-
def create_initialize_response(
|
|
157
|
-
id: int,
|
|
158
|
-
server_info: MCPServerInfo,
|
|
159
|
-
capabilities: MCPServerCapabilities
|
|
160
|
-
) -> MCPMessage:
|
|
161
|
-
"""
|
|
162
|
-
Create response for 'initialize' request.
|
|
163
|
-
|
|
164
|
-
Args:
|
|
165
|
-
id: Request ID
|
|
166
|
-
server_info: Server information
|
|
167
|
-
capabilities: Server capabilities
|
|
168
|
-
|
|
169
|
-
Returns:
|
|
170
|
-
MCPMessage response
|
|
171
|
-
"""
|
|
172
|
-
return MCPProtocol.create_response(id, {
|
|
173
|
-
"protocolVersion": MCPProtocol.MCP_PROTOCOL_VERSION,
|
|
174
|
-
"serverInfo": server_info.to_dict(),
|
|
175
|
-
"capabilities": capabilities.to_dict()
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
@staticmethod
|
|
179
|
-
def create_tools_list_response(id: int, tools: List[MCPTool]) -> MCPMessage:
|
|
180
|
-
"""
|
|
181
|
-
Create response for 'tools/list' request.
|
|
182
|
-
|
|
183
|
-
Args:
|
|
184
|
-
id: Request ID
|
|
185
|
-
tools: List of available tools
|
|
186
|
-
|
|
187
|
-
Returns:
|
|
188
|
-
MCPMessage response
|
|
189
|
-
"""
|
|
190
|
-
return MCPProtocol.create_response(id, {
|
|
191
|
-
"tools": [t.to_dict() for t in tools]
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
@staticmethod
|
|
195
|
-
def create_tools_call_response(id: int, result: MCPToolResult) -> MCPMessage:
|
|
196
|
-
"""
|
|
197
|
-
Create response for 'tools/call' request.
|
|
198
|
-
|
|
199
|
-
Args:
|
|
200
|
-
id: Request ID
|
|
201
|
-
result: Tool execution result
|
|
202
|
-
|
|
203
|
-
Returns:
|
|
204
|
-
MCPMessage response
|
|
205
|
-
"""
|
|
206
|
-
return MCPProtocol.create_response(id, result.to_dict())
|
|
207
|
-
|
|
208
|
-
@staticmethod
|
|
209
|
-
def create_resources_list_response(id: int, resources: List[MCPResource]) -> MCPMessage:
|
|
210
|
-
"""
|
|
211
|
-
Create response for 'resources/list' request.
|
|
212
|
-
|
|
213
|
-
Args:
|
|
214
|
-
id: Request ID
|
|
215
|
-
resources: List of available resources
|
|
216
|
-
|
|
217
|
-
Returns:
|
|
218
|
-
MCPMessage response
|
|
219
|
-
"""
|
|
220
|
-
return MCPProtocol.create_response(id, {
|
|
221
|
-
"resources": [r.to_dict() for r in resources]
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
@staticmethod
|
|
225
|
-
def create_resources_read_response(id: int, contents: List[Dict]) -> MCPMessage:
|
|
226
|
-
"""
|
|
227
|
-
Create response for 'resources/read' request.
|
|
228
|
-
|
|
229
|
-
Args:
|
|
230
|
-
id: Request ID
|
|
231
|
-
contents: List of resource contents
|
|
232
|
-
|
|
233
|
-
Returns:
|
|
234
|
-
MCPMessage response
|
|
235
|
-
"""
|
|
236
|
-
return MCPProtocol.create_response(id, {
|
|
237
|
-
"contents": contents
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
# =========================================================================
|
|
241
|
-
# Error response helpers
|
|
242
|
-
# =========================================================================
|
|
243
|
-
|
|
244
|
-
@staticmethod
|
|
245
|
-
def method_not_found(id: int, method: str) -> MCPMessage:
|
|
246
|
-
"""Create METHOD_NOT_FOUND error response."""
|
|
247
|
-
return MCPProtocol.create_error(
|
|
248
|
-
id,
|
|
249
|
-
MCPErrorCode.METHOD_NOT_FOUND,
|
|
250
|
-
f"Method not found: {method}"
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
@staticmethod
|
|
254
|
-
def invalid_params(id: int, message: str) -> MCPMessage:
|
|
255
|
-
"""Create INVALID_PARAMS error response."""
|
|
256
|
-
return MCPProtocol.create_error(
|
|
257
|
-
id,
|
|
258
|
-
MCPErrorCode.INVALID_PARAMS,
|
|
259
|
-
message
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
@staticmethod
|
|
263
|
-
def tool_not_found(id: int, tool_name: str) -> MCPMessage:
|
|
264
|
-
"""Create TOOL_NOT_FOUND error response."""
|
|
265
|
-
return MCPProtocol.create_error(
|
|
266
|
-
id,
|
|
267
|
-
MCPErrorCode.TOOL_NOT_FOUND,
|
|
268
|
-
f"Tool not found: {tool_name}"
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
@staticmethod
|
|
272
|
-
def resource_not_found(id: int, uri: str) -> MCPMessage:
|
|
273
|
-
"""Create RESOURCE_NOT_FOUND error response."""
|
|
274
|
-
return MCPProtocol.create_error(
|
|
275
|
-
id,
|
|
276
|
-
MCPErrorCode.RESOURCE_NOT_FOUND,
|
|
277
|
-
f"Resource not found: {uri}"
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
@staticmethod
|
|
281
|
-
def internal_error(id: Optional[int], message: str) -> MCPMessage:
|
|
282
|
-
"""Create INTERNAL_ERROR error response."""
|
|
283
|
-
return MCPProtocol.create_error(
|
|
284
|
-
id,
|
|
285
|
-
MCPErrorCode.INTERNAL_ERROR,
|
|
286
|
-
message
|
|
287
|
-
)
|
|
288
|
-
|
|
1
|
+
"""
|
|
2
|
+
MCP Protocol Module - JSON-RPC 2.0 message handling
|
|
3
|
+
|
|
4
|
+
This module provides utilities for parsing and creating MCP messages
|
|
5
|
+
following the JSON-RPC 2.0 specification.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Parse incoming JSON-RPC messages
|
|
9
|
+
- Create response/error messages
|
|
10
|
+
- Validate message structure
|
|
11
|
+
- Handle message batching
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import logging
|
|
16
|
+
from typing import Optional, Any, Dict, List, Union
|
|
17
|
+
|
|
18
|
+
from .schema import (
|
|
19
|
+
MCPMessage,
|
|
20
|
+
MCPError,
|
|
21
|
+
MCPErrorCode,
|
|
22
|
+
MCPTool,
|
|
23
|
+
MCPResource,
|
|
24
|
+
MCPToolResult,
|
|
25
|
+
MCPServerCapabilities,
|
|
26
|
+
MCPServerInfo,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MCPProtocolError(Exception):
|
|
34
|
+
"""Exception raised for protocol-level errors."""
|
|
35
|
+
def __init__(self, code: int, message: str, data: Any = None):
|
|
36
|
+
super().__init__(message)
|
|
37
|
+
self.code = code
|
|
38
|
+
self.message = message
|
|
39
|
+
self.data = data
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class MCPProtocol:
|
|
43
|
+
"""
|
|
44
|
+
MCP Protocol handler for JSON-RPC 2.0 communication.
|
|
45
|
+
|
|
46
|
+
Provides static methods for message parsing, creation, and validation.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# Protocol version
|
|
50
|
+
JSONRPC_VERSION = "2.0"
|
|
51
|
+
MCP_PROTOCOL_VERSION = "2024-11-05"
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def parse(data: str) -> MCPMessage:
|
|
55
|
+
"""
|
|
56
|
+
Parse a JSON-RPC message from string.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
data: JSON string to parse
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
MCPMessage object
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
MCPProtocolError: If parsing fails or message is invalid
|
|
66
|
+
"""
|
|
67
|
+
try:
|
|
68
|
+
obj = json.loads(data)
|
|
69
|
+
except json.JSONDecodeError as e:
|
|
70
|
+
raise MCPProtocolError(
|
|
71
|
+
MCPErrorCode.PARSE_ERROR,
|
|
72
|
+
f"Invalid JSON: {str(e)}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Validate basic structure
|
|
76
|
+
if not isinstance(obj, dict):
|
|
77
|
+
raise MCPProtocolError(
|
|
78
|
+
MCPErrorCode.INVALID_REQUEST,
|
|
79
|
+
"Message must be a JSON object"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Check JSON-RPC version
|
|
83
|
+
if obj.get("jsonrpc") != MCPProtocol.JSONRPC_VERSION:
|
|
84
|
+
raise MCPProtocolError(
|
|
85
|
+
MCPErrorCode.INVALID_REQUEST,
|
|
86
|
+
f"Invalid JSON-RPC version: {obj.get('jsonrpc')}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return MCPMessage.from_dict(obj)
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def serialize(msg: MCPMessage) -> str:
|
|
93
|
+
"""
|
|
94
|
+
Serialize an MCPMessage to JSON string.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
msg: MCPMessage to serialize
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
JSON string
|
|
101
|
+
"""
|
|
102
|
+
return msg.to_json()
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def create_response(id: int, result: Any) -> MCPMessage:
|
|
106
|
+
"""
|
|
107
|
+
Create a success response message.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
id: Request ID to respond to
|
|
111
|
+
result: Result data
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
MCPMessage response
|
|
115
|
+
"""
|
|
116
|
+
return MCPMessage(id=id, result=result)
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def create_error(id: Optional[int], code: int, message: str, data: Any = None) -> MCPMessage:
|
|
120
|
+
"""
|
|
121
|
+
Create an error response message.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
id: Request ID (can be None for parse errors)
|
|
125
|
+
code: Error code
|
|
126
|
+
message: Error message
|
|
127
|
+
data: Optional additional error data
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
MCPMessage error response
|
|
131
|
+
"""
|
|
132
|
+
return MCPMessage(
|
|
133
|
+
id=id,
|
|
134
|
+
error=MCPError(code=code, message=message, data=data)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
@staticmethod
|
|
138
|
+
def create_notification(method: str, params: Optional[Dict] = None) -> MCPMessage:
|
|
139
|
+
"""
|
|
140
|
+
Create a notification message (no response expected).
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
method: Method name
|
|
144
|
+
params: Optional parameters
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
MCPMessage notification
|
|
148
|
+
"""
|
|
149
|
+
return MCPMessage(method=method, params=params)
|
|
150
|
+
|
|
151
|
+
# =========================================================================
|
|
152
|
+
# MCP-specific response creators
|
|
153
|
+
# =========================================================================
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def create_initialize_response(
|
|
157
|
+
id: int,
|
|
158
|
+
server_info: MCPServerInfo,
|
|
159
|
+
capabilities: MCPServerCapabilities
|
|
160
|
+
) -> MCPMessage:
|
|
161
|
+
"""
|
|
162
|
+
Create response for 'initialize' request.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
id: Request ID
|
|
166
|
+
server_info: Server information
|
|
167
|
+
capabilities: Server capabilities
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
MCPMessage response
|
|
171
|
+
"""
|
|
172
|
+
return MCPProtocol.create_response(id, {
|
|
173
|
+
"protocolVersion": MCPProtocol.MCP_PROTOCOL_VERSION,
|
|
174
|
+
"serverInfo": server_info.to_dict(),
|
|
175
|
+
"capabilities": capabilities.to_dict()
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def create_tools_list_response(id: int, tools: List[MCPTool]) -> MCPMessage:
|
|
180
|
+
"""
|
|
181
|
+
Create response for 'tools/list' request.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
id: Request ID
|
|
185
|
+
tools: List of available tools
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
MCPMessage response
|
|
189
|
+
"""
|
|
190
|
+
return MCPProtocol.create_response(id, {
|
|
191
|
+
"tools": [t.to_dict() for t in tools]
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def create_tools_call_response(id: int, result: MCPToolResult) -> MCPMessage:
|
|
196
|
+
"""
|
|
197
|
+
Create response for 'tools/call' request.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
id: Request ID
|
|
201
|
+
result: Tool execution result
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
MCPMessage response
|
|
205
|
+
"""
|
|
206
|
+
return MCPProtocol.create_response(id, result.to_dict())
|
|
207
|
+
|
|
208
|
+
@staticmethod
|
|
209
|
+
def create_resources_list_response(id: int, resources: List[MCPResource]) -> MCPMessage:
|
|
210
|
+
"""
|
|
211
|
+
Create response for 'resources/list' request.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
id: Request ID
|
|
215
|
+
resources: List of available resources
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
MCPMessage response
|
|
219
|
+
"""
|
|
220
|
+
return MCPProtocol.create_response(id, {
|
|
221
|
+
"resources": [r.to_dict() for r in resources]
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
@staticmethod
|
|
225
|
+
def create_resources_read_response(id: int, contents: List[Dict]) -> MCPMessage:
|
|
226
|
+
"""
|
|
227
|
+
Create response for 'resources/read' request.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
id: Request ID
|
|
231
|
+
contents: List of resource contents
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
MCPMessage response
|
|
235
|
+
"""
|
|
236
|
+
return MCPProtocol.create_response(id, {
|
|
237
|
+
"contents": contents
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
# =========================================================================
|
|
241
|
+
# Error response helpers
|
|
242
|
+
# =========================================================================
|
|
243
|
+
|
|
244
|
+
@staticmethod
|
|
245
|
+
def method_not_found(id: int, method: str) -> MCPMessage:
|
|
246
|
+
"""Create METHOD_NOT_FOUND error response."""
|
|
247
|
+
return MCPProtocol.create_error(
|
|
248
|
+
id,
|
|
249
|
+
MCPErrorCode.METHOD_NOT_FOUND,
|
|
250
|
+
f"Method not found: {method}"
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
@staticmethod
|
|
254
|
+
def invalid_params(id: int, message: str) -> MCPMessage:
|
|
255
|
+
"""Create INVALID_PARAMS error response."""
|
|
256
|
+
return MCPProtocol.create_error(
|
|
257
|
+
id,
|
|
258
|
+
MCPErrorCode.INVALID_PARAMS,
|
|
259
|
+
message
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
@staticmethod
|
|
263
|
+
def tool_not_found(id: int, tool_name: str) -> MCPMessage:
|
|
264
|
+
"""Create TOOL_NOT_FOUND error response."""
|
|
265
|
+
return MCPProtocol.create_error(
|
|
266
|
+
id,
|
|
267
|
+
MCPErrorCode.TOOL_NOT_FOUND,
|
|
268
|
+
f"Tool not found: {tool_name}"
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
@staticmethod
|
|
272
|
+
def resource_not_found(id: int, uri: str) -> MCPMessage:
|
|
273
|
+
"""Create RESOURCE_NOT_FOUND error response."""
|
|
274
|
+
return MCPProtocol.create_error(
|
|
275
|
+
id,
|
|
276
|
+
MCPErrorCode.RESOURCE_NOT_FOUND,
|
|
277
|
+
f"Resource not found: {uri}"
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
@staticmethod
|
|
281
|
+
def internal_error(id: Optional[int], message: str) -> MCPMessage:
|
|
282
|
+
"""Create INTERNAL_ERROR error response."""
|
|
283
|
+
return MCPProtocol.create_error(
|
|
284
|
+
id,
|
|
285
|
+
MCPErrorCode.INTERNAL_ERROR,
|
|
286
|
+
message
|
|
287
|
+
)
|
|
288
|
+
|