tyer-mcp-server

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.

Category
Visit Server

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 系统

  1. 在该系统的 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"}
    
  2. 复制 mcp-tyer-srm/ 改名,改 .env(端口、前缀、端点)
  3. 写业务工具——只需要写这部分
  4. 在 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。 典型是定时任务、别的后端系统直接调这些工具。在那之前不要动

要改两处,都是单点

  1. auth.pybuild_auth() 换成 MultiAuth(server=ResilientOAuthProxy(...), verifiers=[StaticTokenVerifier(...)])。FastMCP 的文档场景就是 "OAuth proxy for interactive clients + verifier for machine-to-machine"。

  2. 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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured