mcpower-proxy 0.0.64__tar.gz → 0.0.66__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.

Files changed (49) hide show
  1. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/PKG-INFO +1 -1
  2. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/pyproject.toml +1 -1
  3. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/mcpower_proxy.egg-info/PKG-INFO +1 -1
  4. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/logs/audit_trail.py +7 -3
  5. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/utils/ids.py +5 -3
  6. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/wrapper/__version__.py +1 -1
  7. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/wrapper/middleware.py +16 -8
  8. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/LICENSE +0 -0
  9. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/README.md +0 -0
  10. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/setup.cfg +0 -0
  11. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/LICENSE +0 -0
  12. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/main.py +0 -0
  13. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/mcpower_proxy.egg-info/SOURCES.txt +0 -0
  14. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/mcpower_proxy.egg-info/dependency_links.txt +0 -0
  15. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/mcpower_proxy.egg-info/entry_points.txt +0 -0
  16. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/mcpower_proxy.egg-info/requires.txt +0 -0
  17. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/mcpower_proxy.egg-info/top_level.txt +0 -0
  18. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/__init__.py +0 -0
  19. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/apis/__init__.py +0 -0
  20. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/apis/security_policy.py +0 -0
  21. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/logs/__init__.py +0 -0
  22. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/logs/logger.py +0 -0
  23. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/redaction/__init__.py +0 -0
  24. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/redaction/constants.py +0 -0
  25. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/redaction/gitleaks_rules.py +0 -0
  26. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/redaction/pii_rules.py +0 -0
  27. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/redaction/redactor.py +0 -0
  28. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/__init__.py +0 -0
  29. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/classes.py +0 -0
  30. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/confirmation.py +0 -0
  31. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/simple_dialog.py +0 -0
  32. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/__init__.py +0 -0
  33. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/constants.py +0 -0
  34. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/mac_dialogs.py +0 -0
  35. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/tk_dialogs.py +0 -0
  36. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/windows_custom_dialog.py +0 -0
  37. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/windows_dialogs.py +0 -0
  38. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/windows_structs.py +0 -0
  39. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/yad_dialogs.py +0 -0
  40. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/ui/xdialog/zenity_dialogs.py +0 -0
  41. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/utils/__init__.py +0 -0
  42. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/utils/cli.py +0 -0
  43. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/utils/config.py +0 -0
  44. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/utils/copy.py +0 -0
  45. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/utils/json.py +0 -0
  46. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/modules/utils/mcp_configs.py +0 -0
  47. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/wrapper/__init__.py +0 -0
  48. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/wrapper/schema.py +0 -0
  49. {mcpower_proxy-0.0.64 → mcpower_proxy-0.0.66}/src/wrapper/server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcpower-proxy
3
- Version: 0.0.64
3
+ Version: 0.0.66
4
4
  Summary: MCPower Security proxy
5
5
  Author-email: MCPower Security <support@mcpower.tech>
6
6
  License: Apache License
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mcpower-proxy"
3
- version = "0.0.64"
3
+ version = "0.0.66"
4
4
  description = "MCPower Security proxy"
5
5
  readme = "README.md"
6
6
  requires-python = "~=3.11.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcpower-proxy
3
- Version: 0.0.64
3
+ Version: 0.0.66
4
4
  Summary: MCPower Security proxy
5
5
  Author-email: MCPower Security <support@mcpower.tech>
6
6
  License: Apache License
@@ -130,16 +130,20 @@ class AuditTrailLogger:
130
130
 
131
131
  This is called by the middleware after workspace roots are available.
132
132
  All queued logs will be written with app_uid as the first key.
133
+ Supports updating app_uid when workspace context changes.
133
134
 
134
135
  Args:
135
136
  app_uid: The application UID from workspace root
136
137
  """
137
- if self.app_uid is not None:
138
- self.logger.warning(f"app_uid already set to {self.app_uid}, ignoring new value {app_uid}")
138
+ if self.app_uid == app_uid:
139
139
  return
140
140
 
141
+ if self.app_uid is not None:
142
+ self.logger.info(f"app_uid changed from {self.app_uid} to {app_uid}")
143
+ else:
144
+ self.logger.debug(f"app_uid set to: {app_uid}")
145
+
141
146
  self.app_uid = app_uid
142
- self.logger.debug(f"✅ app_uid set to: {app_uid}")
143
147
 
144
148
  # Flush all pending logs
145
149
  if self._pending_logs:
@@ -2,6 +2,7 @@
2
2
  Utilities for generating event IDs, session IDs, app UIDs, and timing helpers
3
3
  """
4
4
  import os
5
+ import sys
5
6
  import time
6
7
  import uuid
7
8
  from pathlib import Path
@@ -67,7 +68,8 @@ def _atomic_write_uuid(file_path: Path, new_uuid: str) -> bool:
67
68
  True if write succeeded, False if file exists
68
69
  """
69
70
  try:
70
- fd = os.open(str(file_path), os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o600)
71
+ mode = 0o666 if sys.platform == 'win32' else 0o600
72
+ fd = os.open(str(file_path), os.O_CREAT | os.O_EXCL | os.O_WRONLY, mode)
71
73
  try:
72
74
  os.write(fd, new_uuid.encode('utf-8'))
73
75
  finally:
@@ -91,7 +93,7 @@ def _get_or_create_uuid(uid_path: Path, logger, id_type: str) -> str:
91
93
  UUID string
92
94
  """
93
95
  uid_path.parent.mkdir(parents=True, exist_ok=True)
94
-
96
+
95
97
  max_attempts = 3
96
98
  for attempt in range(max_attempts):
97
99
  if uid_path.exists():
@@ -111,7 +113,7 @@ def _get_or_create_uuid(uid_path: Path, logger, id_type: str) -> str:
111
113
  new_uid = str(uuid.uuid4())
112
114
 
113
115
  if _atomic_write_uuid(uid_path, new_uid):
114
- logger.info(f"Generated {id_type}: {new_uid}")
116
+ logger.info(f"Generated {id_type}: {new_uid} at {uid_path}")
115
117
  return new_uid
116
118
 
117
119
  logger.debug(f"{id_type.title()} file created by another process, reading (attempt {attempt + 1}/{max_attempts})")
@@ -3,4 +3,4 @@
3
3
  Wrapper MCP Server Version
4
4
  """
5
5
 
6
- __version__ = "0.0.64"
6
+ __version__ = "0.0.66"
@@ -2,6 +2,7 @@
2
2
  FastMCP middleware for security policy enforcement
3
3
  Implements pre/post interception for all MCP operations
4
4
  """
5
+ import sys
5
6
  import time
6
7
  import urllib.parse
7
8
  from datetime import datetime, timezone
@@ -55,6 +56,7 @@ class SecurityMiddleware(Middleware):
55
56
  app_id: str = ""
56
57
  _TOOLS_INIT_DEBOUNCE_SECONDS = 60
57
58
  _last_tools_init_time: Optional[float] = None
59
+ _last_workspace_root: Optional[str] = None
58
60
 
59
61
  def __init__(self,
60
62
  wrapped_server_configs: dict,
@@ -69,6 +71,7 @@ class SecurityMiddleware(Middleware):
69
71
  self.logger = logger
70
72
  self.audit_logger = audit_logger
71
73
  self.app_id = ""
74
+ self._last_workspace_root = None
72
75
 
73
76
  self.wrapped_server_name, self.wrapped_server_transport = (
74
77
  extract_wrapped_server_info(self.wrapper_server_name, self.logger, self.wrapped_server_configs)
@@ -85,14 +88,13 @@ class SecurityMiddleware(Middleware):
85
88
  async def on_message(self, context: MiddlewareContext, call_next: CallNext) -> Any:
86
89
  self.logger.info(f"on_message: {redact(safe_json_dumps(context))}")
87
90
 
88
- # Ensure app_id is set before making API calls
89
- if not self.app_id:
90
- workspace_roots = await self._extract_workspace_roots(context)
91
- if workspace_roots:
92
- self.app_id = read_app_uid(logger=self.logger, project_folder_path=workspace_roots[0])
93
- else:
94
- # Fallback: read app_uid from ~/.mcpower when no workspace roots
95
- self.app_id = read_app_uid(logger=self.logger, project_folder_path=str(Path.home() / ".mcpower"))
91
+ # Check workspace roots and re-initialize app_uid if workspace changed
92
+ workspace_roots = await self._extract_workspace_roots(context)
93
+ current_workspace_root = workspace_roots[0] if workspace_roots else str(Path.home() / ".mcpower")
94
+ if current_workspace_root != self._last_workspace_root:
95
+ self.logger.debug(f"Workspace root changed from {self._last_workspace_root} to {current_workspace_root}")
96
+ self._last_workspace_root = current_workspace_root
97
+ self.app_id = read_app_uid(logger=self.logger, project_folder_path=current_workspace_root)
96
98
  self.audit_logger.set_app_uid(self.app_id)
97
99
 
98
100
  operation_type = "message"
@@ -480,6 +482,12 @@ class SecurityMiddleware(Middleware):
480
482
  file_path_prefix = 'file://'
481
483
  if uri.startswith(file_path_prefix):
482
484
  path = urllib.parse.unquote(uri[len(file_path_prefix):])
485
+
486
+ # Windows fix: remove leading slash before drive letter
487
+ # file:///C:/path becomes /C:/path, should be C:/path
488
+ if sys.platform == 'win32' and len(path) >= 3 and path[0] == '/' and path[2] == ':':
489
+ path = path[1:]
490
+
483
491
  try:
484
492
  resolved_path = str(Path(path).resolve())
485
493
  workspace_roots.append(resolved_path)
File without changes
File without changes
File without changes