MCP工具学习实验室

一个提供六个渐进式场景的MCP(模型上下文协议)工具实验项目,覆盖本地STDIO服务、HTTP服务、Keycloak认证授权、Ollama Agent及SQLite数据安全过滤,帮助开发者掌握AI工具调用与安全边界。

  • by tuxotron
  • Python
  • 混合部署
  • 更新于
在 GitHub 查看 tuxotron/mcp-lab

使用说明

Model Context Protocol Lab (Python + FastMCP)

This lab gives you six progressively more advanced tool and MCP scenarios:

  1. Direct Ollama tool calling without MCP
  2. Local MCP server over STDIO (no network, great for local tools)
  3. HTTP (Streamable HTTP) MCP server without auth
  4. HTTP (Streamable HTTP) MCP server protected by Keycloak (OIDC), with JWT-based authentication + role-based authorization
  5. Ollama agent using tools discovered from the secure MCP server
  6. 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.