Licensing Hardening MCP Server
A deliberately vulnerable MCP server for local authority licensing, designed to demonstrate and fix native MCP weaknesses such as SQL injection and tool poisoning.
README
Harden the local-authority licensing assistant's MCP server
Local authority — licensing team. The assistant answers questions about taxi and premises licences — "is licence 9003 active, and what did the last inspection say?" — so officers don't dig through the case system by hand. This MCP server is how it reaches the licensing database. A colleague "improved" it before they left; it works, it demos cleanly, and it carries every native MCP weakness from this afternoon. Work through it on your own.
Get it running
Plain Python — no Docker, no Git.
pip install -r requirements.txt
python seed.py # builds licensing.db (includes a planted inspection note)
See the attacks land before you fix anything:
python exploit.py # SQL injection + over-exposure of home addresses / DBS status
python poisoning_demo.py # a tool whose DESCRIPTION carries hidden instructions
Your task
Harden server.py so the native attacks fail while legitimate use still works.
Work through them in this order:
- Result injection —
read_inspection_notehands raw note text back to the model. Return it labelled as untrusted data, and rely on a system-prompt rule that labelled data is content, never command. (Licensee 3's note is an instruction to suspend a licence — the note-reader andsuspend_licence, each harmless, compose into a suspension.) - Tool poisoning —
format_reference's description contains hidden instructions. Review every description; a server you do not trust should not reach the model's context. Neutralise it. - Confused deputy —
suspend_licenceis state-changing and unscoped. Put it behind a scope check, and reject any bearer token whoseaudis not this server (the Week 5 discipline). - Inherited — parameterise
find_licenseeand return only the columns the assistant needs (neverhome_address,dbs_status, orinspection_notes). - Audit — append every tool call to a log.
You are done when poisoning_demo.py finds nothing in your descriptions and
exploit.py's payloads are rejected, while a normal find_licensee("Aisha") still
returns a result.
Stretch
- Add a real
audcheck: decode the presented token and refuse a foreign audience. - With two servers connected to one host, how would a malicious second server reach
this one's
suspend_licence? Write down the control that stops it.
Files
| File | Contents |
|---|---|
server.py |
The vulnerable MCP server — the thing you harden. |
seed.py |
Builds licensing.db — the licensees and licences tables. |
exploit.py |
Proves the inherited flaw (SQL injection + over-exposure). |
poisoning_demo.py |
Prints the model-facing descriptions; flags the poisoned one. |
requirements.txt |
fastmcp. |
Questions worth asking yourself
- Which of your fixes are MCP-specific, and which are ordinary secure coding?
- A description you did not write reached your model. Whose job is it to have caught that — the server author, the host, or the person who approved it?
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.