In MCP, Prompts are user-controlled prompt templates — pre-programmed tactical maneuvers that the user (not the model) can select and invoke. Think of them as Captain Picard's numbered tactical patterns: "Pattern Delta-5" triggers a known sequence of instructions.
Key differences from Tools:
A Prompt is essentially a function that returns a formatted string (or a list of messages) to be injected into the conversation. It can accept arguments to customize the tactical approach.
@mcp.prompt() DecoratorRegistering a prompt is as elegant as programming a new tactical maneuver into the ship's computer:
from mcp.server.fastmcp import FastMCP
enterprise = FastMCP("USS Enterprise NCC-1701-D")
@enterprise.prompt()
def tactical_analysis(threat: str, quadrant: str = 'Alpha') -> str:
"""Request a tactical analysis of a threat in a specific quadrant.
Args:
threat: The nature of the threat (e.g. 'Romulan warbird', 'spatial anomaly')
quadrant: The quadrant where the threat is located
"""
return (
f'You are the tactical officer aboard the USS Enterprise.\n\n'
f'Analyze the following threat: {threat} in the {quadrant} Quadrant.\n\n'
f'Provide: 1) Threat assessment 2) Recommended shield configuration '
f'3) Suggested evasive maneuvers 4) Diplomatic options if applicable.'
)
When a user selects this prompt in their client (e.g., Claude Desktop shows it in a slash-command menu), they provide the arguments, and the resulting text becomes part of the conversation context. The model then responds to that structured prompt.
Prompts can do more than return a simple string. They can assemble multi-message conversations, inject system context, and even embed resource data:
from mcp.server.fastmcp import FastMCP
from mcp.types import TextContent, UserMessage, AssistantMessage
enterprise = FastMCP("USS Enterprise NCC-1701-D")
@enterprise.prompt()
def away_team_briefing(planet: str, mission_type: str = 'survey') -> list:
"""Generate a complete away team briefing for a planetary mission.
Args:
planet: Target planet designation
mission_type: Type of mission (survey, rescue, diplomatic, combat)
"""
return [
{
"role": "system",
"content": (
"You are Commander Data, second officer of the USS Enterprise. "
"You provide precise, thorough briefings with relevant data."
)
},
{
"role": "user",
"content": (
f"Commander Data, prepare an away team briefing for a "
f"{mission_type} mission to {planet}.\n\n"
f"Include:\n"
f"- Environmental hazards\n"
f"- Recommended team composition\n"
f"- Equipment checklist\n"
f"- Contingency protocols\n"
f"- Estimated mission duration"
)
}
]
This creates a fully structured conversation that primes the model to respond as Commander Data giving a mission briefing. The user just picks "Away Team Briefing" from the menu and provides the planet name.
You might wonder: "Why not just put instructions in the system message?" Here's the tactical distinction:
| Criterion | System Message | MCP Prompt |
|---|---|---|
| Who controls it? | Developer (hardcoded) | User (selectable at runtime) |
| When applied? | Always, at conversation start | On demand, user-triggered |
| Parameterized? | No (static) | Yes (dynamic arguments) |
| Discoverable? | No | Yes (listed via prompts/list) |
| Star Trek analogy | Standing orders | Tactical patterns (selectable maneuvers) |
Use system messages for baseline personality and constraints ("You are a helpful assistant"). Use Prompts for specialized interaction patterns the user can invoke on demand ("Analyze this code for security vulnerabilities").
A fully operational starship exposes Resources (sensors), Tools (weapons & systems), and Prompts (tactical patterns). Here's a complete server that demonstrates all three working together:
from mcp.server.fastmcp import FastMCP
enterprise = FastMCP("USS Enterprise NCC-1701-D")
# === RESOURCE: Ship's sensor data (read-only, application-controlled) ===
@enterprise.resource("enterprise://sensors/status")
def sensor_status() -> str:
"""Current sensor array status and readings."""
return (
"Long-range sensors: Online\n"
"Short-range sensors: Online\n"
"Nearest vessel: Romulan Warbird, bearing 247 mark 3, distance 2.4 light-years\n"
"Anomalies detected: Subspace distortion at coordinates 427.3, 291.7"
)
# === TOOL: Actionable capability (model-controlled) ===
@enterprise.tool()
def fire_phasers(target: str, power_level: int = 50) -> str:
"""Fire phaser array at specified target. Power level 1-100."""
if power_level > 80:
return f'Maximum phaser discharge at {target}. Direct hit!'
return f'Phaser burst at {target}, power level {power_level}%. Standing by.'
@enterprise.tool()
def raise_shields(configuration: str = 'standard') -> str:
"""Raise deflector shields with specified configuration."""
configs = {
'standard': 'Standard shield configuration. All frequencies rotating.',
'modulated': 'Shields modulated to Borg cutting beam frequency.',
'metaphasic': 'Metaphasic shields engaged. Safe for stellar corona entry.'
}
return configs.get(configuration, f'Unknown configuration: {configuration}')
# === PROMPT: Tactical pattern (user-controlled) ===
@enterprise.prompt()
def tactical_analysis(threat: str, quadrant: str = 'Alpha') -> str:
"""Request a tactical analysis of a threat in a specific quadrant."""
return (
f'You are the tactical officer aboard the USS Enterprise.\n\n'
f'Analyze the following threat: {threat} in the {quadrant} Quadrant.\n\n'
f'Provide: 1) Threat assessment 2) Recommended shield configuration '
f'3) Suggested evasive maneuvers 4) Diplomatic options if applicable.'
)
@enterprise.prompt()
def captains_log(stardate: str, summary: str) -> str:
"""Format a Captain's Log entry."""
return (
f"Captain's Log, Stardate {stardate}.\n\n"
f"Context: {summary}\n\n"
f"Write a formal Captain's Log entry in the style of Jean-Luc Picard. "
f"Include reflections on the moral and philosophical implications."
)
if __name__ == "__main__":
enterprise.run()
This single server file gives you a fully operational starship:
Engage. 🖖