Articles

Build an MCP Server: Complete MCP Tutorial for Beginners

Building an MCP server allows you to connect AI models like Claude to your local tools, data, and applications through a standardized protocol. In this tutorial, you’ll build an event calendar MCP server from scratch using Python’s FastMCP framework, enabling Claude Desktop to manage calendar events through natural language commands.

What you’ll build:

  • A functional MCP server with tools for adding, viewing, and deleting calendar events
  • Direct integration with Claude Desktop for AI-powered calendar management
  • A complete understanding of how MCP servers communicate with AI models

What you’ll need:

  • Python 3.10 or later installed on your system
  • Basic familiarity with Python functions and syntax
  • Claude Desktop (we’ll install this in Step 1)
  • Learn how to use Model Context Protocol (MCP) servers to extend your LLM's capabilities with hands-on examples.
    • Beginner Friendly.
      1 hour
  • Utilize Claude for data insights by managing CSV files, handling data, performing statistical analysis, using natural language queries, and creating visualizations.
    • Beginner Friendly.
      < 1 hour

What is Model Context Protocol (MCP)?

The Model Context Protocol (MCP) is an open standard designed to create a secure, structured bridge between language models and external data, tools, and systems. Instead of giving AI models direct access to your files or databases, MCP provides a structured way for models to request information through servers you control.

Think of MCP as a standardized interface: Claude (or any AI model) can request specific actions through your MCP server, but you decide exactly what data and operations are available. This architecture ensures security while enabling powerful integrations with local data, whether that’s calendar events, file systems, or custom services.

So now that you know what MCP does and why it matters, let’s build our own event calendar MCP server.

Building an event calendar MCP server

In this section, we’ll build an event calendar MCP Server from scratch. This project will show how an MCP server can help a language model like Claude manage data locally, in this case, creating, viewing, and deleting calendar events. Let’s start with the first step:

Step 1: Install Claude desktop

Claude Desktop will act as the MCP client that can talk to the server, and automatically discover and connect to local MCP servers once they’re running on your system. To install Claude desktop, do the following:

  • Visit the official Claude Desktop download page

  • Download and install the version compatible with your operating system (Windows or macOS).

Screenshot of Claude’s official desktop download page

Once installed, Claude will be ready to detect and interact with the MCP server we’ll create in the next steps.

Step 2: Set up the project structure

Check the Python version on device

Before executing the any commands for project initilaization, check the Python version using this command on the terminal:

python --version

If you see Python 3.10 or later, you’re good to go. If you have an older version or Python isn’t installed, download it from python.org and follow the installation instructions for your operating system.

Initialize the project with uv

Now let’s set up the project structure using the uv init command. uv is a modern Python package manager that creates a new Python project with all the essential boilerplate, containing:

  • A virtual environment
  • pyproject.toml file
  • main.pyfile
  • README.md file

Open your terminal and run:

uv init event-calendar-mcp
cd event-calendar-mcp

A new directory called event-calendar-mcp will be created and initialized as a Python project. The cd command will take us inside this directory.

Understand the project structure

After running uv init, your project looks like this:

event-calendar-mcp/
├── .venv/ # Virtual environment (isolated Python)
├── main.py # Your code goes here
├── pyproject.toml # Project metadata and dependencies
└── README.md # Project documentation

Here’s what each file does:

  • .venv/: This is your virtual environment. It’s a self-contained Python installation that keeps your project’s dependencies separate from your system’s Python.

  • main.py: This is where you’ll write your MCP server code. This is the heart of your application. When you run uv run main.py, this file executes and starts your server.

  • pyproject.toml: This is your project’s configuration file. It contains metadata like your project name and version, and lists all the dependencies your project needs. When you install packages with uv pip install, they get added here.

  • README.md: This is documentation for your project. It explains what your project does, how to install it, and how to use it.

Step 3: Build the MCP server code

Open main.py in your code editor and write the following code. We’ll break it into sections, to understand what each part does.

Imports and server initialization

Start with these imports:

from mcp.server.fastmcp import FastMCP
from typing import List, Dict
from datetime import datetime
# Create an MCP server
mcp = FastMCP("EventCalendar")
# In-memory storage for events
# Each event is a dict: {"title": str, "date": str, "description": str}
events: List[Dict] = []

Here’s what happening:

  • FastMCP is the framework that handles all the MCP protocol complexity for you. It manages how your server communicates with Claude.

  • List and Dict are type hints that tell Python what kind of data structures you’re using (Python lists and dictionaries).

  • datetime is a standard Python library for working with dates and times.

  • mcp = FastMCP("EventCalendar") creates your server and names it “EventCalendar”. Claude will recognize this name.

  • events: List[Dict] = [] creates an empty list to store your calendar events. Each event is a dictionary with a title, date, and description.

Add the add_event tool

This tool lets Claude add events to your calendar:

# Add an event
@mcp.tool()
def add_event(title: str, date: str, description: str = "") -> str:
"""
Add a new calendar event.
Date format: YYYY-MM-DD
"""
try:
# Validate date format
datetime.strptime(date, "%Y-%m-%d")
events.append({"title": title, "date": date, "description": description})
return f"Event '{title}' added for {date}."
except ValueError:
return "Invalid date format. Use YYYY-MM-DD."

In this code:

  • @mcp.tool() is a decorator that tells FastMCP “make this function available as a tool Claude can call.”

  • The function takes three parameters: title (event name), date (in YYYY-MM-DD format), and an optional description.

  • datetime.strptime(date, "%Y-%m-%d") validates that the date is in the correct format. If it’s not, it raises a ValueError.

  • events.append(...) adds the new event to your events list as a dictionary.

  • The function returns a confirmation message to Claude.

Add the view_event tool

This tool lets Claude see all your calendar events:

# View all events
@mcp.tool()
def view_events() -> str:
"""
Return all events in the calendar.
"""
if not events:
return "No events scheduled."
result = "Calendar Events:\n"
for event in sorted(events, key=lambda x: x["date"]):
desc = f" - {event['description']}" if event['description'] else ""
result += f"- {event['date']}: {event['title']}{desc}\n"
return result

This code:

  • First, it checks if there are any events. If the list is empty, it returns “No events scheduled.”

  • sorted(events, key=lambda x: x["date"]) sorts all events by date so they display chronologically.

  • For each event, it builds a formatted string showing the date, title, and description (if one exists).

  • It returns the entire formatted list as a single string that Claude can display.

Add the delete_event tool and summarize prompt

These complete your server’s functionality:

# Delete an event by title
@mcp.tool()
def delete_event(title: str) -> str:
"""
Delete an event by its title.
"""
initial_length = len(events)
events[:] = [e for e in events if e["title"].lower() != title.lower()]
if len(events) < initial_length:
return f"Event '{title}' deleted."
else:
return f"No event found with title '{title}'."
# Summarize events
@mcp.prompt()
def summarize_events() -> str:
"""
Generate a summary of upcoming events.
"""
if not events:
return "No events scheduled."
summary = "Upcoming Events Summary:\n"
for e in sorted(events, key=lambda x: x["date"]):
summary += f"- {e['date']}: {e['title']}"
if e['description']:
summary += f" ({e['description']})"
summary += "\n"
return summary
if __name__ == "__main__":
mcp.run()

Here’s what this code is doing:

  • delete_event() removes an event by title. It compares titles case-insensitively (so “Team Meeting” and “team meeting” are treated the same). It returns a success or “not found” message.

  • @mcp.prompt() creates a reusable prompt (different from @mcp.tool()). Prompts are suggestions Claude can use without you asking. summarize_events() provides a nice summary of all upcoming events.

  • events[:] = [...] is a Python idiom that modifies the list in-place (it doesn’t create a new list). This is important for keeping the same list object.

  • if __name__ == "__main__": mcp.run() is the entry point. When you run this file, this code starts your MCP server.

Step 4: Register your MCP server with uv

Next, we need to tell Claude desktop where to find the server. The uv run mcp install command does this automatically. It reads your main.py file, identifies it as an MCP server, and adds the necessary configuration to Claude’s settings so Claude knows how to start and connect to your server.

Note: Without this step, Claude desktop won’t know your server exists and won’t be able to find it.

Run the following command in your terminal ((in the event-calendar-mcp directory):

uv run mcp install main.py

The uv run executes a command using your project’s Python environment, and mcp install main.py registers main.py as an MCP server.

Command-line window displaying “uv run mcp install main.py” with confirmation message “Added server to Claude config,” demonstrating successful MCP Server installation in the Build MCP Server tutorial.

Finally, let’s test the working of our project.

Step 5: Test the MCP server with Claude desktop

Open Claude desktop (close and reopen it if it was already running). Claude will automatically discover and connect to your registered MCP server. Let’s test adding an event using this prompt:

Add an event called "Team Standup" on 2025-12-15 with description "Daily team sync"

Claude will use your add_event tool to create the event. You should see a response like:

Claude interface showing a user testing the new MCP Server by adding a calendar event called “Team Standup” as part of the MCP Server Tutorial demonstration.

Now ask Claude to show you your events:

Show me all my calendar events

Claude will call your view_events tool and display your event in a formatted list as follows:

MCP Tutorial example of Claude retrieving and listing all local calendar events through the connected MCP Server after setup.

Try asking Claude to summarize:

Summarize my upcoming events

Claude will use the summarize_events prompt to give you a summary of all events.

MCP Server Tutorial screenshot showing Claude summarizing upcoming events using locally stored data from the MCP Server.

Test deleting an event using:

Delete the Team Standup event

Claude will use your delete_event tool to remove it.

Claude prompting the user to allow event deletion, demonstrating secure local operation of the MCP Server in the Build MCP Server tutorial.

Select the ”Allow” option to delete it:

Claude confirming event deletion from the local computer through the MCP Server, illustrating a complete request–response action in the MCP Tutorial.

We’ve successfully created an event calendar MCP server that integrates with Claude! This server manages data locally, responds to Claude’s requests, and demonstrates all the core concepts of the MCP.

Now that you’ve seen how to set one up, let’s look at what’s actually happening behind the scenes, i.e. how MCP servers work.

How do MCP servers work?

When you asked Claude to add an event to your calendar, a lot happened automatically. Claude sent a request to your server, your server processed it, and Claude received a response. But how does this communication actually work?

MCP operates on a simple client-server model. Imagine two programs having a conversation: one asks questions (the client), and the other answers them (the server).

  • Client (Claude desktop): When you open Claude desktop and chat with Claude, Claude is the client. It’s the one asking questions and making requests. When you type “Add an event,” Claude is the client initiating that request.

  • Server (your event calendar program): Your main.py file is the server. It sits quietly waiting for requests from Claude. When a request arrives, it processes it, executes the appropriate function, and sends back a response.

Visual diagram showing MCP architecture with Claude as the client on the left, MCP servers in the center, and local or remote data sources on the right.

They communicate through something called stdio (standard input/output). Think of it like a two-way pipe: Claude writes messages into one end, and your server reads them. This is a local, direct connection with no internet involved, no external services needed.

MCP servers are powerful because they’re secure and put you in control. You define exactly what Claude can do, your data stays local, and everything happens instantly without external dependencies. This is the foundation of how modern AI tools can safely integrate with your personal workflows.

Conclusion

The Model Context Protocol (MCP) provides a standardized way to connect AI models with local tools and data while maintaining security and control. By building this event calendar MCP server, you’ve learned the fundamentals of MCP server development: exposing tools through decorators, managing local data, and integrating with Claude Desktop.

The MCP server you built today demonstrates how AI integration can be both powerful and secure. As you continue developing MCP servers, you’ll discover endless possibilities for connecting AI models to real-world data and systems.

To deepen your knowledge of building AI-powered applications and mastering the tools that power modern development, check out the comprehensive Introduction to Claude Projects.

Frequently asked questions

1. What is the basics of MCP?

MCP, or Model Context Protocol, is a framework that lets AI models like Claude communicate with local tools, data, and apps. It’s built on a client–server model, where the AI (client) sends structured requests to a local MCP server, which processes them and sends back responses in a secure, offline environment.

2. What is an example of an MCP server?

A simple example is a calendar MCP server that can add, view, or delete events on your computer. When Claude asks to “show upcoming meetings,” the MCP server reads your stored events locally and returns the results with no internet connection or external API needed.

3. Is MCP like an API?

In some ways, yes, as it behaves like an API but runs entirely on your local machine. Instead of sending requests over the internet, Claude sends structured messages to your MCP server, which directly executes the logic you define in code.

4. What are MCP tools?

Tools are the functions you expose to Claude through your MCP server. Each tool performs a specific action like adding a calendar event, summarizing a file, or running a local script. Think of tools as your AI assistant’s skill set.

5. What are the benefits of an MCP server?

MCP servers are private, customizable, and offline-first. They let you extend Claude’s abilities using local data and functions while keeping everything secure on your device. No third-party APIs, no data leaks, just precise, local control over your AI’s capabilities.

Codecademy Team

'The Codecademy Team, composed of experienced educators and tech experts, is dedicated to making tech skills accessible to all. We empower learners worldwide with expert-reviewed content that develops and enhances the technical skills needed to advance and succeed in their careers.'

Meet the full team

Learn more on Codecademy

  • Learn how to use Model Context Protocol (MCP) servers to extend your LLM's capabilities with hands-on examples.
    • Beginner Friendly.
      1 hour
  • Utilize Claude for data insights by managing CSV files, handling data, performing statistical analysis, using natural language queries, and creating visualizations.
    • Beginner Friendly.
      < 1 hour
  • Explore Anthropic’s Claude Artifacts. Learn to create and publish documents, SVGs, HTML, and React components with prompt engineering for dynamic projects.
    • Beginner Friendly.
      < 1 hour