-
Notifications
You must be signed in to change notification settings - Fork 19
Description
Bug Description
When an HTTP server is offline (not running), the health calculator incorrectly shows action: login instead of action: restart. This is misleading because the server doesn't require OAuth - it's simply unreachable.
Steps to Reproduce
- Configure an HTTP server without OAuth (e.g., local development server)
- Start mcpproxy with the server running - it connects successfully
- Stop the local server (turn it off)
- Check server health via API or CLI
Expected Behavior
{
"name": "local-chatgpt-app",
"health": {
"level": "unhealthy",
"summary": "Connection refused",
"action": "restart"
}
}Actual Behavior
{
"name": "local-chatgpt-app",
"health": {
"level": "unhealthy",
"summary": "Authentication required",
"action": "login"
},
"last_error": "failed to connect: all authentication strategies failed, last error: OAuth authentication required for local-chatgpt-app..."
}Root Cause Analysis
The issue is in two places:
1. mcp-go client layer
When connecting to an HTTP server, mcp-go tries authentication strategies. If the server is offline, it still generates an error message containing "authentication strategies failed" and "OAuth authentication required".
2. Health calculator (internal/health/calculator.go:336-357)
The isOAuthRelatedError() function matches on patterns like:
- "authentication required"
- "authentication strategies failed"
- "oauth"
This triggers even when the underlying error is a connection failure, not an auth issue.
Comparison: Correct vs Incorrect
| Server | Protocol | Actual Error | Health Action | Correct? |
|---|---|---|---|---|
idea-ide-local |
SSE | "connection refused" | restart |
✅ |
local-chatgpt-app |
HTTP | "all authentication strategies failed..." | login |
❌ |
The SSE server correctly gets restart because its error message contains "connection refused" which is detected first. The HTTP server gets misclassified because the mcp-go error wraps the connection error inside an "authentication strategies failed" message.
Proposed Fix
In isOAuthRelatedError(), check for connection errors FIRST before checking for auth errors:
func isOAuthRelatedError(err string) bool {
if err == "" {
return false
}
// Connection errors take precedence - these are NOT OAuth issues
connectionErrors := []string{
"connection refused",
"connection reset",
"no such host",
"network is unreachable",
"dial tcp",
"i/o timeout",
}
for _, pattern := range connectionErrors {
if containsIgnoreCase(err, pattern) {
return false // This is a connection error, not OAuth
}
}
// Only then check for OAuth patterns
oauthPatterns := []string{...}
// ...
}Alternatively, the fix could be in the mcp-go client to generate clearer error messages that distinguish connection failures from auth failures.
Environment
- mcpproxy version: latest (branch
013-structured-server-state) - OS: macOS
- Related to: Spec 013 (Structured Server State)