Hãy tưởng tượng bạn vừa viết tool edit_document từ Bài 7.4. Làm sao test?
- Khởi chạy MCP Inspector bằng lệnh mcp dev và connect tới server của bạn
- Điều hướng UI Inspector — Tools tab, Resources tab, Prompts tab
- Test một tool: nhập input, chạy, verify output
- Chạy nhiều tool liên tiếp và verify state persistence giữa các lần gọi
- Dùng Inspector như một công cụ debug chính trong development workflow
Starting Inspector
Chuẩn bị
Lệnh khởi động
(Hoặc chỉ mcp dev mcp_server.py nếu bạn đã activate venv.)
Output tương tự:
- Đã hoàn thành Bài 7.3 (setup uv project)
- Có file mcp_server.py từ Bài 7.4 với ít nhất 1 tool
uv run mcp dev mcp_server.pyLệnh khởi động
Mở browser tới http://127.0.0.1:6274 và bạn thấy UI Inspector.
UI overview
┌─────────────────────────────────────────────────────────┐
│ MCP Inspector [Connect] [⚙] │
├─────────────────────────────────────────────────────────┤
│ │
│ [Resources] [Tools] [Prompts] [Resource Templates] │
│ │
│ ┌─────────────────┬───────────────────────────────┐ │
│ │ │ │ │
│ │ List of tools │ Tool detail + input form │ │
│ │ ───────────── │ │ │
│ │ ► read_doc... │ Name: read_doc_contents │ │
│ │ edit_doc... │ Description: Read the... │ │
│ │ list_docs │ │ │
│ │ │ Input: │ │
│ │ │ doc_id: [ ] │ │
│ │ │ │ │
│ │ │ [Run Tool] │ │
│ │ │ │ │
│ └─────────────────┴───────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Output │ │
│ │ ────────────────────────────────────────────── │ │
│ │ { "isError": false, │ │
│ │ "content": [ │ │
│ │ { "type": "text", │ │
│ │ "text": "This deposition covers..." } │ │
│ │ ] } │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘Starting MCP Inspector on http://127.0.0.1:6274
Connected to server: DocumentMCP
Inspector proxy running on port 6277Workflow cơ bản — 3 bước test một tool
Bước 1: Click "Connect"
Ngay sau khi mở UI, trạng thái là "Disconnected". Click nút Connect ở góc phải trên để khởi tạo session MCP.
Inspector sẽ:
Nếu fail:
Bước 2: Vào tab Tools, list & select
Click tab Tools → click List Tools. Bạn thấy danh sách tool server expose, ví dụ:
Click read_doc_contents. Panel phải hiện chi tiết:
- Gửi InitializeRequest tới server
- Nhận lại capabilities (server hỗ trợ tools/resources/prompts nào)
- Đổi trạng thái thành "Connected"
- Populate các tab với items có sẵn
- Check terminal xem server có start được không
- Check port conflict
- Restart mcp dev
► read_doc_contents
edit_document
list_documentsBước 2: Vào tab Tools, list & select
Đây là schema SDK tự gen từ type hints + Field trong code của bạn. Verify:
Nếu sai → quay lại code sửa decorator/type hints.
Bước 3: Run tool với input
Trong form input, nhập doc_id = "deposition.md". Click Run Tool.
Output xuất hiện:
- Tên tool đúng?
- Description hiện đầy đủ, không bị truncate?
- Required fields đúng?
- Type correct?
Name: read_doc_contents
Description: Read the full text contents of a document...
Input Schema:
doc_id (string) required
Description: Exact document ID, e.g. 'deposition.md'Bước 3: Run tool với input
Verify 3 thứ:
Nếu thấy isError: true → đọc content[0].text để biết lỗi gì. Thường là:
- isError: false — tool chạy thành công
- content có data đúng
- Type là "text" (với tool text output)
- ValueError từ code của bạn (doc_id không tồn tại)
- Type mismatch (SDK không parse được input)
- Exception không handle
{
"isError": false,
"content": [
{
"type": "text",
"text": "This deposition covers the testimony of Angela Smith, P.E."
}
]
}Test edge cases
Đây là nơi Inspector shine — bạn không phải viết test harness để thử edge case.
Edge case 1: Input invalid
Nhập doc_id = "không_tồn_tại.md".
Output:
Verify:
Edge case 2: Input trống
Để trống doc_id, click Run.
Tùy SDK, bạn có thể thấy:
Đây là lý do dùng Field(description=...) — Pydantic validate trước khi vào function.
Edge case 3: Unicode / ký tự đặc biệt
Nhập doc_id = "deposition.md 🎉" (có emoji).
Output sẽ báo không tìm thấy — expected. Inspector cho bạn thử nhanh để verify encoding không gây bug nào.
- Error được return đúng (không crash server)
- Message hữu ích cho model/user
- Gợi ý cách fix (Call list_docs())
- Validation error từ Pydantic: "Field required"
- Hoặc isError: true với message lỗi
{
"isError": true,
"content": [
{ "type": "text",
"text": "Error: Doc with id 'không_tồn_tại.md' not found. Call list_docs() to see available IDs." }
]
}Test tool interactions (chain)
Mạnh hơn test đơn lẻ: chain nhiều tool để verify state management.
Scenario: Edit rồi Read
Bước 1 — Click edit_document, nhập:
Click Run. Kết quả empty content (tool không return gì) nhưng isError: false → thành công.
Bước 2 — Quay lại read_doc_contents, nhập doc_id = "plan.md".
Click Run. Output:
Notice: "implementation" đã thành "execution". State persists giữa các tool call vì cùng 1 session.
Tại sao điều này quan trọng
Trong app thật, Claude sẽ chain nhiều tool call. Ví dụ:
Nếu state không persist, Claude sẽ confused. Inspector test pattern này trước khi tích hợp vào CLI chat.
- doc_id: plan.md
- old_str: implementation
- new_str: execution
- list_documents() → thấy doc
- read_doc_contents(doc_id) → đọc nội dung
- edit_document(doc_id, old, new) → sửa
- read_doc_contents(doc_id) → verify đã sửa
{
"isError": false,
"content": [{ "type": "text",
"text": "The plan outlines the steps for the project's execution." }]
}Bảng so sánh: Ba cách test MCP server
Thực tế: dùng cả 3. Inspector cho 90% dev time, unit test cho core logic, integration test trước release lớn.
| Phương pháp | Ưu | Nhược | Khi dùng |
|---|---|---|---|
| MCP Inspector | Browser UI, immediate feedback, xem schema/output JSON | Manual, không automated | Dev iteration, debug |
| Unit test (pytest) | Automated, CI-friendly, test logic Python | Bypass protocol, không test serialization | Business logic cốt lõi |
| Integration test (custom client) | Test full protocol path | Setup phức tạp, slow | Release qualification |
Ví dụ thực chiến: Inspector-driven development
Tình huống
Bạn vừa viết tool summarize_documents(doc_ids: list[str]) — tóm tắt nhiều docs đồng thời.
Bước 1: Code + Run
Code tool, save. Trong terminal khác đã chạy mcp dev.
Bước 2: Happy path
Trong Inspector, run với:
Output OK? Content format đúng?
Bước 3: Edge case 1 — empty list
Bạn muốn behavior gì? Error hay trả summary rỗng? Thử cả hai cách, pick cái có UX tốt hơn.
Bước 4: Edge case 2 — ID không tồn tại
Tool xử lý thế nào? Skip fake.md và summary real.md? Hay error cả batch?
Decide consciously. Update tool description reflect behavior đã chọn.
Bước 5: Stress test
Quá chậm? Crash? Memory spike? Fix nếu cần, hoặc document limit (max 10 docs per call).
Kết quả
Trong ~10 phút, bạn đã test ~5 edge case. Không viết 1 dòng test code. Đây là tốc độ Inspector cho phép.
- doc_ids = ["deposition.md", "plan.md"]
- doc_ids = []
- doc_ids = ["real.md", "fake.md"]
- doc_ids = ["a.md", "b.md", ..., "z.md"] (26 docs)
Ví dụ theo ngành — Dev workflow với Inspector
🛠️ Internal tooling team
Scenario: Build MCP server wrap internal REST API.
Workflow:
Thế mạnh: Feedback loop 30 giây thay vì deploy → test full stack.
📊 Data team
Scenario: SQL tool cho analyst.
Workflow:
Thế mạnh: Verify safety (write-block, timeout) trước khi give analyst access.
🎨 Creative tools dev
Scenario: Image generation MCP server.
Workflow:
Thế mạnh: Qualitative test loại này khó automate — Inspector cho human verify nhanh.
🔐 Security team
Scenario: Auth MCP server.
Workflow:
Thế mạnh: Check security boundaries một cách thủ công trước khi audit formal.
🏢 Enterprise integration
Scenario: Wrap Jira/Confluence internal.
Workflow:
Thế mạnh: Test tích hợp thật-thật trong vài phút.
- Viết tool đầu tiên, chạy mcp dev
- Paste real-world API response vào Inspector để test parsing
- Iterate description cho đến khi Claude gọi tool đúng (test qua Claude Desktop song song)
- Khi Inspector test pass → commit
- Dev tool run_sql(query)
- Test query đơn giản trong Inspector: SELECT 1
- Test query thực tế phức tạp với JOIN, aggregation
- Test sai syntax (cách handle lỗi SQL?)
- Test query chậm (timeout behavior?)
- Dev tool gen_image(prompt, style)
- Inspector test prompt ngắn, prompt dài, prompt có đặc biệt
- Verify URL return valid, ảnh load được
- Thử style values khác nhau: "photorealistic", "oil painting", "3d render"
- Test tool verify_token(token) với token hợp lệ
- Test với token hết hạn
- Test với token malformed
- Test với token signature sai
- Verify không leak thông tin nhạy cảm trong error message
- Connect MCP server tới Jira dev instance
- Test tool search_issues(jql) với JQL thật
- Verify rate limit xử lý đúng (expect isError: true với message rõ)
- Test pagination (large result set)
Anti-patterns — Những sai lầm cần tránh
❌ Skip Inspector, test thẳng trong Claude Desktop
Sai lầm: Paste MCP server vào Claude Desktop config, restart Claude, prompt thử.
Tại sao là sai: Feedback loop dài (restart Claude Desktop), khó isolate lỗi (Claude có thể sửa lỗi tool qua prompt, che mất bug thật).
Cách đúng: Inspector trước cho qualification cơ bản. Claude Desktop sau cho end-to-end UX test.
❌ Chỉ test happy path
Sai lầm: Run tool 1 lần với input đẹp, thấy output OK → "done".
Tại sao là sai: Claude sẽ gọi tool với đủ kiểu input trong production. Bug edge case = bug production.
Cách đúng: Ít nhất 3 test case: happy, edge (empty/large/special), error (invalid input).
❌ Ignore isError: false nhưng content trống
Sai lầm:
Inspector show empty output nhưng isError: false. Bạn thấy "no error" và pass.
Tại sao là sai: Claude nhận empty response, không biết nên làm gì tiếp.
Cách đúng: Luôn return gì đó meaningful hoặc raise exception rõ ràng.
❌ Không test với data realistic
Sai lầm: Test với doc_id = "a.md", content 5 ký tự. Production data có docs 100KB.
Tại sao là sai: Performance issue, memory issue, truncation issue không lộ.
Cách đúng: Tạo fixture data realistic size (500-5000 từ mỗi doc).
❌ Không verify schema gen
Sai lầm: Bỏ qua việc xem JSON schema trong Inspector. Chỉ click Run thử input.
Tại sao là sai: Schema sai → Claude không biết truyền gì → tool không được gọi đúng cách.
Cách đúng: Mỗi tool mới, verify schema trong Inspector có đúng required fields, types, descriptions.
❌ Dùng Inspector prod
Sai lầm: Deploy MCP Inspector lên production server public.
Tại sao là sai: Inspector là dev tool, không có auth mạnh. Expose = cho phép bất kỳ ai chạy tool.
Cách đúng: Inspector chỉ local dev. Production dùng real MCP client có auth.
@mcp.tool(...)
def do_thing():
if some_condition:
return # empty return → content rỗng, isError=falseMẹo nâng cao
Mẹo 1: Inspector với log debug
Khi tool fail mysteriously:
Output terminal sẽ in mọi JSON-RPC message. Đối chiếu với Inspector để thấy exact request/response.
Mẹo 2: mcp dev --port
Default port 6274. Đổi nếu conflict:
mcp = FastMCP("DocumentMCP", log_level="DEBUG")Mẹo 2: mcp dev --port
Mẹo 3: Two servers side-by-side
Test 2 version server cùng lúc:
Terminal 1:
uv run mcp dev mcp_server.py --port 7000Mẹo 3: Two servers side-by-side
Terminal 2:
uv run mcp dev old_server.py --port 6274Mẹo nâng cao (tiếp)
Mở 2 tab browser để so sánh output same input.
Mẹo 4: Inspector output → test fixture
Copy JSON output từ Inspector → save vào file test:
uv run mcp dev new_server.py --port 6275Mẹo 4: Inspector output → test fixture
Dùng fixture này trong unit test để verify wire format không thay đổi.
# tests/fixtures/read_doc_result.json
{
"isError": false,
"content": [...]
}Áp dụng ngay
Bài tập 1: Chạy Inspector (~10 phút)
Bước 1: Mở terminal trong project MCP.
Bước 2: Chạy:
Bước 3: Mở browser tới URL in ra trong terminal.
Bước 4: Click Connect. Verify status đổi thành "Connected".
Bước 5: Click tab Tools → List Tools. Ghi lại:
Bài tập 2: Run 3 test case (~10 phút)
Với tool read_doc_contents:
Test 1: Happy path
Test 2: Error path
Test 3: Special char
Bài tập 3 (thử thách): Chain tools (~10 phút)
Chạy sequence:
Ghi lại:
- Số lượng tool hiện ra: ___________
- Tool name: ___________
- Schema có description đầy đủ không? ___________
- Input: doc_id = "deposition.md"
- Output: _______________
- isError: _______________
- Input: doc_id = "nonexistent.md"
- Output: _______________
- isError: _______________
- Error message có informative không? _______________
- Input: doc_id = "deposition.md " (trailing space)
- Output: _______________
- Tool handle thế nào? _______________
- Run read_doc_contents với doc_id = "plan.md". Note content.
- Run edit_document với:
- doc_id = "plan.md"
- old_str = "outline" (hoặc từ nào có trong content)
- new_str = "sketch"
- Run read_doc_contents lại với "plan.md". Verify đã đổi.
- State có persist giữa 3 calls không? ___________
- Edit tool return gì? ___________
- Nếu bạn đóng Inspector và mở lại, state còn không? ___________ (hint: no, vì server restart)
uv run mcp dev mcp_server.pyTóm tắt bài học
🎯 Inspector = Postman cho MCP — Browser-based testing tool built-in với SDK, cho phép test tool không cần viết client thật.
🎯 3 bước cơ bản — Connect → List & Select tool → Run với input → Check output JSON.
🎯 Test edge case là bắt buộc — Happy path chỉ cover 30% bug. Invalid input, empty, special chars, large data mới lộ vấn đề.
🎯 Verify schema gen — Đọc JSON schema Inspector show để catch bug decorator/type hint ngay, trước khi lỗi lan sang client.
🎯 Chain để test state — Run nhiều tool liên tiếp để verify behavior như Claude sẽ làm trong real session.
- MCP Inspector docs
- MCP Python SDK CLI commands
- "Debugging MCP servers" — community tips on GitHub discussions