使用说明
MCP BI演示(Postgres+SQLAlchemy+FastMCP+OpenAI)
演示如何通过使用官方Python SDK和SQLAlchemy构建的MCP服务器公开Postgres支持的建筑BI数据集。该堆栈通过Docker Compose运行,并准备好使用 gpt-4.1-mini (或 gpt-4o-mini)模型。
使用Qwen3编码器30b(在Ollama本地运行)可以很好地查询这个简单的数据集。还用GPT-4变体进行了测试。
项目布局
docker-compose.yml # Postgres + MCP server services
.env.example # sample environment (copy to .env)
server/
Dockerfile # Python MCP server container
db_models.py # SQLAlchemy models
db_utils.py # schema/seed helpers and readonly role
mcp_db_server.py # FastMCP server exposing DB tools
app/
Dockerfile # Lightweight chat gateway container
main.py # Minimal FastAPI app that calls OpenAI + MCP
pyproject.toml # Gateway dependencies (FastAPI/OpenAI/Ollama)
建筑
详细的服务地图
flowchart TD
subgraph client[Client / Caller]
user[User / UI]
end
subgraph chat[chat_gateway]
api[FastAPI /app/main.py]
llm["OpenAI SDK"]
end
subgraph mcp[mcp_server]
fastmcp["FastMCP (server/main.py -> mcp_db_server.run_server)"]
tools[get_schema\nrun_sql\nproject_cost_overview\ntop_overruns]
end
pg[(Postgres DB)]
user -->|"HTTP POST /chat"| api
api -->|"LLM call + tool schema"| llm
llm -->|"tool_calls"| api
api -->|"SSE MCP transport"| fastmcp
fastmcp --> tools
tools -->|"SELECT (readonly)"| pg
pg --> tools
tools --> fastmcp
fastmcp --> api
api -->|"LLM finalization"| llm
llm -->|"answer text"| api
api -->|"HTTP response"| user
请求/响应序列
sequenceDiagram
participant U as User
participant G as chat_gateway (FastAPI)
participant L as LLM (OpenAI/Ollama)
participant S as MCP server (FastMCP)
participant D as Postgres
U->>G: POST /chat {question}
G->>S: SSE connect (MCP)
G->>S: initialize + list_tools
G->>S: get_schema (once per request)
G->>L: chat.completions.create(messages+tools)
L-->>G: assistant msg + tool_calls?
alt tool_calls present
G->>S: call_tool (e.g., run_sql)
S->>D: SELECT ...
D-->>S: rows
S-->>G: tool result
G->>L: updated messages + tool outputs
L-->>G: final or more tool calls
end
L-->>G: final answer text
G-->>U: HTTP 200 {answer}
先决条件
- Docker和Docker Compose
快速入门(Docker Compose)
- 复制环境模板并填写机密:
cp .env.example .env
# edit .env to set POSTGRES_* credentials and your OpenAI API key
这 DB_URL_* 值在 .env.example 指向 db,这是Compose网络中的主机名。如果您通过以下方式运行这两个服务,则无需更改 docker compose.
- 构建并启动一切:
docker compose up --build
这 mcp_server 容器将连接到 db,创建/种子表,确保 readonly 角色,并在SSE上公开MCP工具 http://mcp_server:8765/sse (集装箱入口点运行 python mcp_db_server.py 随着 MCP_TRANSPORT=sse).这 chat_gateway 容器通过以下方式指向该URL MCP_SSE_URL.
- 检查日志/快速健全性检查:
docker compose logs -f mcp_server
docker compose exec db psql -U admin -d construction -c "SELECT COUNT(*) FROM projects;"
docker compose exec db psql -U admin -d construction -c "SELECT COUNT(*) FROM cost_items;"
- 将MCP客户端/代理连接到正在运行的容器:
- 使用SSE端点
http://mcp_server:8765/sse在Compose网络内部(或http://localhost:8765/sse如果您在本地公开端口)。服务器告诉客户端在哪里POST消息。
- 完成后停止:
docker compose down
使用聊天网关(LLM+MCP)
- 运行为
chat_gateway旁边db和mcp_server当你docker compose up --build. - 模型提供者(设置在
.env):LLM_PROVIDER=openai(默认):设置OPENAI_API_KEY;OPENAI_MODEL默认为gpt-4.1-mini(针对工具使用和成本效益进行了调整)。通过以下方式覆盖每个请求model.LLM_PROVIDER=ollama:setOLLAMA_BASE_URL(默认值http://host.docker.internal:11434/v1)以及OLLAMA_MODEL(默认值qwen3-coder:30b).OLLAMA_API_KEY如果您的Ollama端点强制执行身份验证,则是可选的。根据请求model覆盖默认值。
- 端点:
POST http://localhost:8000/chatJSON正文:{ "question": "Which projects are over budget?", "model": "gpt-4.1-mini", // optional override "temperature": 0.2 // optional, passed to provider } - MCP传输:需要
MCP_SSE_URL(例如。,http://mcp_server:8765/sse)并使用长寿命MCP容器;没有本地stdio回退。
可用的MCP工具
get_schema():返回表/列元数据和关系。run_sql(query: str, max_rows: int = 1000):执行只读SQL(仅限SELECT,禁止的谓词被阻止,行受限)。project_cost_overview(project_name: str):项目的预算与实际与超支。top_overruns(limit: int = 5, min_overrun_pct: float = 0.05):超过预算阈值的项目。
连接OpenAI代理(高级)
- OpenAI应用程序/代理SDK(推荐): 将您的MCP服务器声明为工具端点(SSE URL),将模型设置为
gpt-4.1-mini(或您的选择),并启用工具调用。 - 带有响应API的自定义脚本: 当模型发出工具调用时,使用MCP Python SDK客户端调用服务器工具。
为您的代理推荐的系统提示代码段:
你是一家建筑公司的商业智能分析师。使用MCP DB工具回答数字问题。切勿尝试修改数据库。
示例工具调用(便于手动测试)
-
获取架构:
python - <<'PY' from db_utils import init_schema_and_seed, get_ro_engine from mcp_db_server import get_schema init_schema_and_seed() print(get_schema()) PY -
运行快速BI查询燃烧率(需要运行Postgres):
python - <<'PY' from mcp_db_server import run_sql sql = """ SELECT project_id, DATE_TRUNC('month', cost_date) AS month, SUM(amount_eur) AS total FROM cost_items GROUP BY project_id, month ORDER BY project_id, month """ print(run_sql(sql, max_rows=20)) PY
安全亮点
- 所有MCP工具都使用
readonlyPostgres用户。 run_sql强制执行仅SELECT查询并阻止常见的变异动词。- 查询结果的上限为
max_rows以避免大的响应。 - 机密(DB凭据、OpenAI密钥)通过以下方式提供
.env而不是承诺。