Skip to content

Commit 86850ae

Browse files
committed
feat: add 3 new samples — MCP workflow, CI testing, microservices
All validated against mockd v0.6.0: ai-agents/mcp-workflow: Todo API via MCP tool calls or equivalent config file. 5 CRUD endpoints, 2 seed items. README shows full MCP conversation flow. ci-testing/github-actions: Payment Service with orders + payments tables. GitHub Actions workflow using setup-mockd@v1, contract verification. microservices/docker-compose: Mock User Service + Payment Service for local dev. Docker Compose with health check, 10 CRUD endpoints across 2 services.
1 parent e30f667 commit 86850ae

11 files changed

Lines changed: 1573 additions & 0 deletions

File tree

ai-agents/mcp-workflow/README.md

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
# MCP Workflow: AI Agents Create Mocks via Tool Calls
2+
3+
No CLI commands. No config files. Just ask your AI agent to create a REST API, and mockd builds it through MCP tool calls.
4+
5+
This sample shows the MCP-first workflow: an AI agent creates a stateful todo API entirely through `manage_state` and `manage_mock` tool calls. The equivalent config file is included for reference.
6+
7+
## Setup
8+
9+
### 1. Install mockd
10+
11+
```bash
12+
curl -fsSL https://get.mockd.io | sh
13+
```
14+
15+
### 2. Start the MCP server
16+
17+
mockd's MCP server runs as a stdio transport — your AI editor launches it automatically. You just need to configure it.
18+
19+
### 3. Configure your editor
20+
21+
**Claude Desktop** (`~/.config/claude/claude_desktop_config.json`):
22+
23+
```json
24+
{
25+
"mcpServers": {
26+
"mockd": {
27+
"command": "mockd",
28+
"args": ["mcp"]
29+
}
30+
}
31+
}
32+
```
33+
34+
**Cursor** (`.cursor/mcp.json` in your project root):
35+
36+
```json
37+
{
38+
"mcpServers": {
39+
"mockd": {
40+
"command": "mockd",
41+
"args": ["mcp"]
42+
}
43+
}
44+
}
45+
```
46+
47+
**OpenCode** (`opencode.json` in your project root):
48+
49+
```json
50+
{
51+
"mcpServers": {
52+
"mockd": {
53+
"command": "mockd",
54+
"args": ["mcp"]
55+
}
56+
}
57+
}
58+
```
59+
60+
After configuring, restart your editor. The mockd tools will appear in the agent's tool list.
61+
62+
### 4. Start mockd
63+
64+
The MCP server connects to a running mockd instance. Start one before chatting:
65+
66+
```bash
67+
mockd start --no-auth
68+
```
69+
70+
## Example Conversation
71+
72+
You say:
73+
74+
> Create a REST API for a todo app. I need full CRUD — list, create, get, update, delete. Seed it with a couple of sample todos.
75+
76+
The agent makes these tool calls:
77+
78+
### Step 1: Create the stateful resource
79+
80+
The agent calls `manage_state` to create a `todos` table with seed data:
81+
82+
```json
83+
{
84+
"tool": "manage_state",
85+
"arguments": {
86+
"action": "add_resource",
87+
"resource": "todos",
88+
"seed_data": [
89+
{ "id": "1", "title": "Buy groceries", "completed": false },
90+
{ "id": "2", "title": "Write tests", "completed": true }
91+
]
92+
}
93+
}
94+
```
95+
96+
> Created resource "todos" with 2 seed items.
97+
98+
### Step 2: Create the list endpoint
99+
100+
```json
101+
{
102+
"tool": "manage_mock",
103+
"arguments": {
104+
"action": "create",
105+
"type": "http",
106+
"http": {
107+
"matcher": { "method": "GET", "path": "/api/todos" }
108+
},
109+
"extend": { "table": "todos", "action": "list" }
110+
}
111+
}
112+
```
113+
114+
> Created mock `http_...` — GET /api/todos (list from todos table)
115+
116+
### Step 3: Create the create endpoint
117+
118+
```json
119+
{
120+
"tool": "manage_mock",
121+
"arguments": {
122+
"action": "create",
123+
"type": "http",
124+
"http": {
125+
"matcher": { "method": "POST", "path": "/api/todos" }
126+
},
127+
"extend": { "table": "todos", "action": "create" }
128+
}
129+
}
130+
```
131+
132+
> Created mock `http_...` — POST /api/todos (create in todos table)
133+
134+
### Step 4: Create the get endpoint
135+
136+
```json
137+
{
138+
"tool": "manage_mock",
139+
"arguments": {
140+
"action": "create",
141+
"type": "http",
142+
"http": {
143+
"matcher": { "method": "GET", "path": "/api/todos/{id}" }
144+
},
145+
"extend": { "table": "todos", "action": "get" }
146+
}
147+
}
148+
```
149+
150+
> Created mock `http_...` — GET /api/todos/{id} (get from todos table)
151+
152+
### Step 5: Create the update endpoint
153+
154+
```json
155+
{
156+
"tool": "manage_mock",
157+
"arguments": {
158+
"action": "create",
159+
"type": "http",
160+
"http": {
161+
"matcher": { "method": "PUT", "path": "/api/todos/{id}" }
162+
},
163+
"extend": { "table": "todos", "action": "update" }
164+
}
165+
}
166+
```
167+
168+
> Created mock `http_...` — PUT /api/todos/{id} (update in todos table)
169+
170+
### Step 6: Create the delete endpoint
171+
172+
```json
173+
{
174+
"tool": "manage_mock",
175+
"arguments": {
176+
"action": "create",
177+
"type": "http",
178+
"http": {
179+
"matcher": { "method": "DELETE", "path": "/api/todos/{id}" }
180+
},
181+
"extend": { "table": "todos", "action": "delete" }
182+
}
183+
}
184+
```
185+
186+
> Created mock `http_...` — DELETE /api/todos/{id} (delete from todos table)
187+
188+
### Step 7: Verify it works
189+
190+
The agent can verify the setup by calling `get_server_status`:
191+
192+
```json
193+
{
194+
"tool": "get_server_status",
195+
"arguments": {}
196+
}
197+
```
198+
199+
> Server healthy on :4280 (mock) / :4290 (admin). 5 mocks registered. 1 stateful resource (todos: 2 items).
200+
201+
## Try It
202+
203+
Once the agent finishes, the API is live:
204+
205+
```bash
206+
# List todos (2 from seed data)
207+
curl -s http://localhost:4280/api/todos | jq .
208+
209+
# Create a new todo
210+
curl -s -X POST http://localhost:4280/api/todos \
211+
-H "Content-Type: application/json" \
212+
-d '{"title":"Deploy to production","completed":false}' | jq .
213+
214+
# Get it by ID (use the ID from the create response)
215+
curl -s http://localhost:4280/api/todos/3 | jq .
216+
217+
# Update it — mark as completed
218+
curl -s -X PUT http://localhost:4280/api/todos/3 \
219+
-H "Content-Type: application/json" \
220+
-d '{"title":"Deploy to production","completed":true}' | jq .
221+
222+
# Delete it
223+
curl -s -X DELETE http://localhost:4280/api/todos/3
224+
225+
# List again — back to the 2 seed todos
226+
curl -s http://localhost:4280/api/todos | jq .
227+
```
228+
229+
## What Else Can the Agent Do?
230+
231+
The MCP workflow isn't limited to CRUD. The agent has 18 tools:
232+
233+
| Tool | What it does |
234+
|------|--------------|
235+
| `manage_mock` | Create, update, delete, list, toggle mocks |
236+
| `manage_state` | Add resources, seed data, browse items, reset state |
237+
| `manage_custom_operation` | Register domain logic (e.g., "mark todo as archived") |
238+
| `import_mocks` | Import from OpenAPI, Postman, HAR, WireMock, cURL |
239+
| `export_mocks` | Export current mocks as YAML/JSON |
240+
| `get_server_status` | Health check, ports, statistics |
241+
| `get_request_logs` | See all traffic hitting the mock server |
242+
| `verify_mock` | Assert a mock was called N times |
243+
| `set_chaos_config` | Inject latency, errors, apply chaos profiles |
244+
| `manage_workspace` | Isolate mock configs in separate workspaces |
245+
246+
Example follow-ups you might ask:
247+
248+
- "Add pagination to the list endpoint"
249+
- "Import my OpenAPI spec and wire up stateful tables"
250+
- "Show me what requests hit the server in the last minute"
251+
- "Inject 500ms latency on all POST requests"
252+
- "Verify that GET /api/todos was called at least 3 times"
253+
254+
## Config File Equivalent
255+
256+
The `mockd.yaml` in this directory creates the exact same API via config file instead of MCP:
257+
258+
```bash
259+
mockd start -c mockd.yaml --no-auth
260+
```
261+
262+
Both approaches produce identical behavior — the MCP workflow is just more interactive.
263+
264+
## Running the Test
265+
266+
```bash
267+
./test.sh
268+
```
269+
270+
The test script starts mockd with the config file and exercises all CRUD operations.
271+
272+
## Files
273+
274+
```
275+
mcp-workflow/
276+
├── README.md <- You're here
277+
├── mockd.yaml <- Config file equivalent of the MCP workflow
278+
└── test.sh <- CRUD regression tests
279+
```
280+
281+
## Links
282+
283+
- [mockd](https://github.com/getmockd/mockd) — The mock server
284+
- [docs.mockd.io](https://docs.mockd.io) — Documentation
285+
- [Install mockd](https://get.mockd.io)

ai-agents/mcp-workflow/mockd.yaml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Todo API — Config File Equivalent of the MCP Workflow
2+
# Usage: mockd start -c mockd.yaml --no-auth
3+
#
4+
# This config creates the exact same API that the MCP workflow builds
5+
# interactively through tool calls. Use whichever approach fits your workflow:
6+
#
7+
# MCP workflow: Ask your AI agent "create a todo API" → agent calls tools
8+
# Config file: mockd start -c mockd.yaml
9+
#
10+
# Both produce the same 5 endpoints backed by a stateful "todos" table.
11+
12+
version: "1.0"
13+
14+
# ============================================================================
15+
# Tables — stateful data stores
16+
# ============================================================================
17+
tables:
18+
- name: todos
19+
idField: id
20+
seedData:
21+
- { id: "1", title: "Buy groceries", completed: false }
22+
- { id: "2", title: "Write tests", completed: true }
23+
24+
# ============================================================================
25+
# Mocks — HTTP endpoints bound to the todos table
26+
# ============================================================================
27+
mocks:
28+
- type: http
29+
http:
30+
matcher:
31+
method: GET
32+
path: /api/todos
33+
statefulBinding:
34+
table: todos
35+
action: list
36+
37+
- type: http
38+
http:
39+
matcher:
40+
method: POST
41+
path: /api/todos
42+
statefulBinding:
43+
table: todos
44+
action: create
45+
46+
- type: http
47+
http:
48+
matcher:
49+
method: GET
50+
path: "/api/todos/{id}"
51+
statefulBinding:
52+
table: todos
53+
action: get
54+
55+
- type: http
56+
http:
57+
matcher:
58+
method: PUT
59+
path: "/api/todos/{id}"
60+
statefulBinding:
61+
table: todos
62+
action: update
63+
64+
- type: http
65+
http:
66+
matcher:
67+
method: DELETE
68+
path: "/api/todos/{id}"
69+
statefulBinding:
70+
table: todos
71+
action: delete

0 commit comments

Comments
 (0)