NiWaRe commited on
Commit
7d190a0
·
1 Parent(s): e2aaee8

separate client and server api key for http and weave tracing

Browse files
HUGGINGFACE_DEPLOYMENT.md CHANGED
@@ -39,15 +39,7 @@ The application runs as a FastAPI server on port 7860 (HF Spaces default) with:
39
 
40
  No environment variables are required! The server works without any configuration.
41
 
42
- Optional (for server-side logging only):
43
- ```
44
- WANDB_API_KEY=your_api_key_here # Only if you want server-side Weave tracing
45
- WANDB_ENTITY=your_wandb_entity # For server-side Weave tracing
46
- MCP_LOGS_WANDB_PROJECT=wandb-mcp-logs # Project for server logs
47
- WEAVE_DISABLED=false # Set to enable Weave tracing
48
- ```
49
-
50
- **Note**: For normal operation, users provide their own W&B API keys as Bearer tokens. No server configuration needed.
51
 
52
  ## Deployment Steps
53
 
 
39
 
40
  No environment variables are required! The server works without any configuration.
41
 
42
+ **Note**: Users provide their own W&B API keys as Bearer tokens. No server configuration needed.
 
 
 
 
 
 
 
 
43
 
44
  ## Deployment Steps
45
 
auth.example.env CHANGED
@@ -1,30 +1,20 @@
1
- # W&B MCP Server Authentication Configuration Example
2
  # Copy this file to .env and add your values
3
 
4
  # ================================
5
- # API KEY AUTHENTICATION
6
  # ================================
7
 
8
- # For STDIO transport (required):
9
  # Get your key from: https://wandb.ai/authorize
10
  WANDB_API_KEY=your_wandb_api_key_here
11
 
12
- # For HTTP transport (optional):
13
- # Users provide their own API keys as Bearer tokens
14
- # No server configuration needed
15
-
16
  # ================================
17
- # OPTIONAL SETTINGS
18
  # ================================
19
 
20
- # W&B Entity (team or username) for server-side logging
21
- # WANDB_ENTITY=your_team_or_username
22
-
23
- # Project for MCP operation traces (if Weave tracing enabled)
24
- # MCP_LOGS_WANDB_PROJECT=wandb-mcp-logs
25
-
26
- # Disable Weave tracing (set to true to disable)
27
- # WEAVE_DISABLED=true
28
 
29
  # ================================
30
  # DEVELOPMENT ONLY
 
1
+ # W&B MCP Server Configuration Example
2
  # Copy this file to .env and add your values
3
 
4
  # ================================
5
+ # FOR STDIO TRANSPORT
6
  # ================================
7
 
8
+ # Required for STDIO transport only
9
  # Get your key from: https://wandb.ai/authorize
10
  WANDB_API_KEY=your_wandb_api_key_here
11
 
 
 
 
 
12
  # ================================
13
+ # FOR HTTP TRANSPORT
14
  # ================================
15
 
16
+ # No configuration needed!
17
+ # Users provide their own API keys as Bearer tokens
 
 
 
 
 
 
18
 
19
  # ================================
20
  # DEVELOPMENT ONLY
src/wandb_mcp_server/auth.py CHANGED
@@ -135,32 +135,21 @@ async def mcp_auth_middleware(request: Request, call_next):
135
  wandb_api_key = wandb_api_key.strip()
136
 
137
  # Store the API key in request state for W&B operations
138
- # The MCP tools should access this from the request context
139
  request.state.wandb_api_key = wandb_api_key
140
 
141
- # For now, we'll set it in environment (in production, use contextvars)
142
- # Save the original value to restore later
143
- original_api_key = os.environ.get("WANDB_API_KEY")
144
-
145
- # Set the clean API key
146
  os.environ["WANDB_API_KEY"] = wandb_api_key
147
 
148
- # Debug logging (remove in production)
149
- logger.info(f"Auth middleware: Set WANDB_API_KEY with length={len(wandb_api_key)}, "
150
- f"first_6={wandb_api_key[:6] if len(wandb_api_key) >= 6 else 'N/A'}..., "
151
- f"last_4={wandb_api_key[-4:] if len(wandb_api_key) >= 4 else 'N/A'}, "
152
- f"is_40_chars={len(wandb_api_key) == 40}")
 
 
153
 
154
- try:
155
- # Continue processing
156
- response = await call_next(request)
157
- finally:
158
- # Restore original environment
159
- if original_api_key:
160
- os.environ["WANDB_API_KEY"] = original_api_key
161
- elif "WANDB_API_KEY" in os.environ:
162
- del os.environ["WANDB_API_KEY"]
163
-
164
  return response
165
 
166
  except HTTPException as e:
 
135
  wandb_api_key = wandb_api_key.strip()
136
 
137
  # Store the API key in request state for W&B operations
 
138
  request.state.wandb_api_key = wandb_api_key
139
 
140
+ # Set the API key for this request
141
+ # Note: We don't restore the original value because with streaming responses,
142
+ # the tool execution happens after call_next returns. Each request sets its own key.
 
 
143
  os.environ["WANDB_API_KEY"] = wandb_api_key
144
 
145
+ # Debug logging
146
+ logger.debug(f"Auth middleware: Set WANDB_API_KEY with length={len(wandb_api_key)}, "
147
+ f"is_40_chars={len(wandb_api_key) == 40}")
148
+
149
+ # Continue processing without restoring the env var
150
+ # Each request will set its own API key
151
+ response = await call_next(request)
152
 
 
 
 
 
 
 
 
 
 
 
153
  return response
154
 
155
  except HTTPException as e:
src/wandb_mcp_server/mcp_tools/count_traces.py CHANGED
@@ -176,6 +176,7 @@ def count_traces(
176
  """
177
  project_id = f"{entity_name}/{project_name}"
178
 
 
179
  api_key = os.environ.get("WANDB_API_KEY")
180
  if not api_key:
181
  logger.error("WANDB_API_KEY not found in environment variables.")
 
176
  """
177
  project_id = f"{entity_name}/{project_name}"
178
 
179
+ # Get API key from environment (set by auth middleware for HTTP, or by user for STDIO)
180
  api_key = os.environ.get("WANDB_API_KEY")
181
  if not api_key:
182
  logger.error("WANDB_API_KEY not found in environment variables.")
src/wandb_mcp_server/mcp_tools/create_report.py CHANGED
@@ -130,6 +130,7 @@ def create_report(
130
  processed_plots_html = None
131
 
132
  try:
 
133
  wandb.init(
134
  entity=entity_name, project=project_name, job_type="mcp_report_creation"
135
  )
 
130
  processed_plots_html = None
131
 
132
  try:
133
+ # W&B will use WANDB_API_KEY from environment
134
  wandb.init(
135
  entity=entity_name, project=project_name, job_type="mcp_report_creation"
136
  )
src/wandb_mcp_server/mcp_tools/list_wandb_entities_projects.py CHANGED
@@ -70,6 +70,7 @@ def list_entity_projects(entity: str | None = None) -> dict[str, list[dict[str,
70
  - tags: List of project tags
71
  """
72
  # Initialize wandb API
 
73
  api = wandb.Api()
74
 
75
  # Merge entity and teams into a single list
 
70
  - tags: List of project tags
71
  """
72
  # Initialize wandb API
73
+ # Will use WANDB_API_KEY from environment (set by auth middleware or user)
74
  api = wandb.Api()
75
 
76
  # Merge entity and teams into a single list
src/wandb_mcp_server/mcp_tools/query_wandb_gql.py CHANGED
@@ -591,7 +591,8 @@ def query_paginated_wandb_gql(
591
  api = None
592
  limit_key = None
593
  try:
594
- api = wandb.Api()
 
595
  logger.info(
596
  "--- Inside query_paginated_wandb_gql: Step 0: Execute Initial Query ---"
597
  )
 
591
  api = None
592
  limit_key = None
593
  try:
594
+ # Use API key from environment (set by auth middleware for HTTP, or by user for STDIO)
595
+ api = wandb.Api() # Will use WANDB_API_KEY from environment
596
  logger.info(
597
  "--- Inside query_paginated_wandb_gql: Step 0: Execute Initial Query ---"
598
  )
src/wandb_mcp_server/weave_api/service.py CHANGED
@@ -62,6 +62,7 @@ class TraceService:
62
 
63
  def __init__(
64
  self,
 
65
  server_url: Optional[str] = None,
66
  retries: int = 3,
67
  timeout: int = 10,
@@ -69,18 +70,26 @@ class TraceService:
69
  """Initialize the TraceService.
70
 
71
  Args:
 
72
  server_url: Weave API server URL. Defaults to 'https://trace.wandb.ai'.
73
  retries: Number of retries for failed requests.
74
  timeout: Request timeout in seconds.
75
  """
76
- # Call get_server_args() to ensure API key is loaded from .netrc or env var
77
- # and a warning is logged by get_server_args if no key is found.
78
- server_config = get_server_args()
 
 
 
 
 
 
 
79
 
80
  # Pass the resolved API key to WeaveApiClient.
81
- # If server_config.wandb_api_key is None or "", WeaveApiClient will raise its ValueError.
82
  self.client = WeaveApiClient(
83
- api_key=server_config.wandb_api_key,
84
  server_url=server_url,
85
  retries=retries,
86
  timeout=timeout,
 
62
 
63
  def __init__(
64
  self,
65
+ api_key: Optional[str] = None,
66
  server_url: Optional[str] = None,
67
  retries: int = 3,
68
  timeout: int = 10,
 
70
  """Initialize the TraceService.
71
 
72
  Args:
73
+ api_key: W&B API key. If not provided, uses WANDB_API_KEY env var.
74
  server_url: Weave API server URL. Defaults to 'https://trace.wandb.ai'.
75
  retries: Number of retries for failed requests.
76
  timeout: Request timeout in seconds.
77
  """
78
+ # If no API key provided, try to get from environment
79
+ if api_key is None:
80
+ import os
81
+ # Try to get from environment (set by auth middleware for HTTP or user for STDIO)
82
+ api_key = os.environ.get("WANDB_API_KEY")
83
+
84
+ # If still no key, try get_server_args as fallback
85
+ if not api_key:
86
+ server_config = get_server_args()
87
+ api_key = server_config.wandb_api_key
88
 
89
  # Pass the resolved API key to WeaveApiClient.
90
+ # If api_key is None or "", WeaveApiClient will raise its ValueError.
91
  self.client = WeaveApiClient(
92
+ api_key=api_key,
93
  server_url=server_url,
94
  retries=retries,
95
  timeout=timeout,