使用说明
Model Context Protocol Lab (Python + FastMCP)
This lab gives you six progressively more advanced tool and MCP scenarios:
- Direct Ollama tool calling without MCP
- Local MCP server over STDIO (no network, great for local tools)
- HTTP (Streamable HTTP) MCP server without auth
- HTTP (Streamable HTTP) MCP server protected by Keycloak (OIDC), with JWT-based authentication + role-based authorization
- Ollama agent using tools discovered from the secure MCP server
- SQLite data authorization: vulnerable LLM-side filtering versus secure tool-side filtering
Teaching Infographics
Open lab_concepts.html in a browser to view the five scenario infographics. The individual SVG files are in assets/images/infographic0.svg through assets/images/infographic4.svg.
🚀 Quick Start
For each scenario, run the following:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
0) In the beginning there were tools
cd scenario0
source .venv/bin/activate
python app.py
1) Local MCP server over STDIO
Run server (stdio is default):
cd scenario1
source .venv/bin/activate
python server_stdio.py
In a separate terminal, run the simple test client:
cd scenario1
source .venv/bin/activate
python client_stdio.py
2) HTTP (Streamable HTTP) server (no auth)
Start server:
cd scenario2
source .venv/bin/activate
python server_http.py
# default: http://127.0.0.1:8000/mcp
Test with client:
cd scenario2
source .venv/bin/activate
python scenario2/client_http.py
3) HTTP (Streamable HTTP) server with Keycloak authn/z
Start Keycloak
cd scenario3/keycloak
docker compose up -d
# Admin console: http://localhost:8080 (admin/admin)
# Realm: mcp-lab, Client: mcp-client (public), Roles: mcp-user, mcp-admin
# Users: alice (mcp-user), bob (mcp-admin) – password for both: password
Go to mcp-lab realm. Menu: Client Scopes. Select roles from the list, click on the Mappers tab, select realm roles, turn on Add to ID token. Save!
Run secure MCP server
# back to root
cd scenario3
source .venv/bin/activate
python server_http_keycloak.py
# default: http://127.0.0.1:9000/mcp
Call with a token (client)
cd scenario3
source .venv/bin/activate
python client_http_keycloak.py --username alice --password password # has role mcp-user
python client_http_keycloak.py --username bob --password password # has role mcp-admin
4) Ollama tools calling
Start Keycloak and MCP server from scenario 3
cd scenario4
source .venv/bin/activate
Adjust the OLLAMA_HOST and OLLAMA_MODEL constants in client-ollama.py:
# ----------------------------
# Ollama configuration
# ----------------------------
OLLAMA_HOST = "http://127.0.0.1:11434"
OLLAMA_MODEL = "qwen3-vl:235b-cloud"
Then you could make a call like:
python client-ollama.py --username bob --password password --prompt "Who am I according to the server? Then say hello"
You should see something similar to:
Got token...
Discovered MCP tools: ['whoami', 'admin_only_demo', 'hello']
[agent] Calling tool: whoami({})
[agent] Calling tool: hello({})
agent> <think>
...
...
</think>
The server identifies itself as part of the "mcp-secure" service using Keycloak authentication.
Hello, bob!
We can try with Alice as well:
python client-ollama.py --username alice --password password --prompt "Who am I according to the server? Then say hello"
You should see something like:
Discovered MCP tools: ['whoami', 'admin_only_demo', 'hello']
[agent] Calling tool: whoami({})
[agent] Calling tool: hello({})
agent> <think>
...
...
</think>
The server identifies itself as `mcp-secure` with authentication via `keycloak`.
Hello, alice! How can I assist you today?
5) Never use the LLM as a data authorization boundary
This scenario uses authenticated MCP tools and a local SQLite database to compare:
- a vulnerable tool that returns every user's records and asks the LLM to filter them;
- a fixed tool that derives the caller from the verified token and filters in SQL.
See scenario5/README.md for the walkthrough, adversarial
prompt demo, and tests.