
FastMCP å ¥é (5) - ããã³ãã
ãFastMCPãã®ãããã³ãããã«ã€ããŠãŸãšããŸããã
åå
1. ããã³ãã
ãããã³ãããã¯ãLLMãæ§é åãããç®çã®ããå¿çãçæããã®ã«åœ¹ç«ã€åå©çšå¯èœãªã¡ãã»ãŒãžãã³ãã¬ãŒãã§ããFastMCPã¯ãäž»ã«@mcp.promptãã³ã¬ãŒã¿ã䜿çšããŠããããã®ãã³ãã¬ãŒãã®å®çŸ©ãç°¡çŽ åããŸãã
ã¯ã©ã€ã¢ã³ããããã³ãããèŠæ±ãããšã以äžã®åŠçãå®è¡ãããŸãã
ã»FastMCP ã¯å¯Ÿå¿ããããã³ããå®çŸ©ãæ€çŽ¢
ã»ãã©ã¡ãŒã¿ãããå Žåã¯ã颿°ã·ã°ããã£ãšç §åããŠæ€èšŒ
ã»é¢æ°ã¯æ€èšŒãããå ¥åã䜿çšããŠå®è¡
ã»çæãããã¡ãã»ãŒãžã¯ LLM ã«è¿ãããå¿çã®ã¬ã€ããšããŠäœ¿çš
ããã«ãããLLM ãããŸããŸãªã¯ã©ã€ã¢ã³ããã³ã³ããã¹ãã§äœ¿çšã§ãããäžè²«æ§ãããåå©çšå¯èœãªãã³ãã¬ãŒããå®çŸ©ã§ããŸãã
2. @mcp.promptãã³ã¬ãŒã¿
ããã³ãããå®çŸ©ããæãäžè¬çãªæ¹æ³ã¯ãPython颿°ããã³ã¬ãŒãããããšã§ãããã³ã¬ãŒã¿ã¯é¢æ°åãããã³ããã®èå¥åãšããŠäœ¿çšããŸãã
from fastmcp import FastMCP
from fastmcp.prompts.prompt import UserMessage, AssistantMessage, Message
mcp = FastMCP(name="PromptServer")
# æååãè¿ãåºæ¬ããã³ãã (UserMessage ã«å€æããã)
@mcp.prompt()
def ask_about_topic(topic: str) -> str:
"""ãããã¯ã®èª¬æãæ±ãããŠãŒã¶ãŒ ã¡ãã»ãŒãžãçæ"""
return f"'{topic}'ã®æŠå¿µã説æããŠããã ããŸããïŒ"
# ç¹å®ã®ã¡ãã»ãŒãžã¿ã€ããè¿ãããã³ãã
@mcp.prompt()
def generate_code_request(language: str, task_description: str) -> UserMessage:
"""ã³ãŒãçæãèŠæ±ãããŠãŒã¶ãŒ ã¡ãã»ãŒãžãçæ"""
content = f"次ã®ã¿ã¹ã¯ãå®è¡ãã {language} 颿°ãèšè¿°ããŸã: {task_description}"
return UserMessage(content=content)ã»åå
ããã©ã«ãã§ã¯ãããã³ããåã¯é¢æ°åããååŸãããŸãã
ã»ãã©ã¡ãŒã¿
Â é¢æ°ãã©ã¡ãŒã¿ã¯ãããã³ãããçæããããã«å¿ èŠãªå ¥åãå®çŸ©ããŸãã
ã»æšè«ã¡ã¿ããŒã¿
ããã©ã«ãã§ã¯ã以äžã®ããã«ãªããŸãã
ãã»ããã³ããå :Â é¢æ°å (ask_about_topic) ããååŸãããŸãã
ãã»ããã³ããã®èª¬æ : 颿°ã®ããã¥ã¡ã³ãæååããååŸãããŸãã
3. æ»ãå€
FastMCPã¯ãããã³ãã颿°ããã®ããŸããŸãªæ»ãå€ã®åãã€ã³ããªãžã§ã³ãã«åŠçããŸãã
ã»str : åäžã® UserMessage ã«èªåçã«å€æãããŸãã
ã»Message (äŸ: UserMessageãAssistantMessage) : æäŸããããšããã«ãã®ãŸãŸäœ¿çšãããŸãã
ã»dict : æ£ããæ§é ã§ããã°ãMessage ãªããžã§ã¯ããšããŠè§£æãããŸãã
ã»list[Message] : ã¡ãã»ãŒãžã®ã·ãŒã±ã³ã¹ (äŒè©±) ãšããŠäœ¿çšãããŸãã
@mcp.prompt()
def roleplay_scenario(character: str, situation: str) -> list[Message]:
"""æåã®ã¡ãã»ãŒãžã§ããŒã«ãã¬ã€ã³ã° ã·ããªãªãèšå®"""
return [
UserMessage(f"ããŒã«ãã¬ã€ãããŸããããããªãã¯{character}ã§ããç¶æ³ã¯{situation}ã§ãã"),
AssistantMessage("åãããŸãããæºåã¯ã§ããŸãããæ¬¡ã¯äœããããã§ããïŒ")
]
@mcp.prompt()
def ask_for_feedback() -> dict:
"""ãã£ãŒãããã¯ãæ±ãããŠãŒã¶ãŒ ã¡ãã»ãŒãžãçæ"""
return {"role": "user", "content": "ç§ã®ååã®è¿çã«ã€ããŠã©ãæããŸããã?"}4. åã¢ãããŒã·ã§ã³
åã¢ãããŒã·ã§ã³ã¯ããã³ããã«ãšã£ãŠéèŠã§ãã以äžã®æ©èœããããŸãã
ã»FastMCP ã«åãã©ã¡ãŒã¿ã®æ³å®ãããåãéç¥ããŸãã
ã»ã¯ã©ã€ã¢ã³ãããåä¿¡ãããã©ã¡ãŒã¿ã®æ€èšŒãå¯èœã«ããŸãã
ã»MCP ãããã³ã«çšã®ããã³ããã®ã¹ããŒããçæããããã«äœ¿çšãããŸãã
from pydantic import Field
from typing import Literal, Optional
@mcp.prompt()
def generate_content_request(
topic: str = Field(description="The main subject to cover"),
format: Literal["blog", "email", "social"] = "blog",
tone: str = "professional",
word_count: Optional[int] = None
) -> str:
"""ç¹å®ã®åœ¢åŒã§ã³ã³ãã³ããçæããããã®ãªã¯ãšã¹ããäœæ"""
prompt = f"{topic} ã«ã€ããŠã{tone} ããŒã³ã§ {format} ã®æçš¿ãæžããŠãã ããã"
if word_count:
prompt += f"é·ãã¯çŽ {word_count} èªã§ãã"
return prompt5. å¿ é ãã©ã¡ãŒã¿ãšãªãã·ã§ã³ãã©ã¡ãŒã¿
颿°ã·ã°ããã£å ã®ãã©ã¡ãŒã¿ã¯ãããã©ã«ãå€ãèšå®ãããŠããªãéãå¿ é ãšã¿ãªãããŸãã
@mcp.prompt()
def data_analysis_prompt(
data_uri: str, # å¿
é - ããã©ã«ãå€ãªã
analysis_type: str = "summary", # ãªãã·ã§ã³ - ããã©ã«ãå€ãã
include_charts: bool = False # ãªãã·ã§ã³ - ããã©ã«ãå€ãã
) -> str:
"""ç¹å®ã®ãã©ã¡ãŒã¿ã䜿çšããŠããŒã¿ãåæããããã®ãªã¯ãšã¹ããäœæ"""
prompt = f"{data_uri} ã«ããããŒã¿ã«å¯Ÿã㊠'{analysis_type}' åæãå®è¡ããŠãã ããã"
if include_charts:
prompt += " Include relevant charts and visualizations."
return promptãã®äŸã§ã¯ãã¯ã©ã€ã¢ã³ãã¯data_uriãæå®ããå¿ èŠããããŸããanalysis_typeãŸãã¯include_chartsãçç¥ãããå Žåã¯ãããã©ã«ãå€ã䜿çšãããŸãã
6. ããã³ããã¡ã¿ããŒã¿
FastMCPã¯é¢æ°ããååãšèª¬æãæšæž¬ããŸããã@mcp.promptãã³ã¬ãŒã¿ã«åŒæ°ãäžããããšã§ããããããªãŒããŒã©ã€ãããã¿ã°ã远å ã§ããŸãã
@mcp.prompt(
name="analyze_data_request", # ããã³ããå
description="Creates a request to analyze data with specific parameters", # 説æ
tags={"analysis", "data"} # åé¡ã¿ã°
)
def data_analysis_prompt(
data_uri: str = Field(description="ããŒã¿ãå«ããªãœãŒã¹ã®URI"),
analysis_type: str = Field(default="summary", description="åæã®çš®é¡")
) -> str:
"""説æãæäŸãããŠããå Žåããã®ããã¥ã¡ã³ãæååã¯ç¡èŠããã"""
return f"{data_uri} ã«ããããŒã¿ã«å¯Ÿã㊠'{analysis_type}' åæãå®è¡ããŠãã ããã"ã»name
MCP çµç±ã§å ¬éãããæç€ºçãªããã³ããåãèšå®ããŸãã
ã»description
MCP çµç±ã§å ¬éããã説æãæå®ããŸããèšå®ãããŠããå Žåã颿°ã® docstring ã¯ãã®ç®çã§ã¯ç¡èŠãããŸãã
ã»tags
ããã³ãããåé¡ããããã«äœ¿çšãããæååã®ã»ãããã¯ã©ã€ã¢ã³ãã¯ãå©çšå¯èœãªããã³ããããã£ã«ã¿ãªã³ã°ãŸãã¯ã°ã«ãŒãåããããã«ã¿ã°ã䜿çšã§ããŸãã
7. éåæããã³ãã
FastMCPã¯ãæšæºé¢æ° (def) ãšéåæé¢æ° (async def) ã®äž¡æ¹ãããã³ãããšããŠã·ãŒã ã¬ã¹ã«ãµããŒãããŸãã
# åæããã³ãã
@mcp.prompt()
def simple_question(question: str) -> str:
"""LLM ã«å°ããç°¡åãªè³ªåãçæ"""
return f"Question: {question}"
# éåæããã³ãã
@mcp.prompt()
async def data_based_prompt(data_id: str) -> str:
"""ååŸããå¿
èŠãããããŒã¿ã«åºã¥ããŠããã³ãããçæ"""
# å®éã®ã·ããªãªã§ã¯ãããŒã¿ããŒã¹ãAPIããããŒã¿ãååŸããå Žåããã
async with aiohttp.ClientSession() as session:
async with session.get(f"https://api.example.com/data/{data_id}") as response:
data = await response.json()
return f"Analyze this data: {data['content']}"ããã³ãã颿°ããããã¯ãŒã¯èŠæ±ãããŒã¿ããŒã¹ ã¯ãšãªããã¡ã€ã« I/Oãå€éšãµãŒãã¹åŒã³åºããªã©ã® I/O æäœãå®è¡ããå Žåã¯ãasync def ã䜿çšããŸãã
8. MCPã³ã³ããã¹ããžã®ã¢ã¯ã»ã¹
ããã³ããã¯ãContextãªããžã§ã¯ããä»ããŠMCPã®è¿œå æ å ±ãæ©èœã«ã¢ã¯ã»ã¹ã§ããŸããããã«ã¢ã¯ã»ã¹ããã«ã¯ãããã³ãã颿°ã«Contextåã¢ãããŒã·ã§ã³ãä»äžãããã©ã¡ãŒã¿ã远å ããŸãã
from fastmcp import FastMCP, Context
mcp = FastMCP(name="PromptServer")
@mcp.prompt()
async def generate_report_request(report_type: str, ctx: Context) -> str:
"""ã¬ããŒãã®ãªã¯ãšã¹ããçæ"""
return f"{report_type}ã¬ããŒããäœæããŠãã ããããªã¯ãšã¹ãID: {ctx.request_id}"詳ããã¯ãContextã®ããã¥ã¡ã³ããåç §ããŠãã ããã
9. ãµãŒãã®åäœ
9-1. éè€ããã³ãã
FastMCPãµãŒããåãååã®ããã³ãããè€æ°ç»é²ããããšããå Žåã®åŠçââæ¹æ³ãèšå®ã§ããŸããFastMCPã®åæåæã«on_duplicate_promptsèšå®ã䜿çšããŠãã ããã
from fastmcp import FastMCP
mcp = FastMCP(
name="PromptServer",
on_duplicate_prompts="error" # Raise an error if a prompt name is duplicated
)
@mcp.prompt()
def greeting(): return "Hello, how can I help you today?"
# This registration attempt will raise a ValueError because
# "greeting" is already registered and the behavior is "error".
# @mcp.prompt()
# def greeting(): return "Hi there! What can I do for you?"ã»warn (ããã©ã«ã)
èŠåããã°ã«èšé²ããæ°ããããã³ãããå€ãããã³ããã眮ãæããŸãã
ã»error
ValueError ãçºçãããéè€ç»é²ã鲿¢ããŸãã
ã»replace
æ¢åã®ããã³ãããæ°ããããã³ããã«æé»çã«çœ®ãæããŸãã
ã»ignore
å ã®ããã³ãããç¶æããæ°ããç»é²ã®è©Šè¡ãç¡èŠããŸãã