Test server với MCP Inspector

Xây dựng serverCơ bản20 phút

Hãy tưởng tượng bạn vừa viết tool edit_document từ Bài 7.4. Làm sao test?

Bạn sẽ học được
  • 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.py

Lệ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 6277

Workflow 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_documents

Bướ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ƯuNhượcKhi dùng
MCP InspectorBrowser UI, immediate feedback, xem schema/output JSONManual, không automatedDev iteration, debug
Unit test (pytest)Automated, CI-friendly, test logic PythonBypass protocol, không test serializationBusiness logic cốt lõi
Integration test (custom client)Test full protocol pathSetup phức tạp, slowRelease 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=false

Mẹ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 7000

Mẹo 3: Two servers side-by-side

Terminal 2:

uv run mcp dev old_server.py --port 6274

Mẹ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 6275

Mẹ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.py

Tó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.

Tài liệu tham khảo
  • MCP Inspector docs
  • MCP Python SDK CLI commands
  • "Debugging MCP servers" — community tips on GitHub discussions
Nội dung này có hữu ích không?