pomera-ai-commander 0.1.0

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.
Files changed (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +680 -0
  3. package/bin/pomera-ai-commander.js +62 -0
  4. package/core/__init__.py +66 -0
  5. package/core/__pycache__/__init__.cpython-313.pyc +0 -0
  6. package/core/__pycache__/app_context.cpython-313.pyc +0 -0
  7. package/core/__pycache__/async_text_processor.cpython-313.pyc +0 -0
  8. package/core/__pycache__/backup_manager.cpython-313.pyc +0 -0
  9. package/core/__pycache__/backup_recovery_manager.cpython-313.pyc +0 -0
  10. package/core/__pycache__/content_hash_cache.cpython-313.pyc +0 -0
  11. package/core/__pycache__/context_menu.cpython-313.pyc +0 -0
  12. package/core/__pycache__/data_validator.cpython-313.pyc +0 -0
  13. package/core/__pycache__/database_connection_manager.cpython-313.pyc +0 -0
  14. package/core/__pycache__/database_curl_settings_manager.cpython-313.pyc +0 -0
  15. package/core/__pycache__/database_promera_ai_settings_manager.cpython-313.pyc +0 -0
  16. package/core/__pycache__/database_schema.cpython-313.pyc +0 -0
  17. package/core/__pycache__/database_schema_manager.cpython-313.pyc +0 -0
  18. package/core/__pycache__/database_settings_manager.cpython-313.pyc +0 -0
  19. package/core/__pycache__/database_settings_manager_interface.cpython-313.pyc +0 -0
  20. package/core/__pycache__/dialog_manager.cpython-313.pyc +0 -0
  21. package/core/__pycache__/efficient_line_numbers.cpython-313.pyc +0 -0
  22. package/core/__pycache__/error_handler.cpython-313.pyc +0 -0
  23. package/core/__pycache__/error_service.cpython-313.pyc +0 -0
  24. package/core/__pycache__/event_consolidator.cpython-313.pyc +0 -0
  25. package/core/__pycache__/memory_efficient_text_widget.cpython-313.pyc +0 -0
  26. package/core/__pycache__/migration_manager.cpython-313.pyc +0 -0
  27. package/core/__pycache__/migration_test_suite.cpython-313.pyc +0 -0
  28. package/core/__pycache__/migration_validator.cpython-313.pyc +0 -0
  29. package/core/__pycache__/optimized_find_replace.cpython-313.pyc +0 -0
  30. package/core/__pycache__/optimized_pattern_engine.cpython-313.pyc +0 -0
  31. package/core/__pycache__/optimized_search_highlighter.cpython-313.pyc +0 -0
  32. package/core/__pycache__/performance_monitor.cpython-313.pyc +0 -0
  33. package/core/__pycache__/persistence_manager.cpython-313.pyc +0 -0
  34. package/core/__pycache__/progressive_stats_calculator.cpython-313.pyc +0 -0
  35. package/core/__pycache__/regex_pattern_cache.cpython-313.pyc +0 -0
  36. package/core/__pycache__/regex_pattern_library.cpython-313.pyc +0 -0
  37. package/core/__pycache__/search_operation_manager.cpython-313.pyc +0 -0
  38. package/core/__pycache__/settings_defaults_registry.cpython-313.pyc +0 -0
  39. package/core/__pycache__/settings_integrity_validator.cpython-313.pyc +0 -0
  40. package/core/__pycache__/settings_serializer.cpython-313.pyc +0 -0
  41. package/core/__pycache__/settings_validator.cpython-313.pyc +0 -0
  42. package/core/__pycache__/smart_stats_calculator.cpython-313.pyc +0 -0
  43. package/core/__pycache__/statistics_update_manager.cpython-313.pyc +0 -0
  44. package/core/__pycache__/stats_config_manager.cpython-313.pyc +0 -0
  45. package/core/__pycache__/streaming_text_handler.cpython-313.pyc +0 -0
  46. package/core/__pycache__/task_scheduler.cpython-313.pyc +0 -0
  47. package/core/__pycache__/visibility_monitor.cpython-313.pyc +0 -0
  48. package/core/__pycache__/widget_cache.cpython-313.pyc +0 -0
  49. package/core/app_context.py +482 -0
  50. package/core/async_text_processor.py +422 -0
  51. package/core/backup_manager.py +656 -0
  52. package/core/backup_recovery_manager.py +1034 -0
  53. package/core/content_hash_cache.py +509 -0
  54. package/core/context_menu.py +313 -0
  55. package/core/data_validator.py +1067 -0
  56. package/core/database_connection_manager.py +745 -0
  57. package/core/database_curl_settings_manager.py +609 -0
  58. package/core/database_promera_ai_settings_manager.py +447 -0
  59. package/core/database_schema.py +412 -0
  60. package/core/database_schema_manager.py +396 -0
  61. package/core/database_settings_manager.py +1508 -0
  62. package/core/database_settings_manager_interface.py +457 -0
  63. package/core/dialog_manager.py +735 -0
  64. package/core/efficient_line_numbers.py +511 -0
  65. package/core/error_handler.py +747 -0
  66. package/core/error_service.py +431 -0
  67. package/core/event_consolidator.py +512 -0
  68. package/core/mcp/__init__.py +43 -0
  69. package/core/mcp/__pycache__/__init__.cpython-313.pyc +0 -0
  70. package/core/mcp/__pycache__/protocol.cpython-313.pyc +0 -0
  71. package/core/mcp/__pycache__/schema.cpython-313.pyc +0 -0
  72. package/core/mcp/__pycache__/server_stdio.cpython-313.pyc +0 -0
  73. package/core/mcp/__pycache__/tool_registry.cpython-313.pyc +0 -0
  74. package/core/mcp/protocol.py +288 -0
  75. package/core/mcp/schema.py +251 -0
  76. package/core/mcp/server_stdio.py +299 -0
  77. package/core/mcp/tool_registry.py +2345 -0
  78. package/core/memory_efficient_text_widget.py +712 -0
  79. package/core/migration_manager.py +915 -0
  80. package/core/migration_test_suite.py +1086 -0
  81. package/core/migration_validator.py +1144 -0
  82. package/core/optimized_find_replace.py +715 -0
  83. package/core/optimized_pattern_engine.py +424 -0
  84. package/core/optimized_search_highlighter.py +553 -0
  85. package/core/performance_monitor.py +675 -0
  86. package/core/persistence_manager.py +713 -0
  87. package/core/progressive_stats_calculator.py +632 -0
  88. package/core/regex_pattern_cache.py +530 -0
  89. package/core/regex_pattern_library.py +351 -0
  90. package/core/search_operation_manager.py +435 -0
  91. package/core/settings_defaults_registry.py +1087 -0
  92. package/core/settings_integrity_validator.py +1112 -0
  93. package/core/settings_serializer.py +558 -0
  94. package/core/settings_validator.py +1824 -0
  95. package/core/smart_stats_calculator.py +710 -0
  96. package/core/statistics_update_manager.py +619 -0
  97. package/core/stats_config_manager.py +858 -0
  98. package/core/streaming_text_handler.py +723 -0
  99. package/core/task_scheduler.py +596 -0
  100. package/core/update_pattern_library.py +169 -0
  101. package/core/visibility_monitor.py +596 -0
  102. package/core/widget_cache.py +498 -0
  103. package/mcp.json +61 -0
  104. package/package.json +57 -0
  105. package/pomera.py +7483 -0
  106. package/pomera_mcp_server.py +144 -0
  107. package/tools/__init__.py +5 -0
  108. package/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  109. package/tools/__pycache__/ai_tools.cpython-313.pyc +0 -0
  110. package/tools/__pycache__/ascii_art_generator.cpython-313.pyc +0 -0
  111. package/tools/__pycache__/base64_tools.cpython-313.pyc +0 -0
  112. package/tools/__pycache__/base_tool.cpython-313.pyc +0 -0
  113. package/tools/__pycache__/case_tool.cpython-313.pyc +0 -0
  114. package/tools/__pycache__/column_tools.cpython-313.pyc +0 -0
  115. package/tools/__pycache__/cron_tool.cpython-313.pyc +0 -0
  116. package/tools/__pycache__/curl_history.cpython-313.pyc +0 -0
  117. package/tools/__pycache__/curl_processor.cpython-313.pyc +0 -0
  118. package/tools/__pycache__/curl_settings.cpython-313.pyc +0 -0
  119. package/tools/__pycache__/curl_tool.cpython-313.pyc +0 -0
  120. package/tools/__pycache__/diff_viewer.cpython-313.pyc +0 -0
  121. package/tools/__pycache__/email_extraction_tool.cpython-313.pyc +0 -0
  122. package/tools/__pycache__/email_header_analyzer.cpython-313.pyc +0 -0
  123. package/tools/__pycache__/extraction_tools.cpython-313.pyc +0 -0
  124. package/tools/__pycache__/find_replace.cpython-313.pyc +0 -0
  125. package/tools/__pycache__/folder_file_reporter.cpython-313.pyc +0 -0
  126. package/tools/__pycache__/folder_file_reporter_adapter.cpython-313.pyc +0 -0
  127. package/tools/__pycache__/generator_tools.cpython-313.pyc +0 -0
  128. package/tools/__pycache__/hash_generator.cpython-313.pyc +0 -0
  129. package/tools/__pycache__/html_tool.cpython-313.pyc +0 -0
  130. package/tools/__pycache__/huggingface_helper.cpython-313.pyc +0 -0
  131. package/tools/__pycache__/jsonxml_tool.cpython-313.pyc +0 -0
  132. package/tools/__pycache__/line_tools.cpython-313.pyc +0 -0
  133. package/tools/__pycache__/list_comparator.cpython-313.pyc +0 -0
  134. package/tools/__pycache__/markdown_tools.cpython-313.pyc +0 -0
  135. package/tools/__pycache__/mcp_widget.cpython-313.pyc +0 -0
  136. package/tools/__pycache__/notes_widget.cpython-313.pyc +0 -0
  137. package/tools/__pycache__/number_base_converter.cpython-313.pyc +0 -0
  138. package/tools/__pycache__/regex_extractor.cpython-313.pyc +0 -0
  139. package/tools/__pycache__/slug_generator.cpython-313.pyc +0 -0
  140. package/tools/__pycache__/sorter_tools.cpython-313.pyc +0 -0
  141. package/tools/__pycache__/string_escape_tool.cpython-313.pyc +0 -0
  142. package/tools/__pycache__/text_statistics_tool.cpython-313.pyc +0 -0
  143. package/tools/__pycache__/text_wrapper.cpython-313.pyc +0 -0
  144. package/tools/__pycache__/timestamp_converter.cpython-313.pyc +0 -0
  145. package/tools/__pycache__/tool_loader.cpython-313.pyc +0 -0
  146. package/tools/__pycache__/translator_tools.cpython-313.pyc +0 -0
  147. package/tools/__pycache__/url_link_extractor.cpython-313.pyc +0 -0
  148. package/tools/__pycache__/url_parser.cpython-313.pyc +0 -0
  149. package/tools/__pycache__/whitespace_tools.cpython-313.pyc +0 -0
  150. package/tools/__pycache__/word_frequency_counter.cpython-313.pyc +0 -0
  151. package/tools/ai_tools.py +2892 -0
  152. package/tools/ascii_art_generator.py +353 -0
  153. package/tools/base64_tools.py +184 -0
  154. package/tools/base_tool.py +511 -0
  155. package/tools/case_tool.py +309 -0
  156. package/tools/column_tools.py +396 -0
  157. package/tools/cron_tool.py +885 -0
  158. package/tools/curl_history.py +601 -0
  159. package/tools/curl_processor.py +1208 -0
  160. package/tools/curl_settings.py +503 -0
  161. package/tools/curl_tool.py +5467 -0
  162. package/tools/diff_viewer.py +1072 -0
  163. package/tools/email_extraction_tool.py +249 -0
  164. package/tools/email_header_analyzer.py +426 -0
  165. package/tools/extraction_tools.py +250 -0
  166. package/tools/find_replace.py +1751 -0
  167. package/tools/folder_file_reporter.py +1463 -0
  168. package/tools/folder_file_reporter_adapter.py +480 -0
  169. package/tools/generator_tools.py +1217 -0
  170. package/tools/hash_generator.py +256 -0
  171. package/tools/html_tool.py +657 -0
  172. package/tools/huggingface_helper.py +449 -0
  173. package/tools/jsonxml_tool.py +730 -0
  174. package/tools/line_tools.py +419 -0
  175. package/tools/list_comparator.py +720 -0
  176. package/tools/markdown_tools.py +562 -0
  177. package/tools/mcp_widget.py +1417 -0
  178. package/tools/notes_widget.py +973 -0
  179. package/tools/number_base_converter.py +373 -0
  180. package/tools/regex_extractor.py +572 -0
  181. package/tools/slug_generator.py +311 -0
  182. package/tools/sorter_tools.py +459 -0
  183. package/tools/string_escape_tool.py +393 -0
  184. package/tools/text_statistics_tool.py +366 -0
  185. package/tools/text_wrapper.py +431 -0
  186. package/tools/timestamp_converter.py +422 -0
  187. package/tools/tool_loader.py +710 -0
  188. package/tools/translator_tools.py +523 -0
  189. package/tools/url_link_extractor.py +262 -0
  190. package/tools/url_parser.py +205 -0
  191. package/tools/whitespace_tools.py +356 -0
  192. package/tools/word_frequency_counter.py +147 -0
@@ -0,0 +1,299 @@
1
+ """
2
+ MCP Server stdio Transport - Standard I/O transport for MCP server
3
+
4
+ This module implements the stdio transport for the MCP server,
5
+ allowing communication with MCP clients (like Claude Desktop, Cursor)
6
+ via standard input/output streams.
7
+
8
+ The server reads JSON-RPC messages from stdin and writes responses to stdout.
9
+ Each message is a single line of JSON.
10
+ """
11
+
12
+ import sys
13
+ import json
14
+ import logging
15
+ import asyncio
16
+ from typing import Optional, Callable, Dict, Any
17
+
18
+ from .schema import (
19
+ MCPMessage,
20
+ MCPServerCapabilities,
21
+ MCPServerInfo,
22
+ MCPToolResult,
23
+ MCPResource,
24
+ )
25
+ from .protocol import MCPProtocol, MCPProtocolError
26
+ from .tool_registry import ToolRegistry, get_registry
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class StdioMCPServer:
32
+ """
33
+ MCP Server using stdio transport.
34
+
35
+ Reads JSON-RPC messages from stdin, processes them, and writes
36
+ responses to stdout. This is the primary transport for integration
37
+ with Claude Desktop and Cursor.
38
+ """
39
+
40
+ def __init__(
41
+ self,
42
+ tool_registry: Optional[ToolRegistry] = None,
43
+ server_name: str = "pomera-mcp-server",
44
+ server_version: str = "0.1.0",
45
+ resource_provider: Optional[Callable[[str], str]] = None
46
+ ):
47
+ """
48
+ Initialize the stdio MCP server.
49
+
50
+ Args:
51
+ tool_registry: Registry of available tools (uses default if None)
52
+ server_name: Name to advertise in server info
53
+ server_version: Version to advertise in server info
54
+ resource_provider: Optional callback to read resources by URI
55
+ """
56
+ self.registry = tool_registry or get_registry()
57
+ self.server_info = MCPServerInfo(name=server_name, version=server_version)
58
+ self.capabilities = MCPServerCapabilities(
59
+ tools=True,
60
+ resources=resource_provider is not None,
61
+ prompts=False,
62
+ logging=False
63
+ )
64
+ self.resource_provider = resource_provider
65
+ self.running = False
66
+ self._initialized = False
67
+
68
+ # Resources list (can be populated externally)
69
+ self._resources: list[MCPResource] = []
70
+
71
+ def add_resource(self, resource: MCPResource) -> None:
72
+ """Add a resource to the server's resource list."""
73
+ self._resources.append(resource)
74
+ self.capabilities.resources = True
75
+
76
+ def set_resources(self, resources: list[MCPResource]) -> None:
77
+ """Set the server's resource list."""
78
+ self._resources = resources
79
+ self.capabilities.resources = len(resources) > 0
80
+
81
+ async def run(self) -> None:
82
+ """
83
+ Run the server, reading from stdin and writing to stdout.
84
+
85
+ This method runs indefinitely until stdin is closed or
86
+ stop() is called.
87
+ """
88
+ self.running = True
89
+ logger.info("MCP stdio server starting...")
90
+
91
+ # Use asyncio for non-blocking stdin reading
92
+ loop = asyncio.get_event_loop()
93
+ reader = asyncio.StreamReader()
94
+ protocol = asyncio.StreamReaderProtocol(reader)
95
+
96
+ await loop.connect_read_pipe(lambda: protocol, sys.stdin)
97
+
98
+ while self.running:
99
+ try:
100
+ # Read a line from stdin
101
+ line = await reader.readline()
102
+ if not line:
103
+ logger.info("stdin closed, shutting down")
104
+ break
105
+
106
+ line_str = line.decode('utf-8').strip()
107
+ if not line_str:
108
+ continue
109
+
110
+ logger.debug(f"Received: {line_str[:100]}...")
111
+
112
+ # Process the message
113
+ response = self._handle_message(line_str)
114
+
115
+ if response:
116
+ self._send_response(response)
117
+
118
+ except asyncio.CancelledError:
119
+ logger.info("Server cancelled")
120
+ break
121
+ except Exception as e:
122
+ logger.exception(f"Error processing message: {e}")
123
+ # Send error response
124
+ error_response = MCPProtocol.internal_error(None, str(e))
125
+ self._send_response(error_response)
126
+
127
+ self.running = False
128
+ logger.info("MCP stdio server stopped")
129
+
130
+ def run_sync(self) -> None:
131
+ """
132
+ Run the server synchronously (blocking).
133
+
134
+ Simpler alternative to async run() for single-threaded use.
135
+ """
136
+ self.running = True
137
+ logger.info("MCP stdio server starting (sync mode)...")
138
+
139
+ while self.running:
140
+ try:
141
+ line = sys.stdin.readline()
142
+ if not line:
143
+ logger.info("stdin closed, shutting down")
144
+ break
145
+
146
+ line = line.strip()
147
+ if not line:
148
+ continue
149
+
150
+ logger.debug(f"Received: {line[:100]}...")
151
+
152
+ response = self._handle_message(line)
153
+
154
+ if response:
155
+ self._send_response(response)
156
+
157
+ except KeyboardInterrupt:
158
+ logger.info("Keyboard interrupt, shutting down")
159
+ break
160
+ except Exception as e:
161
+ logger.exception(f"Error processing message: {e}")
162
+ error_response = MCPProtocol.internal_error(None, str(e))
163
+ self._send_response(error_response)
164
+
165
+ self.running = False
166
+ logger.info("MCP stdio server stopped")
167
+
168
+ def stop(self) -> None:
169
+ """Signal the server to stop."""
170
+ self.running = False
171
+
172
+ def _send_response(self, msg: MCPMessage) -> None:
173
+ """Send a response message to stdout."""
174
+ json_str = MCPProtocol.serialize(msg)
175
+ logger.debug(f"Sending: {json_str[:100]}...")
176
+ print(json_str, flush=True)
177
+
178
+ def _handle_message(self, data: str) -> Optional[MCPMessage]:
179
+ """
180
+ Handle an incoming message and return response.
181
+
182
+ Args:
183
+ data: JSON string of incoming message
184
+
185
+ Returns:
186
+ MCPMessage response or None for notifications
187
+ """
188
+ try:
189
+ msg = MCPProtocol.parse(data)
190
+ except MCPProtocolError as e:
191
+ return MCPProtocol.create_error(None, e.code, e.message)
192
+
193
+ # Notifications don't get responses
194
+ if msg.is_notification():
195
+ self._handle_notification(msg)
196
+ return None
197
+
198
+ # Route to appropriate handler
199
+ method = msg.method
200
+ params = msg.params or {}
201
+
202
+ if method == "initialize":
203
+ return self._handle_initialize(msg.id, params)
204
+ elif method == "initialized":
205
+ # This is a notification, but some clients send it as request
206
+ self._initialized = True
207
+ return MCPProtocol.create_response(msg.id, {})
208
+ elif method == "ping":
209
+ return MCPProtocol.create_response(msg.id, {})
210
+ elif method == "tools/list":
211
+ return self._handle_tools_list(msg.id)
212
+ elif method == "tools/call":
213
+ return self._handle_tools_call(msg.id, params)
214
+ elif method == "resources/list":
215
+ return self._handle_resources_list(msg.id)
216
+ elif method == "resources/read":
217
+ return self._handle_resources_read(msg.id, params)
218
+ else:
219
+ return MCPProtocol.method_not_found(msg.id, method)
220
+
221
+ def _handle_notification(self, msg: MCPMessage) -> None:
222
+ """Handle notification messages (no response)."""
223
+ if msg.method == "notifications/initialized":
224
+ self._initialized = True
225
+ logger.info("Client initialized")
226
+ elif msg.method == "notifications/cancelled":
227
+ logger.info(f"Request cancelled: {msg.params}")
228
+
229
+ def _handle_initialize(self, id: int, params: Dict[str, Any]) -> MCPMessage:
230
+ """Handle 'initialize' request."""
231
+ client_info = params.get("clientInfo", {})
232
+ logger.info(f"Client initializing: {client_info.get('name', 'unknown')} "
233
+ f"v{client_info.get('version', 'unknown')}")
234
+
235
+ return MCPProtocol.create_initialize_response(
236
+ id,
237
+ self.server_info,
238
+ self.capabilities
239
+ )
240
+
241
+ def _handle_tools_list(self, id: int) -> MCPMessage:
242
+ """Handle 'tools/list' request."""
243
+ tools = self.registry.list_tools()
244
+ logger.debug(f"Listing {len(tools)} tools")
245
+ return MCPProtocol.create_tools_list_response(id, tools)
246
+
247
+ def _handle_tools_call(self, id: int, params: Dict[str, Any]) -> MCPMessage:
248
+ """Handle 'tools/call' request."""
249
+ tool_name = params.get("name")
250
+ arguments = params.get("arguments", {})
251
+
252
+ if not tool_name:
253
+ return MCPProtocol.invalid_params(id, "Missing 'name' parameter")
254
+
255
+ if tool_name not in self.registry:
256
+ return MCPProtocol.tool_not_found(id, tool_name)
257
+
258
+ logger.info(f"Executing tool: {tool_name}")
259
+ result = self.registry.execute(tool_name, arguments)
260
+
261
+ return MCPProtocol.create_tools_call_response(id, result)
262
+
263
+ def _handle_resources_list(self, id: int) -> MCPMessage:
264
+ """Handle 'resources/list' request."""
265
+ logger.debug(f"Listing {len(self._resources)} resources")
266
+ return MCPProtocol.create_resources_list_response(id, self._resources)
267
+
268
+ def _handle_resources_read(self, id: int, params: Dict[str, Any]) -> MCPMessage:
269
+ """Handle 'resources/read' request."""
270
+ uri = params.get("uri")
271
+
272
+ if not uri:
273
+ return MCPProtocol.invalid_params(id, "Missing 'uri' parameter")
274
+
275
+ # Find the resource
276
+ resource = None
277
+ for r in self._resources:
278
+ if r.uri == uri:
279
+ resource = r
280
+ break
281
+
282
+ if resource is None:
283
+ return MCPProtocol.resource_not_found(id, uri)
284
+
285
+ # Read content via provider
286
+ if self.resource_provider:
287
+ try:
288
+ content = self.resource_provider(uri)
289
+ return MCPProtocol.create_resources_read_response(id, [{
290
+ "uri": uri,
291
+ "mimeType": resource.mimeType,
292
+ "text": content
293
+ }])
294
+ except Exception as e:
295
+ logger.exception(f"Error reading resource: {uri}")
296
+ return MCPProtocol.internal_error(id, f"Error reading resource: {str(e)}")
297
+ else:
298
+ return MCPProtocol.internal_error(id, "No resource provider configured")
299
+