m3 MCP server
Commit Nov 9, 2026Tests MCP servers and the agents that use them by running Python and pytest tests while capturing MCP evidence.
Also known as sineframe/m3
- Stars
- 12
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- —
- Last commit
- Nov 9, 2026
- License
- —
What is m3 MCP?
m3 tests MCP servers and the agents that use them by running Python and pytest tests while capturing MCP evidence.
Summary generated from the project's README
About m3 MCP server
Verifying that AI agents interact correctly with your Model Context Protocol tools is the primary function of m3. This testing framework allows developers to run Python and pytest suites that evaluate not just the final answer from an agent, but the specific MCP calls made during the process. By capturing this evidence, you can ensure agents use the correct tools and arguments rather than relying on outdated training data.
Users set up the environment using the m3 CLI, which can be installed via uv or a shell script. Testing requires an ANTHROPIC_API_KEY in a .env file at the project root. The system supports various agent harnesses including Claude Code, Codex, OpenCode, Pi, and ACP agents. You can run tests against local servers using stdio or compare different agent versions and models to ensure consistent tool usage across your development lifecycle.
What you can do with it
- 1Verify specific tool callsEnsure an agent calls a specific tool with the correct arguments instead of just providing a text response.
- 2Validate tool descriptionsCheck if an agent fails to use a tool because the description is insufficient for the model to understand its purpose.
- 3Compare agent performanceRun the same test suite across different agent harnesses or multiple times to determine a reliable pass rate.
Written from the project's README. Every use case is checked against a quote from it.
README
View on GitHubM3 tests MCP servers and the agents that use them. It runs Python and pytest tests, captures MCP evidence, and can save runs for inspection and comparison.
What a test looks like
A test gives an agent a prompt and your MCP server. M3 records every MCP call the agent makes, so the test can check the calls, not only the answer.
import sys
import pytest
from m3 import StdioServer, expect
pytestmark = pytest.mark.m3(agents=[{"harness": "claude-code", "models": ["claude-sonnet-5-5"]}])
registry = StdioServer(name="registry", command=sys.executable, args=("registry_server.py",))
def test_adds_current_tailwind(agent):
result = agent.run("Add Tailwind to this project.", server=registry)
expect(result).to_have_tool_call("get_latest_version", arguments={"package": "tailwindcss"})
If the agent answers from memory and never calls the server, the test fails. The fix is usually the tool description, not the test:
@mcp.tool(
- description="Get package info",
+ description="Current published version of a package. Call before adding "
+ "or upgrading a dependency; your training data is out of date.",
)
def get_latest_version(package: str) -> str:
def test_revenue_by_month(agent):
result = agent.run("Show me revenue by month.", server=db)
expect(result).to_have_tool_calls(["describe_table", "query"])
@mcp.tool(
- description="Run a SQL query",
+ description="Run a read-only SQL query. Call describe_table first; "
+ "column names are specific to this database.",
)
def query(sql: str) -> list[list]:
def test_last_weeks_orders(agent):
result = agent.run("Get last week's orders from our API.", server=api)
expect(result).to_have_tool_calls(["find_endpoint", "call_endpoint"])
@mcp.tool(
- description="Search the API spec",
+ description="Look up the real path before calling any endpoint. "
+ "Paths are specific to this API; don't guess them.",
)
def find_endpoint(query: str) -> str:
Put ANTHROPIC_API_KEY in .env at the project root, then run the tests:
m3 test -- tests
Run the same tests with another agent, or several times to get a pass rate.
--trials repeats tests that take the agent fixture, like the ones above;
other tests run once.
m3 test --harness codex=gpt-5.6-sol -- tests
m3 test --trials 5 -- tests
Install and start
Install the CLI with uv:
uv tool install sf-m3-cli
On macOS or Linux, the shell installer is an alternative:
curl -LsSf https://m3.sineframe.com/install.sh | sh
Then initialize your project:
m3 init
m3 setup
m3 doctor
Then follow the first MCP test. It uses a local server and needs no model credentials.
Agent skill
m3 init and m3 setup install the testing-with-m3 agent skill for the
installed M3 release. To install it yourself:
npx --yes skills@1.7.0 add sineframe/m3#vVERSION --skill testing-with-m3 --agent universal claude-code -y
VERSION is the output of m3 --version. See the
agent skill guide.
Submitting a server to the Claude, OpenAI or Muse directory? Install the
preparing-directory-submissions skill the same way, with
--skill preparing-directory-submissions. It runs m3 lint --directory,
does the checks that need judgment and writes one readiness report; see
Prepare a directory submission.
Documentation
- Documentation
- Test a local server
- Test agent behavior
- Configure credentials
- Connect an ACP-compatible agent
- Compare agent harnesses and versions
- Pin and inspect harness runtimes
- Handle MCP elicitation
- CLI reference
- Python reference
- Blog
- Contributing
The SDK and CLI use separate environments. The CLI runs pytest in the project environment and saves history; tests import the SDK.
Development
Read Architecture, then use the package README for the area you are changing. Documentation changes follow the documentation writing guide.
just setup
just test-all
just lint
just format-check
M3 is licensed under Apache-2.0.
m3 MCP questions
What does M3 test?
M3 tests MCP servers and the agents that use them, such as Claude Code, Codex, OpenCode, and Pi.
How can I run tests with multiple trials?
You can use the --trials flag to repeat tests that take the agent fixture.
What happens if an agent answers from memory without calling the server?
The test will fail, which usually indicates that the tool description needs to be improved.