Định nghĩa prompts qua MCP

8 — MCPTrung cấp15 phút

Tool = action. Prompt = crafted instruction bạn (server author) carefully designed + tested.

Bạn sẽ học được
  • 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 author

Implement 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.

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