# Test and debug an MCP server with MCP Inspector

> Debug an MCP server before you connect it to ChatGPT: MCP Inspector web UI and CLI, tunnels, logs, schema and annotation checks, and OAuth debugging.

Published: 2026-10-04 · By: Divy Chaurasia · Level: intermediate · Time: 20 min · Tags: mcp, debugging, testing

When an MCP server misbehaves in ChatGPT, the chat window tells you very little. Test it outside ChatGPT first: confirm it initializes, lists valid tools, returns the right results and handles auth. Then add a tunnel and ChatGPT, one layer at a time, so you know which layer broke.

The main tool for this is **MCP Inspector**, the official MCP debugging client. It comes in one package with a web UI, a CLI and a terminal UI.

## Before you start

- **Node.js 22.19 or newer** for the current Inspector (v2). The older v1 line is still available as `npx @modelcontextprotocol/inspector@v1-latest`, but its CLI flags differ from the examples here.
- **Your server running locally**, for example on `http://localhost:8787/mcp`. If you don't have one, follow [Build your first ChatGPT app](/tutorials/build-your-first-chatgpt-app).
- **`jq`**, if you want to script assertions.

> **Tip:** To check that your *client* setup works before blaming your server, point the Inspector at a known-good server. The reference "Everything" server implements every MCP feature, and DeepWiki is a public remote server with no auth (`https://mcp.deepwiki.com/mcp`).

> **MCP server:** [Everything](https://chatgptplugins.directory/mcp/everything): Reference test server exercising every MCP protocol feature
## 1. Inspect it in the web UI

```bash
npx @modelcontextprotocol/inspector@latest
```

This opens the Inspector in your browser. Choose **Streamable HTTP**, enter your server URL, and connect. Then work through this list:

1. **Initialization succeeds.** Note the protocol version and capabilities the server reports.
2. **Server instructions** read well. ChatGPT and Codex use the MCP `instructions` field as server-wide guidance, and Codex recommends keeping the first 512 characters self-contained.
3. **The tool list** is what you expect, with no leftovers from earlier experiments.
4. **Every tool** works with normal inputs, edge cases, missing IDs and empty results.
5. **Errors** come back as readable messages, not stack traces.
6. **Auth** is enforced for private data and write actions.

For a stdio server, the Inspector can start it for you. Pass the command after the package name:

```bash
npx @modelcontextprotocol/inspector node build/index.js
```

> **Note:** The Inspector stores OAuth tokens, client secrets and stdio environment values in your OS keychain when one is available, and otherwise in `~/.mcp-inspector/secrets.json`. Keep that in mind on shared machines.

## 2. Script checks with the Inspector CLI

The CLI runs one MCP call per command and exits with a status code, which makes it good for repeatable checks and CI.

```bash
# Connect-only probe: handshake, print server info, disconnect
npx @modelcontextprotocol/inspector --cli --transport http \
  --server-url http://localhost:8787/mcp --method initialize

# List tools as JSON
npx @modelcontextprotocol/inspector --cli --transport http \
  --server-url http://localhost:8787/mcp --method tools/list --format json

# Call one tool with typed arguments
npx @modelcontextprotocol/inspector --cli --transport http \
  --server-url http://localhost:8787/mcp \
  --method tools/call --tool-name roll_dice \
  --tool-args-json '{"count":2,"sides":6}' --format json
```

Prefer `--tool-args-json` over `--tool-arg key=value`. The `key=value` form parses values as JSON when it can, so an ID like `10001` arrives as a number, and a schema expecting a string will reject it.

Turn checks into assertions with `jq -e`, which fails when the result is `null` or `false`:

```bash
npx @modelcontextprotocol/inspector --cli --transport http \
  --server-url http://localhost:8787/mcp --method tools/list --format json \
  | jq -e '.result.tools | map(.name) | index("roll_dice")' > /dev/null
```

Two more flags worth knowing:

- `--app-info` reports whether a tool has an MCP Apps UI and which `ui://` resource it points to, without calling the tool. It exits `2` when there is no UI.
- `--strict` on `tools/list` adds `schemaFindings` for schema portability problems.

In CI, pin an exact Inspector version (`npx --yes @modelcontextprotocol/inspector@<version> --cli ...`) so results don't change under you.

## 3. Check tool schemas and annotations

Most "the model won't call my tool" problems are metadata problems. For each tool, check:

- **Name**: specific and verb-first (`get_order_status`), unique within the server.
- **Description**: says what it does, when to use it ("Use this when…"), and its limits.
- **Input schema**: every parameter has a type and a description; use enums for fixed choices; mark required fields. Ask only for what the tool needs.
- **Output schema**: if you declare `outputSchema`, `structuredContent` must match it on every call, including error cases.
- **Annotations**: set `readOnlyHint`, `destructiveHint` and `openWorldHint` explicitly. ChatGPT treats a tool with no `readOnlyHint` as a write and asks for confirmation every time. OpenAI's plugin review rejects annotations that don't match behavior.
- **UI link**: for app tools, `_meta.ui.resourceUri` points at a resource that exists, served with MIME type `text/html;profile=mcp-app`.

## 4. Watch the raw traffic and logs

When the Inspector and your expectations disagree, go one level lower. A Streamable HTTP server is just HTTP, so you can call it with `curl`:

```bash
curl -s -X POST http://localhost:8787/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
```

A healthy server returns a JSON-RPC result with `serverInfo` and `capabilities`. A `406 Not Acceptable` from a server built on the official TypeScript SDK means the `Accept` header doesn't list both `application/json` and `text/event-stream`.

On the server side:

- Log every incoming method name, tool name and duration, plus the full error for failures.
- **For stdio servers, never write logs to stdout.** Stdout carries the protocol; a stray `console.log` corrupts it. Log to stderr instead.
- Don't log access tokens or sensitive tool results.

## 5. Test through a tunnel, then ChatGPT

Once it works locally, expose it and repeat the same checks against the public URL:

```bash
ngrok http 8787
# or
cloudflared tunnel --url http://localhost:8787
```

```bash
npx @modelcontextprotocol/inspector --cli --transport http \
  --server-url https://abc123.ngrok.app/mcp --method tools/list --format json
```

If it passes here but fails in ChatGPT, the problem is in the ChatGPT setup (URL, auth mode, stale metadata), not the server. Connect it with [developer mode](/tutorials/add-mcp-server-to-chatgpt), and remember to select **Refresh** on the connection after every server change.

For raw request and response logs from OpenAI's side, use the API Playground: **Tools** > **Add** > **MCP Server**, enter the HTTPS endpoint, and run test prompts.

> **MCP server:** [DeepWiki](https://chatgptplugins.directory/mcp/deepwiki): Ask questions about any public GitHub repo using DeepWiki's generated docs
## 6. Debug OAuth

ChatGPT follows the MCP authorization spec. Check each link in the chain:

1. **Protected resource metadata.** Your server publishes it at `/.well-known/oauth-protected-resource`, or points to it in a `WWW-Authenticate` header on `401` responses:

   ```bash
   curl -i https://mcp.example.com/.well-known/oauth-protected-resource
   curl -i -X POST https://mcp.example.com/mcp -H 'Content-Type: application/json' -d '{}'
   ```

   The second call should return `401` with `WWW-Authenticate: Bearer resource_metadata="..."`.

2. **Authorization server metadata** is reachable at `/.well-known/oauth-authorization-server` or `/.well-known/openid-configuration` on your identity provider.
3. **Client registration** works: CIMD (`client_id_metadata_document_supported: true`), DCR, or static credentials entered in ChatGPT.
4. **Redirect URI** matches exactly. Copy it from the connection's page in ChatGPT; it is either `https://chatgpt.com/connector/oauth/{callback_id}` or the stable `https://chatgpt.com/connector_platform_oauth_redirect`, depending on whether your authorization server supports issuer identification.
5. **Tokens** are checked for issuer, audience, expiry and scopes. Reject bad tokens with a `401` and the `WWW-Authenticate` challenge, so the client re-authorizes.

To test with the Inspector, register its callback URL with your provider (`http://localhost:6274/oauth/callback` for the web UI, `http://127.0.0.1:6276/oauth/callback` for the CLI). Then:

```bash
# skip OAuth and pass a token you already have
npx @modelcontextprotocol/inspector --cli --transport http \
  --server-url https://mcp.example.com/mcp \
  --header "Authorization: Bearer $TOKEN" --method tools/list

# throw away stored tokens and log in again
npx @modelcontextprotocol/inspector --cli --transport http \
  --server-url https://mcp.example.com/mcp --relogin --method tools/list
```

## Common protocol mistakes

- The URL in ChatGPT is missing the `/mcp` path.
- OAuth discovery routes return an HTML error page or `500` on a no-auth server. Return `404`.
- CORS preflight (`OPTIONS`) isn't handled, or `Mcp-Session-Id` isn't exposed.
- A stateful server loses sessions behind a load balancer. Use stateless mode or sticky sessions.
- Tool results include only `content` when the widget needs `structuredContent`.
- Tool results leak internal IDs, timestamps or debug payloads.
- Tool names or schemas change between deploys, breaking chats that already loaded the old list.

## Next steps

- Connect the working server: [How to add a custom MCP server to ChatGPT](/tutorials/add-mcp-server-to-chatgpt).
- Prepare it for review: [Publish a ChatGPT plugin](/tutorials/publish-a-chatgpt-plugin).
- Compare your server with others in the [MCP directory](/mcp).

## Listings in this tutorial

- [Everything](https://chatgptplugins.directory/mcp/everything.md): Reference test server exercising every MCP protocol feature
- [DeepWiki](https://chatgptplugins.directory/mcp/deepwiki.md): Ask questions about any public GitHub repo using DeepWiki's generated docs

---
Source: https://chatgptplugins.directory/tutorials/test-mcp-server-with-inspector · Index: https://chatgptplugins.directory/llms.txt · Independent and community-run. Not affiliated with or endorsed by OpenAI. ChatGPT is a trademark of OpenAI.
