鹅壳
用于保护自托管的最低OAuth 2.0授权服务器 主控程序 服务器。它实现了刚好足够Claude.ai(和其他MCP客户端)进行身份验证的规范,而没有多用户身份验证的复杂性。一个服务器,一个操作员,一组凭据。
为什么
Claude.ai要求OAuth连接到远程MCP服务器。如果你在Caddy后面自托管MCP服务器,你需要一些东西来处理OAuth舞蹈。oauth外壳就是这样:一个没有配置文件、没有外部依赖关系的单一二进制文件,以及一个自行创建的SQLite数据库。
它故意忽略了多用户的任何概念——没有登录页面,没有用户数据库,没有同意屏幕。您使用共享密钥注册客户端,任何具有这些凭据的MCP客户端都可以获得令牌。如果(但可能只有当!)您是唯一的用户,并且MCP服务器是您的,则这是合适的。
安全目标(实用):将oauth-husk视为与预共享承载令牌/API密钥的风险大致相等,同时提供MCP客户端所需的oauth流。
运作原理
Claude.ai → Cloudflare → Caddy → oauth-husk (:8200) — OAuth endpoints
→ your MCP server — after forward_auth- Claude.ai通过以下方式发现OAuth端点
/.well-known/元数据 - 它从以下位置获取授权码
/authorize(使用PKCE) - 它将代码交换为令牌
/token - 在每次MCP请求时,Caddy都会调用oauth husk的
/auth/verify端点 - 如果令牌有效,Caddy会将请求代理到您的MCP服务器
oauth husk永远看不到你的MCP流量。它只是说“是”或“否”。
快速开始
go build
# Install as a launchd service (macOS)
./oauth-husk install
# Register a client
./oauth-husk client add claude-mcp
# → prints the client secret once — save it
# Point Caddy at it (see Caddyfile in this repo)命令
oauth-husk serve Start the server (foreground)
oauth-husk install Install and start as a launchd service
oauth-husk uninstall Stop and remove the launchd service
oauth-husk client add Register a client, print its secret
oauth-husk client list List registered clients
oauth-husk client revoke Revoke all tokens for a clientserve 和 install 接受 --port (默认值8200), --db (默认值 ~/.config/oauth-husk/oauth.db), --allow-from (逗号分隔的CIDR/IPs;仅默认环回,例如。 --allow-from 127.0.0.0/8,::1/128,172.18.0.0/16 Docker),以及 --allow-insecure-http 用于没有TLS的本地测试。数据库和签名密钥在首次运行时自动创建。
球童设置
oauth外壳设计用于坐在Caddy后面 forward_auth。其中包括一个示例Caddyfile——关键部分:
@oauth path /.well-known/oauth-protected-resource /.well-known/oauth-authorization-server /authorize /token
handle @oauth {
reverse_proxy localhost:8200
}
@mcp path /mcp /sse /messages
handle @mcp {
forward_auth localhost:8200 {
uri /auth/verify
}
reverse_proxy localhost:8105
}客户端设置
注册客户端时,您可以选择锁定其重定向URI:
./oauth-husk client add claude-mcp --redirect-uri https://claude.ai/api/mcp/auth_callback如果你忽略了 --redirect-uri,自动捕获并锁定第一次成功授权的URI。之后,只接受那个确切的URI。
设计选择
- 没有配置文件。 标记两个不同的东西(端口和DB路径)。基本URL来源于Caddy的转发标头。
- 没有CGO。 用途
modernc.org/sqlite纯粹的Go构建。单一静态二进制文件。 - 数据库中的签名密钥。 首次运行时自动生成,存储在
settings桌子。命令行或文件中没有秘密。 - 访问令牌是签名的,无状态的。
/auth/verify仅验证签名+过期。刷新令牌以哈希方式存储,用于轮换和撤销。 - bcrypt用于客户端机密。 成本12。即使对于未知的客户端ID,也能进行定时安全比较。
运行测试
go test ./...