mcpower-proxy 0.0.64__py3-none-any.whl → 0.0.66__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.

Potentially problematic release.


This version of mcpower-proxy might be problematic. Click here for more details.

@@ -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,10 +1,10 @@
1
1
  main.py,sha256=4BnzO7q9Atpzgr-_NTc1loRnrRY0m5OxeG9biI-C0es,3707
2
- mcpower_proxy-0.0.64.dist-info/licenses/LICENSE,sha256=U6WUzdnBrbmVxBmY75ikW-KtinwYnowZ7yNb5hECrvY,11337
2
+ mcpower_proxy-0.0.66.dist-info/licenses/LICENSE,sha256=U6WUzdnBrbmVxBmY75ikW-KtinwYnowZ7yNb5hECrvY,11337
3
3
  modules/__init__.py,sha256=mJglXQwSRhU-bBv4LXgfu7NfGN9K4BeQWMPApen5rAA,30
4
4
  modules/apis/__init__.py,sha256=Y5WZpKJzHpnRJebk0F80ZRTjR2PpA2LlYLgqI3XlmRo,15
5
5
  modules/apis/security_policy.py,sha256=AZDHTuOf99WhhzNw9AwC-0KACx1-ZjtQx-Ve3gAKYPM,15000
6
6
  modules/logs/__init__.py,sha256=dpboUQjuO02z8K-liCbm2DYkCa-CB_ZDV9WSSjNm7Fs,15
7
- modules/logs/audit_trail.py,sha256=PjVplAjCSUef9ps8P8xF3PSy6F4DLJicSQoTwpY4y6g,6096
7
+ modules/logs/audit_trail.py,sha256=r8aIjaW-jBXXhSwdafzgOn0AvvdTZG8UPnkI0GmbJnA,6199
8
8
  modules/logs/logger.py,sha256=dfYRLnABZB07SBfoYV4DsD8-ZCpzEeoewFCBGHyqo9k,4171
9
9
  modules/redaction/__init__.py,sha256=e5NTmp-zonUdzzscih-w_WQ-X8Nvb8CE8b_d6SbrwWg,316
10
10
  modules/redaction/constants.py,sha256=xbDSX8n72FuJu6JJ_sbBE0f5OcWuwEwHxBZuK9Xz-TI,1213
@@ -28,16 +28,16 @@ modules/utils/__init__.py,sha256=Ptwu1epT_dW6EHjGkzGHAB-MbrrmYAlcPXGGcr4PvwE,20
28
28
  modules/utils/cli.py,sha256=qYgf7TsWKjwPsCItbDYzNZCih2vfGAbAl2MIem320_Y,1517
29
29
  modules/utils/config.py,sha256=YuGrIYfBsOYABWjFoZosObPz-R7Wdul16RnDed_glYI,6654
30
30
  modules/utils/copy.py,sha256=9OJIqWn8PxPZXr3DTt_01jp0YgmPimckab1969WFh0c,1075
31
- modules/utils/ids.py,sha256=i2MjU_sLFpowYb_5pYQKsbz_wJfjpDXkA9Svqy_wiJQ,4622
31
+ modules/utils/ids.py,sha256=eYN31WDlfCyRSsdNu9F_hr_duuEpYEUJ5-ZMqo1fiAQ,4701
32
32
  modules/utils/json.py,sha256=8GA2akQsufXIn9HIP4SkFGFShzngexEBzejXi4B-Mfg,4031
33
33
  modules/utils/mcp_configs.py,sha256=DZaujZnF9LlPDJHzyepH7fWSt1GTr-FEmShPCqnZ5aI,1829
34
34
  wrapper/__init__.py,sha256=OJUsuWSoN1JqIHq4bSrzuL7ufcYJcwAmYCrJjLH44LM,22
35
- wrapper/__version__.py,sha256=2sNRZJT14qRkv4tRvpyg-2idt5inPq2tBnNecy0GWLI,82
36
- wrapper/middleware.py,sha256=HrxjC0puUxbh7lA0Yp36wJqtJwVsAVZleiqsOKgSt6w,34498
35
+ wrapper/__version__.py,sha256=NMwcKl_v88ECQhojnCXMfvRbXACvhh32_M57YGOUiTE,82
36
+ wrapper/middleware.py,sha256=g8jgIA-ciJMshSYflw9HSv_j6i-t1mQvkhc4pjww7Zc,35080
37
37
  wrapper/schema.py,sha256=O-CtKI9eJ4eEnqeUXPCrK7QJAFJrdp_cFbmMyg452Aw,7952
38
38
  wrapper/server.py,sha256=uVtxELALRrQNd-VrPWyLQPiEzxOpG-oCU7bItAeSjYU,2981
39
- mcpower_proxy-0.0.64.dist-info/METADATA,sha256=yxtClnw6IoEMoxWKA5kBFh6ZjGTk_-sHpDGlu8q_Hps,15667
40
- mcpower_proxy-0.0.64.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
- mcpower_proxy-0.0.64.dist-info/entry_points.txt,sha256=0smL8dxE7ERNz6XEggNaUC3QzKp8mD-v4q5nVEo0MXE,48
42
- mcpower_proxy-0.0.64.dist-info/top_level.txt,sha256=FLbRkTTggoMB-kq14IH4ZUbNGMGtbxtmiWw0QykRlkU,21
43
- mcpower_proxy-0.0.64.dist-info/RECORD,,
39
+ mcpower_proxy-0.0.66.dist-info/METADATA,sha256=j3rSpJS3RFqhTP7QmONIhOVN1l7rIGvB8WXGlcoOIds,15667
40
+ mcpower_proxy-0.0.66.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
+ mcpower_proxy-0.0.66.dist-info/entry_points.txt,sha256=0smL8dxE7ERNz6XEggNaUC3QzKp8mD-v4q5nVEo0MXE,48
42
+ mcpower_proxy-0.0.66.dist-info/top_level.txt,sha256=FLbRkTTggoMB-kq14IH4ZUbNGMGtbxtmiWw0QykRlkU,21
43
+ mcpower_proxy-0.0.66.dist-info/RECORD,,
@@ -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:
modules/utils/ids.py CHANGED
@@ -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})")
wrapper/__version__.py CHANGED
@@ -3,4 +3,4 @@
3
3
  Wrapper MCP Server Version
4
4
  """
5
5
 
6
- __version__ = "0.0.64"
6
+ __version__ = "0.0.66"
wrapper/middleware.py CHANGED
@@ -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)