@cocaxcode/api-testing-mcp 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +215 -138
- package/dist/index.js +938 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,38 +1,67 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">@cocaxcode/api-testing-mcp</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
A complete API testing toolkit built for AI coding agents.<br/>
|
|
5
|
+
Test, validate, mock, and load-test your APIs — all from natural language.
|
|
6
|
+
</p>
|
|
7
|
+
</p>
|
|
2
8
|
|
|
3
|
-
|
|
4
|
-
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/@cocaxcode/api-testing-mcp"><img src="https://img.shields.io/npm/v/@cocaxcode/api-testing-mcp.svg?style=flat-square&color=cb3837" alt="npm version" /></a>
|
|
11
|
+
<a href="https://github.com/cocaxcode/api-testing-mcp/actions"><img src="https://img.shields.io/github/actions/workflow/status/cocaxcode/api-testing-mcp/ci.yml?style=flat-square&label=CI" alt="CI" /></a>
|
|
12
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="License" /></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/tests-70%20passing-brightgreen?style=flat-square" alt="Tests" />
|
|
14
|
+
<img src="https://img.shields.io/badge/tools-20-blueviolet?style=flat-square" alt="Tools" />
|
|
15
|
+
<img src="https://img.shields.io/badge/node-%3E%3D20-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node" />
|
|
16
|
+
</p>
|
|
5
17
|
|
|
6
|
-
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="#installation">Installation</a> •
|
|
20
|
+
<a href="#just-talk-to-it">Just Talk to It</a> •
|
|
21
|
+
<a href="#features">Features</a> •
|
|
22
|
+
<a href="#tool-reference">Tool Reference</a> •
|
|
23
|
+
<a href="#storage">Storage</a> •
|
|
24
|
+
<a href="#contributing">Contributing</a>
|
|
25
|
+
</p>
|
|
7
26
|
|
|
8
|
-
|
|
27
|
+
---
|
|
9
28
|
|
|
10
|
-
##
|
|
29
|
+
## What is this?
|
|
11
30
|
|
|
12
|
-
|
|
13
|
-
- **Authentication** — Bearer token, API Key, Basic Auth built-in
|
|
14
|
-
- **Collections** — Save, organize, and reuse requests locally
|
|
15
|
-
- **Environments** — Manage variables per environment (dev/staging/prod)
|
|
16
|
-
- **Variable interpolation** — Use `{{VARIABLE}}` in URLs, headers, and body
|
|
17
|
-
- **Response metrics** — Timing (ms) and response size for every request
|
|
18
|
-
- **Zero cloud dependencies** — Everything stored locally as JSON files
|
|
31
|
+
An [MCP server](https://modelcontextprotocol.io) that gives your AI assistant the ability to interact with any API. It works with Claude Code, Claude Desktop, Cursor, and any MCP-compatible client.
|
|
19
32
|
|
|
20
|
-
|
|
33
|
+
You describe what you need. The AI figures out the rest.
|
|
21
34
|
|
|
22
|
-
|
|
35
|
+
No cloud accounts. No subscriptions. Everything runs locally and stores data as plain JSON files you can commit to git.
|
|
23
36
|
|
|
24
|
-
|
|
37
|
+
---
|
|
25
38
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
## Just Talk to It
|
|
40
|
+
|
|
41
|
+
This tool is designed to be used through natural language. You don't need to memorize tool names, parameters, or JSON structures — just tell the AI what you want, and it translates your intent into the right API calls.
|
|
42
|
+
|
|
43
|
+
**Here's what a real conversation looks like:**
|
|
44
|
+
|
|
45
|
+
| You say | What happens behind the scenes |
|
|
46
|
+
|---------|-------------------------------|
|
|
47
|
+
| *"Set up an environment for my local API on port 3000"* | Creates environment with `BASE_URL=http://localhost:3000` |
|
|
48
|
+
| *"Import my API spec from /api-docs-json"* | Downloads the OpenAPI spec, stores all endpoints and schemas |
|
|
49
|
+
| *"Show me all user endpoints"* | Filters and lists endpoints tagged `users` |
|
|
50
|
+
| *"Get all users"* | `GET /api/users` → shows the response |
|
|
51
|
+
| *"Create a user with random data"* | Reads the spec, generates valid mock data, sends `POST /api/users` |
|
|
52
|
+
| *"Verify that deleting user 5 returns 204"* | Runs the request + assertion in one step |
|
|
53
|
+
| *"Login as admin and then fetch the dashboard stats"* | Chains 2 requests: login → extract token → use token for next call |
|
|
54
|
+
| *"How fast is the health endpoint under load?"* | Fires 50 concurrent requests, reports p50/p95/p99 latencies |
|
|
55
|
+
| *"Run all my saved smoke tests"* | Executes every request tagged `smoke`, reports pass/fail |
|
|
56
|
+
| *"Export the create-user request as curl"* | Builds a ready-to-paste cURL command with resolved variables |
|
|
57
|
+
| *"Compare the users endpoint between dev and prod"* | Hits both URLs, diffs status codes, body, and timing |
|
|
58
|
+
| *"Switch to the production environment"* | Changes active env — all subsequent requests use prod URLs and tokens |
|
|
59
|
+
|
|
60
|
+
**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.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
36
65
|
|
|
37
66
|
### Claude Code
|
|
38
67
|
|
|
@@ -40,217 +69,265 @@ Add to your `claude_desktop_config.json`:
|
|
|
40
69
|
claude mcp add api-testing -- npx -y @cocaxcode/api-testing-mcp
|
|
41
70
|
```
|
|
42
71
|
|
|
43
|
-
###
|
|
72
|
+
### Claude Desktop / Cursor / Any MCP Client
|
|
73
|
+
|
|
74
|
+
Add to your MCP configuration file:
|
|
44
75
|
|
|
45
76
|
```json
|
|
46
77
|
{
|
|
47
78
|
"mcpServers": {
|
|
48
79
|
"api-testing": {
|
|
49
80
|
"command": "npx",
|
|
50
|
-
"args": ["-y", "@cocaxcode/api-testing-mcp"]
|
|
51
|
-
"env": {
|
|
52
|
-
"API_TESTING_DIR": "/path/to/your/.api-testing"
|
|
53
|
-
}
|
|
81
|
+
"args": ["-y", "@cocaxcode/api-testing-mcp"]
|
|
54
82
|
}
|
|
55
83
|
}
|
|
56
84
|
}
|
|
57
85
|
```
|
|
58
86
|
|
|
59
|
-
|
|
87
|
+
### First steps
|
|
88
|
+
|
|
89
|
+
Set up an environment so the tool knows where your API lives:
|
|
60
90
|
|
|
61
|
-
|
|
91
|
+
```
|
|
92
|
+
"Create an environment called dev with BASE_URL http://localhost:3000"
|
|
93
|
+
```
|
|
62
94
|
|
|
63
|
-
|
|
95
|
+
From here, relative paths work automatically. `/api/users` becomes `http://localhost:3000/api/users`.
|
|
64
96
|
|
|
65
|
-
|
|
97
|
+
If your API has Swagger/OpenAPI, import the spec:
|
|
66
98
|
|
|
67
99
|
```
|
|
68
|
-
|
|
69
|
-
|
|
100
|
+
"Import my API spec from http://localhost:3000/api-docs-json"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Now the AI knows every endpoint, parameter, and schema in your API. You're ready to go.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Features
|
|
108
|
+
|
|
109
|
+
### HTTP Requests
|
|
70
110
|
|
|
71
|
-
|
|
72
|
-
request({ method: "GET", url: "{{BASE_URL}}/api/users" })
|
|
111
|
+
Execute any HTTP method with headers, body, query params, and built-in auth. Relative URLs resolve from the active environment. Variables like `{{TOKEN}}` are replaced from environment values.
|
|
73
112
|
|
|
74
|
-
|
|
113
|
+
```
|
|
75
114
|
request({
|
|
76
|
-
method: "
|
|
115
|
+
method: "POST",
|
|
77
116
|
url: "/api/users",
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
timeout: 5000
|
|
117
|
+
body: { name: "Jane", email: "jane@company.com" },
|
|
118
|
+
auth: { type: "bearer", token: "{{TOKEN}}" }
|
|
81
119
|
})
|
|
82
120
|
```
|
|
83
121
|
|
|
84
|
-
**
|
|
122
|
+
**Supports:** GET · POST · PUT · PATCH · DELETE · HEAD · OPTIONS — Headers · Query params · JSON body · Bearer / API Key / Basic auth · Timeout · `{{variable}}` interpolation
|
|
85
123
|
|
|
86
|
-
|
|
87
|
-
// Bearer token
|
|
88
|
-
request({ method: "GET", url: "...", auth: { type: "bearer", token: "abc123" } })
|
|
124
|
+
### Assertions
|
|
89
125
|
|
|
90
|
-
|
|
91
|
-
request({ method: "GET", url: "...", auth: { type: "api-key", key: "mykey", header: "X-API-Key" } })
|
|
126
|
+
Run a request and validate the response against a set of rules in one step. Get structured pass/fail results.
|
|
92
127
|
|
|
93
|
-
|
|
94
|
-
|
|
128
|
+
```
|
|
129
|
+
assert({
|
|
130
|
+
method: "GET",
|
|
131
|
+
url: "/api/health",
|
|
132
|
+
assertions: [
|
|
133
|
+
{ path: "status", operator: "eq", expected: 200 },
|
|
134
|
+
{ path: "body.status", operator: "eq", expected: "ok" },
|
|
135
|
+
{ path: "timing.total_ms", operator: "lt", expected: 500 }
|
|
136
|
+
]
|
|
137
|
+
})
|
|
95
138
|
```
|
|
96
139
|
|
|
97
|
-
|
|
140
|
+
```
|
|
141
|
+
✅ PASS — 3/3 assertions passed
|
|
142
|
+
GET /api/health → 200 OK (42ms)
|
|
98
143
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
"statusText": "OK",
|
|
103
|
-
"headers": { "content-type": "application/json" },
|
|
104
|
-
"body": { "users": [] },
|
|
105
|
-
"timing": { "total_ms": 142.35 },
|
|
106
|
-
"size_bytes": 1024
|
|
107
|
-
}
|
|
144
|
+
✅ status === 200
|
|
145
|
+
✅ body.status === "ok"
|
|
146
|
+
✅ timing.total_ms < 500
|
|
108
147
|
```
|
|
109
148
|
|
|
110
|
-
|
|
149
|
+
**Operators:** `eq` · `neq` · `gt` · `gte` · `lt` · `lte` · `contains` · `not_contains` · `exists` · `type`
|
|
111
150
|
|
|
112
|
-
|
|
151
|
+
### Request Flows
|
|
152
|
+
|
|
153
|
+
Chain multiple requests together. Extract values from one response and inject them into the next step using `{{variables}}`. Perfect for auth flows, CRUD sequences, and multi-step testing.
|
|
113
154
|
|
|
114
155
|
```
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
156
|
+
flow_run({
|
|
157
|
+
steps: [
|
|
158
|
+
{
|
|
159
|
+
name: "login",
|
|
160
|
+
method: "POST",
|
|
161
|
+
url: "/auth/login",
|
|
162
|
+
body: { email: "admin@test.com", password: "123456" },
|
|
163
|
+
extract: { "TOKEN": "body.access_token" }
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "get-users",
|
|
167
|
+
method: "GET",
|
|
168
|
+
url: "/api/users",
|
|
169
|
+
headers: { "Authorization": "Bearer {{TOKEN}}" }
|
|
170
|
+
}
|
|
171
|
+
]
|
|
119
172
|
})
|
|
120
173
|
```
|
|
121
174
|
|
|
122
|
-
###
|
|
175
|
+
### OpenAPI Import
|
|
123
176
|
|
|
124
|
-
|
|
177
|
+
Import your Swagger/OpenAPI spec from a URL or local file. Once imported, the AI understands every endpoint, parameter, and schema — no guessing, no memorizing.
|
|
125
178
|
|
|
126
179
|
```
|
|
127
|
-
|
|
180
|
+
api_import({ name: "my-backend", source: "http://localhost:3000/api-docs-json" })
|
|
181
|
+
api_endpoints({ name: "my-backend", tag: "users" })
|
|
182
|
+
api_endpoint_detail({ name: "my-backend", method: "POST", path: "/users" })
|
|
128
183
|
```
|
|
129
184
|
|
|
130
|
-
###
|
|
185
|
+
### Mock Data Generation
|
|
131
186
|
|
|
132
|
-
|
|
187
|
+
Generate realistic fake data from your OpenAPI spec. Respects types, formats (`email`, `uuid`, `date-time`), enums, and required fields. Use `count` for arrays.
|
|
133
188
|
|
|
134
189
|
```
|
|
135
|
-
|
|
190
|
+
mock({ name: "my-backend", method: "POST", path: "/users", target: "request" })
|
|
136
191
|
```
|
|
137
192
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"email": "user42@example.com",
|
|
196
|
+
"name": "Test User 73",
|
|
197
|
+
"password": "TestPass123!",
|
|
198
|
+
"role": "admin"
|
|
199
|
+
}
|
|
144
200
|
```
|
|
145
201
|
|
|
146
|
-
###
|
|
202
|
+
### Load Testing
|
|
147
203
|
|
|
148
|
-
|
|
204
|
+
Fire N concurrent requests and get performance metrics: min, avg, percentiles (p50/p95/p99), max, and requests per second.
|
|
149
205
|
|
|
150
206
|
```
|
|
151
|
-
|
|
152
|
-
name: "dev",
|
|
153
|
-
variables: { "BASE_URL": "http://localhost:3000", "TOKEN": "dev-token" }
|
|
154
|
-
})
|
|
207
|
+
load_test({ method: "GET", url: "/api/health", concurrent: 50 })
|
|
155
208
|
```
|
|
156
209
|
|
|
157
|
-
|
|
210
|
+
```
|
|
211
|
+
📊 LOAD TEST — GET /api/health
|
|
158
212
|
|
|
159
|
-
|
|
213
|
+
Requests: 50 concurrent
|
|
214
|
+
Successful: 50 | Failed: 0
|
|
215
|
+
Requests/sec: 23.31
|
|
160
216
|
|
|
161
|
-
|
|
217
|
+
⏱️ Response times:
|
|
218
|
+
Min: 45ms | Avg: 187ms
|
|
219
|
+
p50: 156ms | p95: 412ms
|
|
220
|
+
p99: 523ms | Max: 567ms
|
|
221
|
+
```
|
|
162
222
|
|
|
163
|
-
|
|
223
|
+
### Response Diffing
|
|
224
|
+
|
|
225
|
+
Execute two requests and compare their responses field by field. Detect regressions or compare environments (dev vs prod).
|
|
164
226
|
|
|
165
227
|
```
|
|
166
|
-
|
|
228
|
+
diff_responses({
|
|
229
|
+
request_a: { label: "dev", method: "GET", url: "http://dev.api.com/users" },
|
|
230
|
+
request_b: { label: "prod", method: "GET", url: "http://prod.api.com/users" }
|
|
231
|
+
})
|
|
167
232
|
```
|
|
168
233
|
|
|
169
|
-
###
|
|
234
|
+
### Bulk Testing
|
|
170
235
|
|
|
171
|
-
|
|
236
|
+
Run every saved request in your collection (or filter by tag) and get a pass/fail summary.
|
|
172
237
|
|
|
173
238
|
```
|
|
174
|
-
|
|
175
|
-
env_get({}) // returns all variables
|
|
239
|
+
bulk_test({ tag: "smoke" })
|
|
176
240
|
```
|
|
177
241
|
|
|
178
|
-
### `env_switch`
|
|
179
|
-
|
|
180
|
-
Switch the active environment. Active environment variables are used for `{{interpolation}}`.
|
|
181
|
-
|
|
182
242
|
```
|
|
183
|
-
|
|
243
|
+
✅ BULK TEST — 8/8 passed | 1.2s total
|
|
244
|
+
|
|
245
|
+
✅ health — GET /health → 200 (45ms)
|
|
246
|
+
✅ list-users — GET /users → 200 (123ms)
|
|
247
|
+
✅ create-post — POST /blog → 201 (89ms)
|
|
248
|
+
✅ login — POST /auth/login → 200 (156ms)
|
|
184
249
|
```
|
|
185
250
|
|
|
186
|
-
###
|
|
251
|
+
### cURL Export
|
|
187
252
|
|
|
188
|
-
|
|
253
|
+
Convert any saved request into a cURL command with resolved variables.
|
|
189
254
|
|
|
255
|
+
```bash
|
|
256
|
+
curl -X POST \
|
|
257
|
+
'https://api.example.com/users' \
|
|
258
|
+
-H 'Authorization: Bearer eyJhbGci...' \
|
|
259
|
+
-H 'Content-Type: application/json' \
|
|
260
|
+
-d '{"name":"Jane","email":"jane@company.com"}'
|
|
190
261
|
```
|
|
191
|
-
api_import({
|
|
192
|
-
name: "my-backend",
|
|
193
|
-
source: "http://localhost:3001/api-docs-json"
|
|
194
|
-
})
|
|
195
262
|
|
|
196
|
-
|
|
197
|
-
api_import({ name: "my-backend", source: "./openapi.json" })
|
|
198
|
-
```
|
|
263
|
+
### Collections & Environments
|
|
199
264
|
|
|
200
|
-
|
|
265
|
+
Save requests for reuse (with tags), manage variables across environments (dev/staging/prod), and switch contexts instantly.
|
|
201
266
|
|
|
202
|
-
|
|
267
|
+
---
|
|
203
268
|
|
|
204
|
-
|
|
205
|
-
api_endpoints({ name: "my-backend" })
|
|
206
|
-
api_endpoints({ name: "my-backend", tag: "users" })
|
|
207
|
-
api_endpoints({ name: "my-backend", method: "POST" })
|
|
208
|
-
api_endpoints({ name: "my-backend", path: "/blog" })
|
|
209
|
-
```
|
|
269
|
+
## Tool Reference
|
|
210
270
|
|
|
211
|
-
|
|
271
|
+
20 tools organized in 8 categories:
|
|
212
272
|
|
|
213
|
-
|
|
273
|
+
| Category | Tools | Count |
|
|
274
|
+
|----------|-------|-------|
|
|
275
|
+
| **Requests** | `request` | 1 |
|
|
276
|
+
| **Testing** | `assert` | 1 |
|
|
277
|
+
| **Flows** | `flow_run` | 1 |
|
|
278
|
+
| **Collections** | `collection_save` · `collection_list` · `collection_get` · `collection_delete` | 4 |
|
|
279
|
+
| **Environments** | `env_create` · `env_list` · `env_set` · `env_get` · `env_switch` | 5 |
|
|
280
|
+
| **API Specs** | `api_import` · `api_endpoints` · `api_endpoint_detail` | 3 |
|
|
281
|
+
| **Mock** | `mock` | 1 |
|
|
282
|
+
| **Utilities** | `load_test` · `export_curl` · `diff_responses` · `bulk_test` | 4 |
|
|
214
283
|
|
|
215
|
-
|
|
216
|
-
api_endpoint_detail({ name: "my-backend", method: "POST", path: "/blog" })
|
|
217
|
-
```
|
|
284
|
+
---
|
|
218
285
|
|
|
219
286
|
## Storage
|
|
220
287
|
|
|
221
|
-
All data
|
|
288
|
+
All data lives in `.api-testing/` as plain JSON — no database, no cloud sync:
|
|
222
289
|
|
|
223
290
|
```
|
|
224
291
|
.api-testing/
|
|
225
|
-
├── active-env
|
|
226
|
-
├── collections/
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
├── environments/
|
|
230
|
-
│ ├── dev.json
|
|
231
|
-
│ └── prod.json
|
|
232
|
-
└── specs/
|
|
233
|
-
└── my-backend.json # Imported OpenAPI specs
|
|
292
|
+
├── active-env # Active environment name
|
|
293
|
+
├── collections/ # Saved requests
|
|
294
|
+
├── environments/ # Environment variables (dev, prod, ...)
|
|
295
|
+
└── specs/ # Imported OpenAPI specs
|
|
234
296
|
```
|
|
235
297
|
|
|
236
|
-
|
|
298
|
+
Override the default directory:
|
|
237
299
|
|
|
238
|
-
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"env": { "API_TESTING_DIR": "/path/to/shared/.api-testing" }
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Commit these files to git to share across your team.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Contributing
|
|
239
311
|
|
|
240
312
|
```bash
|
|
241
313
|
git clone https://github.com/cocaxcode/api-testing-mcp.git
|
|
242
314
|
cd api-testing-mcp
|
|
243
315
|
npm install
|
|
244
|
-
npm test
|
|
245
|
-
npm run build
|
|
316
|
+
npm test # 70 tests across 10 suites
|
|
317
|
+
npm run build # ESM bundle via tsup
|
|
318
|
+
npm run typecheck # Strict TypeScript
|
|
246
319
|
```
|
|
247
320
|
|
|
248
|
-
|
|
321
|
+
**Test with MCP Inspector:**
|
|
249
322
|
|
|
250
323
|
```bash
|
|
251
324
|
npx @modelcontextprotocol/inspector node dist/index.js
|
|
252
325
|
```
|
|
253
326
|
|
|
327
|
+
**Stack:** TypeScript · MCP SDK 1.27 · Zod · Vitest · tsup
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
254
331
|
## License
|
|
255
332
|
|
|
256
|
-
MIT
|
|
333
|
+
[MIT](./LICENSE) — built by [cocaxcode](https://github.com/cocaxcode)
|