Testing MCP Servers with the Inspector

AIMCPTestingDeveloper Tools
Share on LinkedIn

You built an MCP server with twelve tools, eight resources, and three prompts. It connects in Cursor without errors. But when the model calls search_tickets, it returns empty results. When it calls create_ticket, the required fields error message is confusing. You need to test each tool in isolation, inspect the raw protocol messages, and verify your schemas before the model ever sees them.

The MCP Inspector is the official debugging tool for this. It connects to your server, exposes every capability in a testable UI, and shows the JSON-RPC wire protocol so you can see exactly what the client and server exchange.

Starting the Inspector

Install and launch against your server:

npx @modelcontextprotocol/inspector node dist/server.js

For a server with environment variables:

npx @modelcontextprotocol/inspector \
  -e DATABASE_URL=postgresql://localhost/test \
  -e API_KEY=test-key \
  node dist/server.js

For a remote HTTP/SSE server:

npx @modelcontextprotocol/inspector \
  --url http://localhost:8080/sse \
  --header "Authorization: Bearer test-token"

The Inspector opens a browser UI at http://localhost:6274 (default port).

Testing tools

The Tools tab lists every registered tool with its input schema:

  1. Select a tool from the list.
  2. Fill in argument fields (the UI renders the JSON Schema as a form).
  3. Click "Invoke" to execute.
  4. Inspect the response content and any errors.

This catches issues before the model encounters them:

Test matrix for each tool:

Test case Input Expected
Happy path Valid arguments Correct result
Missing required field Omit required param Clear validation error
Invalid enum value Out-of-range enum Schema rejection
Empty result Query matching nothing Empty array, not error
Permission denied Unauthorized operation 403-style error message
Timeout Slow backend Graceful timeout error

Testing resources

The Resources tab shows registered resources and their URIs:

  1. Browse the resource list or enter a URI manually.
  2. Click "Fetch" to retrieve content.
  3. Verify MIME type, content encoding, and data correctness.

For template URIs like file://{path}, test with multiple parameter values:

file:///README.md        → expect markdown content
file:///nonexistent.txt  → expect clear error
file:///../etc/passwd    → expect path traversal rejection

Testing prompts

The Prompts tab renders prompt templates with their arguments:

  1. Select a prompt.
  2. Fill in parameters.
  3. Preview the generated messages.
  4. Verify the template produces well-structured instructions.

Prompts should generate messages that work as-is when sent to the model — check formatting, variable substitution, and instruction clarity.

Inspecting the protocol

The Inspector's notification/log panel shows raw JSON-RPC messages:

// Client → Server: tool call
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "search_tickets",
    "arguments": { "query": "login issue", "status": "open" }
  }
}

// Server → Client: tool result
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [{ "type": "text", "text": "[{\"id\": 1, \"title\": \"Login timeout\"}]" }],
    "isError": false
  }
}

Use this to debug:

Automated testing with the SDK

For CI/CD, test programmatically:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { describe, it, expect, beforeAll, afterAll } from "vitest";

describe("CRM MCP Server", () => {
  let client: Client;

  beforeAll(async () => {
    const transport = new StdioClientTransport({
      command: "node",
      args: ["dist/server.js"],
      env: { DATABASE_URL: "postgresql://localhost/test" },
    });
    client = new Client({ name: "test", version: "1.0.0" });
    await client.connect(transport);
  });

  afterAll(async () => {
    await client.close();
  });

  it("lists all expected tools", async () => {
    const { tools } = await client.listTools();
    const names = tools.map(t => t.name);
    expect(names).toContain("search_tickets");
    expect(names).toContain("create_ticket");
  });

  it("search_tickets returns results", async () => {
    const result = await client.callTool({
      name: "search_tickets",
      arguments: { query: "login", status: "open" },
    });
    expect(result.isError).toBeFalsy();
    const tickets = JSON.parse(result.content[0].text);
    expect(Array.isArray(tickets)).toBe(true);
  });

  it("create_ticket validates required fields", async () => {
    const result = await client.callTool({
      name: "create_ticket",
      arguments: { title: "" },
    });
    expect(result.isError).toBe(true);
  });
});

Run in CI on every pull request that modifies the MCP server.

Common issues the Inspector catches

Tool not appearing in list: registration code not reached, server crash during startup, async registration not awaited.

Schema validation too strict: model generates arguments that fail validation because enum values or type constraints are too narrow.

Response too large: tool returns megabytes of data that exceed context limits. Add pagination or truncation.

Missing error handling: unhandled exceptions crash the server process instead of returning isError: true.

Resource URI mismatch: template URIs registered but fetch handler does not parse parameters correctly.

Common production mistakes

Teams get server testing inspector wrong in predictable ways:

Production implementations of server testing inspector fail when staging mirrors production topology poorly, rollback is untested, and on-call runbooks describe the happy path only.

Resources

Frequently asked questions

What is the MCP Inspector?

The MCP Inspector is an official browser-based debugging tool for MCP servers. It connects to a server via stdio or HTTP/SSE and provides a UI to list tools, invoke them with custom arguments, fetch resources, test prompts, and inspect the raw JSON-RPC messages exchanged between client and server.

Can I use the MCP Inspector in CI/CD pipelines?

The Inspector itself is a GUI tool, but you can test MCP servers programmatically using the MCP SDK client in test scripts. Connect to the server, call list_tools, invoke each tool with test inputs, and assert on responses. The Inspector is for development debugging; automated tests use the SDK.

How do I test an MCP server that requires authentication?

For stdio servers, pass credentials via environment variables in the Inspector's server config. For remote HTTP servers, configure the Authorization header in the Inspector's connection settings. The Inspector supports Bearer token auth for testing OAuth-protected servers.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →