mcpower-proxy 0.0.67__py3-none-any.whl → 0.0.77__py3-none-any.whl

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 (41) hide show
  1. ide_tools/__init__.py +12 -0
  2. ide_tools/common/__init__.py +5 -0
  3. ide_tools/common/hooks/__init__.py +5 -0
  4. ide_tools/common/hooks/init.py +129 -0
  5. ide_tools/common/hooks/output.py +63 -0
  6. ide_tools/common/hooks/prompt_submit.py +136 -0
  7. ide_tools/common/hooks/read_file.py +170 -0
  8. ide_tools/common/hooks/shell_execution.py +257 -0
  9. ide_tools/common/hooks/shell_parser_bashlex.py +394 -0
  10. ide_tools/common/hooks/types.py +34 -0
  11. ide_tools/common/hooks/utils.py +286 -0
  12. ide_tools/cursor/__init__.py +11 -0
  13. ide_tools/cursor/constants.py +58 -0
  14. ide_tools/cursor/format.py +35 -0
  15. ide_tools/cursor/router.py +101 -0
  16. ide_tools/router.py +48 -0
  17. main.py +11 -4
  18. {mcpower_proxy-0.0.67.dist-info → mcpower_proxy-0.0.77.dist-info}/METADATA +4 -3
  19. mcpower_proxy-0.0.77.dist-info/RECORD +62 -0
  20. {mcpower_proxy-0.0.67.dist-info → mcpower_proxy-0.0.77.dist-info}/top_level.txt +1 -0
  21. modules/apis/security_policy.py +11 -6
  22. modules/decision_handler.py +219 -0
  23. modules/logs/audit_trail.py +20 -18
  24. modules/logs/logger.py +14 -18
  25. modules/redaction/gitleaks_rules.py +1 -1
  26. modules/redaction/pii_rules.py +0 -48
  27. modules/redaction/redactor.py +112 -107
  28. modules/ui/__init__.py +1 -1
  29. modules/ui/confirmation.py +0 -1
  30. modules/utils/cli.py +36 -6
  31. modules/utils/ids.py +50 -7
  32. modules/utils/json.py +3 -3
  33. modules/utils/platform.py +23 -0
  34. modules/utils/string.py +17 -0
  35. wrapper/__version__.py +1 -1
  36. wrapper/middleware.py +136 -221
  37. wrapper/server.py +19 -11
  38. mcpower_proxy-0.0.67.dist-info/RECORD +0 -43
  39. {mcpower_proxy-0.0.67.dist-info → mcpower_proxy-0.0.77.dist-info}/WHEEL +0 -0
  40. {mcpower_proxy-0.0.67.dist-info → mcpower_proxy-0.0.77.dist-info}/entry_points.txt +0 -0
  41. {mcpower_proxy-0.0.67.dist-info → mcpower_proxy-0.0.77.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,286 @@
1
+ """
2
+ Common utilities for IDE hooks - IDE-agnostic
3
+ """
4
+
5
+ import json
6
+ import re
7
+ from collections import Counter
8
+ from typing import Dict, Any, List, Callable, Optional
9
+
10
+ from mcpower_shared.mcp_types import create_policy_request, create_policy_response, AgentContext, EnvironmentContext, \
11
+ ServerRef, ToolRef
12
+ from modules.apis.security_policy import SecurityPolicyClient
13
+ from modules.decision_handler import DecisionHandler
14
+ from modules.logs.audit_trail import AuditTrailLogger
15
+ from modules.logs.logger import MCPLogger
16
+ from modules.redaction import redact
17
+ from modules.utils.json import safe_json_dumps
18
+ from wrapper.__version__ import __version__
19
+
20
+
21
+ def create_validator(
22
+ required_fields: Dict[str, type],
23
+ optional_fields: Optional[Dict[str, type]] = None
24
+ ) -> Callable[[str], Dict[str, Any]]:
25
+ """
26
+ Factory for input validators
27
+
28
+ Args:
29
+ required_fields: Dict mapping field names to their expected types
30
+ optional_fields: Dict mapping optional field names to their expected types
31
+
32
+ Returns:
33
+ Validator function that parses and validates input
34
+ """
35
+
36
+ def parse_and_validate_input(stdin_input: str) -> Dict[str, Any]:
37
+ try:
38
+ if not stdin_input.strip():
39
+ raise ValueError("No input provided")
40
+ input_data = json.loads(stdin_input)
41
+ except json.JSONDecodeError as e:
42
+ raise ValueError(f"Failed to parse input: {e}")
43
+
44
+ for field, expected_type in required_fields.items():
45
+ if field not in input_data:
46
+ raise ValueError(f"No {field} provided in input")
47
+ if not isinstance(input_data[field], expected_type):
48
+ raise ValueError(f"{field} must be a {expected_type.__name__}")
49
+
50
+ if optional_fields:
51
+ for field, expected_type in optional_fields.items():
52
+ if field in input_data and not isinstance(input_data[field], expected_type):
53
+ raise ValueError(f"{field} must be a {expected_type.__name__}")
54
+
55
+ return input_data
56
+
57
+ return parse_and_validate_input
58
+
59
+
60
+ def extract_redaction_patterns(redacted_content: str) -> Dict[str, int]:
61
+ """
62
+ Extract redaction pattern types and their counts from redacted content
63
+
64
+ Args:
65
+ redacted_content: Content with [REDACTED-type] placeholders
66
+
67
+ Returns:
68
+ Dict mapping redaction types to counts
69
+ """
70
+ pattern = r'\[REDACTED-([^\]]+)\]'
71
+ matches = re.findall(pattern, redacted_content)
72
+ return dict(Counter(matches))
73
+
74
+
75
+ def build_sensitive_data_types(patterns: Dict[str, int], context: str = "file") -> Dict[str, Dict[str, Any]]:
76
+ """
77
+ Convert redaction patterns to structured sensitive_data_types dict
78
+
79
+ Args:
80
+ patterns: Dict mapping pattern text to occurrence counts (from extract_redaction_patterns)
81
+ context: Context string for description (e.g., "file", "prompt text")
82
+
83
+ Returns:
84
+ Dict mapping data types to occurrence info with descriptions
85
+ """
86
+ sensitive_data_types = {}
87
+ for pattern_text, count in patterns.items():
88
+ data_type = pattern_text.replace("[REDACTED-", "").replace("]", "")
89
+ sensitive_data_types[data_type] = {
90
+ "occurrences": count,
91
+ "description": f"Found {count} instance(s) of {data_type} in {context}"
92
+ }
93
+ return sensitive_data_types
94
+
95
+
96
+ def process_single_file_for_redaction(
97
+ file_path: str,
98
+ content: str,
99
+ logger: MCPLogger
100
+ ) -> Optional[Dict[str, Any]]:
101
+ """
102
+ Process a single file's content for redaction patterns
103
+
104
+ Args:
105
+ file_path: Path to the file being processed
106
+ content: File content to check for redactions
107
+ logger: MCPLogger instance
108
+
109
+ Returns:
110
+ Dict with redaction info if sensitive data found, None otherwise
111
+ """
112
+ redacted = redact(content)
113
+ patterns = extract_redaction_patterns(redacted)
114
+ if patterns:
115
+ sensitive_data_types = build_sensitive_data_types(patterns, "file")
116
+ logger.info(f"Found {len(patterns)} sensitive data type(s) in: {file_path}")
117
+ return {
118
+ "file_path": file_path,
119
+ "contains_sensitive_data": True,
120
+ "sensitive_data_types": sensitive_data_types,
121
+ "risk_summary": f"File contains {sum(patterns.values())} sensitive data item(s) across {len(patterns)} type(s)"
122
+ }
123
+ return None
124
+
125
+
126
+ def process_attachments_for_redaction(
127
+ attachments: List[Dict[str, Any]],
128
+ logger: MCPLogger
129
+ ) -> List[Dict[str, Any]]:
130
+ """
131
+ Process file attachments and extract redaction patterns
132
+
133
+ Args:
134
+ attachments: List of attachment dicts with 'type' and 'file_path' or 'filePath'
135
+ logger: MCPLogger instance
136
+
137
+ Returns:
138
+ List of files with redactions found
139
+ """
140
+ files_with_redactions = []
141
+
142
+ for attachment in attachments:
143
+ att_type = attachment.get("type")
144
+ att_path = attachment.get("file_path") or attachment.get("filePath")
145
+
146
+ if att_type != "file":
147
+ logger.debug(f"Skipping non-file attachment (type={att_type}): {att_path}")
148
+ continue
149
+
150
+ if not att_path:
151
+ logger.debug("Skipping attachment with no file_path")
152
+ continue
153
+
154
+ try:
155
+ with open(att_path, 'r', encoding='utf-8', errors='replace') as f:
156
+ content = f.read()
157
+
158
+ result = process_single_file_for_redaction(att_path, content, logger)
159
+ if result:
160
+ files_with_redactions.append(result)
161
+
162
+ except Exception as e:
163
+ logger.warning(f"Could not read attachment file {att_path}: {e}")
164
+
165
+ return files_with_redactions
166
+
167
+
168
+ async def inspect_and_enforce(
169
+ is_request: bool,
170
+ session_id: str,
171
+ logger: MCPLogger,
172
+ audit_logger: AuditTrailLogger,
173
+ app_uid: str,
174
+ event_id: str,
175
+ server_name: str,
176
+ tool_name: str,
177
+ content_data: Dict[str, Any],
178
+ prompt_id: str,
179
+ cwd: Optional[str],
180
+ current_files: Optional[List[str]] = None,
181
+ client_name: str = "ide-tools"
182
+ ) -> Dict[str, Any]:
183
+ """
184
+ Generic handler for API inspection and decision enforcement
185
+
186
+ Args:
187
+ is_request: True for request inspection, False for response inspection
188
+ session_id: Session identifier
189
+ logger: Logger instance
190
+ audit_logger: Audit logger instance
191
+ app_uid: Application UID
192
+ event_id: Event identifier
193
+ server_name: Server name (IDE-specific, e.g. "cursor_tools_mcp")
194
+ tool_name: Tool/hook name
195
+ content_data: Data to inspect
196
+ prompt_id: Prompt identifier
197
+ cwd: Current working directory
198
+ current_files: Optional list of current files
199
+ client_name: Client name (e.g. "cursor", "claude-code")
200
+
201
+ Returns:
202
+ Decision dict from security API
203
+
204
+ Raises:
205
+ Exception: If decision blocks the operation or API call fails
206
+ """
207
+ agent_context = AgentContext(
208
+ last_user_prompt="",
209
+ user_prompt_id=prompt_id,
210
+ context_summary=""
211
+ )
212
+
213
+ env_context = EnvironmentContext(
214
+ session_id=session_id,
215
+ workspace={
216
+ "roots": [cwd] if cwd else [],
217
+ "current_files": current_files or []
218
+ },
219
+ client=client_name,
220
+ client_version=__version__,
221
+ selection_hash=""
222
+ )
223
+
224
+ async with SecurityPolicyClient(
225
+ session_id=session_id,
226
+ logger=logger,
227
+ audit_logger=audit_logger,
228
+ app_id=app_uid
229
+ ) as client:
230
+ if is_request:
231
+ policy_request = create_policy_request(
232
+ event_id=event_id,
233
+ server=ServerRef(
234
+ name=server_name,
235
+ transport="stdio",
236
+ context="ide"
237
+ ),
238
+ tool=ToolRef(
239
+ name=tool_name
240
+ ),
241
+ agent_context=agent_context,
242
+ env_context=env_context,
243
+ arguments=content_data
244
+ )
245
+ decision = await client.inspect_policy_request(
246
+ policy_request=policy_request,
247
+ prompt_id=prompt_id
248
+ )
249
+ else:
250
+ policy_response = create_policy_response(
251
+ event_id=event_id,
252
+ server=ServerRef(
253
+ name=server_name,
254
+ transport="stdio",
255
+ context="ide"
256
+ ),
257
+ tool=ToolRef(
258
+ name=tool_name
259
+ ),
260
+ response_content=safe_json_dumps(content_data),
261
+ agent_context=agent_context,
262
+ env_context=env_context
263
+ )
264
+ decision = await client.inspect_policy_response(
265
+ policy_response=policy_response,
266
+ prompt_id=prompt_id
267
+ )
268
+
269
+ await DecisionHandler(
270
+ logger=logger,
271
+ audit_logger=audit_logger,
272
+ session_id=session_id,
273
+ app_id=app_uid
274
+ ).enforce_decision(
275
+ decision=decision,
276
+ is_request=is_request,
277
+ event_id=event_id,
278
+ tool_name=tool_name,
279
+ content_data=content_data,
280
+ operation_type="hook",
281
+ prompt_id=prompt_id,
282
+ server_name=server_name,
283
+ error_message_prefix=f"Operation blocked by security policy"
284
+ )
285
+
286
+ return decision
@@ -0,0 +1,11 @@
1
+ """
2
+ Cursor IDE Handler
3
+
4
+ Handles Cursor-specific hooks and operations.
5
+ """
6
+
7
+ from .router import route_cursor_hook
8
+
9
+ __all__ = [
10
+ "route_cursor_hook",
11
+ ]
@@ -0,0 +1,58 @@
1
+ """
2
+ Cursor Hook Constants
3
+
4
+ Configuration values specific to Cursor hook handlers.
5
+ """
6
+
7
+ from enum import Enum
8
+
9
+ from ide_tools.common.hooks.types import HookConfig, OutputFormat
10
+ from ide_tools.cursor.format import cursor_output_formatter
11
+
12
+
13
+ class HookPermission(str, Enum):
14
+ """Cursor hook response permission values"""
15
+ ALLOW = "allow"
16
+ DENY = "deny"
17
+
18
+
19
+ # Cursor-specific configuration
20
+ CURSOR_CONFIG = HookConfig(
21
+ output_format=OutputFormat(
22
+ allow_exit_code=0,
23
+ deny_exit_code=1,
24
+ error_exit_code=1,
25
+ formatter=cursor_output_formatter
26
+ ),
27
+ server_name="mcpower_cursor",
28
+ client_name="cursor",
29
+ max_content_length=100000
30
+ )
31
+
32
+ # Hook descriptions from https://cursor.com/docs/agent/hooks#hook-events
33
+ CURSOR_HOOKS = {
34
+ "beforeShellExecution": {
35
+ "name": "beforeShellExecution",
36
+ "description": "Triggered before a shell command is executed by the agent. "
37
+ "Allows inspection and potential blocking of shell commands.",
38
+ "version": "1.0.0"
39
+ },
40
+ "afterShellExecution": {
41
+ "name": "afterShellExecution",
42
+ "description": "Triggered after a shell command completes execution. "
43
+ "Provides access to command output and exit status.",
44
+ "version": "1.0.0"
45
+ },
46
+ "beforeReadFile": {
47
+ "name": "beforeReadFile",
48
+ "description": "Triggered before the agent reads a file. "
49
+ "Allows inspection and potential blocking of file read operations.",
50
+ "version": "1.0.0"
51
+ },
52
+ "beforeSubmitPrompt": {
53
+ "name": "beforeSubmitPrompt",
54
+ "description": "Triggered before a prompt is submitted to the AI model. "
55
+ "Allows inspection and modification of prompts.",
56
+ "version": "1.0.0"
57
+ }
58
+ }
@@ -0,0 +1,35 @@
1
+ """
2
+ Cursor-specific output formatting
3
+ """
4
+
5
+ import json
6
+ from typing import Optional
7
+
8
+
9
+ def cursor_output_formatter(hook_type: str, allowed: bool, user_msg: Optional[str], agent_msg: Optional[str]) -> str:
10
+ """
11
+ Format output for Cursor IDE
12
+
13
+ Args:
14
+ hook_type: "permission" or "continue"
15
+ allowed: True for allow/continue, False for deny/block
16
+ user_msg: Message for user
17
+ agent_msg: Message for agent/logs
18
+
19
+ Returns:
20
+ JSON string in Cursor format
21
+ """
22
+ if hook_type == "permission":
23
+ result = {"permission": "allow" if allowed else "deny"}
24
+ if user_msg:
25
+ result["user_message"] = user_msg
26
+ if agent_msg:
27
+ result["agent_message"] = agent_msg
28
+ else: # continue
29
+ result = {"continue": allowed}
30
+ if user_msg:
31
+ result["user_message"] = user_msg
32
+ if agent_msg:
33
+ result["agent_message"] = agent_msg
34
+
35
+ return json.dumps(result)
@@ -0,0 +1,101 @@
1
+ """
2
+ Cursor Router
3
+
4
+ Routes Cursor hook calls to appropriate handlers.
5
+ """
6
+
7
+ import asyncio
8
+ import json
9
+ import sys
10
+ import uuid
11
+
12
+ from ide_tools.common.hooks.init import handle_init
13
+ from ide_tools.common.hooks.prompt_submit import handle_prompt_submit
14
+ from ide_tools.common.hooks.read_file import handle_read_file
15
+ from ide_tools.common.hooks.shell_execution import handle_shell_execution
16
+ from modules.logs.audit_trail import AuditTrailLogger
17
+ from modules.logs.logger import MCPLogger
18
+ from .constants import CURSOR_HOOKS, CURSOR_CONFIG
19
+
20
+
21
+ def route_cursor_hook(logger: MCPLogger, audit_logger: AuditTrailLogger, stdin_input: str):
22
+ """
23
+ Route Cursor hook to appropriate shared handler
24
+
25
+ Args:
26
+ logger: MCPLogger instance
27
+ audit_logger: AuditTrailLogger instance
28
+ stdin_input: Raw input string from stdin
29
+ """
30
+ try:
31
+ input_data = json.loads(stdin_input)
32
+
33
+ hook_event_name = input_data.get("hook_event_name")
34
+ if not hook_event_name:
35
+ logger.error("Missing required field 'hook_event_name' in input")
36
+ sys.exit(1)
37
+
38
+ conversation_id = input_data.get("conversation_id")
39
+ if not conversation_id:
40
+ logger.error("Missing required field 'conversation_id' in input")
41
+ sys.exit(1)
42
+
43
+ generation_id = input_data.get("generation_id")
44
+ if not generation_id:
45
+ logger.error("Missing required field 'generation_id' in input")
46
+ sys.exit(1)
47
+
48
+ workspace_roots = input_data.get("workspace_roots")
49
+ if workspace_roots is None:
50
+ logger.error("Missing required field 'workspace_roots' in input")
51
+ sys.exit(1)
52
+
53
+ if not isinstance(workspace_roots, list):
54
+ logger.error("Invalid 'workspace_roots': must be a list")
55
+ sys.exit(1)
56
+
57
+ prompt_id = conversation_id[:8]
58
+ event_id = uuid.uuid4().hex[:8]
59
+ cwd = workspace_roots[0] if workspace_roots else None
60
+
61
+ logger.info(
62
+ f"Cursor router: routing to {hook_event_name} handler "
63
+ f"(prompt_id={prompt_id}, event_id={event_id}, cwd={cwd})")
64
+
65
+ # Route to appropriate handler
66
+ if hook_event_name == "init":
67
+ asyncio.run(handle_init(
68
+ logger=logger,
69
+ audit_logger=audit_logger,
70
+ event_id=event_id,
71
+ prompt_id=prompt_id,
72
+ cwd=cwd,
73
+ server_name=CURSOR_CONFIG.server_name,
74
+ client_name="cursor",
75
+ hooks=CURSOR_HOOKS
76
+ ))
77
+ elif hook_event_name == "beforeShellExecution":
78
+ asyncio.run(
79
+ handle_shell_execution(logger, audit_logger, stdin_input, prompt_id, event_id, cwd, CURSOR_CONFIG,
80
+ hook_event_name, is_request=True))
81
+ elif hook_event_name == "afterShellExecution":
82
+ asyncio.run(
83
+ handle_shell_execution(logger, audit_logger, stdin_input, prompt_id, event_id, cwd, CURSOR_CONFIG,
84
+ hook_event_name, is_request=False))
85
+ elif hook_event_name == "beforeReadFile":
86
+ asyncio.run(handle_read_file(logger, audit_logger, stdin_input, prompt_id, event_id, cwd, CURSOR_CONFIG,
87
+ hook_event_name))
88
+ elif hook_event_name == "beforeSubmitPrompt":
89
+ asyncio.run(
90
+ handle_prompt_submit(logger, audit_logger, stdin_input, prompt_id, event_id, cwd, CURSOR_CONFIG,
91
+ hook_event_name))
92
+ else:
93
+ logger.error(f"Unknown hook_event_name: {hook_event_name}")
94
+ sys.exit(1)
95
+
96
+ except json.JSONDecodeError as e:
97
+ logger.error(f"Failed to parse input JSON: {e}")
98
+ sys.exit(1)
99
+ except Exception as e:
100
+ logger.error(f"Routing error: {e}", exc_info=True)
101
+ sys.exit(1)
ide_tools/router.py ADDED
@@ -0,0 +1,48 @@
1
+ """
2
+ IDE Tools Router
3
+
4
+ Routes hook calls to appropriate IDE-specific routers based on --ide flag.
5
+ """
6
+
7
+ import sys
8
+ from typing import Optional
9
+
10
+ from modules.logs.audit_trail import AuditTrailLogger
11
+ from modules.logs.logger import MCPLogger
12
+
13
+
14
+ def main(logger: MCPLogger, audit_logger: AuditTrailLogger, ide: str, context: Optional[str]):
15
+ """
16
+ Main entry point for IDE tools - routes to appropriate IDE router
17
+
18
+ Args:
19
+ logger: MCPLogger instance
20
+ audit_logger: AuditTrailLogger instance
21
+ ide: IDE name (e.g., "cursor")
22
+ context: Additional context (to be verified as optional by the associated --ide handler)
23
+ """
24
+ # Monkey patch sys.exit to log exit code
25
+ original_exit = sys.exit
26
+
27
+ def logged_exit(code=0):
28
+ logger.info(f"sys.exit called with code: {code}")
29
+ original_exit(code)
30
+
31
+ sys.exit = logged_exit
32
+
33
+ logger.info(f"IDE Tools router: ide={ide}, context={context}")
34
+
35
+ # Read stdin input once at the top level (raw string)
36
+ # Each handler will parse it according to its own schema
37
+ stdin_input = sys.stdin.read()
38
+
39
+ # Route to appropriate IDE handler with the raw input string
40
+ if ide == "cursor":
41
+ from ide_tools.cursor import route_cursor_hook
42
+ route_cursor_hook(logger, audit_logger, stdin_input)
43
+ elif ide == "claude-code":
44
+ from ide_tools.claude_code import route_claude_code_hook
45
+ route_claude_code_hook(logger, audit_logger, stdin_input)
46
+ else:
47
+ logger.error(f"Unknown IDE: {ide}")
48
+ sys.exit(1)
main.py CHANGED
@@ -45,13 +45,20 @@ def main():
45
45
  logger.info('=' * 66)
46
46
  logger.info('')
47
47
 
48
- # Start config monitoring
49
- config.start_monitoring(logger)
50
-
51
48
  # Setup audit trail logging
52
49
  audit_logger = setup_audit_trail_logger(logger)
53
50
 
54
- logger.info(f"Starting MCPower Proxy:\n{{'args': {args}, 'log_file': {log_file}, 'log_level': {log_level}, 'debug_mode': {debug_mode}}}")
51
+ if args.ide_tool:
52
+ from ide_tools.router import main as ide_tools_main
53
+ ide_tools_main(logger, audit_logger, args.ide, args.context)
54
+ return
55
+
56
+ # Continue with MCP wrapper mode
57
+ # Start config monitoring
58
+ config.start_monitoring(logger)
59
+
60
+ logger.info(
61
+ f"Starting MCPower Proxy:\n{{'args': {args}, 'log_file': {log_file}, 'log_level': {log_level}, 'debug_mode': {debug_mode}}}")
55
62
 
56
63
  try:
57
64
  # Parse JSON/JSONC config
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcpower-proxy
3
- Version: 0.0.67
3
+ Version: 0.0.77
4
4
  Summary: MCPower Security proxy
5
5
  Author-email: MCPower Security <support@mcpower.tech>
6
6
  License: Apache License
@@ -209,14 +209,15 @@ Keywords: mcp,security,proxy,monitoring,audit,redaction,policy-enforcement
209
209
  Requires-Python: ~=3.11.0
210
210
  Description-Content-Type: text/markdown
211
211
  License-File: LICENSE
212
- Requires-Dist: fastmcp==2.13.0.1
212
+ Requires-Dist: fastmcp==2.13.0.2
213
213
  Requires-Dist: httpx>=0.25.0
214
214
  Requires-Dist: mcp>=1.0.0
215
215
  Requires-Dist: watchdog>=3.0.0
216
216
  Requires-Dist: jsonc-parser>=1.1.5
217
217
  Requires-Dist: jsonpath-ng>=1.7.0
218
218
  Requires-Dist: pydantic>=2.8.0
219
- Requires-Dist: mcpower-shared==0.1.1
219
+ Requires-Dist: mcpower-shared==0.1.4
220
+ Requires-Dist: bashlex>=0.18
220
221
  Dynamic: license-file
221
222
 
222
223
  # MCPower Proxy
@@ -0,0 +1,62 @@
1
+ main.py,sha256=MahoqxG5euEJwLhosv2OVUkVbTaMkph_je8lgmtc7Z4,3920
2
+ ide_tools/__init__.py,sha256=odLisqEeKVuZupQoeM-uP9WgQseVTYQG0eP2hhwUyAc,250
3
+ ide_tools/router.py,sha256=PbGz1cwUXR3Bcy879W2wgmT4f2uThXiXevpWSxcgKZQ,1538
4
+ ide_tools/common/__init__.py,sha256=cW2cN5y2l4PHGkkWtYgydrtXtmLU_UipJAf_c0VMTk0,65
5
+ ide_tools/common/hooks/__init__.py,sha256=O-waaJU1OQFxplrLZymSSiIyLDNlGlki6nX-nbJiqz0,61
6
+ ide_tools/common/hooks/init.py,sha256=X0J_rEjU6qjvDaPOh-obzSqfICMsOGc6VxRjcZqLTqQ,4117
7
+ ide_tools/common/hooks/output.py,sha256=FBezJL1S5vzLJWW_cLht4XFLDJvhV_w-UTqCQOLEusE,1879
8
+ ide_tools/common/hooks/prompt_submit.py,sha256=_FysGrlJXcblex-OapWVIv1bedP1IKR2d1cvkINU0uM,4907
9
+ ide_tools/common/hooks/read_file.py,sha256=FBHTxOXrQWlw2qtddAq4gfv5h1g6rTbQ-0uqqL9wXE0,6456
10
+ ide_tools/common/hooks/shell_execution.py,sha256=KbJSGLW__bPso45eAlbV13nnkKYwwd7-KodZ6VyUnS0,9522
11
+ ide_tools/common/hooks/shell_parser_bashlex.py,sha256=ePit2jduHvBYkmEvcslpjCGJ5H-amVEm1We1vVCmMNc,15002
12
+ ide_tools/common/hooks/types.py,sha256=ndisZ8YoasQ3HlVzzyLmpiBCQJs43YPmixbaIIxRpZM,1023
13
+ ide_tools/common/hooks/utils.py,sha256=7Q95IZZG_lShq5Jvw78M7QN5-tVNVeFzLU33qB8boEU,9425
14
+ ide_tools/cursor/__init__.py,sha256=YW_V8m0A0bou0wQW_wy3nt2L_7MaNWeNKYBx-NQkilw,153
15
+ ide_tools/cursor/constants.py,sha256=KMRBRqxRxTdemMoq81TVG6avt3ATtsPo4aJo8XhSctk,1804
16
+ ide_tools/cursor/format.py,sha256=Lh-KH1IlsLL-0B98Bz-ywxpwXL8urK7yPteZGBTPOiY,972
17
+ ide_tools/cursor/router.py,sha256=GXmXcNSIA9pe1vnmmoYpz0dyC_B7OSpQwOVHIV7YUEI,3893
18
+ mcpower_proxy-0.0.77.dist-info/licenses/LICENSE,sha256=U6WUzdnBrbmVxBmY75ikW-KtinwYnowZ7yNb5hECrvY,11337
19
+ modules/__init__.py,sha256=mJglXQwSRhU-bBv4LXgfu7NfGN9K4BeQWMPApen5rAA,30
20
+ modules/decision_handler.py,sha256=P8isKzf4GIWz9SK-VJPtO8VJEgNp7rAIcVZngnaLHmw,9574
21
+ modules/apis/__init__.py,sha256=Y5WZpKJzHpnRJebk0F80ZRTjR2PpA2LlYLgqI3XlmRo,15
22
+ modules/apis/security_policy.py,sha256=3fljaTpzfh_Nj0-jVvbnCJBL-CZxvqFNWfSlrAawsBc,15103
23
+ modules/logs/__init__.py,sha256=dpboUQjuO02z8K-liCbm2DYkCa-CB_ZDV9WSSjNm7Fs,15
24
+ modules/logs/audit_trail.py,sha256=yoxzvRDI8ldjC-5o9__PkvaAbM33jWbq_8Sm6uKj8o8,6198
25
+ modules/logs/logger.py,sha256=MJS0P8VEzUX-5udzQitznaBPCBAcZJCygUgwaDWSq94,4087
26
+ modules/redaction/__init__.py,sha256=e5NTmp-zonUdzzscih-w_WQ-X8Nvb8CE8b_d6SbrwWg,316
27
+ modules/redaction/constants.py,sha256=xbDSX8n72FuJu6JJ_sbBE0f5OcWuwEwHxBZuK9Xz-TI,1213
28
+ modules/redaction/gitleaks_rules.py,sha256=8NHR5kr2XSrPn4c0PsjD0je6p8gmNzq2vI098QUxAx0,46397
29
+ modules/redaction/pii_rules.py,sha256=H7WOIMZZK8mkwdvnBe0J2nPwqzKqGHdUbCSGpxJGT8s,7666
30
+ modules/redaction/redactor.py,sha256=Y3PSxXJSLJZj8gkKZ3OQ7XxoIPUilFk6gY0dbeqfjwE,23352
31
+ modules/ui/__init__.py,sha256=YlW4XfQEGW1ezg3UFU59nHw95LicmlpNPhim5IqSB50,34
32
+ modules/ui/classes.py,sha256=ZvVRdzO_hD4WnpS3_eVa0WCyaooXiYVpHLzQkzBaH6M,1777
33
+ modules/ui/confirmation.py,sha256=y2A8j5_z64cDdbvUEh4lI8iTgTFBcTjVbIXioMfmkpw,7740
34
+ modules/ui/simple_dialog.py,sha256=PZW3WSPUVtnGXx-Kkg6hTQTr5NvpTQVhgHyro1z_3aY,3900
35
+ modules/ui/xdialog/__init__.py,sha256=KYQKVF6pGrwc99swRBxtWVXM__j9kVX_r6KikzbCOM4,9359
36
+ modules/ui/xdialog/constants.py,sha256=UjtqzT_O3OHUXJOyeTGroOUnaxdVyYukf7kK6vj1rog,200
37
+ modules/ui/xdialog/mac_dialogs.py,sha256=6r3hkJzJJdHSt-aH1Hy4lZ1MEuZK4Kc5D_YiWglKHAA,6129
38
+ modules/ui/xdialog/tk_dialogs.py,sha256=isxxN_mvZUFUQu8RD1J-GC7UMH2spqR3v_domgRbczQ,2403
39
+ modules/ui/xdialog/windows_custom_dialog.py,sha256=tcdo35d4ZoBydAj-4yzzgW2luw97-Sdjsr3X_3-a7jM,14849
40
+ modules/ui/xdialog/windows_dialogs.py,sha256=ohOoK4ciyv2s4BC9r7-zvGL6mECM-RCPTVOmzDnD6VQ,7626
41
+ modules/ui/xdialog/windows_structs.py,sha256=xzG44OGT5hBFnimJgOLXZBhmpQ_9CFxjtz-QNjP-VCw,8698
42
+ modules/ui/xdialog/yad_dialogs.py,sha256=EiajZVJg-xDwYymz1fyQwLtT5DzbJR3e8plMEnOgcpo,6933
43
+ modules/ui/xdialog/zenity_dialogs.py,sha256=wE71I_Ovf0sjhxHVNocbrhhDd8Y8X8loLETp8TMGMPQ,4512
44
+ modules/utils/__init__.py,sha256=Ptwu1epT_dW6EHjGkzGHAB-MbrrmYAlcPXGGcr4PvwE,20
45
+ modules/utils/cli.py,sha256=5QLwsZNMKdyh3xt4NDk20vCGD-eqZ514LnVWA0J0Lbg,2414
46
+ modules/utils/config.py,sha256=YuGrIYfBsOYABWjFoZosObPz-R7Wdul16RnDed_glYI,6654
47
+ modules/utils/copy.py,sha256=9OJIqWn8PxPZXr3DTt_01jp0YgmPimckab1969WFh0c,1075
48
+ modules/utils/ids.py,sha256=rhhRz7RmFjuJGYLft1erHz7vJII1DRpr3iHxBhhFl1s,5743
49
+ modules/utils/json.py,sha256=OA-JtSBqh9qd1yfm-iyOefNBMH3ITFUdxAkj7O_JZ-Y,4024
50
+ modules/utils/mcp_configs.py,sha256=DZaujZnF9LlPDJHzyepH7fWSt1GTr-FEmShPCqnZ5aI,1829
51
+ modules/utils/platform.py,sha256=Kz1Dh_UkvMbfXqiyZIEj7INYaWE9wT6nM9WIKXM91uM,552
52
+ modules/utils/string.py,sha256=cOuwWReyBwOgjxtTRPq1R6pCpfkgfqVmjdiaDPufIZU,456
53
+ wrapper/__init__.py,sha256=OJUsuWSoN1JqIHq4bSrzuL7ufcYJcwAmYCrJjLH44LM,22
54
+ wrapper/__version__.py,sha256=4LwZ6ftjxW5rGtS8e8B6V7iXNQZbgnact3whK05F-gg,82
55
+ wrapper/middleware.py,sha256=rXOIduymDLeJ56AWmpMnRnkf7sCmSz7jADMk-v8lcsw,30232
56
+ wrapper/schema.py,sha256=O-CtKI9eJ4eEnqeUXPCrK7QJAFJrdp_cFbmMyg452Aw,7952
57
+ wrapper/server.py,sha256=zoIW_bqXV9vKZNFtD-ij0X_LtKJEjucda6lQI5mU6qY,3440
58
+ mcpower_proxy-0.0.77.dist-info/METADATA,sha256=qX1CZtp76YNug7gOFHOmdJG4gXn3FvV7P_bHQ9iySV0,15698
59
+ mcpower_proxy-0.0.77.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
60
+ mcpower_proxy-0.0.77.dist-info/entry_points.txt,sha256=0smL8dxE7ERNz6XEggNaUC3QzKp8mD-v4q5nVEo0MXE,48
61
+ mcpower_proxy-0.0.77.dist-info/top_level.txt,sha256=OcCYMHHqbZq3mP5IZDRGdHUNOsKhT1XVnk_mDF_49Es,31
62
+ mcpower_proxy-0.0.77.dist-info/RECORD,,
@@ -1,3 +1,4 @@
1
+ ide_tools
1
2
  main
2
3
  modules
3
4
  wrapper