yourco-mcp
yourco-mcp — 面向 AI Registry 的 MCP SDK
构建一个 MCP 服务器,其工具元数据存放在 AI Registry 中,并在运行时热重载。你只需编写处理函数;其余一切——描述、schema、受众、按工具划分的 scope、暴露方式——都由管理员在 registry UI 中管理,并在毫秒级时间内到达正在运行的服务器,无需重新部署。
Registry (control plane) Your server (data plane, this SDK)
admins edit metadata ──push──▶ in-memory manifest ──▶ answers MCP calls
UI / RBAC / versions your handlers ──▶ your business logic你的服务器永远不会因 registry 而阻塞:所有 MCP 流量都从内存中提供,即使 registry 宕机,你的服务器也能继续运行(参见「韧性」)。
安装
pip install "yourco-mcp[server,redis] @ git+https://github.com/amitmohapatra/mcp-sdk.git"在生产环境固定一个 tag(...mcp-sdk.git@v0.1.0)。可选依赖:server 附带 uvicorn 以支持 server.run();redis 启用 Redis pub/sub(生产环境推荐——没有它时 SDK 会自动回退到 registry 的 SSE 流)。
Related MCP server: dynamic-mcp
快速开始——完整集成
import os
from yourco_mcp import ProductServer
server = ProductServer(
registry_url="https://registry.yourco.com",
product_key="billing", # your product's key in the registry
api_key=os.environ["REGISTRY_API_KEY"], # issued in the UI: Manage -> SDK API keys
)
@server.tool("get_invoice") # bound by NAME — metadata comes from the registry
async def get_invoice(ctx, invoice_id: str, max_results: int = 100):
return {"invoice_id": invoice_id, "max_results": max_results}
if __name__ == "__main__":
server.run(port=8080) # stateless MCP over HTTP at POST /mcp注意缺失了什么:没有描述、没有 JSON schema、没有 Redis 配置、没有认证样板代码。registry 拥有元数据;你的代码拥有行为。如果 registry 列出了某个你没有对应处理函数的工具,它会从 tools/list 中被排除并给出警告(故障安全,绝不故障崩溃)。
认证——你拥有身份,SDK 负责执行
每个产品为自己的工具处理认证。 SDK 永远不会看到你的密码、密钥或令牌格式——你只需实现一个方法:传入 headers,返回 user。
from yourco_mcp import ProductServer, AuthProvider, AuthUser
class MyProductAuth(AuthProvider):
async def authenticate(self, headers) -> AuthUser | None:
token = headers.get("authorization", "").removeprefix("Bearer ")
claims = my_jwt_verify(token) # YOUR auth: your JWT lib, your OAuth
if not claims: # introspection, your session store
return None
return AuthUser(id=claims["sub"], scopes=claims.get("scopes", []))
server = ProductServer(..., auth=MyProductAuth())普通的 async def fn(headers) -> AuthUser | None 也可以。
框架的职责止于接口。 authenticate 内部发生什么完全是你自己的业务逻辑——Firebase、Auth0、Keycloak、你自己的 JWT 签发器、会话表、mTLS、LDAP,任何方案都可以。SDK 从不导入、捆绑或偏向任何身份系统;它只消费你返回的 AuthUser。下面的示例恰好使用 Firebase,纯粹是为了说明:
import asyncio
import firebase_admin
from firebase_admin import auth as fb_auth
from yourco_mcp import AuthProvider, AuthUser
firebase_admin.initialize_app() # your service account creds
class FirebaseAuth(AuthProvider):
async def authenticate(self, headers) -> AuthUser | None:
token = headers.get("authorization", "").removeprefix("Bearer ").strip()
try: # verify_id_token is blocking:
decoded = await asyncio.to_thread(fb_auth.verify_id_token, token)
except Exception:
return None
roles = await my_db.fetch_roles(decoded["uid"]) # YOUR roles table
return AuthUser(id=decoded["uid"],
scopes=[f"role:{r}" for r in roles], # roles become scopes
claims=decoded)然后在装饰器上按工具要求角色:
@server.tool("refund_payment", scopes=["role:finance-admin"])
async def refund_payment(ctx, payment_id: str, amount: float): ...代码声明的 scopes 与 registry 设置的 required_scopes 以并集方式强制执行——任何一方都可以收紧工具,但任何一方都不能放宽另一方。内置提供者:ApiKeyAuthProvider({key: {...}})、StaticTokenProvider({token: {...}}) 和 NoAuth()——这是对真正开放服务器的显式退出选项(任何东西都不会意外开放)。
一句话概括契约: 发现始终公开;执行的一切都是你产品可插拔的选择。
tools/list(以及 initialize/ping)永远不需要认证——这是一个不变量,而非默认值。网关和目录(例如 Bifrost)可以在零凭据的情况下枚举每个产品的工具。匿名调用者看到的是默认受众的视图。认证是可插拔的:你的
AuthProvider——或者对完全开放的服务器使用NoAuth()(这是一个显式选择,绝非意外)。授权是可插拔的:你的 scopes 由你的认证系统签发,按工具与 registry 设置的
required_scopes进行校验,再加上你的@server.authorize钩子来处理 scopes 无法表达的任何情况。按工具的执行认证由你决定:
@server.tool("ping", public=True) # executes without auth
async def ping(ctx): ...
@server.tool("refund_payment") # gated (the default)
async def refund(ctx, payment_id: str): ...安全规则:如果管理员在 registry 中为某个工具附加了 required_scopes,那么即使代码将其标记为公开,仍然需要认证——运行时收紧始终优先;代码侧的退出选项永远不能覆盖它。
一旦你的验证器就位,SDK 就会强制执行——你无需编写以下任何内容:
层级 | 行为 | 你的配置方式… |
默认策略 |
| 从不(或替换为 |
受众授权 | 仅当用户的 scopes 包含 | 通过你的认证系统签发的 scopes |
按工具 scopes | registry 中带有 | 在 registry UI 中 |
业务规则 | scope 检查之后的任意代码检查 |
|
@server.authorize
async def gate(user, tool, args) -> bool:
return not (tool == "refund_payment" and args["amount"] > 10_000
and "payments:admin" not in user.scopes)公司 scope 约定(全组织统一一次):
audience:<key>— 授予某个受众(例如内部代理使用audience:internal)<domain>:<action>— 管理员在 registry 中设置的按工具要求(例如payments:write、invoices:read)
受众、隐藏参数、固定值
管理员可以按受众(例如 external 与 internal)以不同方式暴露同一个工具:不同的描述、额外的仅内部参数,或者对某个受众隐藏的参数,改为向你的处理函数发送固定值——调用者永远无法看到或覆盖它。你的处理函数只需用默认值声明该参数;SDK 会根据调用者的受众 schema 校验参数、剥离未知参数,并在你的代码运行之前注入固定值。
@server.tool("charge_card")
async def charge_card(ctx, card_id: str, amount: float, currency: str = "USD"):
# external callers can't even see `currency` — the SDK always passes the
# admin-fixed value; internal callers control it. ctx.audience tells you which.
...ctx 为你提供 ctx.user(即 AuthUser)、ctx.audience 和 ctx.tool。
实时更新——registry 的保存如何到达你的服务器
管理员在 registry 中保存 → 一个事务递增产品的序列号,并发布携带已解析视图的事件。
你的服务器(自启动起即订阅——如果你的产品配置了 Redis 则使用 Redis,否则使用 registry 的 SSE 流;manifest 会告诉 SDK 使用哪种方式)接收该事件。
序列检查:按顺序的下一个 → 作为原子 manifest 交换应用;过期 → 忽略;有缺口 → 完全重新获取并协调。收敛是有保证的。
下一次
tools/list/tools/call将提供新的元数据。典型延迟:个位数毫秒(Redis)到几百毫秒(SSE)。
韧性
Registry 宕机 → 你的服务器继续从内存提供服务,包括最新应用的更新。registry 是控制平面,绝不是运行时依赖。
Registry 宕机时的冷启动 → 从 SDK 自动维护的最近一次良好快照提供服务(缓存在
~/.cache/yourco-mcp/下;如果你的运行时需要,可以用YOURCO_MCP_CACHE_DIR覆盖该位置)。Pub/sub 中断 → 自动回退到廉价的带指数退避的条件轮询(ETag/304),同时持续尝试重新订阅——更新持续流动,只是慢几秒。
错误/格式损坏的更新 → 记录日志、忽略、重新同步;完好的 manifest 永远不会被损坏的 manifest 替换。
无状态 HTTP → 在任何负载均衡器后面运行 N 个副本;无需粘性会话。
新产品团队检查清单
请 registry 管理员将你的产品接入并给你一个 API key。
pip install(见上文),在部署环境中设置REGISTRY_API_KEY。为你产品拥有的工具编写处理函数(名称必须与 registry 匹配)。
将你现有的认证接入一个
AuthProvider.authenticate方法。决定你的哪些令牌携带
audience:*scopes(内部代理等)。server.run()— 用curl localhost:8080/healthz和 MCPtools/list验证。在 registry UI 中编辑一个描述,然后观察它实时变化。
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
One OAuth connector for your team's remote MCP servers, with Tool Packs, guardrails and logs.
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
MCP registry & directory: search, find & install 31k+ MCP servers & tools. Catalog and marketplace.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA flexible, extensible framework for building MCP servers with API key authentication, user management, and dynamic tool sharing.7 npm11MIT
- AlicenseBqualityCmaintenanceDynamic MCP server for Node.js enabling runtime tool creation, management, and execution in isolated sandboxes (Docker or Node).88 npm1MIT
- FlicenseNot gradedqualityDmaintenanceA universal MCP server for registering internal, external, and OpenAPI-based APIs as MCP tools. It exposes them to MCP clients via Streamable HTTP and provides admin portal, RBAC/session auth, credential injection, and audit logging.-
- AlicenseNot gradedqualityBmaintenanceProvides a reusable MCP server foundation with explicit tool registration, operation-mode separation, scope-based permissions, structured results, and built-in health/status tools.MIT