How to Monitor an MCP Server
Monitor an MCP server with statusas - JSON-RPC health checks, tools/list assertions, authenticated endpoints, and uptime alerts from 28 regions.
Just want to test a server once? Run it through the free MCP server health check — full JSON-RPC handshake from your browser, no account. This guide is for monitoring it continuously.
Problem
Running a Model Context Protocol (MCP) server is critical for your AI applications, but traditional HTTP monitoring often falls short. MCP servers communicate using the JSON-RPC 2.0 protocol, requiring specific request/response patterns that standard health checks don't cover. A server can return 200 OK with an HTML error page, stop echoing the JSON-RPC id, or quietly return an empty tools/list — and every one of those looks healthy to a status-code pinger while breaking every AI client that connects.
How can you confidently ensure your MCP server is healthy and responsive at all times, without custom scripts or complex setups?
Solution
statusas monitors MCP servers by sending JSON-RPC ping requests to your endpoint from multiple global locations. This verifies not only network reachability but also the correct functioning of your server's JSON-RPC interface. This guide declares those monitors with the statusas Terraform provider, so your monitoring lives in version control alongside the rest of your infrastructure.
Prerequisites
- An statusas account.
- Terraform and the statusas provider configured — see Manage statusas with Terraform if you have not set it up yet.
- An MCP server with a publicly accessible endpoint.
- A basic understanding of the JSON-RPC 2.0 protocol.
Step-by-step guide
1. Declare the monitor
Add an openstatus_http_monitor resource, adapting it for your own MCP endpoint. This example
targets a Hugging Face MCP server.
resource "openstatus_http_monitor" "mcp_server" {
name = "HF MCP Server"
description = "Hugging Face MCP server monitoring"
url = "https://hf.co/mcp"
method = "POST"
periodicity = "1m"
active = true
retry = 3
regions = ["fly-iad", "fly-ams", "fly-lax"]
body = jsonencode({
jsonrpc = "2.0"
id = "statusas"
method = "ping"
})
headers {
key = "Content-Type"
value = "application/json"
}
headers {
key = "Accept"
value = "application/json, text/event-stream"
}
status_code_assertions {
target = 200
comparator = "eq"
}
body_assertions {
target = "{\"result\":{},\"jsonrpc\":\"2.0\",\"id\":\"statusas\"}"
comparator = "eq"
}
}2. Understand the configuration
The fields that matter for an MCP check:
nameanddescription— human-readable name and explanation for your monitor.url— the full URL of your MCP server's JSON-RPC endpoint.method— must bePOSTfor JSON-RPC requests.periodicity— how often statusas runs the check (30s,1m,5m,10m,30m,1h).regions— the locations the check runs from. Monitoring from several catches localised issues. Terraform uses the prefixed region codes (fly-iad), unlike the dashboard — see the location reference.retry— how many times a failed check is retried before the monitor is marked down.body— the JSON-RPCpingpayload.jsonencodekeeps it readable and correctly escaped.headers— one block per header. statusas already sendsUser-Agent: Statusas/1.0; override it only if your server cares.status_code_assertions— ensures the HTTP response is200 OK.body_assertions— verifies the response payload matches the expected JSON-RPCpingresult.
3. Test your MCP server online first
Before deploying a monitor, confirm the server actually speaks MCP. The quickest way is the MCP server health check — paste your URL and it runs the full handshake (initialize, ping, tools/list) from the browser, shows the per-step latency, and tells you whether the endpoint is Healthy, Partial, Auth Required, or Unreachable. Use it to read off the exact response your assertion needs to match.
You can also test the ping endpoint manually with curl. This helps verify the target value for your body assertion.
curl -X POST \\
-H "Content-Type: application/json" \\
-d '{"jsonrpc": "2.0", "id": "statusas", "method": "ping"}' \\
https://hf.co/mcp # Replace with your MCP server URLA healthy server should return a JSON response like {"result":{},"jsonrpc":"2.0","id":"statusas"}.
4. Deploy your monitor
Review the plan, then apply it:
terraform plan # confirm the monitor is what you expect
terraform applyMonitoring begins as soon as the apply completes.
Monitoring an MCP server that requires authentication
Most production MCP servers are not public. An unauthenticated ping against one returns 401 Unauthorized, usually with a WWW-Authenticate: Bearer header, so a monitor without credentials will report your healthy server as down.
Add the same Authorization header your AI clients use:
variable "mcp_token" {
type = string
sensitive = true
}
resource "openstatus_http_monitor" "mcp_server" {
# ...
headers {
key = "Authorization"
value = "Bearer ${var.mcp_token}"
}
}Two things to plan for:
- Token rotation is the most common false alarm. When the token expires, the monitor goes down while the server is perfectly healthy. Assert on the status code being
200so a401fails loudly and is easy to recognise, rather than debugging it as an outage. - Keep the credential out of your repository. Mark the variable
sensitiveand pass it in withTF_VAR_mcp_tokenor from a secrets manager. Use a token scoped to read-only health checks — not a production credential — and rotate it on a schedule you control.
If you are unsure which authorization server issues your token, the health check tool parses the WWW-Authenticate challenge and surfaces the OAuth resource metadata for you.
Monitoring tool availability and latency
A ping proves the server is answering. It does not prove the server still exposes the tools your agents call — an empty tools/list is the failure mode that breaks AI clients while every uptime dashboard stays green.
Add a second monitor that calls tools/list and asserts a known tool name is present:
resource "openstatus_http_monitor" "mcp_tools" {
name = "MCP tools/list"
description = "Verify the MCP server still exposes its tools"
url = "https://hf.co/mcp"
method = "POST"
periodicity = "5m"
active = true
retry = 3
regions = ["fly-iad", "fly-ams", "fly-sin"]
body = jsonencode({
jsonrpc = "2.0"
id = "statusas"
method = "tools/list"
})
headers {
key = "Content-Type"
value = "application/json"
}
headers {
key = "Accept"
value = "application/json, text/event-stream"
}
status_code_assertions {
target = 200
comparator = "eq"
}
body_assertions {
target = "your_tool_name"
comparator = "contains"
}
}Assert on the bare tool name, not on "name":"your_tool_name". contains matches literally, and servers differ in whether they emit a space after the JSON key — an assertion written against the compact form fails the moment a server pretty-prints its response.
tools/list is also the more honest latency signal. ping usually returns an empty result and measures little more than the network round trip, whereas tools/list exercises the server's actual request path — which is what an agent waits on. Run it at a lower frequency than ping if you want to keep request volume down.
What to alert on
Not every MCP failure deserves the same response:
pingfailing across all regions — the server is down. Alert immediately.pingfailing in one region — usually a network path problem rather than your server. Retries handle most of these, which is whatretry = 3is for.401after a period of200s — a rotated or expired token. This is a credentials problem, not an outage.tools/listsucceeding but missing a tool — a deploy removed or renamed a tool. Nothing is "down", but your agents are already broken.- Latency climbing on
tools/listwhilepingstays flat — the server is under load in its application layer rather than its network layer.
What you've accomplished
- Configured a JSON-RPC based monitor for your MCP server
- Implemented precise assertions to validate
pingresponses - Handled authenticated endpoints without turning token rotation into a false outage
- Added a
tools/listcheck so a missing tool is caught before your agents hit it - Set up global monitoring to detect localised or widespread issues
- Declared both monitors in Terraform, so they are reviewable and reproducible
Both monitors run on statusas uptime monitoring from up to 28 regions, with alerting and history — so a broken handshake reaches you before it reaches the agents depending on it.
What's next
- Export metrics to OTLP — integrate your MCP monitoring data with your existing observability platform.
- Run synthetic tests in GitHub Actions — incorporate these synthetic checks into your CI/CD pipeline.
Learn more
- JSON-RPC 2.0 specification — deep dive into the JSON-RPC protocol.
- MCP official documentation — official insights into MCP health checks.
- HTTP monitor reference — comprehensive reference for HTTP monitors.
- Terraform provider reference — every resource, argument, and block.