Lộ trình học›Claude API›Building with the Claude API Mở bản đồ

6.67 · Truy cập resources từ client

Bài viếtTrung cấp15 phút đọc
Sau bài này, bạn sẽ
  1. Client enumerate và read resources
  2. Inject resource content vào Claude prompt
  3. UX pattern: @mentions, file pickers
  4. Caching resources client-side

Client operations

List

resources = await client.list_resources()
for r in resources:
    print(f"URI: {r.uri}")
    print(f"Name: {r.name}")
    print(f"Description: {r.description}")

Read

result = await client.read_resource("docs://report.pdf")

for content in result.contents:
    if content.type == "text":
        print(content.text)
    elif content.type == "blob":
        print(f"Binary data: {len(content.blob)} bytes")

UX: @mentions

User references resource trong chat:

You: Summarize @docs://report.pdf

Detect @uri → fetch resource → include in context.

Implementation

import re

URI_PATTERN = re.compile(r"@(\w+://[^\s]+)")


async def expand_mentions(user_input: str, client) -> str:
    """Replace @mentions with resource content."""
    uris = URI_PATTERN.findall(user_input)
    
    for uri in uris:
        try:
            result = await client.read_resource(uri)
            content = "\n".join(c.text for c in result.contents if c.type == "text")
            user_input = user_input.replace(f"@{uri}", f"\n<{uri}>\n{content}\n</{uri}>\n")
        except Exception as e:
            print(f"Error reading {uri}: {e}")
    
    return user_input


user_input = input("You: ")
expanded = await expand_mentions(user_input, client)
messages.append({"role": "user", "content": expanded})

User: @docs://report.pdf what's the main finding?

→ expanded:

<docs://report.pdf>
Q4 report content...
</docs://report.pdf>

what's the main finding?

Claude has full context.

UX: Resource picker

Menu for user:

async def select_resource(client):
    resources = await client.list_resources()
    print("Select resource:")
    for i, r in enumerate(resources):
        print(f"  {i+1}. {r.name} ({r.uri})")
    
    choice = int(input("Number: ")) - 1
    selected = resources[choice]
    
    result = await client.read_resource(selected.uri)
    return result

Works for CLI. UI uses dropdown, modal, etc.

Resources as context

Inject resources preemptively vào conversation:

async def init_conversation_with_context(client, resource_uris):
    messages = []
    
    for uri in resource_uris:
        result = await client.read_resource(uri)
        content = format_content(result)
        messages.append({
            "role": "user",
            "content": f"Reference data:\n<{uri}>\n{content}\n</{uri}>"
        })
        messages.append({
            "role": "assistant",
            "content": f"Understood. I have access to {uri}."
        })
    
    return messages

Start chat với loaded context.

Caching

Resources read-only → cache by URI:

class CachedMCPClient:
    def __init__(self, base_client):
        self.client = base_client
        self._cache: dict[str, Any] = {}
        self._cache_ttl = 300  # 5 min
        self._cache_timestamps = {}
    
    async def read_resource(self, uri: str):
        now = time.time()
        
        if uri in self._cache:
            if now - self._cache_timestamps[uri] < self._cache_ttl:
                return self._cache[uri]
        
        result = await self.client.read_resource(uri)
        self._cache[uri] = result
        self._cache_timestamps[uri] = now
        return result
    
    def invalidate(self, uri: str = None):
        if uri:
            self._cache.pop(uri, None)
        else:
            self._cache.clear()

Reduce server calls, speed up repeated access.

Combine với prompt caching (Anthropic)

Load resource, cache it with Anthropic prompt cache:

result = await client.read_resource("docs://report.pdf")
content = format_content(result)

messages = [{
    "role": "user",
    "content": [
        {
            "type": "text",
            "text": f"Document: {content}",
            "cache_control": {"type": "ephemeral"}  # ← Anthropic cache
        },
        {
            "type": "text",
            "text": user_question  # dynamic part
        }
    ]
}]

Resource content cached 1 giờ. Multiple queries on same doc → 90% cheaper.

Auto-suggest resources

Claude có thể mention resources trong response:

User: What's in our Q4 plans?
Claude: Based on docs://plan.md, the key steps are...

Client detect URIs → show link (clickable to view full).

Example: Mini IDE

async def run_ide(client):
    print("Welcome to mini-IDE. Commands:")
    print("  ls              - list resources")
    print("  cat <uri>       - read resource")
    print("  chat <message>  - chat with Claude")
    
    while True:
        cmd = input("\n> ").strip()
        
        if cmd == "ls":
            resources = await client.list_resources()
            for r in resources:
                print(f"  {r.uri}  — {r.name}")
        
        elif cmd.startswith("cat "):
            uri = cmd[4:]
            result = await client.read_resource(uri)
            print(format_content(result))
        
        elif cmd.startswith("chat "):
            user_input = await expand_mentions(cmd[5:], client)
            # ... send to Claude

Resources + tools + prompts = powerful agentic interface.

Anti-patterns

Read resource every turn

Each query re-reads → slow + server load.

Fix: Cache client-side + Anthropic prompt cache.

Inject all resources

Load everything at start → expensive, context overflow.

Fix: Lazy load on demand via @mentions.

No error handling

Resource deleted → crash.

Fix: try-except, show graceful "unavailable".

Áp dụng ngay

Bài tập 1: @mention expander (25 phút)

Implement expand_mentions. Test: Summarize @docs://report.pdf.

Bài tập 2: Resource picker UI (20 phút)

CLI picker: list resources numbered, user select by number, read + show.

Tóm tắt bài học

Những điều cốt lõi
  • Client list_resources + read_resource basic ops.
  • @mention UX — user reference @uri → auto-expand.
  • Cache resources client-side + Anthropic prompt cache.
  • Resources as preloaded context cho conversations.
  • Read-only contract — no side effects on read.
Bạn đã hoàn thành bài này chưa?Tiến độ lưu trên trình duyệt của bạn.