mcp-server-template
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-server-templateAdd a tool that cancels an order with a timeout and retryable errors."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-server-template
A production-shaped starting point for an MCP server.
The quickstart in the MCP docs gets you a working tool in ten lines. This is what you end up adding over the following three weeks, once that tool is being called by something you do not control.
@mcp.tool()
def add(a: int, b: int) -> int:
return a + b # fine on a laptopWhat is missing there is not features. It is what happens when the tool hangs, raises, returns a novel, or gets called forty times at once — and what the model is allowed to see when it does.
The problem this solves
An MCP tool's caller is a language model, which changes the engineering.
A model cannot read a stack trace, but it will cheerfully repeat one to your user. So a leaked traceback is both useless and a disclosure.
A model has its own deadline. A tool that hangs does not produce a slow answer; it produces a dead conversation.
A model cannot tell a truncated result from a complete one. Silently overflowing its context does not raise an error — it degrades the answer, and you find out from a customer.
A model will retry if you let it. So "not found" and "upstream is down" have to be different answers, or it will hammer a service over a record that was never there.
Every one of those is handled once, in one place, so that a tool added on a Friday afternoon inherits the same protections as the one written carefully on day one.
Related MCP server: Graft
What you get
Per-tool timeout | Real cancellation, not a warning afterwards. Returns a |
Concurrency ceiling | Bounded parallel execution, so a burst cannot stampede whatever your tools call |
Error boundary | Declared errors reach the caller; unexpected ones become |
Secret redaction | Applied to logs and outbound messages, because keys escape through interpolated exception strings more often than through code |
Visible truncation | Oversized results are cut with a marker, never silently |
Correlation ids | One id per call, in the log and in the error the user can quote back to you |
Structured logs on stderr | stdout belongs to the protocol — a stray |
Fail-fast config | Bad settings stop the server at boot, not on the first request |
Offline tests | The suite runs on a train. No live keys, no network |
Quickstart
git clone https://github.com/muhammadwaqasmbd/mcp-server-template
cd mcp-server-template
make install
make test
make run # stdio, ready for a desktop MCP clientServe it over the network instead:
TRANSPORT=streamable-http PORT=8000 python -m mcp_server_templatePoint a desktop client at it
{
"mcpServers": {
"template": {
"command": "python",
"args": ["-m", "mcp_server_template"],
"cwd": "/absolute/path/to/mcp-server-template"
}
}
}Adding your own tool
Write the function. Nothing else.
# src/mcp_server_template/tools/orders.py
from ..errors import InvalidInput, UpstreamUnavailable
async def cancel_order(order_id: str) -> dict:
"""Cancel an order. Returns the order's new state."""
if not order_id.strip():
raise InvalidInput("order_id must not be empty") # model can fix this
...
raise UpstreamUnavailable("order service timed out") # model may retryRegister it behind the guard:
mcp.tool(name="cancel_order", description="Cancel an order by id.")(
guard.wrap(orders.cancel_order)
)It now has the timeout, the ceiling, the error boundary, the truncation and the logging. You wrote none of that.
Raise InvalidInput when the model can fix it. Raise UpstreamUnavailable
when retrying might work. Return normally for outcomes that are simply false —
a missing record is an answer, not a failure.
Architecture
server.py the ONLY module that imports the MCP SDK
│
├── guard.py timeout · concurrency · error boundary · truncation · timing
├── errors.py what a model is allowed to see, and secret redaction
├── observability.py JSON logs on stderr, correlation ids
├── config.py validated once at boot, immutable thereafter
└── tools/ plain functions. No protocol knowledge. No decoratorsThe dependency arrow points one way: tools know nothing about MCP, and the guard knows nothing about your tools. That is why the tests run in milliseconds without a server, and why an SDK change touches exactly one file.
What this deliberately does not do
Being honest about the edges is more useful than a longer feature list.
No authentication. Over stdio the OS boundary is the security boundary. If you expose it over HTTP, put real auth in front — the SDK supports it, and wiring it here would imply a threat model you have not chosen yet.
No retry logic inside tools. The guard reports whether a failure is retryable; deciding to retry belongs to the caller, which has the context and the budget.
No rate limiting per caller. The concurrency ceiling bounds total work, not per-identity fairness. If you need that, you need identity first.
No persistence, queue or scheduler. A tool server that quietly became a job runner is a distributed system nobody designed.
No streaming partial results. Worth adding for long-running tools; left out because it complicates the error boundary and most tools do not need it.
Testing
make testThe suite is deliberately about failure, not coverage. It asserts that a hung tool is cancelled, that an unexpected exception cannot leak its message, that oversized output is truncated visibly, that the concurrency ceiling holds under ten simultaneous calls, and that a blocking sync tool does not starve the event loop.
Licence
MIT — see LICENSE.
Built by Muhammad Waqas, who spends most of his time on agent systems in regulated industries, where a confident wrong answer is a reportable incident.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceA production-grade, extensible Python template for building Model Context Protocol servers with support for Streamable HTTP and stdio transports. It provides a structured framework for implementing tools, resources, and prompts with built-in authentication, observability, and background task management.11MIT
- AlicenseNot gradedqualityCmaintenanceEnables building agent-ready APIs that expose tools as both HTTP and MCP endpoints from a single server definition, with automatic OpenAPI, discovery docs, and interactive API reference.5Apache 2.0
- AlicenseNot gradedqualityDmaintenanceA production-grade MCP server designed for multi-tenant, authenticated, and observable AI agent systems, enabling secure tool execution across heterogeneous data sources.57MIT
- AlicenseAqualityCmaintenanceA production-ready foundation for building secure, observable MCP servers with built-in authentication, rate limiting, and reference tools like database-query and semantic-search.1578MIT
Related MCP Connectors
Hosted MCP server for LLM cost estimation, model comparison, and budget-aware routing.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
An MCP server for Arcjet - the runtime security platform that ships with your AI code.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/muhammadwaqasmbd/mcp-server-template'
If you have feedback or need assistance with the MCP directory API, please join our Discord server