Skip to main content
Glama
mcp-server-template

mcp-server-template

by JustFady

mcp-server-template

A starting point for MCP servers that are going in front of real users, not just a demo. Clone it, replace the three example tools with your product's operations, and you already have:

  • Bearer-token auth on the HTTP transport (MCP_TOKENS="alice:token1,bob:token2"), constant-time compare, 401 + WWW-Authenticate on failure

  • Per-client rate limits (sliding window per token, 429 + Retry-After) and a process-wide tool budget as defense in depth

  • Host allow-list (the SDK's DNS-rebinding protection, configured instead of disabled)

  • Structured call logging: one JSON line per request with method, tool, duration, outcome

  • stdio and Streamable HTTP from the same code (mcp-template stdio / mcp-template http)

  • Tests that run without a network (Starlette TestClient against the real transport), CI on Linux and macOS, a Dockerfile that runs as non-root

  • Tool docstrings written for the model, and a swappable Backend class so tests never touch your real API

Built on the official Python SDK (mcp 2.x, MCPServer).

Quickstart

git clone https://github.com/JustFady/mcp-server-template my-server && cd my-server
uv venv && uv pip install -e ".[dev]"
.venv/bin/python -m pytest -q

# local, for Claude Desktop / Claude Code / Cursor
.venv/bin/mcp-template stdio

# network
MCP_TOKENS="alice:$(openssl rand -hex 24)" .venv/bin/mcp-template http --host 0.0.0.0 --port 8000 --rate 60
curl -s localhost:8000/healthz

Claude Code: claude mcp add my-server -- /path/to/.venv/bin/mcp-template stdio

Claude Desktop (claude_desktop_config.json):

{ "mcpServers": { "my-server": { "command": "/path/to/.venv/bin/mcp-template", "args": ["stdio"] } } }

Remote clients connect to https://your-host/mcp with Authorization: Bearer <token>. Set the public hostname so the SDK's DNS-rebinding protection accepts it: --allowed-host mcp.example.com (repeatable) or MCP_ALLOWED_HOSTS=mcp.example.com,mcp.example.com:443. Unknown Host headers are rejected (421 from the SDK middleware; some servers surface it as 400).

Related MCP server: Python MCP Server Kit

Adapting it to your product

  1. src/mcp_template/server.py: replace Backend with your API client and the example tools with 5–10 operations your users actually ask for. Keep return values small and structured; the model reads them every call.

  2. Write each docstring as instructions to the model: what it does, when to use it, what it returns, what it must not be used for.

  3. tests/: fake the backend; assert tool names, descriptions and error behavior.

  4. Decide limits: --rate per client per minute; GlobalToolBudget per process.

  5. Put it behind TLS (a reverse proxy or your platform's ingress). Rotate tokens by editing MCP_TOKENS and restarting.

Layout

src/mcp_template/
  server.py      tools + build_server()
  http.py        BearerAuth ASGI middleware, make_app()
  middleware.py  call_logger, GlobalToolBudget (MCP-level middleware)
  ratelimit.py   SlidingWindow
  __main__.py    CLI
tests/           ratelimit, server, http (real transport via TestClient)
Dockerfile, .github/workflows/ci.yml

Docker

docker build -t my-mcp .
docker run --rm -p 8000:8000 -e MCP_TOKENS="alice:changeme" my-mcp

Why not OAuth?

For a server you operate for a known set of clients, static bearer tokens over TLS are simpler to run and to audit. The SDK supports full OAuth (AuthSettings + a TokenVerifier) when you need third-party clients to self-register; this template leaves that door open rather than making you walk through it on day one.

License

MIT © Fady Youssef

Available Tools

3 tools
addA

Add two numbers and return {"sum": a + b}. Use for arithmetic the model should not do mentally.

NameRequiredDescriptionDefault
aYes
bYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose the operation and its output shape ('return {"sum": a + b}'). For a stateless pure computation that is nearly the whole behavioral picture; it omits only edge-case behavior such as float precision or overflow.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the operation before the usage note. The explicit return shape is mildly redundant given an output schema exists, but it costs little and reads cleanly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A 2-parameter, side-effect-free tool with an output schema needs little more than this; the return value need not be re-explained. Completeness would be perfect with a one-line note on precision or input domain (e.g., decimals vs integers).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% (params a and b have only titles), so the description must compensate, and 'a + b' does map both parameters to their role as numeric addends. It doesn't restate types, which the schema already carries via "type": "number".

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Add two numbers') and the exact result, with zero ambiguity. The sibling tools (lookup, store) are unrelated, so no differentiation is needed and none is possible to confuse.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Use for arithmetic the model should not do mentally" gives a clear condition for selecting this tool over doing the work inline. It stops short of explicit exclusions (e.g., large integers, floating-point precision caveats), but the intent is unmistakable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookupA

Read the value stored under key. Returns {"key", "value", "found"}; never raises for a missing key.

NameRequiredDescriptionDefault
keyYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the burden and does disclose a genuine behavioral trait: it never raises for a missing key, signalling that callers should inspect a flag rather than catch exceptions. It also enumerates the returned fields, though the meaning of `found` is only implied rather than spelled out.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short clauses, purpose first and the behavioral caveat second, with no filler. Every element — verb, resource, return shape, missing-key behavior — earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool with an output schema, the description covers what it does, what comes back, and the key edge case. Minor gaps remain around key formatting and whether lookups are scoped to any namespace, but nothing critical to a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate for the single undocumented `key` parameter. Saying the value is stored 'under `key`' establishes that it is the lookup identifier, but gives no format, casing, namespace, or examples that would help an agent construct a valid key.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

A specific verb plus resource ('Read the value stored under `key`') that makes the read-only nature unambiguous, implicitly separating it from the write-side siblings `store` and `add`. It does not name those siblings explicitly, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by 'Read the value stored under `key`' — an agent understands this is the retrieval path — but there is no explicit when-to-use versus `store`/`add`, nor any stated precondition. The only guidance is behavioral (missing keys do not raise), which is not a selection rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

storeA

Store value under key, overwriting any previous value. Keys are case-sensitive and max 64 chars.

NameRequiredDescriptionDefault
keyYes
valueYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose key overwrite semantics and key constraints (case sensitivity, 64-char max). It does not mention error behavior or persistence guarantees, leaving meaningful behavioral gaps for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences that front-load the core operation and then add the critical overwrite and key-length caveats. No sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and has an output schema, so return values need not be explained. The description covers overwrite behavior and key constraints, though it could say more about what happens when the key is missing or invalid.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds useful meaning for the key parameter (case-sensitive, max 64 chars) but says nothing about constraints or handling for the value parameter beyond the verb 'store'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb (store) and names both resources (key and value), making the operation unambiguous. It does not explicitly distinguish itself from sibling tools like add or lookup, which is the only thing keeping it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The overwrite behavior implies this is a set-style operation rather than an append-style one, which gives some implicit usage guidance. However, it never names the alternative tools or states when to prefer this over add or lookup, so the agent must infer the choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.0
    • First observedadd
    • First observedlookup
    • First observedstore

TDQS

A3.9/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct role: add performs arithmetic, lookup reads a key, and store writes a key. There is no overlap between read and write operations, and the descriptions make the boundaries obvious.

Naming Consistency4/5

All three names are simple lowercase verbs, which is readable and consistent in style. However, they do not follow a predictable verb_noun pattern such as get_value/set_value, so the convention is only mostly consistent.

Tool Count5/5

Three tools is a small, well-scoped surface for a template server. Each tool has a clear purpose, and none feels redundant or excessive.

Completeness3/5

The key-value portion covers read and write/update, but there is no delete or list-keys operation, leaving notable lifecycle gaps. The arithmetic tool is complete for its narrow purpose but is unrelated to the storage domain.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to securely discover, execute, and observe tools with role-based access control and audit logging. Serves tools over MCP stdio and HTTP for integration with Claude Desktop, Cursor, and other clients.
    1
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables developers to build and deploy secure, typed Model Context Protocol servers with tools, resources, prompts, bearer-token authentication, per-tool scopes, rate limiting, and health probes over Streamable HTTP.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables secure exposure of internal tools to LLM clients with API-key authentication, tenant isolation, per-tool guardrails, PII scrubbing, rate limiting, audit logging, and telemetry over stdio and HTTP/SSE.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to call backend tools under per-agent policy, deciding which tools each agent can see, what arguments it may pass, how often it may call, and which writes wait for human approval. It also redacts secrets and PII from tool results, fences untrusted output against injection, and records every call in a hash-chained audit log.
    4 npm
    MIT