Tool = action. Prompt = crafted instruction bạn (server author) carefully designed + tested.
- Hiểu MCP prompts — pre-built templates
- Use @mcp.prompt decorator
- Return list of messages to client
- Khi nào prompts valuable
Why MCP prompts?
Raised consistency, lowered user effort.
User typing their own prompt:
"convert report.pdf to markdown"
→ Variable quality, missing best practices
Using server's prompt:
/format doc_id=report.pdf
→ Curated instructions:
- Specific formatting rules
- Output structure
- Edge case handling
- Tested by server authorImplement prompt
# mcp_server.py
from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.prompts import base
from pydantic import Field
mcp = FastMCP("DocumentMCP")
@mcp.prompt(
name="format",
description="Reformat a document to clean markdown syntax with headers, lists, tables."
)
def format_document(
doc_id: str = Field(description="ID of document to format")
) -> list[base.Message]:
prompt_text = f"""Your goal is to reformat a document to use clean markdown syntax.
The document ID is: {doc_id}
Steps:
1. Use `read_doc_contents` tool to fetch content
2. Identify sections, lists, tables, code blocks
3. Apply markdown formatting:
- Headers (H1/H2/H3) for sections
- Bullet lists for enumerations
- Tables for tabular data
- Code blocks with language hints
4. Use `edit_document` to save reformatted content
5. Verify changes with another `read_doc_contents`
Output format:
- Clean, well-structured markdown
- Preserve all original content
- Add formatting only where it enhances readability"""
return [base.UserMessage(prompt_text)]Prompt returns messages
List of messages client can inject into conversation:
For few-shot:
- base.UserMessage(text) — user-role message
- base.AssistantMessage(text) — assistant-role message
return [
base.UserMessage("Example input: raw text"),
base.AssistantMessage("Example output: formatted markdown"),
base.UserMessage(actual_prompt_with_doc_id)
]Client use prompt
User typed /format report.pdf, server expands to full instruction.
# In your MCP client
prompts = await client.list_prompts()
# [{"name": "format", "description": "..."}]
# User trigger
prompt_result = await client.get_prompt("format", {"doc_id": "report.pdf"})
# prompt_result.messages = [UserMessage(...)]
# Inject into conversation
for msg in prompt_result.messages:
messages.append({"role": msg.role, "content": msg.content.text})
# Send to Claude
response = anthropic.messages.create(
model=MODEL,
messages=messages,
tools=anthropic_tools,
...
)Common prompt patterns
Prompt 1: Summarize
Prompt 2: Compare
@mcp.prompt(name="summarize")
def summarize(doc_id: str, max_words: int = 200) -> list[base.Message]:
return [
base.UserMessage(f"""Summarize document {doc_id}.
Constraints:
- Under {max_words} words
- Capture key findings
- Neutral tone
- Use `read_doc_contents` to fetch content first""")
]Prompt 2: Compare
Prompt 3: Review
@mcp.prompt(name="compare")
def compare(doc_id_a: str, doc_id_b: str) -> list[base.Message]:
return [
base.UserMessage(f"""Compare documents {doc_id_a} and {doc_id_b}.
Steps:
1. Read both docs
2. Identify key differences in:
- Content
- Tone
- Structure
3. Output side-by-side diff table""")
]Prompt 3: Review
@mcp.prompt(name="review")
def review(doc_id: str, reviewer_role: str = "senior engineer") -> list[base.Message]:
return [
base.UserMessage(f"""Review document {doc_id} as a {reviewer_role}.
For each section:
- Strengths
- Concerns
- Suggested improvements
Focus on clarity, correctness, completeness.""")
]Client UI integration
UI có thể show prompts as commands:
User type /summarize report.pdf → client call get_prompt → inject.
Available prompts:
/format <doc_id> - Reformat to markdown
/summarize <doc_id> - Summarize document
/compare <doc_a> <doc_b> - Compare 2 docs
/review <doc_id> [role] - Expert review
Type command or chat normally.Test qua Inspector
Inspector → Prompts tab:
Verify interpolation correct.
- List prompts
- Select prompt
- Fill args (e.g., doc_id: "report.pdf")
- See generated messages
When to use prompts
✅ Good fit
⚠️ Skip when
- Expert workflows (legal review, code analysis)
- Complex multi-step tasks
- Domain-specific language
- Quality matters over user flexibility
- Generic queries (user's own question)
- Highly personalized
- Changes frequently
Anti-patterns
❌ Vague prompts
Why MCP prompt? User could type that themselves.
Fix: Detailed, tested, value-adding prompts.
❌ Too many prompts
20 prompts for 1 server → user overwhelmed.
Fix: 3-10 well-crafted prompts.
❌ Prompt bypassing tools
return [base.UserMessage("Do something with " + doc_id)]❌ Prompt bypassing tools
Bypass tool = client loses access to real data.
Fix: Prompt instructs AI to use tools, not inject data.
return [base.UserMessage("Here's the content: ..." + fetch_content(doc_id))]Áp dụng ngay
Bài tập 1: Add 2 prompts (20 phút)
Add /summarize and /review prompts to server. Test via Inspector.
Bài tập 2: Client integration (30 phút)
Update main.py: detect /commands from user input. Call get_prompt, inject messages, continue.
Test end-to-end.
Tóm tắt
🎯 MCP prompts = curated templates, server author expert knowledge.
🎯 @mcp.prompt decorator, return list of messages.
🎯 Client get_prompt(name, args) to retrieve.
🎯 UI pattern: slash commands /format, /summarize.
🎯 Value-add over user-typed prompts qua tested quality.