Skip to main content

FastMCP Template

A production-ready FastMCP server template with mcp-refcache integration for building AI agent tools that handle large data efficiently.

Using This Template

Create Your Project

  1. Use as GitHub Template (recommended):

    • Click "Use this template" → "Create a new repository"
    • Or use GitHub CLI: gh repo create my-mcp-server --template l4b4r4b4b4/fastmcp-template
  2. Or clone directly:

    git clone https://github.com/l4b4r4b4b4/fastmcp-template my-mcp-server
    cd my-mcp-server
    rm -rf .git && git init
    

Rename the Project

After creating your project, rename it from fastmcp-template to your project name:

1. Update pyproject.toml

[project]
name = "my-mcp-server"  # Your project name
version = "0.0.1"
description = "Your project description"
authors = [{ name = "Your Name", email = "you@example.com" }]

[project.scripts]
my-mcp-server = "app.__main__:app"  # Your CLI command

2. Update Docker images in docker-compose.yml

services:
  my-mcp-server:
    image: ghcr.io/your-org/my-mcp-server:latest

3. Update docker/Dockerfile.base labels

LABEL org.opencontainers.image.source="https://github.com/your-org/my-mcp-server"

4. Update app/server.py

mcp = FastMCP(
    name="My MCP Server",  # Your server name
    instructions="Your server description...",
)

_cache = RefCache(
    name="my-mcp-server",  # Your cache namespace
    ...
)

5. Update GitHub workflows

In .github/workflows/release.yml:

env:
  APP_IMAGE_NAME: ${{ github.repository_owner }}/my-mcp-server
  BASE_IMAGE_NAME: ${{ github.repository_owner }}/my-mcp-base

6. Update Zed/Editor settings

In .zed/settings.json, update the context server name and command.

Add Your Tools

Create new tool modules in app/tools/:

# app/tools/my_feature.py
from pydantic import BaseModel, Field

class MyInput(BaseModel):
    """Input for my tool."""
    query: str = Field(description="The query to process")

async def my_tool(query: str) -> dict:
    """Process a query and return results."""
    # Your business logic here
    return {"result": f"Processed: {query}"}

Then register in app/tools/__init__.py and app/server.py:

# app/tools/__init__.py
from app.tools.my_feature import MyInput, my_tool
__all__ = [..., "MyInput", "my_tool"]

# app/server.py
from app.tools import my_tool
mcp.tool(my_tool)

Configure PyPI Publishing

  1. Go to PyPI Trusted Publishers
  2. Add a new pending publisher:
    • Project name: my-mcp-server
    • Owner: your-github-username
    • Repository: my-mcp-server
    • Workflow: publish.yml
    • Environment: pypi

Features

  • Reference-Based Caching - Return references instead of large data, reducing context window usage
  • Preview Generation - Automatic previews for large results (sample, truncate, paginate strategies)
  • Pagination - Navigate large datasets without loading everything at once
  • Access Control - Separate user and agent permissions for sensitive data
  • Private Computation - Let agents compute with values they cannot see
  • Docker Ready - Production-ready containers with Python slim base image
  • Optional Langfuse Tracing - Built-in observability integration

Quick Start

Prerequisites

  • Python 3.12+
  • uv (recommended) or pip

Installation

# Clone the template
git clone https://github.com/l4b4r4b4b4/fastmcp-template
cd fastmcp-template

# Install dependencies
uv sync

# Run the server (stdio mode for Claude Desktop)
uv run fastmcp-template

# Run the server (SSE/HTTP mode for deployment)
uv run fastmcp-template --transport sse --port 8000

Install from PyPI

# Run directly with uvx (no install needed)
uvx fastmcp-template stdio

# Or install globally
uv tool install fastmcp-template
fastmcp-template --help

Docker Deployment

# Pull and run from GHCR
docker pull ghcr.io/l4b4r4b4b4/fastmcp-template:latest
docker run -p 8000:8000 ghcr.io/l4b4r4b4b4/fastmcp-template:latest

# Or build locally with Docker Compose
docker compose up

# Build images manually
docker compose --profile build build base
docker compose build

Using with Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "fastmcp-template": {
      "command": "uv",
      "args": ["run", "fastmcp-template"],
      "cwd": "/path/to/fastmcp-template"
    }
  }
}

Using with Zed

The template includes .zed/settings.json pre-configured for MCP context servers.

Example Tools

The template includes several example tools demonstrating different patterns:

Simple Tool (No Caching)

@mcp.tool
def hello(name: str = "World") -> dict[str, Any]:
    """Say hello to someone."""
    return {"message": f"Hello, {name}!"}

Cached Tool (Public Namespace)

@mcp.tool
@cache.cached(namespace="public")
async def generate_items(count: int = 10, prefix: str = "item") -> list[dict]:
    """Generate items with automatic caching for large results."""
    return [{"id": i, "name": f"{prefix}_{i}"} for i in range(count)]

Private Computation (EXECUTE Permission)

@mcp.tool
def store_secret(name: str, value: float) -> dict[str, Any]:
    """Store a secret that agents can use but not read."""
    secret_policy = AccessPolicy(
        user_permissions=Permission.FULL,
        agent_permissions=Permission.EXECUTE,  # Can use, cannot see
    )
    ref = cache.set(key=f"secret_{name}", value=value, policy=secret_policy)
    return {"ref_id": ref.ref_id}

@mcp.tool
def compute_with_secret(secret_ref: str, multiplier: float = 1.0) -> dict[str, Any]:
    """Compute using a secret without revealing it."""
    secret = cache.resolve(secret_ref, actor=DefaultActor.system())
    return {"result": secret * multiplier}

Project Structure

fastmcp-template/
├── app/                     # Application code (flat structure for containers)
│   ├── __init__.py          # Version export
│   ├── server.py            # Main server with example tools
│   └── tools/               # Additional tool modules
├── docker/
│   ├── Dockerfile.base      # Python slim base image with dependencies
│   ├── Dockerfile           # Production image (extends base)
│   └── Dockerfile.dev       # Development with hot reload
├── tests/
│   ├── conftest.py          # Pytest fixtures
│   └── test_server.py       # Server tests
├── .github/
│   └── workflows/
│       ├── ci.yml           # CI pipeline (lint, test, security)
│       ├── publish.yml      # PyPI trusted publisher
│       └── release.yml      # Docker build & publish to GHCR
├── docker-compose.yml       # Local development & production
├── pyproject.toml           # Project config
├── flake.nix                # Nix dev shell
└── .rules                   # AI assistant guidelines

Development

Setup

# Install dependencies
uv sync

# Install pre-commit and pre-push hooks (configured in .pre-commit-config.yaml)
uv run pre-commit install --install-hooks
uv run pre-commit install --hook-type pre-push

Running Tests

uv run pytest
uv run pytest --cov  # With coverage

Linting and Formatting

uv run ruff check . --fix
uv run ruff format .

Type Checking

uv run mypy app/

Docker Development

# Run development container with hot reload
docker compose --profile dev up

# Build base image (for publishing)
docker compose --profile build build base

# Build all images
docker compose build

Using Nix (Optional)

nix develop  # Enter dev shell with all tools

Customization

  1. Rename the project: Update pyproject.toml, app/, and imports
  2. Add your tools: Create new tools in app/server.py or add modules to app/tools/
  3. Configure caching: Adjust RefCache settings in app/server.py
  4. Add Langfuse: Install with uv add langfuse and configure environment variables
  5. Extend base image: Use FROM ghcr.io/l4b4r4b4b4/fastmcp-base:latest in your Dockerfile

Configuration

Environment Variables

Variable Description Default
LANGFUSE_PUBLIC_KEY Langfuse public key -
LANGFUSE_SECRET_KEY Langfuse secret key -
LANGFUSE_HOST Langfuse host URL https://cloud.langfuse.com

CLI Commands

uvx fastmcp-template --help

Commands:
  stdio             Start server in stdio mode (for Claude Desktop and local CLI)
  sse               Start server in SSE mode (Server-Sent Events)
  streamable-http   Start server in streamable HTTP mode (recommended for remote/Docker)

# Examples:
uvx fastmcp-template stdio                          # Local CLI mode
uvx fastmcp-template sse --port 8000                # SSE on port 8000
uvx fastmcp-template streamable-http --host 0.0.0.0 # Docker/remote mode

Test Prompts

Use these prompts in a fresh chat session to verify the MCP server is working correctly. Each prompt demonstrates different capabilities of mcp-refcache.

🟢 Basic: Hello World

Prompt: "Say hello to 'MCP Developer' using the fastmcp-template tools"

Expected: The assistant calls hello with name="MCP Developer" and returns a greeting.


🟢 Basic: Health Check

Prompt: "Check if the fastmcp-template server is healthy"

Expected: The assistant calls health_check and reports server status.


🟡 Intermediate: Generate & Explore Items

Prompt: "Generate 50 widgets and tell me about the first and last items"

Expected: The assistant calls generate_items(count=50, prefix="widget") and describes widget_0 and widget_49.


🟡 Intermediate: Salary Calculator (Private Computation)

Prompt: "I want to calculate a 5% raise on my salary, but I don't want you to know my actual salary. Store $75,000 as a secret called 'current_salary', then calculate what it would be with a 5% raise."

Expected:

  1. Assistant calls store_secret(name="current_salary", value=75000)
  2. Assistant calls compute_with_secret(secret_ref="...", multiplier=1.05)
  3. Assistant reports the result ($78,750) without ever seeing the original value

🔴 Advanced: Multi-Step Private Computation

Prompt: "Help me compare two investment options without seeing my principal. Store $10,000 as 'principal'. Then calculate returns for: Option A (8% return) and Option B (12% return). Which is better?"

Expected:

  1. Assistant stores the secret principal
  2. Assistant computes both options using the same secret reference
  3. Assistant compares results ($10,800 vs $11,200) and recommends Option B
  4. The actual principal value is never revealed to the assistant

🔴 Advanced: Access Control Verification

Prompt: "Store my API key hash as a secret (use value 12345), then try to read it back directly using get_cached_result"

Expected:

  1. Assistant stores the secret successfully
  2. When attempting to read with get_cached_result, it gets "access denied"
  3. Assistant explains that secrets have EXECUTE-only permission for agents

🔴 Advanced: Admin Tool Verification

Prompt: "Show me the cache statistics using admin_get_cache_stats"

Expected: Assistant receives "Admin access required" error and explains that admin tools are permission-gated.


Test Coverage Summary

Feature Prompt Level Tools Used
Basic greeting 🟢 Basic hello
Server health 🟢 Basic health_check
Item generation 🟡 Intermediate generate_items
Secret storage 🟡 Intermediate store_secret
Private computation 🟡 Intermediate compute_with_secret
Access control 🔴 Advanced get_cached_result
Admin gating 🔴 Advanced admin_* tools

License

MIT License - see LICENSE for details.

Contributing

See CONTRIBUTING.md for development guidelines.

Related Projects

Metadata

Release files for fastmcp-template 0.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastmcp-template 0.0.3
File Size Uploaded
fastmcp_template-0.0.3.tar.gz 182.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastmcp-template 0.0.3
File Interpreter ABI Platform
fastmcp_template-0.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 210.5 kB

Release files / fastmcp_template-0.0.3.tar.gz

Download URL fastmcp_template-0.0.3.tar.gz
Size 182.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f36da049d6dd8f7759931707792766887e5c3b154ab81f8809a5200c11499c55
BLAKE2b-256 checksum
How to use checksums
fe1d010dd8eb48ca6638f23737b73928de1ca6bec4bc187b9d3db91ccf2216d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 13, 2025.

Transparency log

Release files / fastmcp_template-0.0.3-py3-none-any.whl

Download URL fastmcp_template-0.0.3-py3-none-any.whl
Size 27.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a17c8453e0bbd36c51ba104c42157f9743827a9ff659ccb827cbc0dfba2639ee
BLAKE2b-256 checksum
How to use checksums
daf670285b8a7dd68e84806cf232e5ae9a560d01fc2cf7bc083e832dc815338e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 13, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.3 This release

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page