-
Notifications
You must be signed in to change notification settings - Fork 10
Labels
Milestone
Description
Is your feature request related to a problem? Please describe.
I'd like a way to see the health of my mcpd hosted MCP servers, this way I can better understand if there's a problem with a particular MCP server.
Describe the solution you'd like
API endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/health/servers |
Health of all MCP servers |
GET |
/api/v1/health/servers/{server_name} |
Health of a specified MCP server |
This leaves /api/v1/health free for mcpd to later implement it's own health endpoint.
HTTP response status codes
| Status code | Meaning | Description |
|---|---|---|
200 |
OK | Always for successful API responses |
404 |
Not Found | Only if the server name is invalid (not known to mcpd) |
Object schema
ServerHealth
| Field | Type | Description |
|---|---|---|
| name | string |
Server identifier (e.g. time, fetch, elevenlabs) |
| status | enum |
HealthStatus: ok | timeout | unreachable | unknown |
| latency | string | null |
Duration string (e.g., "41ms") if successful; null if not |
| last_checked | RFC3339 | null |
Time when ping was last attempted |
| last_successful | RFC3339 | null |
Time of most recent successful ping |
HealthStatus
| Value | Meaning |
|---|---|
ok |
Ping succeeded, server is healthy |
timeout |
Ping failed due to timeout (e.g. context deadline) |
unreachable |
Network/DNS failure or connection refused |
unknown |
No health data recorded yet (e.g. new server/just started) |
Sample JSON responses
Get health for a specific server
GET /api/v1/health/servers/time
{
"name": "time",
"status": "ok",
"latency": "2ms",
"last_checked": "2025-06-27T14:10:25Z",
"last_successful": "2025-06-27T14:10:25Z"
}Get health for all servers
GET /api/v1/health/servers
{
"servers": [
{
"name": "time",
"status": "ok",
"latency": "37ms",
"last_checked": "2025-06-27T14:13:00Z",
"last_successful": "2025-06-27T14:13:00Z"
},
{
"name": "fetch",
"status": "timeout",
"latency": null,
"last_checked": "2025-06-27T14:12:58Z",
"last_successful": "2025-06-27T13:45:11Z"
},
{
"name": "foo",
"status": "unreachable",
"latency": null,
"last_checked": "2025-06-27T14:12:45Z",
"last_successful": "2025-06-27T12:02:18Z"
},
{
"name": "bar",
"status": "unknown",
"latency": null,
"last_checked": null,
"last_successful": null
}
]
}Go implementation
internal/daemon/health_tracker.go
Types
type HealthStatus string
const (
HealthStatusOK HealthStatus = "ok"
HealthStatusTimeout HealthStatus = "timeout"
HealthStatusUnreachable HealthStatus = "unreachable"
HealthStatusUnknown HealthStatus = "unknown"
)type ServerHealth struct {
Name string `json:"name"`
Status HealthStatus `json:"status"`
Latency *time.Duration `json:"latency"` // nil if unavailable
LastChecked *time.Time `json:"last_checked"` // nil if never checked
LastSuccessful *time.Time `json:"last_successful"` // nil if never succeeded
}type HealthTracker struct {
mu sync.RWMutex
statuses map[string]ServerHealth
}HealthTracker can provide the abstraction for updating the health status of an MCP server, and can be composed as part of Daemon alongside the ClientManager.
internal/daemon/daemon.go
type Daemon struct {
apiServer *ApiServer
logger hclog.Logger
clientManager *ClientManager
healthTracker *HealthTracker
supportedRuntimes map[runtime.Runtime]struct{}
cfgLoader config.Loader
}Describe alternatives you've considered
No alternatives considered at present.
Additional Context
No response
Self-Checklist
- I have read the Contributing Guidelines.
- I have searched the existing issues and found no duplicate.
- I have provided a clear and concise description of the problem.
- I have provided a clear and concise description of the proposed solution.