FastMCP & @mcp.tool()

This is the pivotal step. Remember those 108+ lines of glue code per integration? Watch what happens when we use MCP instead.

Step 1: Create an MCP server. Two lines. That's it. The server can run immediately with 0 tools, 0 resources, 0 prompts.

06-build-mcp-server.py
python
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("DevTools Assistant")

One import, one line. Your MCP server exists.

Step 2: Add your first tool. Just add the @mcp.tool() decorator to your existing function. The decorator reads your type hints and docstring to auto-generate the exact same JSON schema you wrote by hand in Step 05.

06-build-mcp-server.py
python
@mcp.tool()
def search_articles(topic: str, max_results: int = 5) -> List[str]:
    """Search for articles on Wikipedia based on a topic."""
    search_results = wikipedia.search(topic, results=max_results)
    article_titles = []
    for title in search_results:
        article_titles.append(title)
    return article_titles

One decorator. No hand-written schema. No mapping dict. No dispatcher.

Look what disappeared: - JSON schema definitions: gone (auto-generated from type hints) - Name-to-function mapping: gone (decorator registers automatically) - execute_tool() dispatcher: gone (MCP protocol handles routing) - Response normalization: gone (protocol handles serialization) Step 05 needed ~70 lines of glue for each tool. Step 06 needs 0 lines.

Before vs after: manual vs MCP

MCP eliminates four entire layers of boilerplate.

Want to add a second tool? Just write another function with @mcp.tool(). No schema to update, no mapping to extend, no dispatcher to modify.

06-build-mcp-server.py
python
@mcp.tool()
def get_article_content(article_title: str) -> str:
    """Get the full content of a Wikipedia article."""
    try:
        page = wikipedia.page(article_title)
        return page.content[:2000] + "..." \
            if len(page.content) > 2000 else page.content
    except wikipedia.exceptions.DisambiguationError as e:
        return f"Disambiguation error: {e.options[:5]}"
    except wikipedia.exceptions.PageError:
        return f"Page not found: {article_title}"

Second tool. Same pattern: decorator + function. Zero additional boilerplate.

06-build-mcp-server.py
python
if __name__ == "__main__":
    mcp.run(transport='stdio')

Run the server. ~40 lines total vs ~200+ in the manual approach.

Quiz: Quiz

Loading practice…