@frontmcp/testing is the official testing library for FrontMCP, providing a complete toolkit for end-to-end testing of MCP servers. Test your tools, resources, prompts, authentication, plugins, and the full MCP protocol.
Fixture-Based Playwright-inspired fixtures inject ready-to-use test clients
Full Protocol Test tools, resources, prompts, and raw JSON-RPC
Offline Testing Mock HTTP calls for fully offline test suites
Installation
npm install -D @frontmcp/testing
@frontmcp/testing requires @frontmcp/sdk as a peer dependency and uses Jest as the test runner.
Quick Start
Create or update your jest.e2e.config.ts:
import type { Config } from ' jest ' ;
const config : Config = {
displayName : ' e2e ' ,
preset : ' @frontmcp/testing/jest-preset ' ,
testMatch : [ ' **/*.e2e.ts ' ],
testTimeout : 30000 ,
};
export default config ;
2. Write Your First Test
import { test , expect } from ' @frontmcp/testing ' ;
// Point to your FrontMCP server entry file
test . use ({
server : ' ./src/main.ts ' ,
port : 3003 ,
});
test ( ' server exposes tools ' , async ({ mcp }) => {
const tools = await mcp . tools . list ();
expect ( tools ). toContainTool ( ' my-tool ' );
});
test ( ' tool execution works ' , async ({ mcp }) => {
const result = await mcp . tools . call ( ' my-tool ' , { input : ' test ' });
expect ( result ). toBeSuccessful ();
expect ( result . json ()). toHaveProperty ( ' success ' , true );
});
3. Run Tests
# Using jest directly
npx jest --config jest.e2e.config.ts
# Using nx
nx e2e my-app
The library automatically:
Starts your FrontMCP server on the specified port
Connects an MCP client using Streamable-HTTP transport
Runs your tests with injected fixtures
Cleans up after all tests complete
Key Features
Fixture System
Tests receive pre-configured fixtures via dependency injection:
Fixture Description mcpAuto-connected MCP client for making requests serverServer control (restart, logs, create additional clients) authToken factory for authentication testing
test ( ' example with all fixtures ' , async ({ mcp , server , auth }) => {
// mcp: ready-to-use MCP client
const tools = await mcp . tools . list ();
// auth: create test tokens
const token = await auth . createToken ({ sub : ' user-123 ' , scopes : [ ' read ' ] });
// server: create additional clients
const client2 = await server . createClient ({ token });
});
Custom Jest Matchers
MCP-specific matchers for cleaner assertions:
// Tool matchers
expect ( tools ). toContainTool ( ' create-note ' );
// Result matchers
expect ( result ). toBeSuccessful ();
expect ( result ). toBeError (- 32602 );
// Content matchers
expect ( result ). toHaveTextContent ();
expect ( content ). toHaveMimeType ( ' application/json ' );
// Resource matchers
expect ( resources ). toContainResource ( ' notes://all ' );
expect ( templates ). toContainResourceTemplate ( ' notes://note/{id} ' );
HTTP Mocking
Mock external HTTP calls made by your tools for offline testing:
import { httpMock } from ' @frontmcp/testing ' ;
test ( ' tool with external API ' , async ({ mcp }) => {
const interceptor = httpMock . interceptor ();
interceptor . get ( ' https://api.example.com/users ' , {
body : [{ id : 1 , name : ' John ' }],
});
const result = await mcp . tools . call ( ' fetch-users ' , {});
expect ( result ). toBeSuccessful ();
interceptor . restore ();
});
MCP Request Interception
Mock or modify MCP protocol requests:
test ( ' mock tool response ' , async ({ mcp }) => {
mcp . mock . tool ( ' expensive-tool ' , { cached : true });
const result = await mcp . tools . call ( ' expensive-tool ' , {});
expect ( result . json ()). toEqual ({ cached : true });
});
Test Configuration
Configure tests using test.use():
test . use ({
// Server configuration
server : ' ./src/main.ts ' , // Entry file path
port : 3003 , // Port (default: auto-select)
startupTimeout : 30000 , // Startup timeout in ms
// Transport
transport : ' streamable-http ' , // 'sse' | 'streamable-http'
// Authentication
auth : {
mode : ' public ' , // 'public' | 'orchestrated'
type : ' local ' , // 'local' | 'remote'
},
// Debugging
logLevel : ' debug ' , // 'debug' | 'info' | 'warn' | 'error'
env : { API_KEY : ' test ' }, // Environment variables
});
Use port: 0 to automatically select an available port. This prevents conflicts when running multiple test suites in parallel.
Demo E2E reference suites
The repository ships scenario-focused Nx projects under apps/e2e/**. Each server mirrors a real deployment surface (auth modes, caching, CodeCall, OpenAPI ingestion, notifications) and already includes Jest suites wired to @frontmcp/testing.
Source layout: server code lives in apps/e2e/<project>/src, with matching tests in apps/e2e/<project>/e2e. Copy a project into your workspace or point TestServer at it during CI runs.
demo-e2e-public – minimal Notes + Tasks server that enforces public auth defaults and anonymous scopes.
demo-e2e-codecall – CRM sample that groups eight CRUD tools behind the CodeCall plugin and the new crm.store.ts.
demo-e2e-openapi – OpenAPI adapter smoke tests with built-in HTTP mocking examples.
demo-e2e-cache – Cache plugin playground for validating cache hits/misses plus execution tracking resources.
apps/e2e/demo-e2e-public/e2e/public-auth.e2e.test.ts
test . use ({
server : ' apps/e2e/demo-e2e-public/src/main.ts ' ,
publicMode : true ,
});
test . describe ( ' Public Auth Mode E2E ' , () => {
test ( ' lists all tools without auth ' , async ({ mcp }) => {
const tools = await mcp . tools . list ();
expect ( tools ). toContainTool ( ' create-note ' );
});
});
Pair apps/e2e/demo-e2e-openapi/e2e/openapi.e2e.test.ts with httpMock.interceptor() to keep tests offline: stub Beeceptor endpoints, allow passthrough for the OpenAPI spec, then call interceptor.restore() in finally.
Next Steps
Test Fixtures Deep dive into the fixture system and available APIs
Custom Matchers Full reference for all MCP-specific Jest matchers
Auth Testing Test authentication flows with token generation
HTTP Mocking Mock external API calls for offline testing