
Security News
Open VSX Unblocks Extension IDs Used in Malware Campaign
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.
@cocaxcode/api-testing-mcp
Advanced tools
The most complete MCP server for API testing. 35 tools: HTTP requests, assertions, request flows, OpenAPI import, mock data, load testing, collections, environments, native export/import, Postman import/export, cURL export, response diffing. Zero config,
The most complete API testing MCP server available.
35 tools · Zero config · Zero dependencies · Everything runs inside your AI conversation.
Why This One · Installation · Just Talk to It · Features · Tool Reference · Storage · Contributing
An MCP server that gives your AI assistant the ability to test, validate, mock, chain, diff, load-test, import/export, and manage any API — all from natural language.
You describe what you need. The AI figures out the rest.
No cloud accounts. No subscriptions. No external frameworks. Everything runs locally and stores data as plain JSON files you can commit to git.
Works with Claude Code, Claude Desktop, Cursor, Windsurf, Codex CLI, Gemini CLI, and any MCP-compatible client.
There are other API testing MCP servers out there. Here's why this one is different:
| Capability | @cocaxcode/api-testing-mcp | Others |
|---|---|---|
| HTTP requests with auth | 35 tools | 1-11 tools |
| Assertions (eq, neq, gt, lt, contains, exists, type...) | 10 operators | Status code only or none |
| Request flows with variable extraction | flow_run with extract | Not available |
| Collections with tags and CRUD | Full CRUD + tag filtering | Basic or none |
| Environments with variable interpolation | CRUD + project-scoped | Manual set_env_vars or none |
OpenAPI import (JSON & YAML) with $ref, allOf, oneOf, anyOf | ~95% real-world coverage | Basic or none |
| Mock data generation from schemas | Types, formats, enums | Not available |
| Load testing with percentiles | p50/p95/p99 + req/s | Basic or none |
| Response diffing | Field-by-field comparison | Not available |
| Bulk testing by tag | Collection-wide pass/fail | Not available |
| Native export/import | Portable .atm/ folder — copy & paste between projects | Not available |
| Postman import + export | Bidirectional: import from & export to Postman | Not available |
| cURL export | With resolved variables | Not available |
| Project-scoped environments | Per-directory context | Not available |
| External dependencies | Zero — just Node.js | Playwright, Jest, pytest... |
| Configuration needed | Zero — npx and go | Scaffolding + framework setup |
Most API testing MCPs either (a) generate test code for external frameworks (Playwright, Jest, pytest) that you then run separately, or (b) wrap a single fetch call with no state management.
This tool executes everything inline. The AI is the test runner. No generated files, no framework installs, no context switching. You say "verify that POST /users returns 201" and you get the result in the same conversation.
claude mcp add --scope user api-testing -- npx -y @cocaxcode/api-testing-mcp@latest
Add to your config file:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json{
"mcpServers": {
"api-testing": {
"command": "npx",
"args": ["-y", "@cocaxcode/api-testing-mcp@latest"]
}
}
}
Add to .cursor/mcp.json (or .windsurf/mcp.json) in your project root:
{
"mcpServers": {
"api-testing": {
"command": "npx",
"args": ["-y", "@cocaxcode/api-testing-mcp@latest"]
}
}
}
codex mcp add api-testing -- npx -y @cocaxcode/api-testing-mcp@latest
Or add manually to ~/.codex/config.toml:
[mcp_servers.api-testing]
command = "npx"
args = ["-y", "@cocaxcode/api-testing-mcp@latest"]
Add to ~/.gemini/settings.json:
{
"mcpServers": {
"api-testing": {
"command": "npx",
"args": ["-y", "@cocaxcode/api-testing-mcp@latest"]
}
}
}
Once installed, set up an environment so the tool knows where your API lives:
"Create an environment called dev with BASE_URL http://localhost:3000"
From here, relative paths work automatically. /api/users becomes http://localhost:3000/api/users.
If your API has Swagger/OpenAPI, import the spec (JSON or YAML):
"Import my API spec from http://localhost:3000/api-docs-json"
"Import the spec from ./openapi.yaml"
Now the AI knows every endpoint, parameter, and schema in your API. You're ready to go.
To verify the installation is working, try: "List my environments" — it should show the one you just created.
Available on npm.
You don't need to memorize tool names, parameters, or JSON structures — just tell the AI what you want.
Here's what a real conversation looks like:
| You say | What happens |
|---|---|
| "Set up an environment for my local API on port 3000" | Creates environment with BASE_URL=http://localhost:3000 |
| "Import my API spec from /api-docs-json" | Downloads the OpenAPI spec, stores all endpoints and schemas |
| "Show me all user endpoints" | Filters and lists endpoints tagged users |
| "Get all users" | GET /api/users → shows the response |
| "Create a user with random data" | Reads the spec, generates valid mock data, sends POST /api/users |
| "Verify that deleting user 5 returns 204" | Runs the request + assertion in one step |
| "Login as admin and then fetch the dashboard stats" | Chains 2 requests: login → extract token → use token for next call |
| "How fast is the health endpoint under load?" | Fires 50 concurrent requests, reports p50/p95/p99 latencies |
| "Run all my saved smoke tests" | Executes every request tagged smoke, reports pass/fail |
| "Export the create-user request as curl" | Builds a ready-to-paste cURL command with resolved variables |
| "Export my collection and environment" | Writes portable files to .atm/ — ready to share |
| "Import the collection from .atm/" | Auto-detects exported files and imports them |
| "Import my Postman collection from exported.json" | Reads a Postman Collection v2.1, converts all requests |
| "Export my collection to Postman" | Writes a .postman_collection.json file ready to import |
| "Compare the users endpoint between dev and prod" | Hits both URLs, diffs status codes, body, and timing |
| "Switch to the production environment" | Changes active env — all subsequent requests use prod URLs and tokens |
The AI already knows your API if you've imported the spec. It knows which fields are required, what types they expect, valid enum values, and what the response looks like. When you say "create a blog post", it doesn't guess — it reads the schema and builds the request correctly.
This isn't limited to your own backend. You can test any API — public, third-party, or internal — and manage them all simultaneously through environments.
Set up one environment per API and switch between them instantly:
"Create an environment called github with BASE_URL https://api.github.com"
"Create an environment called cloudflare with BASE_URL https://api.cloudflare.com/client/v4"
"Create an environment called dokploy with BASE_URL https://my-server:3000/api"
"Create an environment called my-backend with BASE_URL http://localhost:3000"
Add authentication variables to each one:
"Set GITHUB_TOKEN in the github environment"
"Set API_KEY in cloudflare"
"Set TOKEN in dokploy"
Then just switch context and start working:
"Switch to github"
"Get my repos" → GET /user/repos with Bearer token
"Switch to cloudflare"
"List all DNS zones" → GET /zones with API key auth
"Switch to dokploy"
"Show me all running projects" → GET /project with token
"Switch to my-backend"
"Create a user with random data" → POST /users with mock body from spec
You: "Set up Cloudflare with my API key"
You: "List my DNS zones"
You: "Show me all DNS records for cocaxcode.dev"
You: "Verify that the A record for api.cocaxcode.dev exists"
You: "How fast is the zones endpoint under load?"
You: "Save this request as cf-list-zones with tag cloudflare"
Every request, collection, and spec is isolated per environment. Your Cloudflare tests don't mix with your local backend tests.
Send any request by describing what you need. The AI resolves relative URLs, injects environment variables, and handles authentication automatically.
"POST to /api/users with name Jane and email jane@company.com using my bearer token"
request({
method: "POST",
url: "/api/users",
body: { name: "Jane", email: "jane@company.com" },
auth: { type: "bearer", token: "{{TOKEN}}" }
})
Supports: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS — Headers, query params, JSON body, Bearer / API Key / Basic auth, timeout, {{variable}} interpolation.
Validate API responses against a set of rules in one step. Get structured pass/fail results.
"Verify that GET /api/health returns 200, body.status is ok, and responds in under 500ms"
PASS — 3/3 assertions passed
GET /api/health → 200 OK (42ms)
status === 200
body.status === "ok"
timing.total_ms < 500
10 operators: eq, neq, gt, gte, lt, lte, contains, not_contains, exists, type
Chain multiple requests together. Extract values from one response and inject them into the next step. Perfect for auth flows, CRUD sequences, and multi-step testing.
"Login as admin@test.com, extract the access token, then use it to fetch all users"
flow_run({
steps: [
{
name: "login",
method: "POST",
url: "/auth/login",
body: { email: "admin@test.com", password: "SecurePass#99" },
extract: { "TOKEN": "body.access_token" }
},
{
name: "get-users",
method: "GET",
url: "/api/users",
headers: { "Authorization": "Bearer {{TOKEN}}" }
}
]
})
Features: Variable extraction with dot-notation (body.data.0.id), stop_on_error flag, {{variable}} interpolation between steps.
Import your Swagger/OpenAPI spec from a URL or local file — JSON or YAML. Once imported, the AI understands every endpoint, parameter, and schema — no guessing, no memorizing.
"Import my API spec from http://localhost:3000/api-docs-json"
"Import the spec from ./openapi.yaml"
"Show me all user endpoints"
"What parameters does POST /users expect?"
Supports: OpenAPI 3.x (JSON & YAML) with full $ref resolution, allOf (schema merging), oneOf/anyOf (union types) — covers ~95% of real-world API specs. OpenAPI 2.0 (Swagger) partially supported.
Generate realistic fake data from your OpenAPI spec. Respects types, formats (email, uuid, date-time), enums, and required fields.
"Generate mock data for creating a user"
{
"email": "user42@example.com",
"name": "Test User 73",
"password": "TestPass123!",
"role": "admin"
}
Fire N concurrent requests and get performance metrics: min, avg, percentiles (p50/p95/p99), max, and requests per second.
"How fast is the health endpoint with 50 concurrent requests?"
LOAD TEST — GET /api/health
Requests: 50 concurrent
Successful: 50 | Failed: 0
Requests/sec: 23.31
Response times:
Min: 45ms | Avg: 187ms
p50: 156ms | p95: 412ms
p99: 523ms | Max: 567ms
Execute two requests and compare their responses field by field. Detect regressions, compare environments, or validate API versioning.
"Compare the users endpoint between dev and prod"
Run every saved request in your collection (or filter by tag) and get a pass/fail summary.
"Run all my saved smoke tests"
BULK TEST — 8/8 passed | 1.2s total
health — GET /health → 200 (45ms)
list-users — GET /users → 200 (123ms)
create-post — POST /blog → 201 (89ms)
login — POST /auth/login → 200 (156ms)
Export your collections and environments to a portable .atm/ folder. Copy it to another project (or share it with your team) and import with zero configuration.
"Export my collection"
"Export the dev environment"
Both commands write to .atm/ in your project root:
your-project/
└── .atm/
├── collection.json ← All saved requests
└── dev.env.json ← Environment variables
.atm/ is automatically added to .gitignore on first export — your credentials stay safe.
"Import the collection"
"Import the environment"
No file path needed. The tools auto-detect files in .atm/. If there's no .atm/ folder, they search the current directory. You can always specify a path manually if needed.
# Developer A: exports
"Export my collection and dev environment"
→ .atm/collection.json + .atm/dev.env.json created
# Developer A shares .atm/ folder (email, Slack, USB, whatever)
# Developer B: copies .atm/ to their project root, then:
"Import the collection"
→ All requests imported
"Import the environment and activate it"
→ Environment ready, variables loaded
Bidirectional Postman support. Import existing Postman collections and environments, or export yours for use in Postman. Migrate seamlessly between Postman and your AI workflow.
"Import my Postman collection from ./exported.postman_collection.json"
"Import the collection and tag everything as legacy"
"Import the Postman environment from ./prod.postman_environment.json and activate it"
Collection import features:
Users > Admin gets tags ["Users", "Admin"]overwrite option to update existing requestsEnvironment import features:
currentValue over value (matches Postman runtime behavior)activate flag to make it the active environment immediately"Export my collection to Postman"
"Export only the smoke tests to Postman"
"Export the dev environment for Postman"
What you get:
your-project/
└── postman/
├── my-api.postman_collection.json ← Import in Postman: File → Import
└── dev.postman_environment.json ← Import in Postman: File → Import
Collection export features:
{{variables}} preserved as-is (Postman uses the same syntax)Environment export features:
enabled: true_postman_variable_scope: "environment")You: "Import the Postman collection from ./legacy-api.postman_collection.json with tag migrated"
→ 47 requests imported with tag "migrated"
You: "Run all migrated requests"
→ Bulk test: 45/47 passed
You: "Fix the failing ones and export back to Postman"
→ Updated collection exported to postman/legacy-api.postman_collection.json
Convert any saved request into a ready-to-paste cURL command with resolved variables.
"Export the create-user request as curl"
curl -X POST \
'https://api.example.com/users' \
-H 'Authorization: Bearer eyJhbGci...' \
-H 'Content-Type: application/json' \
-d '{"name":"Jane","email":"jane@company.com"}'
Save requests for reuse with tags. Filter, list, and manage your request library. Perfect for building regression suites.
"Save this request as create-user with tags auth, smoke"
"List all requests tagged smoke"
"Delete the old health-check request"
Manage variables across environments (dev/staging/prod) and switch contexts instantly. Supports {{variable}} interpolation in URLs, headers, and body.
Different projects can have different active environments. When you switch to an environment for a specific project, it only affects that project — other projects keep their own active environment.
"Switch to dev for this project" → dev is active only in the current project
"Switch to prod globally" → prod is the default for projects without a specific assignment
"Show me which projects have environments" → lists all project-environment assignments
"Clear the project environment" → falls back to the global active environment
Resolution order: project-specific environment → global active environment.
35 tools organized in 8 categories:
| Category | Tools | Count |
|---|---|---|
| Requests | request | 1 |
| Testing | assert | 1 |
| Flows | flow_run | 1 |
| Collections | collection_save collection_list collection_get collection_delete | 4 |
| Environments | env_create env_list env_set env_get env_switch env_rename env_delete env_spec env_project_clear env_project_list | 10 |
| API Specs | api_import api_spec_list api_endpoints api_endpoint_detail | 4 |
| Mock | mock | 1 |
| Utilities | load_test export_curl diff_responses bulk_test export_collection import_collection export_environment import_environment export_postman_collection import_postman_collection export_postman_environment import_postman_environment | 12 |
You don't need to call these tools directly. Just describe what you want and the AI picks the right one.
All data lives in ~/.api-testing/ (user home directory) as plain JSON — no database, no cloud sync. This keeps credentials out of your project repos by default.
~/.api-testing/
├── active-env # Global active environment name
├── project-envs.json # Per-project active environments
├── collections/ # Saved requests
├── environments/ # Environment variables (dev, prod, ...)
└── specs/ # Imported OpenAPI specs
Exports go to .atm/ in your project root (portable folder for sharing):
your-project/
└── .atm/ # Auto-added to .gitignore
├── collection.json # Exported requests
└── dev.env.json # Exported environment
Override the default storage directory in your MCP config:
{
"env": { "API_TESTING_DIR": "/path/to/custom/.api-testing" }
}
Warning: If you override
API_TESTING_DIRto a path inside a git repository, add.api-testing/to your.gitignoreto avoid accidentally pushing credentials (API keys, tokens, passwords) to your remote.
Built for reliability and testability:
@modelcontextprotocol/sdk and zodcreateServer(storageDir?) for isolated test instancesany, full type coveragesrc/
├── tools/ # 35 MCP tool handlers (one file per category)
├── lib/ # Business logic (no MCP dependency)
│ ├── http-client # fetch wrapper with timing
│ ├── storage # JSON file storage engine
│ ├── schemas # Shared Zod schemas (DRY across all tools)
│ ├── url # BASE_URL resolution
│ ├── path # Dot-notation accessor (body.data.0.id)
│ ├── interpolation # {{variable}} resolver
│ └── openapi-parser # $ref + allOf/oneOf/anyOf resolution
└── __tests__/ # 10 test suites, 120 tests
$ref, allOf, oneOf, and anyOf — covers ~95% of real-world API specs. OpenAPI 2.0 (Swagger) is partially supported. AsyncAPI is not supported.git clone https://github.com/cocaxcode/api-testing-mcp.git
cd api-testing-mcp
npm install
npm test # 120 tests across 10 suites
npm run build # ESM bundle via tsup
npm run typecheck # Strict TypeScript
Test with MCP Inspector:
npx @modelcontextprotocol/inspector node dist/index.js
Stack: TypeScript · MCP SDK 1.27 · Zod · Vitest · tsup
npm test and npm run typecheck pass, then open a PR.FAQs
The most complete MCP server for API testing. 36 tools: HTTP requests (with token-optimized responses), assertions, request flows, OpenAPI import, mock data, load testing, collections, environments, native export/import, Postman import/export, cURL export
The npm package @cocaxcode/api-testing-mcp receives a total of 57 weekly downloads. As such, @cocaxcode/api-testing-mcp popularity was classified as not popular.
We found that @cocaxcode/api-testing-mcp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.

Product
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.

Product
Socket is bringing experimental protection to Firefox, scanning 97,000+ extensions in Mozilla's official directory for malware and risky updates.