Create Your First MCP Server

Now for a challenge! So far you’ve learned about the MCP Python SDK and FastMCP, and set up your development environment.

Now it’s time to put that knowledge into practice by creating your own MCP server from scratch.

Your challenge is to create a simple MCP server that demonstrates the core concepts you’ve learned, then run and test it using the tools you’ve set up.

GitHub Codespace

If you haven’t completed the setup lesson yet, go back to Setting Up Your Development Environment to configure your Codespace and environment variables.

You can keep the Codespace open while completing the course. You can open your existing codespaces at github.com/codespaces.

Challenge Goals

To complete this challenge, you will need to:

  1. Create a new MCP server using the MCP Python SDK

  2. Create a tool that counts the number of times a letter appears in a word

  3. Run your MCP server with HTTP transport

  4. Test the server using the interactive client

Solution Available

If you get stuck, you can review the complete solution in the repository at solutions/3c-create-first-server/main.py.

To see the solution in action, run:

bash
uv --directory solutions/3c-create-first-server run main.py

Step-by-Step Instructions

Step 1: Set up your project directory

First, create a new directory for your MCP server:

bash
Create a new directory
mkdir strawberry
cd strawberry

Step 2: Initialize the project with uv

Initialize a new Python project using uv:

bash
Initialize a new UV project
uv init

This will create a basic project structure with a pyproject.toml file and a main.py file that you will use to build your MCP server.

Step 3: Add the MCP dependency

Add the MCP Python SDK to your project:

bash
Add the MCP Python SDK to your project
uv add "mcp[cli]"

Step 4: Create your MCP server

Open main.py in your editor and add the following code to create a simple MCP server:

python
main.py
from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Strawberry")

@mcp.tool()
def count_letters(text: str, search: str) -> int:
    """Count occurrences of a letter in the text"""
    return text.lower().count(search.lower())

# Run the server when executed directly
if __name__ == "__main__":
    mcp.run(transport="streaming-http")

Streaming HTTP

This example uses the streaming-http transport method to run the server. This differs from stdio in that the client uses HTTP to communicate with the server.

We have made this choice to make it easier to test the server in GitHub Codespaces with the interactive Python client. For local development, using stdio is also a valid option.

Learn more about transports

Step 5: Run Your Server

Start your MCP server:

bash
Run your MCP server
uv run main.py

If the server is running successfully, you will see output similar to:

Console Output
INFO:     Started server process [30256]
INFO:     Waiting for application startup.
[10/15/25 12:52:22] INFO     StreamableHTTP session manager     streamable_http_manager.py:110
                             started
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Your server is now running on port 8000 and ready to accept connections from MCP clients.

Test with the Interactive Client

Now let’s test your server. The course repository includes an interactive Python client in the client/ folder that you can use to test your MCP server.

Open a new terminal (keep the server running in the first one) and run the following command:

bash
Run the interactive client
uv --directory client run main.py

The client will connect to your server and display an interactive menu showing available tools:

output
Console Output
============================================================
🔧 Available Tools:
============================================================

1. count_letters
   Count occurrences of a letter in the text

0. Exit
============================================================

Select a tool, resource, or template (enter number):

Enter 1 to select the count_letters tool.

The client will prompt you for the required parameters with type information:

output
Console Output
text (required)
  Type: string
  Enter value: strawberry

search (required)
  Type: string
  Enter value: r

After entering the parameters, you’ll see the result returned by the tool:

output
Console Output
✨ Result:
------------------------------------------------------------
3
------------------------------------------------------------

Try testing with different inputs to verify the tool works correctly. Press Enter to return to the menu, or q to quit.

Other Testing Options

VS Code Agent Mode: You can also test your MCP server directly in VS Code by configuring it in .vscode/mcp.json and using the Chat window in Agent mode. This allows you to interact with your tools conversationally.

Configuring the server for VS Code Agent mode
json
vscode/mcp.json
{
  "servers": {
    "strawberry": {
      "type": "http",
      "url": "http://localhost:8000/mcp"
    }
  }
}

MCP Inspector: For visual debugging, the MCP Inspector provides a web-based UI for exploring tools, resources, and prompts. Run it with npx @modelcontextprotocol/inspector.

That’s it!

You have just created and tested your first MCP server!

Summary

In this challenge, you successfully built your first MCP server from scratch:

  • FastMCP setup - Created a new MCP server using the FastMCP class with the MCP Python SDK

  • Tool implementation - Added a count_letters tool using the @mcp.tool() decorator to solve LLM counting limitations

  • HTTP transport - Configured the server to use streaming-HTTP transport for easy testing

  • Interactive testing - Tested the server with the Python client for immediate feedback

In the next module, you will learn about context management for handling server lifecycle and resource management, and you’ll start building tools that connect to Neo4j.

Chatbot

How can I help you today?