Should I test that?

Should I test MCP servers?

Verdict

Yes

Test an MCP server that customers connect to: in CI, call each tool through an in-memory MCP client with valid, ambiguous and invalid arguments, and assert what the tool stores and which error it returns.

Why

Test an MCP server that customers use, through an in-memory client in CI. My typical case is a remote MCP server that lets customers create and read their records from an AI client. Blast radius is users, because a wrong tool call changes a customer's data. Change frequency is regularly, because tools and arguments change about once a month. Detectability is eventually, because the model reports success even when the tool did the wrong thing, and Reversibility is with-effort, because support repairs the records. Test cost is moderate, because a scripted tool call has a result a test compares exactly, so rule R11 gives Test.

When the decision changes
WhenDecisionWhy
The failure to catch is the model picking the wrong MCP tool after you edit a tool description or add a toolTest it differently: an evaluation set of real requests labelled with the expected tool, run against a real model on each description changeTest cost rises to heavy, because the real model's choice differs between runs
A remote MCP server's tools read records by an ID from the model's argumentsTest mandatory: calls with one account's token and another account's record ID that assert the tool returns no dataBlast radius rises to safety-or-legal and Detectability to never, because a leaked record reads like a normal tool result
An MCP tool issues account credits with an amount taken from the model's argumentsTest mandatory: calls with a negative amount, an amount above the limit and a repeated callBlast radius rises to money and Reversibility to costly, because credits already spent need a claw-back
Every tool on the MCP server only reads public documentation, and a failed call shows an error in the chat that users reportTest minimally: one in-memory client call per tool, plus a regression test for each reported failureDetectability moves to same-day and Reversibility to trivial, because users see the error and nothing is saved
Only your team searches internal wiki pages through the MCP server, and colleagues open the page each answer links before acting on itDo not write MCP server tests; the colleague who opens the linked page is the checkBlast radius falls to internal, Detectability to same-day and Reversibility to trivial
The MCP server runs over stdio on your own machine, and only you use it from your own editorDo not test; try each tool by hand in the MCP InspectorBlast radius falls to none, because only you run the server

What breaks if you don't test

A tool guesses from an argument it should reject, such as a partial project name. The model tells the customer the task is done while the record sits in the wrong place, and the customer notices weeks later.

What you lose if you over-test

Tests that drive the server with a real model fail at random and cost tokens on every push. Tests that assert the full JSON of tools/list break on every wording change in a description.

How to test

  1. Connect a client to the server object in memory, with no process or network. FastMCP's testing guide passes the server straight to Client.
  2. For each tool, write one valid call, one call per argument the tool must reject, and one ambiguous call.
  3. Assert what the tool stored, and that a rejected call returns isError: true with a message the model can act on, as the tools specification describes.
  4. For a remote server, add calls with a second account's token; the MCP security guide lists the token and session attacks.

When the answer changes

  • A tool reads records by an ID the model supplies, or moves money.
  • You rewrite tool descriptions and need to know the model still picks the right tool.
  • Only your team uses the server, or only you run it.

Real incident + Code example

The tasks that went to an archived project

On a project tracker I worked on, our MCP server's create_task tool took a project name. The handler matched names by prefix, archived projects included, oldest first, so "Mobile" matched "Mobile 2024 (archived)" before "Mobile app", and the model replied that each task was created. Three weeks later a customer asked why sixty tasks were missing. We moved 212 tasks out of archived projects in nine workspaces with a script. The tool now accepts only an exact active project name and returns the candidates as an error otherwise:

import pytest
from fastmcp import Client
from tracker.mcp import mcp

@pytest.fixture
async def client(workspace):
    workspace.add_project("Mobile 2024", archived=True)
    workspace.add_project("Mobile app")
    async with Client(mcp) as c:
        yield c

async def test_task_goes_to_the_active_project(client, workspace):
    await client.call_tool("create_task", {"title": "Fix login", "project": "Mobile app"})
    assert workspace.project("Mobile app").task_titles() == ["Fix login"]
    assert workspace.project("Mobile 2024").task_titles() == []

async def test_partial_name_goes_back_to_the_model(client, workspace):
    result = await client.call_tool(
        "create_task", {"title": "Fix login", "project": "Mobile"}, raise_on_error=False)
    assert result.is_error
    assert "Mobile app" in result.content[0].text
    assert workspace.task_count() == 0

FAQ

Do MCP servers need tests?

MCP servers that other people connect to need tests of each tool, because a model reports success even when a tool stored the wrong record. A server that only you run needs a manual check of each tool in the MCP Inspector instead.

How do I test an MCP server without an AI client?

Test an MCP server without an AI client by connecting a test client to the server in memory and calling each tool with fixed arguments. FastMCP's Client accepts the server object directly, with no process or network port.

Is the MCP Inspector enough to test my server?

The MCP Inspector is not enough on its own, because it checks a tool by hand once and does not rerun when the code changes. Explore a new tool with it, then keep the calls as client tests in CI.

Should MCP server tests call a real model?

MCP server tests should not call a real model, because the model's calls differ between runs and each run costs tokens. Check whether a real model picks the right tool in a separate evaluation set that runs when tool descriptions change.