What are the three core MCP Server primitives (Resources, Tools, Prompts) and when to use each?
Resources: represent data Claude can read from the MCP Server. Resources are "passive" — Claude can request to read them, but they don't execute operations. Suitable for: static or dynamic data access (file contents, database records, API snapshots). Each Resource has a URI; Claude reads corresponding content via this URI.
Tools: represent functions Claude can execute. Tools are "active" — Claude calls them when it judges it needs to, passing parameters and receiving results. The most commonly used primitive. Suitable for: any operation you want Claude to "do" (search, write, query, send, transform). Each Tool has a name, description, and input parameter JSON Schema.
Prompts: represent predefined prompt workflows letting MCP Clients quickly invoke standardized tasks. Prompts are "reusable task templates" — users can select them directly from the MCP Client interface without manually entering full prompts each time. Suitable for: standardized workflows you want users to invoke with one click.
Selection principle: use Resources to let Claude read a data source; Tools to let Claude execute an operation; Prompts for standardized task flows for quick user access. In most MCP Server implementations, Tools are the core primitive; Resources and Prompts are supplementary.
How do you build a basic MCP Server with Python? What's the structure of a minimum viable version?
Using Anthropic's official Python MCP SDK, the core structure:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def search_documents(query: str, max_results: int = 5) -> str:
"""
Search the document library.
Use when: user needs to find documents on a specific topic.
Don't use when: looking for a specific document by ID (use get_document).
Args:
query: search keywords
max_results: max results to return (default 5)
"""
return format_results(your_search_function(query, max_results))
@mcp.resource("docs://{doc_id}")
def get_document(doc_id: str) -> str:
"""Read the full content of a specific document by ID."""
return your_db.get_document(doc_id)
if __name__ == "__main__":
mcp.run()
The most important design decision: the Tool's docstring. Claude relies entirely on this text to decide when to call the tool. A good Tool docstring includes: what it does (one-sentence description), when to call it (applicable scenarios), when not to call it (exclusion scenarios), and input parameter meanings and formats.
Connect in Claude Desktop's claude_desktop_config.json by adding the server configuration.
What are the technical differences between local and remote MCP Servers, and their applicable scenarios?
Local MCP Server: runs on the user's own computer, communicates with MCP Client via Standard I/O (stdio). Currently the primary MCP connection method for Claude Desktop.
Suited for local Server: accessing local file systems or databases; executing local command-line tools; personal development and testing; sensitive data that shouldn't be sent to external services.
Remote MCP Server: deployed on cloud or enterprise servers, communicating via HTTP/HTTPS and Server-Sent Events (SSE). Multiple users can share one remote Server.
Suited for remote Server: multiple users sharing the same tools (enterprise internal knowledge base); connecting to external SaaS services (Slack, GitHub, Salesforce); centralized management and updates (change once, all users immediately get new version); authentication and authorization (remote Server integrates OAuth and SSO more easily).
Enterprise deployment principle: local Server for personal tools and local resources; remote Server for team-shared tools and centrally-managed services. Many enterprise MCP architectures are "hybrid" — internal system connections as remote Server, personal workflow tools remaining local Server.
What are common mistakes and best practices when deploying MCP Servers in production?
Most common mistake 1: Tool description too vague
Most common, highest-impact issue. "Search for information" or "query database" doesn't tell Claude when to use this tool or how it differs from others. Good descriptions specify: applicable scenarios, exclusion scenarios, and parameter formats.
Most common mistake 2: Returning too much data
Tools returning thousands of characters of raw data make it hard for Claude to identify key information. Best practice: do server-side preprocessing, return only the key fields and summaries Claude actually needs, not entire database records or full document text.
Most common mistake 3: No error handling design
When tool execution fails (network timeout, data not found, API rate limiting), return a structured error message (containing error type, reason, suggested next step), not an unhandled Python exception. Claude can give users more meaningful responses with structured error messages.
Best practices: test your Server with MCP Inspector (Anthropic official tool) before connecting to Claude Desktop; put input validation on the server side (using Pydantic or TypeScript's Zod); for complex multi-step tasks, split into multiple Tools letting Claude execute and verify step-by-step.
A media company building an internal MCP Server for editorial teams, giving Claude access to article database, image library, and publishing system. This implementation illustrates Tool design for real enterprise scenarios:
Wrong design (too vague description):
Tool: search_content
Description: Search content.
Parameters: query (string)
Claude receives "find an appropriate image for this tech article" and doesn't know to use search_content (description doesn't say it can search images), may just say "I don't have a search tool."
Correct design (precise descriptions for each tool):
Tool: search_articles
Description: Search the article database for published articles.
Use when: finding past articles on a topic, checking for duplicate coverage, finding citable related reporting.
Don't use for: searching images (use search_images), searching drafts (use search_drafts).
Tool: search_images
Description: Search the image library.
Use when: finding images for articles, finding images of specific events or people.
Returns: image ID, title, copyright info, thumbnail URL.
This design lets Claude correctly identify calling search_images vs search_articles for image requests, improving call accuracy from 40% to 95%.
MCP Server development's core trade-off: flexibility vs maintenance cost. Custom-built MCP Servers can be fully tailored to your needs but require development and ongoing maintenance; third-party ready-made MCP Servers are simpler to set up but may not fully match your needs and require trusting third-party security practices. Recommended strategy: for connecting general tools (Google Drive, Slack, GitHub), prefer official or well-known open-source Servers; for connecting business systems (internal databases, custom APIs, services with specific security requirements), self-built Servers ensure full control and security compliance. Another trade-off is Tool granularity: finer-grained tools make Claude's call decisions more precise but increase Server maintenance complexity; too coarse-grained tools reduce call accuracy. One clear responsibility per tool is the best design principle.