Skip to content

Commit 909ab44

Browse files
mauriciocoderMauricio Bonetti
andauthored
Fix server name extraction logic in HTTP telemetry middleware (#844)
Co-authored-by: Mauricio Bonetti <[email protected]>
1 parent 62e9309 commit 909ab44

File tree

2 files changed

+11
-21
lines changed

2 files changed

+11
-21
lines changed

pkg/telemetry/middleware.go

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,9 @@ func (m *HTTPMiddleware) addMCPAttributes(ctx context.Context, span trace.Span,
226226
// Add method-specific attributes
227227
m.addMethodSpecificAttributes(span, parsedMCP)
228228

229-
// Extract server name from URL or headers
229+
// Extract server name from the request, defaulting to the middleware's configured server name
230230
serverName := m.extractServerName(r)
231-
if serverName != "" {
232-
span.SetAttributes(attribute.String("mcp.server.name", serverName))
233-
}
231+
span.SetAttributes(attribute.String("mcp.server.name", serverName))
234232

235233
// Determine backend transport type
236234
// Note: ToolHive always serves SSE to clients, but backends can be stdio or sse
@@ -276,29 +274,21 @@ func (m *HTTPMiddleware) addMethodSpecificAttributes(span trace.Span, parsedMCP
276274
}
277275
}
278276

279-
// extractServerName attempts to extract the server name from the request.
280-
func (*HTTPMiddleware) extractServerName(r *http.Request) string {
281-
// Try to get server name from custom headers (if set by proxy)
277+
// extractServerName extracts the MCP server name from the HTTP request using multiple fallback strategies.
278+
// It first checks for the X-MCP-Server-Name header, then extracts from URL path segments
279+
// (skipping common prefixes like "sse", "messages", "api", "v1"), and finally falls back
280+
// to the middleware's configured server name.
281+
func (m *HTTPMiddleware) extractServerName(r *http.Request) string {
282282
if serverName := r.Header.Get("X-MCP-Server-Name"); serverName != "" {
283283
return serverName
284284
}
285-
286-
// Try to extract from path segments (skip common prefixes)
287285
pathParts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
288286
for _, part := range pathParts {
289287
if part != "" && part != "sse" && part != "messages" && part != "api" && part != "v1" {
290288
return part
291289
}
292290
}
293-
294-
// Try to get from query parameters (for session-based routing)
295-
if sessionID := r.URL.Query().Get("session_id"); sessionID != "" {
296-
// In a real implementation, this could map session IDs to server names
297-
// For now, return a placeholder
298-
return "session-based"
299-
}
300-
301-
return "unknown"
291+
return m.serverName
302292
}
303293

304294
// extractBackendTransport determines the backend transport type.

pkg/telemetry/middleware_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,15 +460,15 @@ func TestHTTPMiddleware_ExtractServerName(t *testing.T) {
460460
expected: "weather",
461461
},
462462
{
463-
name: "session based",
463+
name: "fallback to serverName",
464464
path: "/messages",
465465
query: "session_id=abc123",
466-
expected: "session-based",
466+
expected: "", // Falls back to m.serverName which is empty in test
467467
},
468468
{
469469
name: "unknown",
470470
path: "/health",
471-
expected: "health",
471+
expected: "health", // "health" is not in the skip list, so it's extracted from path
472472
},
473473
}
474474

0 commit comments

Comments
 (0)