# MCP monitors

An MCP server is not a web page. A 200 from the address tells you little: the server can be up while a tool has vanished or its sign-in is broken. An MCP monitor walks the whole path a client walks.

## What each run does

1. **Reach.** TLS, HTTP, and an answer from the endpoint.
2. **Sign-in.** If the server answers 401, we follow its `WWW-Authenticate` header to `/.well-known/oauth-protected-resource`, then to the authorization server’s metadata, and check that PKCE (S256) is offered. Unattended runs sign in with client credentials or a stored token.
3. **Handshake.** We try `server/discover` from the 2026-07-28 spec first, and fall back to `initialize` for older servers. The protocol version, server name and capabilities are recorded.
4. **Lists.** `tools/list`, `resources/list` and `prompts/list`, following every page.
5. **Changes.** Tool names, descriptions and input schemas are compared with the last accepted snapshot.
6. **Test call** (optional). One tool you pick, with fixed arguments.

Each step is timed, so you can see which one got slow.

## When the tool list changes

- **A tool was removed, or its input schema changed:** the monitor goes Degraded and you get an alert. Clients that depend on that tool are about to break.
- **Only a description changed:** a warning to look at, with the before and after side by side.
- Every changed description is scanned for hidden instructions: text aimed at the model (“ignore previous…”), invisible characters, and links that were not there before.

If the change is expected, press **Accept as the new normal** and the new list becomes the one we compare against.

## The test call

A test call only uses a tool the server marks read-only (`readOnlyHint`), or one you have allowed by name. It never calls a tool marked destructive. It passes when the result is not an error and, if you set one, contains the value you expect.

## Down and degraded

- **Down:** we can’t connect, sign-in fails or the handshake fails, confirmed from another region.
- **Degraded:** a tool disappeared or changed shape, the test call failed, or it’s slow.

## As code

openping.yml

```yaml
monitors:
  - name: My MCP server
    type: mcp
    url: https://mcp.yourapp.com/mcp
    auth: { oauth: client_credentials, secret: secret.MCP_CLIENT }
    expect:
      tools: { includes: [search, get_item] }
      on_change: alert
    call:
      tool: search
      args: { query: "ping" }
```

`on_change` is `alert`, `warn` (the default) or `ignore`.

## On your laptop and in CI

The same checks run against a local server over stdio, or any URL:

```bash
openping mcp test -- npx your-server
openping mcp test --url https://mcp.yourapp.com/mcp
```

It exits non-zero when a step fails, so it drops into CI. See [the CLI](https://openping.ai/docs/cli).

## A badge for your README

Each monitor has a badge you can paste into a README. Copy it from the monitor’s page in the app.
