C.W.K.
Stream
Lesson 03 of 05 · published

Tools — Callable, Side-effectful

~22 min · tools, side-effects, schema, annotations

Level 0호기심 많은 독자
0 XP0/48 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

MCP 의 Tool 은 어떤 provider tool-calling API 의 tool 과 동일해 보임: name, description, input schema. Resource 와 핵심 차이는 tool 이 일을 함 — 세상에 side effect 있을 수 있어. Protocol 이 이걸 — 각 tool description 의 optional annotation (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) — 으로 인정하고, host 가 user 에게 승인 요청할 때 surface 가능.

Flow: client tool list → host 가 LLM tool list 에 통합 → LLM 이 tool call emit → host 가 server tools/call → server 실행하고 구조화된 result 반환 → host 가 LLM 에 result 다시 → LLM 이 더 부르거나 끝냄. Server 는 인자 검증, retry 시 idempotency, 구조화된 error 반환 책임; host 는 user 한테 destructive 의도 surface 책임.

한 가지 미묘함: tool 결과는 단순 문자열이 아니라 구조화된 content. Result 는 text, image, audio, resource 참조일 수 있는 content item list. Tool 이 chart image + text summary 동시 반환하거나 host 가 read 할 resource URI list 반환 가능. Tool result 를 monomorphic string 으로 다루면 capability 버리는 거.

Code

Annotation 과 구조화된 result 가진 tool·python
from mcp.server.fastmcp import FastMCP
from mcp.types import TextContent, ImageContent

app = FastMCP("orders-server")

@app.tool(
    annotations={
        "readOnlyHint": False,
        "destructiveHint": False,
        "idempotentHint": True,
    }
)
async def refund_order(order_id: str, amount_cents: int, reason: str) -> list:
    """Issue a refund. Idempotent on (order_id, amount_cents)."""
    receipt = await stripe.refund(order_id, amount_cents, idempotency_key=f"{order_id}:{amount_cents}")
    return [
        TextContent(type="text", text=f"Refunded ${amount_cents/100:.2f}"),
        TextContent(type="text", text=f"Receipt id: {receipt.id}"),
    ]
tools/list 와 tools/call wire 위에서·json
// Client -> Server
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}

// Server -> Client
{"jsonrpc":"2.0","id":2,"result":{"tools":[
  {"name":"refund_order","description":"Issue a refund. Idempotent on (order_id, amount_cents).",
   "inputSchema":{"type":"object","properties":{...},"required":["order_id","amount_cents","reason"]},
   "annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}}
]}}

// Client -> Server
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"refund_order","arguments":{...}}}

External links

Exercise

작은 server 에 write tool 추가. destructiveHint=true 와 openWorldHint=true 마크. Claude Desktop 또는 MCP-aware client 로 연결해서 — 모델이 처음 호출 시도할 때 host 가 경고 surface 하는 거 봐. Read-only tool 보다 prompt 가 더 무서워 보이면 annotation 동작 중.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.