tyer-mcp-server
Wraps PigX system business APIs (CRM, SRM) as MCP tools for WeKnora agents, with per-user OAuth authentication that forwards each user's own token to uphold upstream permissions.
README
tyer MCP Server
把 PigX 系统(翌核 CRM、SRM…)的业务接口包装成 MCP 工具,供 WeKnora 智能体调用。
核心是按人鉴权:每个 WeKnora 用户各自 OAuth 授权,本服务原样转发其本人的 上游令牌,权限判定完全交给上游系统。服务侧不写任何权限代码——所以永远不会 和上游的权限模型漂移。
目录结构
tyer_mcp_core/ 共享层:PigX 鉴权 + 响应处理 + 雪花 ID,接新系统时一行不用改
mcp-tyer-crm/ 翌核 CRM :8765 .env + 业务工具
mcp-tyer-srm/ SRM 骨架 :8766 .env + 业务工具(待接入)
tests/ 核心层测试
start-crm.bat 双击启动 CRM
start-srm.bat 双击启动 SRM
start-all.bat 两个一起
启动
双击 start-crm.bat。关闭窗口即停止。
依赖上游先起:MCP 服务启动时不连上游,但首次调用/刷新令牌时需要。 上游没起就授权,会失败。
为什么是两个进程而不是一个
鉴权边界是每个 MCP server 一个:一份 .well-known 元数据、一个上游 IdP、
一个 OAuthProxy。合成一个进程后,第二个系统就没法按人鉴权了。
运维上也更稳:改 SRM 的工具重启进程,不会连累 CRM 的用户重新授权 (实测过——上游重启撞上令牌刷新会清空授权)。
接一个新的 PigX 系统
- 在该系统的 PigX 里注册 OAuth2 客户端(照抄 CRM 的
weknora-mcp,改回调端口):authorizedGrantTypes authorization_code,refresh_token web_server_redirect_uri http://127.0.0.1:<本服务端口>/auth/callback scope server autoapprove true additional_information {"enc_flag":"1","captcha_flag":"0"} - 复制
mcp-tyer-srm/改名,改.env(端口、前缀、端点) - 写业务工具——只需要写这部分
- 在 WeKnora 里加一个 MCP 服务,认证方式选 OAuth 2.0,用户各自授权
踩过的坑(都已固化进代码,接新系统不用再踩)
| 坑 | 现象 | 解法 |
|---|---|---|
| PigX 不支持 RFC 7591 DCR | WeKnora 无法完成 OAuth | OAuthProxy 桥接 |
check_token 不合规 RFC 7662 |
授权成功但调用 401 | 改用 /user/info 验令牌 |
| OAuth 端点与登录页跨源 | 登录后跳到 {"code":1,"msg":"No static resource ."} |
端点必须与登录页同源 |
前端 vite changeOrigin: true |
同上(Host 被改写) | 改成 false |
| 雪花 ID 经 JSON 数字传递 | 报「不存在或无权访问」,看起来像权限问题 | ID 全程 str,用 as_id() |
| 业务异常是 HTTP 500 + code=1 | 业务提示被压成一句 "HTTP 500" | 按 code 判成败 |
| 「不存在或无权访问」 | — | 防 ID 探测的含糊语义,按空结果返回不抛异常 |
| 上游重启撞上令牌刷新 | 全部用户授权被清空 | ResilientOAuthProxy 区分连接错误与授权失效 |
雪花 ID 那条用演示数据(id=1)测不出来,必须拿真实的 19 位 ID 验证。
加了工具之后
改完 server.py 重启服务还不够:WeKnora 缓存着 MCP 连接,ListTools 返回旧列表。
必须去 WeKnora → 设置 → MCP 服务 → 点「测试连接」 强制重连。
不做这一步的表现是「模型调用一个不存在的工具」,很容易误判成模型的问题。
越权复验
CRM 里留了只读测试账号 test_agent_ro(迁移脚本 2026-08-05-agent-readonly-testuser.sql)。
每次新增工具接口后用它复验一遍:同一个 Agent、同样的问题,低权限账号应当
查不到高权限才能看的数据。
切换账号前要先登出上游会话,否则 /oauth2/authorize 看到已登录会直接发码、不弹登录页:
http://127.0.0.1:9999/admin/oauth2/logout
已验证(2026-08-06):sales01 能查自己名下的 5 个客户、查不到 admin 的 6 个;
未授权接口返回 403。MCP 侧零权限代码。
扩展点:将来要同时支持 API Key 调用
当前鉴权是互斥的:build_auth() 里 OAuth 优先,配齐了就完全不看 MCP_API_KEY。
这是故意的——两者若能同时生效,OAuth 一出问题就会悄悄退回共用服务账号,
不报错、没人发现,按人鉴权名存实亡。
什么时候需要改:出现非 WeKnora 的调用方,且它不支持 OAuth。 典型是定时任务、别的后端系统直接调这些工具。在那之前不要动。
要改两处,都是单点:
-
auth.py的build_auth()换成MultiAuth(server=ResilientOAuthProxy(...), verifiers=[StaticTokenVerifier(...)])。FastMCP 的文档场景就是 "OAuth proxy for interactive clients + verifier for machine-to-machine"。 -
client.py的_bearer()必须加分流,否则会出错: OAuth 模式下它拿get_access_token().token转发给上游,而 API Key 进来的 调用方,那个 token 就是MCP_API_KEY本身——它不是 PigX 令牌,转发过去 只会得到 424。要靠client_id或 scope 区分来路:API Key 那条走cfg.fallback_token(服务账号),OAuth 那条走用户本人令牌。
别只改第一处。只加 MultiAuth 不改 _bearer(),机器调用会以一种很难懂的
方式失败(授权明明通过了,取数却报凭证过期)。
安全说明
- 服务默认监听
127.0.0.1,无 HTTPS。要绑0.0.0.0或放内网前,先加 TLS。 .env已被 gitignore,不要提交真实凭据。- WeKnora 侧需要
SSRF_WHITELIST_EXTRA=127.0.0.1,...,否则保存 MCP 服务时会被 安全校验拦下。生产环境应只放行具体主机,不要放行回环地址。 - 将来接入写操作接口时,务必在 WeKnora 的 MCP 服务里打开对应工具的 **「需人工审核」**开关。
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.