mcpower-proxy 0.0.67__tar.gz → 0.0.68__tar.gz
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.
Potentially problematic release.
This version of mcpower-proxy might be problematic. Click here for more details.
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/PKG-INFO +1 -1
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/pyproject.toml +1 -1
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/mcpower_proxy.egg-info/PKG-INFO +1 -1
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/apis/security_policy.py +3 -1
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/utils/cli.py +2 -4
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/wrapper/__version__.py +1 -1
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/wrapper/middleware.py +20 -16
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/LICENSE +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/README.md +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/setup.cfg +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/LICENSE +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/main.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/mcpower_proxy.egg-info/SOURCES.txt +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/mcpower_proxy.egg-info/dependency_links.txt +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/mcpower_proxy.egg-info/entry_points.txt +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/mcpower_proxy.egg-info/requires.txt +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/mcpower_proxy.egg-info/top_level.txt +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/apis/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/logs/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/logs/audit_trail.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/logs/logger.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/redaction/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/redaction/constants.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/redaction/gitleaks_rules.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/redaction/pii_rules.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/redaction/redactor.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/classes.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/confirmation.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/simple_dialog.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/constants.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/mac_dialogs.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/tk_dialogs.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/windows_custom_dialog.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/windows_dialogs.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/windows_structs.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/yad_dialogs.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/zenity_dialogs.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/utils/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/utils/config.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/utils/copy.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/utils/ids.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/utils/json.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/utils/mcp_configs.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/wrapper/__init__.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/wrapper/schema.py +0 -0
- {mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/wrapper/server.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Security Policy API Client"""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import time
|
|
4
5
|
import uuid
|
|
5
6
|
from typing import Dict, Any, Optional, List
|
|
6
|
-
import time
|
|
7
7
|
|
|
8
8
|
import httpx
|
|
9
9
|
|
|
@@ -13,6 +13,7 @@ from modules.logs.logger import MCPLogger
|
|
|
13
13
|
from modules.redaction import redact
|
|
14
14
|
from modules.utils.config import get_api_url, get_user_id
|
|
15
15
|
from modules.utils.json import safe_json_dumps, to_dict
|
|
16
|
+
from wrapper.__version__ import __version__
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class SecurityAPIError(Exception):
|
|
@@ -166,6 +167,7 @@ class SecurityPolicyClient:
|
|
|
166
167
|
|
|
167
168
|
headers = {
|
|
168
169
|
"Content-Type": "application/json",
|
|
170
|
+
"User-Agent": f"MCPower-{__version__}",
|
|
169
171
|
"X-User-UID": self.user_id,
|
|
170
172
|
"X-App-UID": self.app_id
|
|
171
173
|
}
|
|
@@ -7,7 +7,7 @@ import argparse
|
|
|
7
7
|
def parse_args():
|
|
8
8
|
"""Parse command line arguments"""
|
|
9
9
|
parser = argparse.ArgumentParser(
|
|
10
|
-
description="
|
|
10
|
+
description="Transparent MCP wrapper with security middleware for real-time policy enforcement and monitoring.",
|
|
11
11
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
12
12
|
epilog="""
|
|
13
13
|
Examples:
|
|
@@ -24,10 +24,8 @@ Examples:
|
|
|
24
24
|
%(prog)s --wrapped-config '{"command": "node", "args": ["server.js"]}' --name MyWrapper
|
|
25
25
|
|
|
26
26
|
Reference Links:
|
|
27
|
-
•
|
|
28
|
-
• FastMCP Middleware: https://gofastmcp.com/servers/middleware
|
|
27
|
+
• MCPower Proxy: https://github.com/ai-mcpower/mcpower-proxy
|
|
29
28
|
• MCP Official: https://modelcontextprotocol.io
|
|
30
|
-
• Claude MCP Config: https://docs.anthropic.com/en/docs/claude-code/mcp
|
|
31
29
|
"""
|
|
32
30
|
)
|
|
33
31
|
|
|
@@ -12,6 +12,10 @@ from typing import Any, Dict, List, Optional
|
|
|
12
12
|
from fastmcp.exceptions import FastMCPError
|
|
13
13
|
from fastmcp.server.middleware.middleware import Middleware, MiddlewareContext, CallNext
|
|
14
14
|
from fastmcp.server.proxy import ProxyClient
|
|
15
|
+
|
|
16
|
+
from mcpower_shared.mcp_types import (create_policy_request, create_policy_response, AgentContext, EnvironmentContext,
|
|
17
|
+
InitRequest,
|
|
18
|
+
ServerRef, ToolRef, UserConfirmation)
|
|
15
19
|
from modules.apis.security_policy import SecurityPolicyClient
|
|
16
20
|
from modules.logs.audit_trail import AuditTrailLogger
|
|
17
21
|
from modules.logs.logger import MCPLogger
|
|
@@ -24,10 +28,6 @@ from modules.utils.json import safe_json_dumps, to_dict
|
|
|
24
28
|
from modules.utils.mcp_configs import extract_wrapped_server_info
|
|
25
29
|
from wrapper.schema import merge_input_schema_with_existing
|
|
26
30
|
|
|
27
|
-
from mcpower_shared.mcp_types import (create_policy_request, create_policy_response, AgentContext, EnvironmentContext,
|
|
28
|
-
InitRequest,
|
|
29
|
-
ServerRef, ToolRef, UserConfirmation)
|
|
30
|
-
|
|
31
31
|
|
|
32
32
|
class MockContext:
|
|
33
33
|
"""Mock context for internal operations"""
|
|
@@ -88,14 +88,18 @@ class SecurityMiddleware(Middleware):
|
|
|
88
88
|
async def on_message(self, context: MiddlewareContext, call_next: CallNext) -> Any:
|
|
89
89
|
self.logger.info(f"on_message: {redact(safe_json_dumps(context))}")
|
|
90
90
|
|
|
91
|
-
#
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
self.
|
|
91
|
+
# Skip workspace check for `initialize` calls to avoid premature app_uid changes.
|
|
92
|
+
# The `initialize` request doesn't contain workspace data, so checking it would
|
|
93
|
+
# cause unnecessary audit log flushes before the actual workspace init arrives.
|
|
94
|
+
if context.method != "initialize":
|
|
95
|
+
# Check workspace roots and re-initialize app_uid if workspace changed
|
|
96
|
+
workspace_roots = await self._extract_workspace_roots(context)
|
|
97
|
+
current_workspace_root = workspace_roots[0] if workspace_roots else str(Path.home() / ".mcpower")
|
|
98
|
+
if current_workspace_root != self._last_workspace_root:
|
|
99
|
+
self.logger.debug(f"Workspace root changed from {self._last_workspace_root} to {current_workspace_root}")
|
|
100
|
+
self._last_workspace_root = current_workspace_root
|
|
101
|
+
self.app_id = read_app_uid(logger=self.logger, project_folder_path=current_workspace_root)
|
|
102
|
+
self.audit_logger.set_app_uid(self.app_id)
|
|
99
103
|
|
|
100
104
|
operation_type = "message"
|
|
101
105
|
call_next_callback = call_next
|
|
@@ -184,12 +188,12 @@ class SecurityMiddleware(Middleware):
|
|
|
184
188
|
# FIXME: log_message should be redacted before logging,
|
|
185
189
|
self.logger.info(f"secure_log_handler: {str(log_message)[:100]}...")
|
|
186
190
|
# FIXME: log_message should be reviewed with policy before forwarding
|
|
187
|
-
|
|
191
|
+
|
|
188
192
|
# Handle case where log_message.data is a string instead of dict
|
|
189
193
|
# The default_log_handler expects data to be a dict with 'msg' and 'extra' keys
|
|
190
194
|
if hasattr(log_message, 'data') and isinstance(log_message.data, str):
|
|
191
195
|
log_message = safe_copy(log_message, {'data': {'msg': log_message.data, 'extra': None}})
|
|
192
|
-
|
|
196
|
+
|
|
193
197
|
return await ProxyClient.default_log_handler(log_message)
|
|
194
198
|
|
|
195
199
|
async def _handle_operation(self, context: MiddlewareContext, call_next, error_class, operation_type: str):
|
|
@@ -482,12 +486,12 @@ class SecurityMiddleware(Middleware):
|
|
|
482
486
|
file_path_prefix = 'file://'
|
|
483
487
|
if uri.startswith(file_path_prefix):
|
|
484
488
|
path = urllib.parse.unquote(uri[len(file_path_prefix):])
|
|
485
|
-
|
|
489
|
+
|
|
486
490
|
# Windows fix: remove leading slash before drive letter
|
|
487
491
|
# file:///C:/path becomes /C:/path, should be C:/path
|
|
488
492
|
if sys.platform == 'win32' and len(path) >= 3 and path[0] == '/' and path[2] == ':':
|
|
489
493
|
path = path[1:]
|
|
490
|
-
|
|
494
|
+
|
|
491
495
|
try:
|
|
492
496
|
resolved_path = str(Path(path).resolve())
|
|
493
497
|
workspace_roots.append(resolved_path)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/mcpower_proxy.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcpower_proxy-0.0.67 → mcpower_proxy-0.0.68}/src/modules/ui/xdialog/windows_custom_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|