- Client enumerate và read resources
- Inject resource content vào Claude prompt
- UX pattern: @mentions, file pickers
- Caching resources client-side
Client operations
List
Read
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")
# Content parts
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:
Implementation
You: Summarize @docs://report.pdf
Detect @uri → fetch resource → include in context.Implementation
User: @docs://report.pdf what's the main finding?
→ expanded:
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
# In chat loop
user_input = input("You: ")
expanded = await expand_mentions(user_input, client)
messages.append({"role": "user", "content": expanded})UX: @mentions (tiếp)
Claude has full context.
<docs://report.pdf>
Q4 report content...
</docs://report.pdf>
what's the main finding?UX: Resource picker
Menu for user:
Works for CLI. UI uses dropdown, modal, etc.
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 resultResources as context
Inject resources preemptively vào conversation:
Start chat với loaded context.
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 messagesCaching
Resources read-only → cache by URI:
Reduce server calls, speed up repeated access.
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()Combine với prompt caching (Anthropic)
Load resource, cache it with Anthropic prompt cache:
Resource content cached 1 giờ. Multiple queries on same doc → 90% cheaper.
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
}
]
}]Auto-suggest resources
Claude có thể mention resources trong response:
Client detect URIs → show link (clickable to view full).
User: What's in our Q4 plans?
Claude: Based on docs://plan.md, the key steps are...Example: Mini IDE
Resources + tools + prompts = powerful agentic interface.
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 ClaudeAnti-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
🎯 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.