fenix-mcp 1.11.1__tar.gz → 1.13.0__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.
Files changed (35) hide show
  1. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/PKG-INFO +1 -1
  2. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/__init__.py +1 -1
  3. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tools/initialize.py +19 -0
  4. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tools/intelligence.py +7 -1
  5. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/infrastructure/http_client.py +7 -0
  6. fenix_mcp-1.13.0/fenix_mcp/infrastructure/request_context.py +37 -0
  7. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/interface/transports.py +11 -1
  8. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp.egg-info/PKG-INFO +1 -1
  9. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp.egg-info/SOURCES.txt +1 -0
  10. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/README.md +0 -0
  11. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/presenters.py +0 -0
  12. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tool_base.py +0 -0
  13. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tool_registry.py +0 -0
  14. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tools/__init__.py +0 -0
  15. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tools/health.py +0 -0
  16. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tools/knowledge.py +0 -0
  17. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tools/productivity.py +0 -0
  18. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/application/tools/user_config.py +0 -0
  19. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/domain/initialization.py +0 -0
  20. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/domain/intelligence.py +0 -0
  21. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/domain/knowledge.py +0 -0
  22. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/domain/productivity.py +0 -0
  23. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/domain/user_config.py +0 -0
  24. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/infrastructure/config.py +0 -0
  25. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/infrastructure/context.py +0 -0
  26. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/infrastructure/fenix_api/client.py +0 -0
  27. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/infrastructure/logging.py +0 -0
  28. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/interface/mcp_server.py +0 -0
  29. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp/main.py +0 -0
  30. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp.egg-info/dependency_links.txt +0 -0
  31. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp.egg-info/entry_points.txt +0 -0
  32. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp.egg-info/requires.txt +0 -0
  33. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/fenix_mcp.egg-info/top_level.txt +0 -0
  34. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/pyproject.toml +0 -0
  35. {fenix_mcp-1.11.1 → fenix_mcp-1.13.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fenix-mcp
3
- Version: 1.11.1
3
+ Version: 1.13.0
4
4
  Summary: Fênix Cloud MCP server implemented in Python
5
5
  Author: Fenix Inc
6
6
  Requires-Python: >=3.10
@@ -8,4 +8,4 @@ Fênix Cloud MCP Server (Python edition).
8
8
  __all__ = ["__version__"]
9
9
 
10
10
 
11
- __version__ = "1.11.1"
11
+ __version__ = "1.13.0"
@@ -124,6 +124,25 @@ class InitializeTool(Tool):
124
124
  ]
125
125
  )
126
126
 
127
+ # Add memory usage instructions
128
+ message_lines.extend(
129
+ [
130
+ "",
131
+ "🧠 **Memory Usage Instructions**",
132
+ "",
133
+ "To provide continuity across sessions, use the `intelligence` tool:",
134
+ "",
135
+ '1. **At conversation START**: Call `intelligence(action="memory_query", query="<relevant_topic>")` to retrieve context from previous sessions',
136
+ '2. **When learning important info**: Call `intelligence(action="memory_smart_create", ...)` to save:',
137
+ " - User preferences and decisions",
138
+ " - Project context and architecture choices",
139
+ " - Problems solved and solutions found",
140
+ " - Technical learnings and patterns",
141
+ "",
142
+ "This prevents users from repeating themselves and enables personalized assistance.",
143
+ ]
144
+ )
145
+
127
146
  return text("\n".join(message_lines))
128
147
 
129
148
  async def _handle_setup(self, payload: InitializeRequest):
@@ -172,7 +172,13 @@ class IntelligenceRequest(ToolRequest):
172
172
 
173
173
  class IntelligenceTool(Tool):
174
174
  name = "intelligence"
175
- description = "Fenix Cloud intelligence operations (memories and smart operations)."
175
+ description = (
176
+ "Fenix persistent memory system for cross-session continuity. "
177
+ "RECOMMENDED USAGE: "
178
+ "(1) Call memory_query at the START of conversations to retrieve relevant context from previous sessions. "
179
+ "(2) Call memory_smart_create to save important information, decisions, user preferences, and learnings. "
180
+ "This enables personalized responses and prevents users from repeating themselves."
181
+ )
176
182
  request_model = IntelligenceRequest
177
183
 
178
184
  def __init__(self, context: AppContext):
@@ -12,6 +12,8 @@ from requests import Response, Session
12
12
  from requests.adapters import HTTPAdapter
13
13
  from urllib3.util.retry import Retry
14
14
 
15
+ from fenix_mcp.infrastructure.request_context import get_request_token
16
+
15
17
 
16
18
  @dataclass(slots=True)
17
19
  class HttpClient:
@@ -53,6 +55,11 @@ class HttpClient:
53
55
  merged_headers = dict(self.default_headers or {})
54
56
  merged_headers.update(headers or {})
55
57
 
58
+ # Use request-scoped token if available (overrides default)
59
+ request_token = get_request_token()
60
+ if request_token:
61
+ merged_headers["Authorization"] = f"Bearer {request_token}"
62
+
56
63
  self._logger.debug(
57
64
  "HTTP request",
58
65
  extra={
@@ -0,0 +1,37 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """Request-scoped context using contextvars for async isolation."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from contextvars import ContextVar
7
+ from dataclasses import dataclass
8
+ from typing import Optional
9
+
10
+ # Context variable for the current request's token
11
+ # This is automatically isolated per async task/request
12
+ _current_token: ContextVar[Optional[str]] = ContextVar("current_token", default=None)
13
+
14
+
15
+ @dataclass(slots=True, frozen=True)
16
+ class RequestContext:
17
+ """Holds request-scoped data like the user's token."""
18
+
19
+ token: Optional[str] = None
20
+ user_id: Optional[str] = None
21
+ tenant_id: Optional[str] = None
22
+ team_id: Optional[str] = None
23
+
24
+
25
+ def set_request_token(token: Optional[str]) -> None:
26
+ """Set the token for the current async context/request."""
27
+ _current_token.set(token)
28
+
29
+
30
+ def get_request_token() -> Optional[str]:
31
+ """Get the token for the current async context/request."""
32
+ return _current_token.get()
33
+
34
+
35
+ def clear_request_token() -> None:
36
+ """Clear the token for the current async context/request."""
37
+ _current_token.set(None)
@@ -14,6 +14,10 @@ from typing import Iterable, List, Protocol
14
14
  from aiohttp import web
15
15
 
16
16
  from fenix_mcp.infrastructure.config import Settings
17
+ from fenix_mcp.infrastructure.request_context import (
18
+ set_request_token,
19
+ clear_request_token,
20
+ )
17
21
 
18
22
 
19
23
  class Transport(Protocol):
@@ -147,17 +151,20 @@ class HttpTransport:
147
151
  return self._with_cors(web.Response(status=204))
148
152
 
149
153
  async def _handle_jsonrpc(self, request: web.Request) -> web.StreamResponse:
154
+ # Extract token from Authorization header (per-request isolation)
150
155
  auth_header = request.headers.get("Authorization") or request.headers.get(
151
156
  "authorization"
152
157
  )
153
158
  if auth_header and auth_header.lower().startswith("bearer "):
154
159
  token = auth_header.split(" ", 1)[1].strip()
155
160
  if token:
156
- self._server.set_personal_access_token(token)
161
+ # Set token in contextvar (isolated per async request)
162
+ set_request_token(token)
157
163
 
158
164
  try:
159
165
  payload = await request.json()
160
166
  except Exception: # pragma: no cover - defensive
167
+ clear_request_token()
161
168
  return self._with_cors(
162
169
  web.json_response(
163
170
  {"error": {"code": -32700, "message": "Invalid JSON"}}, status=400
@@ -175,6 +182,9 @@ class HttpTransport:
175
182
  {"error": {"code": -32000, "message": str(exc)}}, status=500
176
183
  )
177
184
  )
185
+ finally:
186
+ # Clear token after request completes
187
+ clear_request_token()
178
188
 
179
189
  if response is None:
180
190
  return self._with_cors(web.Response(status=204))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fenix-mcp
3
- Version: 1.11.1
3
+ Version: 1.13.0
4
4
  Summary: Fênix Cloud MCP server implemented in Python
5
5
  Author: Fenix Inc
6
6
  Requires-Python: >=3.10
@@ -27,6 +27,7 @@ fenix_mcp/infrastructure/config.py
27
27
  fenix_mcp/infrastructure/context.py
28
28
  fenix_mcp/infrastructure/http_client.py
29
29
  fenix_mcp/infrastructure/logging.py
30
+ fenix_mcp/infrastructure/request_context.py
30
31
  fenix_mcp/infrastructure/fenix_api/client.py
31
32
  fenix_mcp/interface/mcp_server.py
32
33
  fenix_mcp/interface/transports.py
File without changes
File without changes
File without changes
File without changes