Định nghĩa resources qua MCP

8 — MCPTrung cấp15 phút

3 concepts MCP: - Tools — actions (create, update, delete) - Prompts — instructions (templates) - Resources — data (read-only)

Bạn sẽ học được
  • Hiểu MCP resources — read-only data exposed by server
  • Static vs dynamic resources
  • Use @mcp.resource decorator
  • URI patterns cho resources

When resources vs tools?

Resource = GET. Tool = POST/PUT/DELETE (loose analogy).

ResourceTool
PurposeExpose dataPerform action
Side effectNone (read)May have
URIYes (unique identifier)No
Examplefile://report.pdf, db://users/123get_user(123), create_post()

Static resource

Fixed URI, content:

Clients can read resource docs://report.pdf.

@mcp.resource("docs://report.pdf")
def get_report():
    return """This report describes Q3 performance..."""

Dynamic resource (URI template)

URI with parameters:

Client reads docs://report.pdf or docs://plan.md — same function.

@mcp.resource("docs://{doc_id}")
def get_doc(doc_id: str):
    if doc_id not in docs:
        raise ValueError(f"Doc {doc_id} not found")
    return docs[doc_id]

Full example — documents

Test via Inspector → Resources tab.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("DocumentMCP")

docs = {
    "report.pdf": "Q4 report content...",
    "plan.md": "Project plan content...",
}


# List all docs (static resource listing)
@mcp.resource("docs://all")
def list_all_docs() -> str:
    return "\n".join(docs.keys())


# Individual doc (dynamic)
@mcp.resource("docs://{doc_id}")
def read_doc(doc_id: str) -> str:
    if doc_id not in docs:
        raise ValueError(f"Doc '{doc_id}' not found")
    return docs[doc_id]

Client read resource

resources = await client.list_resources()
# [{"uri": "docs://all", "name": "All docs"}, ...]

# Read specific
result = await client.read_resource("docs://report.pdf")
# ReadResourceResult with contents
for content in result.contents:
    if content.type == "text":
        print(content.text)

Why resources matter

1. Auto-discovery

Client list all resources without prior knowledge. User browse data without remembering tool names.

2. Caching-friendly

Read-only + URI-identified → client can cache by URI.

3. Standard contract

Any client can read any resource từ any MCP server. Universal data access pattern.

4. Claude awareness

Claude thấy resources available, có thể reference: "Based on docs://report.pdf, the answer is..."

Resource types

Text

JSON

@mcp.resource("schema://users")
def get_schema() -> str:
    return """CREATE TABLE users (
        id INT PRIMARY KEY,
        name VARCHAR(100)
    )"""

JSON

Binary (via URI)

import json

@mcp.resource("config://app")
def get_config() -> str:
    return json.dumps({"version": "1.0", "debug": False})

Binary (via URI)

MCP supports binary resources qua specific content type.

@mcp.resource("image://logo")
def get_logo():
    with open("logo.png", "rb") as f:
        return f.read()  # binary content

Resources + tools combo

Resources cho browsing, tools cho mutation:

Clean separation.

# Resource: read-only
@mcp.resource("docs://{doc_id}")
def get_doc(doc_id):
    return docs[doc_id]

# Tool: modify
@mcp.tool()
def edit_doc(doc_id: str, old: str, new: str):
    docs[doc_id] = docs[doc_id].replace(old, new)

URI conventions

Good:

Bad:

Use scheme that makes sense cho domain.

  • docs://report.pdf — clear scheme + identifier
  • users://alice — namespace
  • file:///home/jimmy/note.md — RFC 3986 format
  • doc1 — no scheme
  • somedata — no structure

Anti-patterns

❌ Resource with side effects

Resources MUST be read-only. Client caches, call multiple times → inconsistent.

Fix: Tool if action needed.

❌ Expose entire database as resource

Too much data, tied to impl details.

Fix: Curated views. docs://all, docs://{id}, specific.

❌ Mix text + binary without content type

Client parse fail.

Fix: Explicit MIME types.

@mcp.resource("counter://next")
def counter():
    global count
    count += 1
    return str(count)  # MUTATING on read!

Áp dụng ngay

Bài tập 1: Add resources (20 phút)

Add to server:

Test via Inspector.

Bài tập 2: Client list + read (15 phút)

Client enumerate resources, read one, print content.

  • docs://list — list all doc IDs
  • docs://{id} — specific doc
  • docs://stats — count + total size

Tóm tắt

🎯 Resources = read-only data với URI.

🎯 Static: fixed URI. Dynamic: URI template with params.

🎯 @mcp.resource("scheme://path") decorator.

🎯 Complement tools: resources for browse, tools for mutate.

🎯 Never mutate on resource read — contract.

Nội dung này có hữu ích không?