SESSION_STATE_FIX.md•4.03 kB
# Session State Management Fix - RESOLVED ✅
## Issue
FastMCP's `ServerSession` object does not have a `.metadata` attribute, causing the error:
```
'ServerSession' object has no attribute 'metadata'
```
## Root Cause
The code was attempting to use `ctx.session.metadata` which doesn't exist in FastMCP's implementation.
## Solution Implemented
Created a global session state dictionary pattern that stores session data keyed by session ID.
### Changes Made
#### 1. Updated `/src/finizi_b4b_mcp/auth/token_handler.py`
- Added global `_session_state = {}` dictionary
- Created `get_session_state(ctx)` helper function
- Updated `extract_user_token()` to use the new session state
```python
# Global session state store - keyed by session ID
_session_state = {}
def get_session_state(ctx: Context) -> dict:
"""Get the session state dictionary for the current session."""
session_id = id(ctx.session)
if session_id not in _session_state:
_session_state[session_id] = {}
return _session_state[session_id]
```
#### 2. Updated `/src/finizi_b4b_mcp/tools/auth.py`
- Imported `get_session_state` function
- Changed all `ctx.session.metadata` references to use `get_session_state(ctx)`
- Updated login, logout, and whoami tools
**Before:**
```python
ctx.session.metadata["user_token"] = data["access_token"]
```
**After:**
```python
state = get_session_state(ctx)
state["user_token"] = data["access_token"]
```
#### 3. Fixed Claude Desktop Configuration
Updated `claude_desktop_config.json` to use the `--directory` flag:
```json
{
"mcpServers": {
"finizi-b4b": {
"command": "/Users/trunghuynh/.local/bin/uv",
"args": [
"--directory",
"/Users/trunghuynh/development/finizi-mcp",
"run",
"python",
"run_mcp_server.py"
],
"env": {
"B4B_API_BASE_URL": "http://localhost:8000",
"B4B_API_VERSION": "v1",
"LOG_LEVEL": "INFO"
}
}
}
}
```
## Testing Results ✅
### Manual Test (`test_mcp_connection.py`)
```
✅ Found 15 tools
✅ Login tool called successfully
✅ MCP server is working correctly
```
### Full Integration Test (`test_full_integration.py`)
```
✅ Session initialized
✅ Found 15 tools
✅ Login successful
✅ Whoami (authenticated call) successful
✅ List entities (authenticated call) successful
✅ All integration tests passed
```
## Deployment Instructions
1. Copy the configuration to Claude Desktop:
```bash
cp /Users/trunghuynh/development/finizi-mcp/claude_desktop_config.json \
~/Library/Application\ Support/Claude/claude_desktop_config.json
```
2. Restart Claude Desktop
3. The Finizi B4B MCP server should now appear with all 15 tools available
## Available Tools
1. login - Authenticate with phone and password
2. logout - Clear authentication session
3. whoami - Get current user info
4. list_entities - List entities (requires auth)
5. get_entity - Get entity details (requires auth)
6. create_entity - Create new entity (requires auth)
7. update_entity - Update entity (requires auth)
8. list_invoices - List invoices (requires auth)
9. get_invoice - Get invoice details (requires auth)
10. import_invoice_xml - Import XML invoice (requires auth)
11. get_invoice_statistics - Get invoice stats (requires auth)
12. list_vendors - List vendors (requires auth)
13. get_vendor - Get vendor details (requires auth)
14. list_products - List products (requires auth)
15. search_similar_products - Search products (requires auth)
## Session State Management Pattern
The session state is managed using a global dictionary:
- Each session is identified by `id(ctx.session)`
- State persists across tool calls within the same session
- State is automatically isolated between different sessions
- Login stores: `user_token`, `refresh_token`, `user_email`, `user_id`, `is_super_admin`
- All authenticated tools retrieve the token using `extract_user_token(ctx)`
## Status: FULLY FUNCTIONAL ✅
All components tested and working correctly with the B4B API.