mcpower-proxy 0.0.58__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 (43) hide show
  1. main.py +112 -0
  2. mcpower_proxy-0.0.58.dist-info/METADATA +250 -0
  3. mcpower_proxy-0.0.58.dist-info/RECORD +43 -0
  4. mcpower_proxy-0.0.58.dist-info/WHEEL +5 -0
  5. mcpower_proxy-0.0.58.dist-info/entry_points.txt +2 -0
  6. mcpower_proxy-0.0.58.dist-info/licenses/LICENSE +201 -0
  7. mcpower_proxy-0.0.58.dist-info/top_level.txt +3 -0
  8. modules/__init__.py +1 -0
  9. modules/apis/__init__.py +1 -0
  10. modules/apis/security_policy.py +322 -0
  11. modules/logs/__init__.py +1 -0
  12. modules/logs/audit_trail.py +162 -0
  13. modules/logs/logger.py +128 -0
  14. modules/redaction/__init__.py +13 -0
  15. modules/redaction/constants.py +38 -0
  16. modules/redaction/gitleaks_rules.py +1268 -0
  17. modules/redaction/pii_rules.py +271 -0
  18. modules/redaction/redactor.py +599 -0
  19. modules/ui/__init__.py +1 -0
  20. modules/ui/classes.py +48 -0
  21. modules/ui/confirmation.py +200 -0
  22. modules/ui/simple_dialog.py +104 -0
  23. modules/ui/xdialog/__init__.py +249 -0
  24. modules/ui/xdialog/constants.py +13 -0
  25. modules/ui/xdialog/mac_dialogs.py +190 -0
  26. modules/ui/xdialog/tk_dialogs.py +78 -0
  27. modules/ui/xdialog/windows_custom_dialog.py +426 -0
  28. modules/ui/xdialog/windows_dialogs.py +250 -0
  29. modules/ui/xdialog/windows_structs.py +183 -0
  30. modules/ui/xdialog/yad_dialogs.py +236 -0
  31. modules/ui/xdialog/zenity_dialogs.py +156 -0
  32. modules/utils/__init__.py +1 -0
  33. modules/utils/cli.py +46 -0
  34. modules/utils/config.py +193 -0
  35. modules/utils/copy.py +36 -0
  36. modules/utils/ids.py +160 -0
  37. modules/utils/json.py +120 -0
  38. modules/utils/mcp_configs.py +48 -0
  39. wrapper/__init__.py +1 -0
  40. wrapper/__version__.py +6 -0
  41. wrapper/middleware.py +750 -0
  42. wrapper/schema.py +227 -0
  43. wrapper/server.py +78 -0
modules/utils/json.py ADDED
@@ -0,0 +1,120 @@
1
+ """
2
+ JSON utilities for safe serialization and JSONC parsing
3
+ """
4
+ import json
5
+ from dataclasses import is_dataclass, asdict
6
+ from enum import Enum
7
+ from typing import Any
8
+
9
+ from jsonc_parser.parser import JsoncParser
10
+ from pydantic import BaseModel, AnyUrl
11
+
12
+
13
+ def to_dict(value: Any) -> Any:
14
+ """
15
+ Convert any value to a dict/primitive structure suitable for JSON serialization.
16
+ Handles dataclasses, Pydantic models, dicts, lists, Enums, and nested structures.
17
+
18
+ Args:
19
+ value: Any value to convert
20
+
21
+ Returns:
22
+ Dict, list, or primitive value ready for JSON serialization
23
+ """
24
+ if value is None:
25
+ return None
26
+ elif isinstance(value, (str, int, float, bool)):
27
+ return value
28
+ elif isinstance(value, Enum):
29
+ # Convert Enum to its value for JSON serialization
30
+ return value.value
31
+ elif isinstance(value, dict):
32
+ return {k: to_dict(v) for k, v in value.items()}
33
+ elif isinstance(value, (list, tuple)):
34
+ return [to_dict(item) for item in value]
35
+ elif is_dataclass(value):
36
+ # Use asdict and recursively convert Enums to their values
37
+ return to_dict(asdict(value))
38
+ elif hasattr(value, 'model_dump'):
39
+ return value.model_dump()
40
+ elif hasattr(value, '__dict__'):
41
+ # Extract __dict__ for objects, excluding private attrs only
42
+ return {k: to_dict(v) for k, v in value.__dict__.items() if not k.startswith('_')}
43
+ else:
44
+ # Last resort - convert to string
45
+ return str(value)
46
+
47
+
48
+ def safe_json_dumps(obj: Any, **kwargs) -> str:
49
+ """
50
+ Safely serialize objects to JSON, using Pydantic's built-in serialization when available
51
+ """
52
+ # If it's a Pydantic BaseModel, use its built-in JSON serialization
53
+ if isinstance(obj, BaseModel):
54
+ return obj.model_dump_json(**kwargs)
55
+
56
+ # If it's a dict or list that might contain Pydantic objects, use custom serializer
57
+ def default_serializer(o):
58
+ if isinstance(o, BaseModel):
59
+ return o.model_dump()
60
+ if isinstance(o, AnyUrl):
61
+ return str(o)
62
+ # Handle Enums by converting to their value
63
+ if isinstance(o, Enum):
64
+ return o.value
65
+ # Handle dataclasses properly - recursively convert via to_dict to handle nested Enums
66
+ if is_dataclass(o):
67
+ return to_dict(o)
68
+ # Handle other objects with dict method
69
+ if hasattr(o, 'dict') and callable(o.dict):
70
+ return o.dict()
71
+ if hasattr(o, '__dict__'):
72
+ return o.__dict__
73
+ # Fallback to string representation
74
+ return str(o)
75
+
76
+ return json.dumps(obj, default=default_serializer, **kwargs)
77
+
78
+
79
+ def stringify_jsonc(obj: Any, **kwargs) -> str:
80
+ """
81
+ Serialize object to JSONC format when possible, falling back to regular JSON
82
+
83
+ Args:
84
+ obj: The object to serialize
85
+ **kwargs: Additional arguments passed to the serializer
86
+
87
+ Returns:
88
+ JSONC string representation
89
+ """
90
+ try:
91
+ # Use regular JSON for serialization
92
+ return json.dumps(obj, **kwargs)
93
+ except Exception:
94
+ # Fallback to safe_json_dumps if regular json.dumps fails
95
+ return safe_json_dumps(obj, **kwargs)
96
+
97
+
98
+ def parse_jsonc(text: str) -> Any:
99
+ """
100
+ Parse JSONC (JSON with Comments) text using jsonc-parser, falling back to regular JSON if parsing fails
101
+
102
+ Args:
103
+ text: The JSONC/JSON string to parse
104
+
105
+ Returns:
106
+ Parsed object
107
+
108
+ Raises:
109
+ json.JSONDecodeError: If parsing fails with both JSONC and JSON parsers
110
+ """
111
+ try:
112
+ # Use jsonc-parser for JSONC handling (comments support)
113
+ return JsoncParser.parse_str(text)
114
+ except Exception as e:
115
+ # If JSONC parsing fails, try regular JSON as fallback
116
+ try:
117
+ return json.loads(text)
118
+ except json.JSONDecodeError:
119
+ # Re-raise the original JSONC error if JSON also fails
120
+ raise json.JSONDecodeError(f"JSONC parsing failed: {str(e)}", text, 0)
@@ -0,0 +1,48 @@
1
+ from fastmcp import mcp_config
2
+
3
+
4
+ def extract_wrapped_server_info(wrapper_server_name, logger, configs: dict) -> tuple[str, str]:
5
+ """
6
+ Extract wrapped server name and transport using FastMCP utilities
7
+
8
+ Returns:
9
+ tuple: (server_name, transport_name)
10
+ """
11
+ try:
12
+ # Parse config using FastMCP's built-in utilities
13
+ parsed_config = mcp_config.MCPConfig.from_dict(configs)
14
+
15
+ # Get the first server (the most common case - single wrapped server)
16
+ first_server = list(parsed_config.mcpServers.values())[0]
17
+ first_server_key = list(parsed_config.mcpServers.keys())[0]
18
+
19
+ # Extract server name
20
+ # If the key is "default" (from raw config conversion) - use the wrapper name
21
+ if first_server_key == "default":
22
+ server_name = wrapper_server_name
23
+ else:
24
+ server_name = first_server_key
25
+
26
+ # Extract transport using FastMCP's transport resolution
27
+ transport_obj = first_server.to_transport()
28
+ transport_class = type(transport_obj).__name__
29
+
30
+ # Map FastMCP transport classes to simple string names
31
+ transport_mapping = {
32
+ 'StdioTransport': 'stdio',
33
+ 'StreamableHttpTransport': 'streamable-http',
34
+ 'SSETransport': 'sse',
35
+ 'WSTransport': 'ws',
36
+ }
37
+
38
+ wrapped_server_transport_name = transport_mapping.get(transport_class,
39
+ transport_class.lower().replace('transport', ''))
40
+
41
+ logger.debug(f"Extracted wrapped server info: name={server_name}, "
42
+ f"transport={wrapped_server_transport_name}")
43
+
44
+ return server_name, wrapped_server_transport_name
45
+
46
+ except Exception as e:
47
+ logger.error(f"Failed to extract wrapped server info: {e}")
48
+ raise e
wrapper/__init__.py ADDED
@@ -0,0 +1 @@
1
+ # MCP Wrapper package
wrapper/__version__.py ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Wrapper MCP Server Version
4
+ """
5
+
6
+ __version__ = "0.0.58"