mcp-server-prod
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-prodShow me all paid orders"
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-prod
A hardened MCP server — because MCP tool arguments are written by an LLM, from untrusted user text. Exposes read-only "orders" tools to an AI agent, and treats every argument as hostile: validated, parameterized, and served over a read-only connection.
Runs offline.
docker compose upruns the security battery with no API key and no network — the standard library only. (The MCP server itself needspip install mcp.)
The problem
An MCP tool signature like search_orders(status: str) looks safe. But status doesn't come from your code — it comes from a model, interpreting whatever a user typed. That's a network boundary wearing a function signature. The naive server everyone writes first concatenates that string into SQL and calls it a day:
sql = f"SELECT * FROM orders WHERE status = '{status}'" # ← LLM-controlledOne status = "paid' OR '1'='1" and the agent just dumped your whole table.
Related MCP server: odoo-mcp-server
Quickstart
docker compose up # security battery: naive vs prod scorecard (offline)
make demo # same, without Docker
make test # the security contract tests (pytest)
make serve # run the actual MCP server over stdio (needs: pip install mcp)The scorecard (before → after)
The same five hostile tool-calls, run against the naive server and this one:
attack | naive | prod |
filter bypass — | 🔴 LEAK | 🟢 SAFE |
table exfil — | 🔴 LEAK | 🟢 SAFE |
numeric injection — | 🔴 LEAK | 🟢 SAFE |
id injection — | 🔴 LEAK | 🟢 SAFE |
write reaches the DB (read-only?) | 🔴 LEAK | 🟢 SAFE |
safely handled | 0 / 5 | 5 / 5 |
Meanwhile legitimate queries are unaffected — search_orders(status="paid") returns the 12 paid orders, revenue_summary("paid") returns {count: 12, total: 25451.24}. Hardening didn't cost functionality.
The three defenses
Validate every argument (
validation.py) —statusmust be an enum member,order_idmust be an integer,limitis clamped to 100. An agent asking for a million rows gets 100; a bad enum is a structured error, not a silent mis-query.Parameterize every query (
tools.py) — user values are bound, never concatenated.customer = "zzz' OR '1'='1"becomes a literal name that matches nobody, not a bypass.Open the database read-only —
file:...?mode=ro. Defense in depth: even a query that slips through cannot mutate data. The write test raises at the driver.
Wire it into a desktop MCP client
{
"mcpServers": {
"orders": { "command": "python", "args": ["-m", "mcp_server_prod.server"] }
}
}Drop that into Claude Desktop's MCP config and the search_orders / get_order / revenue_summary tools appear to the agent. (A short screen recording of that flow makes a good demo GIF — the server code and config here are what it records.)
How it's verified
Security is a contract test suite, not a claim: the production tools must reject or safely handle each hostile input, and the naive implementation must demonstrably leak (so the threat is real, not hypothetical). CI also builds the server against the official mcp SDK. All checks run offline; the battery scorecard is computed from real behavior.
9 passed # pytest
0/5 → 5/5 # security battery
mcp server ok # builds with the official SDKHonest limitations
· Synthetic 20-row SQLite dataset — a demonstrator of the access pattern, not a product.
· Scope is read-only retrieval. A write-capable server needs authЗ, per-tool authorization,
and audit logging (authn/authz) — explicitly out of scope here and called out, not faked.
· The "naive vs prod" contrast is illustrative; it doesn't enumerate every injection class
(no second-order, stored, or ORM-specific vectors).
· Parameterization + read-only defends the data layer; it is not a full threat model
(rate limiting, secrets handling, and prompt-injection of the agent itself are separate).Layout
mcp_server_prod/ db.py · validation.py · tools.py (prod) · naive.py · server.py · demo.py
tests/ test_security.py # the security contract
Dockerfile · docker-compose.yml · .github/workflows/ci.ymlMIT © 2026 Jigon Yoo
This server cannot be installed
Maintenance
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
- 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/jigonyoo/mcp-server-prod'
If you have feedback or need assistance with the MCP directory API, please join our Discord server