Một bài đăng “Ableton Live MCP” trên Show HN đã đạt 118 điểm và 78 bình luận vào đầu tuần này. Mẫu hình này ngày càng quen thuộc: ai đó viết một máy chủ Model Context Protocol (MCP) cho một công cụ thú vị, cộng đồng Claude Desktop thử ngay, rồi kéo theo hàng loạt câu hỏi “có nên viết MCP server cho X không?”. MCP đã đi từ thử nghiệm của Anthropic thành một lớp tích hợp tác nhân phổ biến trong chưa đầy một năm.
Điểm còn thiếu trong hệ sinh thái này là cách kiểm thử MCP server một cách có hệ thống. Gửi JSON-RPC thủ công qua stdio có thể ổn với ví dụ “hello world”, nhưng sẽ nhanh chóng vỡ khi server có 12 tools, 3 prompts và một upstream API không ổn định. Bài viết này đưa ra quy trình thực hành để kiểm thử MCP server thủ công, sau đó tự động hóa bằng Apidog: có contract, mock server và regression test như với một API production.
Nếu bạn đang làm việc trong bối cảnh agent rộng hơn, hướng dẫn agents.md của chúng tôi cũng phù hợp với quy trình này; các quy ước trong đó giúp contract của MCP server dễ truyền đạt hơn trong nhóm.
TL;DR
-
MCP là Model Context Protocol của Anthropic: JSON-RPC 2.0 qua
stdiohoặc HTTP, phơi bàytools,resourcesvàprompts. - Kiểm thử MCP server nghĩa là xác minh các response như
initialize,tools/list,tools/call,resources/read,prompts/getso với một contract rõ ràng. - Bắt đầu bằng kiểm thử thủ công qua MCP Inspector hoặc JSON-RPC thô.
- Sau đó lưu các request/response chuẩn vào Apidog, thêm assertion JSONPath và chạy trong CI.
- Dùng mock server của Apidog để mô phỏng upstream API, giúp test ổn định và không phụ thuộc mạng ngoài.
- Tải Apidog nếu bạn muốn request collection, mock server và CI runner trong cùng một nơi.
MCP thực sự là gì?
Đặc tả Model Context Protocol định nghĩa một giao thức JSON-RPC 2.0 với bề mặt tương đối nhỏ. Một MCP client như Claude Desktop, Cursor hoặc agent nội bộ sẽ khởi động MCP server, gọi initialize, sau đó tương tác qua các method chuẩn.
Các method bạn nên kiểm thử nhiều nhất:
| Method | Mục đích kiểm thử |
|---|---|
initialize |
Đàm phán version và capabilities |
tools/list |
Trả về danh sách tools và JSON Schema cho arguments |
tools/call |
Gọi một tool cụ thể với arguments |
resources/list |
Liệt kê resource có thể đọc |
resources/read |
Đọc resource theo URI |
prompts/list |
Liệt kê prompt templates |
prompts/get |
Render một prompt với arguments |
MCP có thể chạy qua:
-
stdio: JSON-RPC frame phân tách bằng newline trênstdin/stdout. - HTTP transport: thường là
POST /, có thể dùng SSE cho streaming.
Phần lớn server local dùng stdio; server remote thường dùng HTTP.
Lý do cần kiểm thử nghiêm túc: nếu tools/list sai shape, mọi client sử dụng server của bạn đều hỏng cùng lúc.
Bạn nên kiểm thử những gì?
Một bộ test MCP server nên bao phủ 6 nhóm chính.
1. Tuân thủ giao thức
Kiểm tra initialize:
- Có trả về đúng
protocolVersionkhông? - Có quảng bá đúng
capabilitieskhông? - Có trả về lỗi hợp lệ khi client gửi version không hỗ trợ không?
Ví dụ request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2026-04-01",
"capabilities": {}
}
}
2. Tính đúng đắn của schema
Với tools/list, kiểm tra mỗi tool có:
namedescriptioninputSchema
Mô tả tool không nên rỗng hoặc quá mơ hồ. Description kém làm giảm khả năng chọn tool chính xác của client như Claude.
3. Hành vi của tool
Với mỗi tools/call, kiểm tra:
- Response có
contentđúng format không? - Content block có type hợp lệ như
text,image,resourcekhông? - Lỗi nghiệp vụ có trả về
isError: truekhông?
Ví dụ response thành công:
{
"jsonrpc": "2.0",
"id": 42,
"result": {
"content": [
{
"type": "text",
"text": "Weather in Tokyo: 21°C, cloudy"
}
]
}
}
Ví dụ lỗi cấp tool:
{
"jsonrpc": "2.0",
"id": 43,
"result": {
"isError": true,
"content": [
{
"type": "text",
"text": "Missing required argument: city"
}
]
}
}
Không nên ném JSON-RPC error cho lỗi nghiệp vụ bên trong tool. JSON-RPC error nên dành cho lỗi cấp giao thức.
4. Truy cập resource
Kiểm tra:
- URI từ
resources/listcó đọc được bằngresources/readkhông? - Pagination có hoạt động sau trang đầu tiên không?
- Resource không tồn tại có trả về lỗi phù hợp không?
5. Render prompt
Với prompts/get, kiểm tra:
- Response có mảng
messageshợp lệ không? - Arguments được thay thế đúng vị trí không?
- Prompt thiếu argument có trả về lỗi rõ ràng không?
6. Chế độ lỗi
Mô phỏng các tình huống production:
- Upstream API timeout.
- Thiếu argument bắt buộc.
- Argument sai type.
- Client gửi nhiều
tools/callđồng thời. - Server bị upstream trả về response sai shape.
Kiểm thử thủ công với stdio
Bắt đầu bằng setup nhỏ nhất:
- Một terminal.
- File thực thi MCP server.
- MCP Inspector hoặc JSON-RPC thô.
Nếu bạn chưa có server, hãy tạo một server mẫu theo MCP SDK quickstart chính thức. Ví dụ weather server là đủ để bắt đầu.
Chạy MCP Inspector:
npx @modelcontextprotocol/inspector node your-server.js
Inspector mở một UI local để gửi MCP request và xem response. Dùng nó để xác nhận:
- Server khởi động được.
-
initializetrả về đúng capabilities. -
tools/listtrả về danh sách tool hợp lệ. -
tools/callchạy được với input mẫu.
Sau khi UI ổn, chạy lại một số call bằng stdio thô để lấy request/response chuẩn cho bộ test.
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-04-01","capabilities":{}}}' | node your-server.js
Lưu lại các cặp request/response cho:
initializetools/listtools/callresources/listresources/readprompts/listprompts/get
Đến cuối bước này, bạn nên có 6-12 fixture JSON-RPC mô tả contract cấp wire của server.
Từ thủ công đến tự động với Apidog
Kiểm thử thủ công giúp bắt lỗi rõ ràng. Nhưng khi server có nhiều tools, bạn cần regression test: mỗi lần push code, toàn bộ contract phải được kiểm tra lại.
Mô hình triển khai:
- Lưu request JSON-RPC vào Apidog.
- Thêm assertion cho response.
- Mock upstream API nếu server phụ thuộc dịch vụ ngoài.
- Chạy test suite trong CI.
1. Tạo project Apidog cho MCP server
Trong Apidog:
- Tạo project mới.
- Cấu hình base URL là HTTP endpoint của MCP server.
- Nếu server chỉ hỗ trợ
stdio, chạy thêm một HTTP wrapper mỏng trong môi trường test. - Tạo environment riêng cho local, CI, staging hoặc production.
Với server stdio, bạn có thể dùng MCP Inspector hoặc tự viết wrapper HTTP đơn giản để nhận JSON-RPC qua HTTP rồi forward vào process stdio. Cách tiếp cận tương tự cũng được dùng trong bài kiểm thử API không cần Postman vào năm 2026.
2. Lưu các request chuẩn
Tạo request riêng cho từng method quan trọng.
Ví dụ tools/call:
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "Tokyo"
}
}
}
Nên lưu ít nhất:
- Một request happy path cho mỗi tool.
- Một request thiếu argument bắt buộc.
- Một request argument sai type.
- Một request mô phỏng upstream lỗi.
3. Thêm assertion
Mục tiêu của automation không chỉ là gửi request, mà là xác minh response.
Với tools/list, thêm assertion như:
-
$.result.toolstồn tại. -
$.result.tools.lengthlớn hơn0. - Mỗi item có
name,description,inputSchema. -
inputSchemalà JSON Schema hợp lệ.
Với tools/call thành công:
-
$.result.isErrorlàfalsehoặc không tồn tại. -
$.result.contentlà array. -
$.result.content[0].typetồn tại. - Nội dung trả về khớp expectation ổn định.
Với tools/call lỗi:
-
$.result.isErrorlàtrue. -
$.result.content[0].texttồn tại. - Nếu có error code ổn định, assert trên error code thay vì toàn bộ chuỗi lỗi.
Ví dụ expectation nên tránh:
Missing required argument city in function get_weather at line 42
Ví dụ expectation tốt hơn:
{
"isError": true,
"code": "MISSING_ARGUMENT"
}
Nếu server hiện chưa trả về error code ổn định, ít nhất hãy dùng regex thay vì so khớp toàn bộ message.
4. Mock upstream API
Phần lớn MCP server chỉ là lớp bọc quanh API khác: weather API, GitHub, Linear, database nội bộ hoặc hệ thống quan sát.
Không nên để CI gọi API thật trong mỗi commit vì:
- Dễ bị rate limit.
- Test chậm.
- Response thay đổi theo thời gian.
- Lỗi mạng ngoài làm test flaky.
Dùng mock server của Apidog để định nghĩa upstream endpoint giả.
Ví dụ server của bạn gọi:
GET https://weather.example.com/current?city=Tokyo
Trong test, cấu hình server trỏ đến mock URL:
WEATHER_API_BASE_URL=https://mock.apidog.com/your-project/weather
Mock response:
{
"city": "Tokyo",
"temperature": 21,
"condition": "cloudy"
}
Sau đó tools/call luôn nhận dữ liệu ổn định. Bạn có thể tạo thêm mock cho timeout, 500 error hoặc response sai schema.
Quy trình contract-first tương tự được trình bày trong bài phát triển API theo hợp đồng trước.
5. Chạy test suite trong CI
Khi request và assertion đã sẵn sàng, chạy bộ test bằng CLI trong CI.
Ví dụ GitHub Actions tối thiểu:
name: MCP server tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- name: Start MCP HTTP wrapper
run: node test/wrapper.js &
- name: Run Apidog suite
run: npx apidog run --project-id $APIDOG_PROJECT --env ci
env:
APIDOG_PROJECT: ${{ secrets.APIDOG_PROJECT }}
APIDOG_TOKEN: ${{ secrets.APIDOG_TOKEN }}
Mỗi lần push sẽ chạy lại toàn bộ contract MCP. Nếu tool thứ 7 bị đổi schema argument, CI sẽ báo lỗi trước khi merge.
Phạm vi test nên có
Một MCP server test suite trong Apidog thường bao gồm:
- 1 request
initialize. - 1 request
tools/list. - 2-4 request
tools/callcho mỗi tool:- happy path
- thiếu argument
- argument sai type
- upstream lỗi
- 1 request
resources/list. - 1 request
resources/readcho mỗi nhóm resource. - 1 request
prompts/list. - 1 request
prompts/getcho mỗi prompt template.
Với server có 10 tools, 3 resource groups và 4 prompts, bạn có thể có khoảng 50-70 request test. Nếu upstream được mock, bộ test này thường đủ nhanh để chạy trên mỗi pull request.
Các lỗi thường gặp khi kiểm thử MCP server
Bỏ qua initialize
Một số server chỉ build tool registry trong bước initialize. Nếu gọi tools/list trước, response có thể sai hoặc server crash.
Luôn chạy flow theo thứ tự:
initialize -> tools/list -> tools/call
Assert quá chặt trên error message
Error message thường thay đổi. Nên assert trên:
isError: true- error code ổn định
- regex cho phần message quan trọng
Không nên assert toàn bộ chuỗi lỗi nếu chuỗi đó chứa stack trace, line number hoặc text dễ thay đổi.
Mock lệch khỏi production
Mock trả về shape khác API thật sẽ tạo cảm giác an toàn giả.
Nên:
- Ghi lại fixture từ response thật.
- Cập nhật fixture sau mỗi thay đổi API.
- Có test staging định kỳ với upstream thật nếu phù hợp.
Quên streaming
MCP HTTP server có thể truyền kết quả qua SSE. Nếu server dùng streaming, test runner phải xử lý SSE và assert trên output đã được tập hợp. Apidog hỗ trợ SSE trong saved request; hãy bật streaming ở request tương ứng.
Không kiểm thử concurrency
MCP client có thể gửi nhiều tools/call song song. Nếu server có shared state không được khóa đúng, test tuần tự sẽ pass nhưng production vẫn lỗi.
Thêm ít nhất một test chạy song song cho các tool có state hoặc cache.
Nhầm lỗi protocol với lỗi tool
Lỗi tool nên trả về result với isError: true.
Lỗi protocol mới nên dùng JSON-RPC error.
Nếu trộn hai loại này, client như Claude Desktop có thể đóng kết nối. Đây cũng là dạng lỗi contract từng được đề cập trong bài phát triển nền tảng API theo hợp đồng trước.
Ví dụ kế hoạch test cho một weather MCP server
Giả sử server có 2 tools:
get_weatherget_forecast
Bộ test tối thiểu:
01_initialize
02_tools_list
03_get_weather_success
04_get_weather_missing_city
05_get_weather_invalid_city_type
06_get_weather_upstream_500
07_get_forecast_success
08_get_forecast_missing_days
09_get_forecast_invalid_days_type
10_get_forecast_upstream_timeout
Ví dụ request lỗi argument:
{
"jsonrpc": "2.0",
"id": 44,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {}
}
}
Assertion mong muốn:
$.result.isError == true
$.result.content[0].type == "text"
$.result.content[0].text contains "city"
Ví dụ request upstream lỗi, với mock server trả về HTTP 500:
{
"jsonrpc": "2.0",
"id": 45,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "mock-upstream-error"
}
}
}
Assertion:
$.result.isError == true
$.result.content[0].text contains "upstream"
Các trường hợp sử dụng thực tế
Một nhóm xây dựng MCP server nội bộ cho API quản lý sự cố đã phát hiện ba lỗi hồi quy trong một tuần nhờ assertion trên shape của tools/list trong Apidog. Nếu không có test, lỗi schema đó sẽ được đẩy đến toàn bộ kỹ sư dùng Claude Desktop cùng lúc.
Một maintainer mã nguồn mở xây dựng MCP server cho Notion dùng mock Apidog để chạy CI mà không chạm rate limit của Notion. Bộ test chạy trên mọi PR, mất vài giây và cho phép contributor phát triển mà không cần API key thật.
Một nhóm platform vận hành nhiều MCP server nội bộ đã tạo workspace Apidog dùng chung để lưu contract của từng server. Server mới kế thừa baseline test; reviewer có thể so sánh schema diff trước khi merge.
Một nhóm khác dùng environment switcher của Apidog để chạy cùng test suite trên staging và production. Mỗi environment trỏ đến fixture mock khác nhau, nên cùng một bộ assertion có thể xác minh nhiều deployment mà không cần viết lại request.
Kết luận
MCP đã phổ biến nhanh, nhưng cách kiểm thử MCP server vẫn còn khá thủ công. Cách tiếp cận bền vững là coi MCP server như một API thực sự:
- Xác định contract.
- Kiểm thử thủ công bằng Inspector hoặc JSON-RPC thô.
- Lưu request chuẩn vào Apidog.
- Thêm assertion cho response.
- Mock upstream API.
- Chạy test trong CI.
Năm điểm cần nhớ:
- MCP server là JSON-RPC API; hãy kiểm thử nghiêm túc như REST API.
- Luôn bắt đầu bằng
initialize. -
tools/listlà contract quan trọng nhất cho tool discovery. - Lỗi nghiệp vụ trong tool nên trả về
isError: true, không phải JSON-RPC protocol error. - Apidog có thể gom request, assertion, mock và CI runner vào một workflow.
Bước tiếp theo: mở Apidog, tạo project, dán các JSON-RPC request bạn đã capture, thêm assertion cho tools/list, rồi chạy suite đầu tiên. Trong vòng một giờ, bạn sẽ biết contract MCP server của mình có đủ ổn để phát hành hay chưa.
FAQ
MCP là gì?
MCP, Model Context Protocol, là đặc tả mở của Anthropic cho cách AI client như Claude Desktop gọi tools, resources và prompts bên ngoài. Nó dùng JSON-RPC 2.0 qua stdio hoặc HTTP transport. Đặc tả MCP đầy đủ được công bố trên modelcontextprotocol.io.
Tôi có thể kiểm thử MCP server mà không cần HTTP wrapper không?
Có. MCP Inspector chính thức giao tiếp trực tiếp qua stdio và phù hợp cho kiểm thử thủ công. Với kiểm thử tự động trong Apidog, bạn nên bọc stdio bằng một HTTP wrapper mỏng trong CI. Production vẫn có thể dùng stdio.
Làm sao để mock upstream API mà MCP server gọi?
Định nghĩa mỗi upstream endpoint thành một mock route trong Apidog. Khi test, trỏ cấu hình MCP server đến mock URL. Khi chạy thật, dùng production URL. Mẫu này cũng được trình bày trong bài công cụ kiểm thử API cho kỹ sư QA.
Còn tool result dạng streaming thì sao?
MCP HTTP server có thể stream kết quả qua Server-Sent Events. Apidog hỗ trợ SSE trong saved request; bật streaming ở request đó và assert trên luồng đã được tập hợp.
Có nên kiểm thử protocol version không?
Có. Hãy pin protocolVersion bạn hỗ trợ trong initialize và assert trên giá trị đó. Version mismatch có thể gây lỗi client khó phát hiện.
Có nên kiểm thử với Claude Desktop thật không?
Có, ít nhất một lần trước mỗi release. Nhưng không nên dùng Claude Desktop làm regression test chính vì nó thủ công, chậm và không deterministic. Dùng Apidog cho test tự động, Claude Desktop cho smoke test cuối cùng.
Có thể xem ví dụ MCP server thực ở đâu?
Kho MCP servers chính thức có nhiều triển khai tham chiếu như filesystem, GitHub, Slack, Postgres và các server khác. Đọc phần tool definitions trong các server đó là cách nhanh nhất để hiểu một MCP contract tốt trông như thế nào.
Top comments (0)