Skip to main content
Glama
aystzh
by aystzh

Business Data MCP

Secure, Auditable Read-only Search · English

一个可接入 Codex / Claude Code 的 Python MCP 服务:查询 PostgreSQL 客户与订单、JSON Mock CRM、Markdown 业务文档,并统一执行权限检查、租户隔离、脱敏和审计。

所有内置业务数据都是虚构数据。项目定位是可复现的本地工程展示,生产边界见 安全说明

架构

flowchart TD
    A[Codex / Claude Code / SDK Client] -->|Streamable HTTP + Bearer Token| B[HTTP 认证]
    B --> C[MCP 策略层:参数校验、Scope、限流、审计]
    C --> D[业务查询服务]
    D --> P[PostgreSQL 只读账号]
    D --> R[Mock CRM JSON]
    D --> F[受控 Markdown 文档]
    P --> E[脱敏 + 来源引用 + 结果大小限制]
    R --> E
    F --> E
    E --> C
    C --> L[JSON Lines 审计]
    C --> A
  • Python 3.12,uv 管理 .venv 和锁定依赖。

  • MCP Python SDK 2.2,支持现代协议及需要初始化握手的客户端。

  • Pydantic 校验,Psycopg 异步连接池,PostgreSQL 17。

  • 四个有类型定义的只读工具,不提供 SQL 执行、任意文件读取、写操作或导出。

Related MCP server: PostgreSQL MCP Server

快速启动

前置条件:Docker Desktop / Docker Engine + Compose、uv。命令均在仓库根目录执行;uv 会使用或下载 Python 3.12。

uv sync --locked
uv run business-data-init
docker compose up -d --wait
uv run business-data-mcp

首次初始化会创建权限为 0600.env.local 凭据文件,不打印密码或 Token,也不覆盖已有凭据。开发 Token 有效期为 30 天。

服务地址:http://127.0.0.1:8000/mcp。PostgreSQL 默认监听本机 5433,使用本项目独立 volume。

在另一个终端进入仓库根目录:

curl http://127.0.0.1:8000/health/ready
uv run business-data-demo

演示脚本依次切换四个身份,调用四个工具,不需要付费模型 API。输出包含脱敏结果、来源和 query_id。若设置了 BUSINESS_DATA_MCP_TOKEN,脚本会仅使用该 Token。

uv run business-data-demo --identity support
uv run business-data-demo --identity pii
uv run business-data-demo --identity tenant-b
uv run business-data-demo --identity restricted

工具

工具

参数

行为

search_customers

query, limit=10

客户名称字面子串或精确客户 ID

get_customer

customer_id

客户资料及获授权的 CRM 摘要

search_orders

order_no, phone, status, date_from, date_to, limit=10

至少一个条件,多个条件使用 AND

search_business_docs

query, limit=10

当前租户文档关键词检索,返回摘录和行号

  • 关键词去除首尾空格后为 2–100 个字符;ID 仅允许字母、数字、下划线和短横线,最长 64 个字符。

  • 条数为整数 1–20;无分页。订单手机号为完整值匹配,状态为 pending / paid / shipped / cancelled

  • 日期使用 YYYY-MM-DD,按 UTC 自然日包含起止日期。

  • 文档按空白分词,全部词命中才返回;按出现次数降序、文档 ID 升序排列。

  • 搜索无结果和访问不到的对象均返回空记录;错误使用 MCP isError,不伪装成空结果。

成功结果示意(structuredContent;文本内容也包含相同数据):

{
  "records": [{
    "customer_id": "C10001",
    "name": "星河科技",
    "phone": "138****8000",
    "source_uris": ["business://tenant-a/customers/C10001"]
  }],
  "sources": [{
    "uri": "business://tenant-a/customers/C10001",
    "source_type": "postgres",
    "label": "C10001",
    "updated_at": "2026-09-14T10:00:00Z"
  }],
  "query_id": "qry_example",
  "notices": ["PII fields are masked."],
  "truncated": false
}

逻辑 URI 是来源标识,不是可直接打开的网址。源信息以各演示数据源提供的更新时间为准。

身份与审计

身份

租户

权限

support

tenant-a

四个工具及 CRM,PII 脱敏

pii

tenant-a

同上,额外允许原始 PII

tenant-b

tenant-b

仅乙租户数据,PII 脱敏

restricted

tenant-a

仅客户查询,省略 CRM,订单和文档拒绝

.local/tokens.json 保存 Token 的 SHA-256 摘要和身份映射;.local/client-tokens.json 保存仅供本地演示的原始 Token。服务启动时加载映射,修改后需要重启。

审计位于 .local/audit.jsonl,通过返回的 ID 查找:

rg 'qry_返回的ID' .local/audit.jsonl

记录开始、结束、身份、租户、工具、条件字段名、条数、耗时和状态;不保存完整查询值或响应正文。认证失败有单独的 request_id。审计不可写时不返回业务数据。

接入 Codex / Claude Code:CLI 与桌面端

以下步骤以 macOS、本地客户端、本地 MCP 服务 为例。在仓库根目录操作,先完成前面的快速启动。客户端的模型账号登录和本服务的 Token 认证彼此独立。

共同准备:确认服务并选择身份

curl -fsS http://127.0.0.1:8000/health/ready

应返回 {"status":"ready"}。若连接失败,在一个终端运行并保持服务不退出:

docker compose up -d --wait
uv run business-data-mcp

在另一个终端进入仓库根目录。CLI 使用下面的环境变量;桌面端使用下文的本地静态请求头,避免依赖终端环境:

export BUSINESS_DATA_MCP_TOKEN="$(uv run python -c 'import json; print(json.load(open(".local/client-tokens.json"))["support"])')"

这个命令不打印 Token。新终端需要重新执行,客户端必须在同一个终端启动。桌面端需要粘贴 Token 时,可在 macOS 执行:

uv run python -c 'import json; print(json.load(open(".local/client-tokens.json"))["support"], end="")' | pbcopy

下文的 PASTE_SUPPORT_TOKEN_HERE 均需替换为剪贴板中的 Token,并保留 Bearer 后的一个空格。真实凭据仅放在本机私有配置,不放入 README、示例文件或 Git。

1. Codex CLI

先确认 codex --version 能运行。如果提示 zsh: command not found: codex,且 macOS 应用包含下面的可执行文件,可执行:

# 先确认文件存在;应用安装位置可能不同。
test -x /Applications/ChatGPT.app/Contents/Resources/codex
export PATH="/Applications/ChatGPT.app/Contents/Resources:$PATH"
codex --version

希望新终端也可用,可将该 export PATH=... 行加入 ~/.zshrc。若本机没有这个文件,按 Codex CLI 官方说明安装 CLI。

加载上面的 Token 环境变量后注册服务:

codex mcp add business-data \
  --url http://127.0.0.1:8000/mcp \
  --bearer-token-env-var BUSINESS_DATA_MCP_TOKEN
codex mcp get business-data
codex

注册只需一次。get 应显示 enabled: truetransport: streamable_http、正确 URL 和环境变量名称;它只验证已保存的配置。进入 Codex 后输入 /mcp 检查连接,再发送下文的验收提示。

2. Codex 桌面端

桌面端与 CLI 在同一 Codex host 上共享 ~/.codex/config.toml,但从 Dock 打开的应用不会自动继承终端里的 export。本地演示采用静态请求头:

  1. 用上面的 pbcopy 命令复制 Token。

  2. 执行 open -e ~/.codex/config.toml 打开配置;若文件不存在,先通过桌面 Settings → MCP servers → Add server 添加名为 business-data 的 Streamable HTTP 服务。

  3. 找到已有的 business-data 段,只替换该段,保留其他服务;不要创建重复段:

[mcp_servers.business-data]
url = "http://127.0.0.1:8000/mcp"
enabled = true
http_headers = { Authorization = "Bearer PASTE_SUPPORT_TOKEN_HERE" }

删除这一服务原来的 bearer_token_env_var 行;如有 env_http_headers 或 header helper 提供 Authorization,也移除冲突项。这样 CLI 也会使用相同的静态 Token,不再需要为这个服务执行 export

  1. 保存后在 Settings → MCP servers 确认已启用,点击 Restart;没有此按钮时完全退出应用后重开。

  2. 打开新的本地对话,输入 /mcp 查看服务并发送验收提示。

参见 Codex MCP 官方文档。本服务使用开发 Bearer Token,不需要点击 OAuth 登录。

3. Claude Code CLI

确认 claude --version 可用,并完成客户端登录。使用共同准备步骤中的 Token,在同一个终端执行:

claude --mcp-config examples/claude.mcp.json --strict-mcp-config

示例配置的内容如下,CLI 会展开环境变量:

{
  "mcpServers": {
    "business-data": {
      "type": "http",
      "url": "http://127.0.0.1:8000/mcp",
      "headers": {
        "Authorization": "Bearer ${BUSINESS_DATA_MCP_TOKEN}"
      }
    }
  }
}

--strict-mcp-config 让本次演示只加载指定文件里的 MCP 服务。进入后输入 /mcp 查看状态,按客户端提示批准工具使用,再发送验收提示。参见 Claude Code MCP 官方文档

4. Claude Code 桌面端(Claude 应用的 Code 标签页)

选择 Code → 本地会话,打开本仓库。Code 标签页可读取项目 .mcp.json。为了从 Dock 启动也能读取 Token,在仓库根目录的 .mcp.json 中设置静态请求头:

{
  "mcpServers": {
    "business-data": {
      "type": "http",
      "url": "http://127.0.0.1:8000/mcp",
      "headers": {
        "Authorization": "Bearer PASTE_SUPPORT_TOKEN_HERE"
      }
    }
  }
}

如果已有 .mcp.json,只合并 mcpServers.business-data,不要覆盖其他服务。本项目已将 .mcp.json 加入 .gitignore;可运行 chmod 600 .mcp.json 限制本机读取权限。不要把这个含真实 Token 的配置复制回 examples/claude.mcp.json

保存后重开本地 Code 会话,按提示信任项目并启用 MCP,发送验收提示。选择原始项目目录;新 worktree 不会自动包含这个被 Git 忽略的配置文件。CLI 的 --mcp-config 参数不会自动传给桌面应用。参见 Claude Code Desktop 官方说明

可选:Claude Desktop 的普通 Chat 标签页

Chat 与 Code 的接入入口不同。不要直接把 http://127.0.0.1:8000/mcp 填进账户级 Add custom connector:该功能从 Anthropic 云端连接,无法访问你的本机回环地址。见 远程连接器网络要求

普通 Chat 可通过本地 stdio → HTTP 桥接器接入当前服务。此方式额外依赖 Node.js / npx 和第三方 mcp-remote,不属于本项目 Python 运行依赖:

  1. 确认 node --versionnpx --version 可用。

  2. 在 Claude 的 Settings → Developer → Edit Config 打开本地配置。macOS 常见位置为 ~/Library/Application Support/Claude/claude_desktop_config.json

  3. 将以下服务合并到 mcpServers,替换 Token:

{
  "mcpServers": {
    "business-data": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "http://127.0.0.1:8000/mcp",
        "--transport", "http-only", "--header", "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer PASTE_SUPPORT_TOKEN_HERE"
      }
    }
  }
}
  1. 完全退出并重开 Claude,在新 Chat 对话中启用工具并发送验收提示。首次启动需下载桥接器;桌面进程必须能找到 Node/npx。如果使用 nvm,配置 commandcommand -v npx 得到的绝对路径,并在 env.PATH 中配置 command -v node 对应目录及系统路径;更新 Node 后检查路径。

以上为配置说明,尚未实际验收 Claude 桌面 Code / Chat 或该桥接器。已验证的客户端和证据见 验收记录

验收提示、身份切换与排错

在任一客户端发送:

请实际调用 business-data 的 get_customer 工具查询 C10001,展示客户资料、CRM 跟进、来源 URI 和 query_id。不要通过终端或本地文件读取数据。

support 的预期结果:星河科技、手机号 138****8000、跟进“已发送产品方案,等待技术评估”,来源包含 business://tenant-a/customers/C10001crm://tenant-a/customers/C10001,以及新生成的 qry_...。用该 ID 在 .local/audit.jsonl 中查找 query_started / query_finished,确认发生了真实调用。

  • 切换身份:CLI 环境变量方案将读取命令中的 support 改为 piitenant-brestricted,退出并重启客户端;静态配置方案替换配置中的 Token 后重新加载。不要重新初始化服务端凭据。

  • 权限验证restricted 查询 ORD-10001 应返回 FORBIDDENpii 查询 C10001 显示完整手机号;tenant-b 查询同一订单返回 cancelled9900.00

  • 401 / 环境变量缺失:检查 Token、过期时间和认证配置来源;桌面端避免依赖终端临时环境。

  • 连接拒绝:检查健康接口和服务进程,确认客户端 URL 与 PORT 一致。

  • 找不到工具:重新加载 MCP 或打开新会话;确认服务启用、项目目录正确、没有同名服务覆盖配置。

  • 远程会话:云端或 SSH 会话的 127.0.0.1 指向执行端,不是本机;本文步骤仅针对本机会话。

自动化验证

make check                 # Ruff + 格式检查 + mypy
make test                  # 单元测试;数据库测试明确跳过
make test-integration      # 全部测试;需要已启动的演示数据库

GitHub Actions 使用独立 PostgreSQL service、同一初始化脚本和锁定依赖运行全套检查。

配置与运行维护

默认配置见 .env.example.env 不提交 Git;进程环境变量优先于 .env

配置

默认值 / 含义

DATABASE_URL

必填,只读账号连接串

TOKEN_FILE / AUDIT_FILE

.local/tokens.json / .local/audit.jsonl

DATA_DIR

data,必须从可信本地目录加载

HOST / PORT

127.0.0.1 / 8000

RATE_LIMIT

每身份每分钟 60 次工具调用

QUERY_TIMEOUT

工具 10 秒,数据库语句另限 5 秒

MAX_RESULT_BYTES

MCP 工具结果最多 65536 字节,含文本和结构化内容

结果超限时去掉完整记录并标记 truncated;单条仍过大返回 RESULT_TOO_LARGE。请求体最多 16 KiB。/health/live 表示进程存活,/health/ready 检查数据库连接。

停止服务用 Ctrl+C,停止数据库用 docker compose stop。普通重启保留数据。

重置数据库会删除本项目演示数据,先停止 MCP 服务再执行:

bash scripts/reset-demo.sh --confirm-delete-demo-data

凭据不会随数据库重置。需要重新生成凭据时,先停止服务,手动备份并移走 .env.local/tokens.json.local/client-tokens.json,再运行初始化并重置数据库;新密码不会自动应用到旧 volume。

常见问题

  • Docker 报 docker-credential-desktop 找不到:在 macOS 终端执行 export PATH="/Applications/Docker.app/Contents/Resources/bin:$PATH",再启动 Compose。

  • 5433 冲突:首次初始化使用 POSTGRES_PORT=55433 uv run business-data-init。已有环境需同步修改 .env 中端口和 DATABASE_URL

  • 8000 冲突:使用 PORT=8001 uv run business-data-mcp,并同步修改客户端地址。

  • 数据库连接失败:检查 docker compose ps;确保应用密码与首次初始化的 volume 一致。

  • 401:检查客户端是否继承 Token 环境变量、Token 是否过期;Token 变更后重启服务和客户端。

  • FORBIDDEN:检查身份 scopes;restricted 的订单拒绝属于预期演示。

  • 远程客户端连接不到:127.0.0.1 只支持同机访问;首版未配置远程 HTTPS 部署。

后续方向

真实 OAuth → PostgreSQL RLS → 真实 CRM → 集中审计与分布式限流 → 应用容器化和部署。

许可证:Apache-2.0

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables read-only access to PostgreSQL databases with multi-tenant support, allowing users to query data, explore schemas, inspect table structures, and view function definitions across different tenant schemas safely.
    55 npm
    1
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides read-only access to PostgreSQL databases with schema inspection, query execution in multiple formats (JSON, CSV, Markdown), and query history tracking with built-in security features.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides secure read-only SQL access to PostgreSQL and ClickHouse databases with built-in safety features like read-only enforcement, timeouts, and managed result files.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables e-commerce clients to query their own analytics data in plain English with strict tenant isolation enforced by the database.
    MIT