Skip to main content
Glama

MCP Template

A minimal, production-ready FastMCP server template. Use this as a starting point for building your own MCP (Model Context Protocol) server.

What This Is

A clean reference implementation that includes:

Feature

Details

Auto-discovery

Drop .py files into src/tools/, src/prompts/, or src/resources/ — they register automatically

YAML config

Base + environment-specific overrides with env-var substitution

Auth middleware

Bearer token, toggle on/off via config — no code change needed

Graceful shutdown

SIGINT / SIGTERM handlers

Request logging

Correlation IDs, per-request timing, level-aware

Knowledgebase

YAML-backed topic store, live-reloadable without restart

Docker

Dockerfile + docker-compose.yml included

3 example tools

echo_message, greet, calculate

2 KB tools

search_knowledgebase, get_knowledgebase_topic

3 example prompts

general_assistant, task_helper, analysis_mode

3 example resources

capabilities, quick-reference, server info

Related MCP server: mcp-base

Project Structure

├── src/
│   ├── mcp_app.py                      # FastMCP instance — import `mcp` from here
│   ├── server.py                       # Entry point: Starlette app, middleware, routing
│   ├── tools/
│   │   ├── example_tools.py            # echo_message, greet, calculate
│   │   └── knowledgebase_tools.py      # search_knowledgebase, get_knowledgebase_topic
│   ├── prompts/
│   │   └── example_prompts.py          # general_assistant, task_helper, analysis_mode
│   ├── resources/
│   │   ├── help_resources.py           # help://<name>/capabilities, quick-reference
│   │   └── server_info.py              # data://server/info
│   └── utils/
│       └── logging_middleware.py       # HTTP logging with correlation IDs
├── config/
│   ├── config.py                       # Config loader (YAML + env vars)
│   ├── settings.yaml                   # Base configuration
│   ├── settings.dev.yaml               # Overrides for ENV=dev
│   └── settings.prod.yaml              # Overrides for ENV=prod
├── knowledgebase/
│   ├── loader.py                       # Loads topics.yaml (no caching)
│   └── topics.yaml                     # Knowledgebase topic definitions
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
├── .env.example
├── requirements.txt
├── README.md
└── CLAUDE.md

Installation

python -m venv .venv

# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activate

pip install -r requirements.txt

Running Locally

# Default (port 8000, no auth, INFO logging):
python src/server.py

# Development mode (DEBUG logging):
ENV=dev python src/server.py

# Custom port:
MCP_PORT=9000 python src/server.py

# With authentication:
AUTH_ENABLED=true AUTH_TOKEN=my-secret python src/server.py

# Production mode (auth on, WARNING logging):
ENV=prod AUTH_TOKEN=my-secret python src/server.py

Server is available at http://localhost:8000.

Running with Docker

# Build and start:
docker compose up --build

# With auth enabled:
AUTH_ENABLED=true AUTH_TOKEN=my-secret docker compose up --build

# Detached:
docker compose up -d

# Stop:
docker compose down

The container exposes port 8000 (override with MCP_PORT env var for the host port). knowledgebase/topics.yaml is bind-mounted so you can update topics without rebuilding the image.

Configuration

Environment Variables

Variable

Default

Description

ENV

default

Config file selector: default, dev, prod

MCP_PORT

8000

HTTP listen port

AUTH_ENABLED

false

Enable bearer token auth (true / false)

AUTH_TOKEN

Bearer token value (required when auth is enabled)

AUTO_DISCOVER

true

Auto-import all tools / prompts / resources

YAML Configuration

Edit config/settings.yaml for persistent defaults. Copy .env.example to .env for local overrides (never commit .env).

Logging Level

Set logging.level in config/settings.yaml to DEBUG, INFO, WARNING, or ERROR. Override per environment in settings.dev.yaml / settings.prod.yaml.

Authentication

Disabled by default. To enable:

  1. Set AUTH_ENABLED=true env var or security.authentication.enabled: true in YAML

  2. Set AUTH_TOKEN=<your-token> env var or security.authentication.token in YAML

All MCP requests then require:

Authorization: Bearer <your-token>

Health-check paths (/healthz, /health, /version) are always unauthenticated.

How Auto-Discovery Works

On startup src/server.py calls import_submodules() for the tools, resources, and prompts packages. This uses pkgutil.iter_modules() to find every non-private .py file, imports it, and the @mcp.tool() / @mcp.resource() / @mcp.prompt() decorators register with the global mcp instance in src/mcp_app.py.

  • Files starting with _ are skipped automatically — use this to temporarily disable a module.

  • To disable entirely: AUTO_DISCOVER=false, then import modules manually in src/server.py.

How to Add a New Tool

# src/tools/my_tool.py
from mcp_app import mcp

@mcp.tool(name="my_tool", description="Does something useful.")
def my_tool(input: str) -> dict:
    return {"result": input.upper()}

Restart the server — no other changes needed.

How to Add a New Prompt

# src/prompts/my_prompt.py
from mcp_app import mcp

@mcp.prompt(name="my_prompt", description="A focused system prompt.")
def my_prompt(context: str = "") -> str:
    return f"You are a helpful assistant. Context: {context}"

How to Add a New Resource

# src/resources/my_resource.py
from mcp_app import mcp

@mcp.resource("data://my-domain/my-resource")
def my_resource() -> dict:
    return {"data": "your payload here"}

How to Add Knowledgebase Topics

Edit knowledgebase/topics.yamlno server restart needed:

topics:
  my_topic:
    title: "My Topic"
    tags: [example]
    content: |
      Topic content goes here.

How to Test

# Health check:
curl http://localhost:8000/healthz

# Version:
curl http://localhost:8000/version

# With auth:
curl -H "Authorization: Bearer my-secret" http://localhost:8000/healthz

Connect with any MCP-compatible client (Claude Desktop, MCP Inspector, etc.).

Getting Started with AI Agents

This template is designed to be cloned and extended with the help of AI coding agents (Claude Code, Amazon Q, Cursor, etc.).

Claude Code (CLI)

git clone <this-repo> my-mcp-server
cd my-mcp-server
claude

Claude Code automatically reads CLAUDE.md at the project root — no extra setup needed. Just describe what you want to build.

Amazon Q (IDE)

Open the project in your IDE with the Amazon Q plugin installed. The .amazonq/rules/mcp-conventions.md file is auto-loaded into every chat session. Describe what you want to build — Q will follow the template conventions.

Cursor / Windsurf / Other IDEs

Reference the conventions file explicitly:

@CLAUDE.md Build me an MCP server that does X, Y, Z.

Starter Prompts

See STARTER_PROMPTS.md for ready-to-paste prompts you can give any AI agent to scaffold a new MCP server from this template.


FastMCP Notes

Targets FastMCP >= 2.0.0. Key patterns:

Pattern

Where

FastMCP(name="...")

src/mcp_app.py

mcp.http_app(transport="streamable-http")

src/server.py

async with mcp_http_app.lifespan(app)

src/server.py lifespan

@mcp.tool() / @mcp.resource() / @mcp.prompt()

tools / resources / prompts

If you upgrade to a new FastMCP major version, verify these four patterns first. See CLAUDE.md for full architecture details and coding rules.

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aviciot/mcp-template'

If you have feedback or need assistance with the MCP directory API, please join our Discord server