mashrur950 commited on
Commit
f474e49
·
1 Parent(s): b338c26

add api key

Browse files
Files changed (4) hide show
  1. README.md +14 -18
  2. app.py +11 -11
  3. database/user_context.py +3 -63
  4. server.py +33 -8
README.md CHANGED
@@ -185,11 +185,8 @@ Edit your `claude_desktop_config.json`:
185
  "command": "npx",
186
  "args": [
187
  "mcp-remote",
188
- "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse"
189
- ],
190
- "env": {
191
- "FLEETMIND_API_KEY": "fm_your_api_key_here"
192
- }
193
  }
194
  }
195
  }
@@ -197,6 +194,8 @@ Edit your `claude_desktop_config.json`:
197
 
198
  ⚠️ **Important:** Replace `fm_your_api_key_here` with your actual API key from Step 1!
199
 
 
 
200
  **For Local Development (with API Key):**
201
  ```json
202
  {
@@ -205,11 +204,8 @@ Edit your `claude_desktop_config.json`:
205
  "command": "npx",
206
  "args": [
207
  "mcp-remote",
208
- "http://localhost:7860/sse"
209
- ],
210
- "env": {
211
- "FLEETMIND_API_KEY": "your_local_api_key"
212
- }
213
  }
214
  }
215
  }
@@ -237,17 +233,17 @@ Edit your `claude_desktop_config.json`:
237
  "mcpServers": {
238
  "fleetmind_local": {
239
  "command": "npx",
240
- "args": ["mcp-remote", "http://localhost:7860/sse"],
241
- "env": {
242
- "FLEETMIND_API_KEY": "your_local_key"
243
- }
244
  },
245
  "fleetmind": {
246
  "command": "npx",
247
- "args": ["mcp-remote", "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse"],
248
- "env": {
249
- "FLEETMIND_API_KEY": "your_production_key"
250
- }
251
  }
252
  }
253
  }
 
185
  "command": "npx",
186
  "args": [
187
  "mcp-remote",
188
+ "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse?api_key=fm_your_api_key_here"
189
+ ]
 
 
 
190
  }
191
  }
192
  }
 
194
 
195
  ⚠️ **Important:** Replace `fm_your_api_key_here` with your actual API key from Step 1!
196
 
197
+ 💡 **Note:** The API key is passed as a **query parameter** (`?api_key=...`) in the URL. This is because `mcp-remote` doesn't forward environment variables to remote servers.
198
+
199
  **For Local Development (with API Key):**
200
  ```json
201
  {
 
204
  "command": "npx",
205
  "args": [
206
  "mcp-remote",
207
+ "http://localhost:7860/sse?api_key=your_local_api_key"
208
+ ]
 
 
 
209
  }
210
  }
211
  }
 
233
  "mcpServers": {
234
  "fleetmind_local": {
235
  "command": "npx",
236
+ "args": [
237
+ "mcp-remote",
238
+ "http://localhost:7860/sse?api_key=your_local_key"
239
+ ]
240
  },
241
  "fleetmind": {
242
  "command": "npx",
243
+ "args": [
244
+ "mcp-remote",
245
+ "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse?api_key=your_production_key"
246
+ ]
247
  }
248
  }
249
  }
app.py CHANGED
@@ -155,21 +155,21 @@ if __name__ == "__main__":
155
  "command": "npx",
156
  "args": [
157
  "mcp-remote",
158
- "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse"
159
- ],
160
- "env": {
161
- "FLEETMIND_API_KEY": "fm_your_api_key_here"
162
- }
163
  }
164
  }
165
  }</pre>
 
 
 
166
 
167
  <h3>📋 Step 3: Connect</h3>
168
  <ol>
169
  <li><strong>Generate your API key</strong> using the button above</li>
170
  <li>Install <a href="https://claude.ai/download" target="_blank">Claude Desktop</a></li>
171
  <li>Locate your <code>claude_desktop_config.json</code> file</li>
172
- <li>Add the configuration (replace <code>fm_your_api_key_here</code> with your actual key)</li>
173
  <li>Restart Claude Desktop</li>
174
  <li>Look for "FleetMind" in the 🔌 tools menu</li>
175
  </ol>
@@ -349,14 +349,14 @@ if __name__ == "__main__":
349
  "command": "npx",
350
  "args": [
351
  "mcp-remote",
352
- "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse"
353
- ],
354
- "env": {{
355
- "FLEETMIND_API_KEY": "{result["api_key"]}"
356
- }}
357
  }}
358
  }}
359
  }}</pre>
 
 
 
360
 
361
  <h2>🚀 Next Steps:</h2>
362
  <ol>
 
155
  "command": "npx",
156
  "args": [
157
  "mcp-remote",
158
+ "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse<strong style="color: #60a5fa;">?api_key=fm_your_api_key_here</strong>"
159
+ ]
 
 
 
160
  }
161
  }
162
  }</pre>
163
+ <p style="background: #1e3a5f; padding: 10px; border-radius: 6px; margin: 10px 0; border-left: 4px solid #3b82f6;">
164
+ 💡 <strong>Important:</strong> Add your API key as a query parameter (<code>?api_key=...</code>) in the URL, not in the <code>env</code> section!
165
+ </p>
166
 
167
  <h3>📋 Step 3: Connect</h3>
168
  <ol>
169
  <li><strong>Generate your API key</strong> using the button above</li>
170
  <li>Install <a href="https://claude.ai/download" target="_blank">Claude Desktop</a></li>
171
  <li>Locate your <code>claude_desktop_config.json</code> file</li>
172
+ <li>Add the configuration, replacing <code>fm_your_api_key_here</code> with your actual API key <strong>in the URL</strong></li>
173
  <li>Restart Claude Desktop</li>
174
  <li>Look for "FleetMind" in the 🔌 tools menu</li>
175
  </ol>
 
349
  "command": "npx",
350
  "args": [
351
  "mcp-remote",
352
+ "https://mcp-1st-birthday-fleetmind-dispatch-ai.hf.space/sse?api_key={result["api_key"]}"
353
+ ]
 
 
 
354
  }}
355
  }}
356
  }}</pre>
357
+ <p style="background: #1e3a5f; padding: 10px; border-radius: 6px; margin: 10px 0; border-left: 4px solid #3b82f6;">
358
+ 💡 <strong>Important:</strong> The API key is included in the URL as a query parameter (<code>?api_key=...</code>)
359
+ </p>
360
 
361
  <h2>🚀 Next Steps:</h2>
362
  <ol>
database/user_context.py CHANGED
@@ -1,69 +1,9 @@
1
  """
2
- User Context and Authentication Module
3
- Handles Stytch authentication and user permission checks
4
  """
5
 
6
- from typing import Optional, Dict, Any
7
- import os
8
- from stytch import Client
9
-
10
- # Initialize Stytch client
11
- stytch_client = None
12
- if os.getenv('STYTCH_PROJECT_ID') and os.getenv('STYTCH_SECRET'):
13
- try:
14
- stytch_client = Client(
15
- project_id=os.getenv('STYTCH_PROJECT_ID'),
16
- secret=os.getenv('STYTCH_SECRET')
17
- )
18
- print(f"Stytch client initialized with project: {os.getenv('STYTCH_PROJECT_ID')[:20]}...")
19
- except Exception as e:
20
- print(f"Warning: Stytch client initialization failed: {e}")
21
-
22
-
23
- def verify_token(token: str) -> Optional[Dict[str, Any]]:
24
- """
25
- Verify authentication token and return user info
26
-
27
- Args:
28
- token: Bearer token from Authorization header
29
-
30
- Returns:
31
- User info dict with user_id, email, scopes
32
- None if token is invalid
33
- """
34
- # Development mode: Skip authentication
35
- if os.getenv('ENVIRONMENT') == 'development' and os.getenv('SKIP_AUTH') == 'true':
36
- return {
37
- 'user_id': 'dev-user',
38
- 'email': 'dev@fleetmind.local',
39
- 'scopes': ['admin'],
40
- 'name': 'Development User'
41
- }
42
-
43
- if not stytch_client:
44
- print("Error: Stytch client not initialized")
45
- return None
46
-
47
- if not token:
48
- return None
49
-
50
- try:
51
- # Verify session token with Stytch
52
- result = stytch_client.sessions.authenticate(session_token=token)
53
-
54
- # Extract user information
55
- user_info = {
56
- 'user_id': result.user.user_id,
57
- 'email': result.user.emails[0].email if result.user.emails else 'unknown',
58
- 'scopes': result.session.custom_claims.get('scopes', ['orders:read', 'drivers:read']),
59
- 'name': result.user.name if hasattr(result.user, 'name') else 'Unknown User'
60
- }
61
-
62
- return user_info
63
-
64
- except Exception as e:
65
- print(f"Token validation failed: {e}")
66
- return None
67
 
68
 
69
  def check_permission(user_scopes: list, required_scope: str) -> bool:
 
1
  """
2
+ User Context and Permission Module
3
+ Handles permission checks for API key authentication
4
  """
5
 
6
+ from typing import Optional
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
 
9
  def check_permission(user_scopes: list, required_scope: str) -> bool:
server.py CHANGED
@@ -65,18 +65,43 @@ def get_authenticated_user():
65
  """
66
  Extract and verify user via API Key authentication
67
 
68
- Supports 2 authentication methods:
69
- 1. API Key (from FLEETMIND_API_KEY env var) - Production & user auth
70
- 2. Development Mode (SKIP_AUTH=true) - Local testing only
 
71
 
72
  Returns:
73
  User info dict with user_id, email, scopes, name or None if not authenticated
74
  """
75
  try:
76
- # METHOD 1: API Key Authentication
77
- # Users set this in their Claude Desktop config:
78
- # "env": {"FLEETMIND_API_KEY": "fm_xxxxx"}
79
- api_key = os.getenv("FLEETMIND_API_KEY")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  if api_key:
81
  from database.api_keys import verify_api_key
82
  user_info = verify_api_key(api_key)
@@ -87,7 +112,7 @@ def get_authenticated_user():
87
  logger.warning(f"❌ Invalid API key provided")
88
  return None
89
 
90
- # METHOD 2: Development bypass mode (local testing only)
91
  if os.getenv("SKIP_AUTH") == "true":
92
  logger.debug("SKIP_AUTH enabled - using development user")
93
  return {
 
65
  """
66
  Extract and verify user via API Key authentication
67
 
68
+ Supports 3 authentication methods (in order):
69
+ 1. Request context (from FastMCP request, if available)
70
+ 2. Server environment variable FLEETMIND_API_KEY
71
+ 3. Development Mode (SKIP_AUTH=true)
72
 
73
  Returns:
74
  User info dict with user_id, email, scopes, name or None if not authenticated
75
  """
76
  try:
77
+ api_key = None
78
+
79
+ # METHOD 1: Try to get API key from request context (SSE/HTTP)
80
+ # This is populated by FastMCP from query params or headers
81
+ try:
82
+ from fastmcp.server.dependencies import get_request_context
83
+ context = get_request_context()
84
+ if context and hasattr(context, 'query_params'):
85
+ api_key = context.query_params.get('api_key')
86
+ if api_key:
87
+ logger.debug("API key found in query params")
88
+ elif context and hasattr(context, 'headers'):
89
+ # Try Authorization header
90
+ auth_header = context.headers.get('authorization', '')
91
+ if auth_header.startswith('Bearer '):
92
+ api_key = auth_header[7:]
93
+ logger.debug("API key found in Authorization header")
94
+ except (ImportError, RuntimeError, AttributeError) as e:
95
+ logger.debug(f"No request context available: {e}")
96
+ pass
97
+
98
+ # METHOD 2: Try server environment variable (for local development)
99
+ if not api_key:
100
+ api_key = os.getenv("FLEETMIND_API_KEY")
101
+ if api_key:
102
+ logger.debug("API key found in server environment")
103
+
104
+ # Verify the API key if we found one
105
  if api_key:
106
  from database.api_keys import verify_api_key
107
  user_info = verify_api_key(api_key)
 
112
  logger.warning(f"❌ Invalid API key provided")
113
  return None
114
 
115
+ # METHOD 3: Development bypass mode (local testing only)
116
  if os.getenv("SKIP_AUTH") == "true":
117
  logger.debug("SKIP_AUTH enabled - using development user")
118
  return {