DEV Community

pawan deore
pawan deore

Posted on

Build an MCP Server with FastMCP and Connect It to Claude

Model Context Protocol (MCP) makes it possible for AI assistants to interact with external tools and data sources in a standardized way.

In this tutorial, we'll build a simple MCP server using FastMCP, expose it over HTTPS with LocalTunnel, and connect it to Claude as a custom connector.

Our example will be a simple note-taking server with two tools:

  • get_notes — retrieve saved notes
  • add_note — add a new note

By the end, Claude will be able to read from and write to our MCP server.

🎥 Watch the Tutorial

What We'll Build

Claude
   │
   │ MCP
   ▼
HTTPS Tunnel
   │
   ▼
FastMCP Server
   │
   ▼
Mock Database
Enter fullscreen mode Exit fullscreen mode

We'll use an in-memory list as our database for simplicity. In a real application, you could replace it with PostgreSQL, SQLite, MongoDB, or another database.

Prerequisites

You'll need:

  • Python 3
  • VS Code
  • Node.js and npm
  • A Claude account that supports custom connectors

Create a new project and open it in VS Code.

1. Create a Virtual Environment

Start by creating a Python virtual environment:

python3 -m venv venv
Enter fullscreen mode Exit fullscreen mode

Activate it on macOS/Linux:

source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

2. Install FastMCP

Install FastMCP using pip:

pip install fastmcp
Enter fullscreen mode Exit fullscreen mode

FastMCP makes it much easier to create MCP servers in Python without implementing the MCP protocol yourself.

3. Create the MCP Server

Create a file named main.py.

Start by importing FastMCP and creating an MCP server:

from fastmcp import FastMCP

mcp = FastMCP("Simple Note Taker")
Enter fullscreen mode Exit fullscreen mode

For this tutorial, we'll use a simple Python list as our temporary database:

notes = [
    {
        "id": 0,
        "text": "Remember to deploy server"
    },
    {
        "id": 1,
        "text": "Eat Apple at 5 PM"
    }
]
Enter fullscreen mode Exit fullscreen mode

We now have two initial notes.

4. Create the get_notes Tool

FastMCP allows us to turn a normal Python function into an MCP tool using the @mcp.tool decorator.

@mcp.tool
def get_notes() -> str:
    output = ""

    for note in notes:
        output += f"Note #{note['id']}: {note['text']}\n"

    return output
Enter fullscreen mode Exit fullscreen mode

This function loops through our notes and returns them as a string.

5. Create the add_note Tool

Next, let's create a tool that allows Claude to add a new note.

@mcp.tool
def add_note(text: str) -> str:
    new_id = len(notes)

    notes.append({
        "id": new_id,
        "text": text
    })

    return f"Successfully saved note #{new_id}"
Enter fullscreen mode Exit fullscreen mode

The function accepts the note text, generates a new ID, stores the note, and returns a success message.

Our MCP server now exposes two tools:

Tool Description
get_notes Returns all saved notes
add_note Adds a new note

6. Configure the MCP Server

We want our MCP server to run over HTTP on port 8000.

Add this to the bottom of main.py:

if __name__ == "__main__":
    mcp.run(
        transport="http",
        host="0.0.0.0",
        port=8000
    )
Enter fullscreen mode Exit fullscreen mode

The complete main.py looks like this:

from fastmcp import FastMCP

mcp = FastMCP("Simple Note Taker")

notes = [
    {
        "id": 0,
        "text": "Remember to deploy server"
    },
    {
        "id": 1,
        "text": "Eat Apple at 5 PM"
    }
]


@mcp.tool
def get_notes() -> str:
    output = ""

    for note in notes:
        output += f"Note #{note['id']}: {note['text']}\n"

    return output


@mcp.tool
def add_note(text: str) -> str:
    new_id = len(notes)

    notes.append({
        "id": new_id,
        "text": text
    })

    return f"Successfully saved note #{new_id}"


if __name__ == "__main__":
    mcp.run(
        transport="http",
        host="0.0.0.0",
        port=8000
    )
Enter fullscreen mode Exit fullscreen mode

7. Run the MCP Server

Start the server:

python3 main.py
Enter fullscreen mode Exit fullscreen mode

FastMCP should start listening on port 8000.

Our MCP server is now running locally.

However, Claude cannot directly access localhost:8000, so we need to expose it through an HTTPS URL.

8. Create an HTTPS Tunnel with LocalTunnel

For this tutorial, we'll use LocalTunnel.

Install it globally:

npm install -g localtunnel
Enter fullscreen mode Exit fullscreen mode

Then create a tunnel to port 8000:

lt --port 8000
Enter fullscreen mode Exit fullscreen mode

LocalTunnel will provide an HTTPS URL similar to:

https://your-generated-url.loca.lt
Enter fullscreen mode Exit fullscreen mode

Keep the LocalTunnel process running while you're using the MCP server.

Note: LocalTunnel is useful for development and tutorials. For production, use a properly hosted HTTPS endpoint with authentication and appropriate security controls.

9. Connect the MCP Server to Claude

Now let's connect our MCP server to Claude.

In Claude, open:

Customize → Connectors

Then select:

Add a custom connector

Give the connector a name, for example:

Custom Todo
Enter fullscreen mode Exit fullscreen mode

For the remote server URL, enter your LocalTunnel URL with the MCP endpoint:

https://your-generated-url.loca.lt/mcp
Enter fullscreen mode Exit fullscreen mode

Then click Add.

Claude will try to connect to your MCP server.

If the connection succeeds, Claude should discover the two tools:

add_note
get_notes
Enter fullscreen mode Exit fullscreen mode

Approve the tools so Claude can use them.

10. Test the get_notes Tool

Go back to the Claude chat and ask:

Show me my notes.
Enter fullscreen mode Exit fullscreen mode

Claude should call the get_notes MCP tool.

You should get a response similar to:

Note #0: Remember to deploy server
Note #1: Eat Apple at 5 PM
Enter fullscreen mode Exit fullscreen mode

The important part is that Claude is actually calling our MCP server to retrieve this information.

11. Test the add_note Tool

Now let's add a new note.

Ask Claude:

Add a new note: Research MCP authentication.
Enter fullscreen mode Exit fullscreen mode

Claude should recognize that add_note is the appropriate MCP tool and call it with the provided text.

The server will add the note to our in-memory database.

Now ask Claude:

Show me my notes.
Enter fullscreen mode Exit fullscreen mode

You should now see:

Note #0: Remember to deploy server
Note #1: Eat Apple at 5 PM
Note #2: Research MCP authentication.
Enter fullscreen mode Exit fullscreen mode

We've successfully created an MCP server and connected it to Claude.

How the Request Flows

Here's what happens when you ask Claude to add a note:

You
 │
 │ "Add a new note..."
 ▼
Claude
 │
 │ MCP tool call
 ▼
HTTPS LocalTunnel URL
 │
 ▼
FastMCP Server
 │
 │ add_note()
 ▼
Mock Database
 │
 │ result
 ▼
Claude
Enter fullscreen mode Exit fullscreen mode

This is the core idea behind MCP: an AI assistant can discover and interact with external tools through a standardized protocol.

From Mock Database to a Real Database

Our example uses a Python list:

notes = [...]
Enter fullscreen mode Exit fullscreen mode

This is fine for learning, but the data will disappear when the server restarts.

A real application could use a persistent database such as PostgreSQL or SQLite:

FastMCP Server
      │
      ├── get_notes()
      │       │
      │       ▼
      │    Database
      │
      └── add_note()
              │
              ▼
           Database
Enter fullscreen mode Exit fullscreen mode

You could also add more tools:

  • get_notes
  • add_note
  • update_note
  • delete_note
  • search_notes

At that point, you have the foundation for a proper AI-powered task or note management system.

Production Considerations

The LocalTunnel setup is great for experimentation, but you should take additional precautions before deploying an MCP server to production.

Consider:

  • Using a stable HTTPS domain
  • Adding authentication and authorization
  • Validating tool inputs
  • Using a persistent database
  • Adding logging and monitoring
  • Handling errors properly
  • Limiting access to sensitive tools
  • Protecting sensitive data
  • Adding rate limiting where appropriate

This is particularly important when an AI assistant has permission to perform actions on your behalf.

Conclusion

In this tutorial, we built a simple MCP server with FastMCP and connected it to Claude.

The process was:

  1. Create a Python virtual environment.
  2. Install FastMCP.
  3. Create an MCP server.
  4. Add get_notes and add_note tools.
  5. Run the server on port 8000.
  6. Expose the local server using LocalTunnel.
  7. Add the server as a custom connector in Claude.
  8. Use Claude to read and create notes.

The example is intentionally simple, but the same pattern can be used to expose APIs, databases, internal services, automation workflows, and other capabilities to AI assistants.

That's what makes MCP powerful: you can give an AI model access to capabilities, not just information.

If you're experimenting with MCP, start small. Build one useful tool, connect it to an MCP client, and then expand the server as your use case grows.

Top comments (0)