Skip to main content

Uno OAuth MCP

Python 3.10+ PyPI License: MIT

让 MCP Server 快速接入 mcpmarket.cn OAuth 认证。

✨ 特性

  • 🔐 开箱即用 - 几行代码接入 OAuth 认证
  • 🎯 双模式支持 - FastMCP(简洁)和 底层 Server(灵活)
  • ⚡ 高性能 - 内置 Token 缓存(LRU + TTL)
  • 📋 标准规范 - 自动生成 RFC 9728/8414 well-known 端点

📦 安装

pip install uno-oauth-mcp

或使用 uv:

uv add uno-oauth-mcp

🚀 快速开始

方式一:基于 FastMCP(推荐新手)

FastMCP 是官方提供的高层封装,API 更简洁:

from uno_oauth_mcp import UnoOAuthMCP

# 创建带 OAuth 的 MCP Server
mcp = UnoOAuthMCP(name="My Server", port=8080)

@mcp.tool()
def hello(name: str) -> str:
    """向用户问好"""
    return f"Hello, {name}!"

@mcp.tool()
def add(a: int, b: int) -> int:
    """计算两个数的和"""
    return a + b

# 运行
mcp.run(transport="streamable-http")

方式二:基于底层 Server(更灵活)

底层 Server 提供更完整的 MCP 协议控制:

import mcp.types as types
from uno_oauth_mcp import UnoOAuthServer

# 创建带 OAuth 的 Server
server = UnoOAuthServer(name="My Server", port=8080)

@server.list_tools()
async def list_tools():
    return [
        types.Tool(
            name="hello",
            description="向用户问好",
            inputSchema={
                "type": "object",
                "properties": {"name": {"type": "string"}},
                "required": ["name"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "hello":
        return [types.TextContent(type="text", text=f"Hello, {arguments['name']}!")]
    return []

# 运行
server.run()

🆚 两种方式对比

特性 UnoOAuthMCP (FastMCP) UnoOAuthServer (底层 Server)
适合人群 新手、快速开发 需要完整控制的开发者
API 风格 装饰器 + 类型推断 显式定义 MCP 类型
工具定义 @mcp.tool() 自动推断 手动构建 types.Tool
灵活性 ⭐⭐⭐ ⭐⭐⭐⭐⭐
代码量 更少 稍多

🔧 配置选项

# FastMCP 方式
mcp = UnoOAuthMCP(
    name="My Server",                    # Server 名称
    port=8080,                           # 监听端口
    host="0.0.0.0",                      # 监听地址
    mcpmarket_url="https://mcpmarket.cn", # 认证服务器
    required_scopes=["read", "write"],   # OAuth scopes
    cache_ttl=300,                       # Token 缓存时间(秒)
    # 生产环境需要指定外部访问 URL
    # resource_server_url="https://my-mcp.example.com",
)

# 底层 Server 方式
server = UnoOAuthServer(
    name="My Server",
    port=8080,
    mcp_path="/mcp",                     # MCP 端点路径
    # ... 其他参数同上
)

🌐 自动注册的端点

SDK 会自动注册以下端点:

端点 描述
/.well-known/oauth-protected-resource OAuth 资源服务器元数据 (RFC 9728)
/.well-known/oauth-authorization-server OAuth 授权服务器元数据 (RFC 8414)
/mcp MCP 协议端点(需认证)
/health 健康检查
/ 服务器信息

🔐 认证流程

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  MCP Client  │     │ Your Server  │     │ mcpmarket.cn │
│(Cursor/Claude)│    │              │     │              │
└──────┬───────┘     └──────┬───────┘     └──────┬───────┘
       │                    │                    │
       │ 1. 访问 MCP 端点   │                    │
       │ ─────────────────> │                    │
       │                    │                    │
       │ 2. 401 + well-known│                    │
       │ <───────────────── │                    │
       │                    │                    │
       │ 3. OAuth 授权      │                    │
       │ ──────────────────────────────────────> │
       │                    │                    │
       │ 4. 获取 Token      │                    │
       │ <────────────────────────────────────── │
       │                    │                    │
       │ 5. 带 Token 访问   │                    │
       │ ─────────────────> │                    │
       │                    │ 6. 验证 Token      │
       │                    │ ─────────────────> │
       │                    │ 7. 验证成功        │
       │                    │ <───────────────── │
       │ 8. MCP 响应        │                    │
       │ <───────────────── │                    │

📚 更多示例

带资源的 Server

from uno_oauth_mcp import UnoOAuthMCP

mcp = UnoOAuthMCP(name="Resource Server")

@mcp.tool()
def get_data(key: str) -> str:
    return f"Data for {key}"

@mcp.resource("config://app")
def get_config() -> str:
    return '{"version": "1.0.0"}'

@mcp.resource("data://{item_id}")
def get_item(item_id: str) -> str:
    return f'{{"id": "{item_id}"}}'

mcp.run(transport="streamable-http")

使用原生 Server + create_oauth_starlette_app

from mcp.server.lowlevel import Server
from uno_oauth_mcp import create_oauth_starlette_app
import uvicorn

server = Server("my-server")

@server.list_tools()
async def list_tools():
    return [...]

# 创建带 OAuth 的 Starlette 应用
app = create_oauth_starlette_app(server, port=8080)

# 可以添加自定义路由
# from starlette.routing import Route
# app.routes.append(Route("/custom", ...))

uvicorn.run(app, host="0.0.0.0", port=8080)

🔗 相关资源

📄 许可证

MIT License


Made with ❤️ by MCPMarket

Metadata

Release files for uno-oauth-mcp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for uno-oauth-mcp 0.1.0
File Size Uploaded Provenance
uno_oauth_mcp-0.1.0.tar.gz 71.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for uno-oauth-mcp 0.1.0
File Interpreter ABI Platform
uno_oauth_mcp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 81.8 kB

Release files / uno_oauth_mcp-0.1.0.tar.gz

Download URL uno_oauth_mcp-0.1.0.tar.gz
Size 71.6 kB
Tags Source
SHA-256 checksum
How to use checksums
4a2eb6c7583de2c5584ef89354b31e32c13b2953bbc505d7a8fcd519dfd307b2
BLAKE2b-256 checksum
How to use checksums
a0c10b32d78caca3302d82b8e52e025f085c858dfe0c8dcc55fc895197ee82d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.15

Release files / uno_oauth_mcp-0.1.0-py3-none-any.whl

Download URL uno_oauth_mcp-0.1.0-py3-none-any.whl
Size 10.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5a2f6383c5f0b2d011343bf68a303b3dce97d14494f82ea83013539d425dc712
BLAKE2b-256 checksum
How to use checksums
ed3418a45b1fe39fafc38702c92aed91abb8931d684229f7eb65e91cb6254527
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.15

Security for uno-oauth-mcp 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page