Skip to main content
Glama
NapthaAI

HTTP OAuth MCP Server

by NapthaAI

🌊 HTTP + SSE MCP 服务器,带 OAuth

介绍

此 repo 提供了创建支持可流式 HTTP 和 SSE 传输的远程 MCP 服务器的参考实现,并根据 MCP 规范通过 OAuth 授权。

请注意,此 repo 中的 MCP 服务器在逻辑上与处理报告 SSE + HTTP 传输的应用程序以及 OAuth 分开。

因此,您可以轻松分叉此 repo,并将您自己的 MCP 服务器和 OAuth 凭据插入到具有您自己的功能的 SSE/HTTP + OAuth MCP 服务器中。

但为什么?

好问题!MCP 规范于 2025 年 3 月 25 日添加了基于 OAuth 的授权规范。目前,截至 2025 年 5 月 1 日:

  • Typescript SDK 包含许多用于实现具有可流式 HTTP 的 OAuth 授权 MCP 服务器的构建块,但没有关于如何构建此类服务器的文档或教程

  • Python SDK 既不包含可流式传输 HTTP 传输的实现,也不包含 TypeScript SDK 中存在的 OAuth 构建块的实现

  • Streamable HTTP 传输不受 MCP 主机应用程序(例如 Cursor 和 Claude 桌面)的广泛支持,尽管可以使用 JS/TS SDK 的StreamableHttpClientTransport类将其直接集成到用 JavaScript 编写的代理中

Naptha AI ,我们确实想在可流式传输的 HTTP 传输上构建一个 OAuth 授权的 MCP 服务器,但找不到任何参考实现,所以我们决定自己构建一个!

Related MCP server: MCP Dockerized Server

依赖项

Bun是一款快速的一体化 JavaScript 运行时,也是本仓库推荐使用的运行时和包管理器。我们已使用npm + tsc进行了有限的兼容性测试。

概述

该存储库提供以下内容:

  1. 您可以轻松地用自己的 MCP 服务器替换它

  2. 一个管理 SSEStreamable HTTP 传输以及OAuth 授权的 express.js 应用程序。

您可以将凭证和 MCP 服务器插入到这个快速应用程序。

请注意,虽然此快速应用程序实现了所需的 OAuth 端点,包括/authorize和授权服务器元数据端点( RFC8414 ),但它并未实现 OAuth 授权服务器!

此示例将 OAuth 代理到支持动态客户端注册 ( RFC7591 ) 的上游 OAuth 服务器。要使用此示例,您需要自带授权服务器。我们建议使用Auth0 ;请参阅下文的“设置 OAuth”部分

配置服务器

关于 OAuth 和动态客户端注册的说明

要使用此示例,您需要一个 OAuth 授权服务器。*请勿自行实现!*为了创建演示,我们使用了Auth0——这是一个不错的选择,尽管还有很多其他选择。

MCP 规范要求支持一项不常见的 OAuth 功能,具体来说是RFC7591 —— 动态客户端注册。MCP规范规定 MCP 客户端和服务器应支持动态客户端注册协议,以便 MCP 客户端(无论您的客户端传输位于何处)无需用户注册即可获取客户端 ID。这使得新客户端(代理、应用程序等)能够自动向新服务器注册。更多详细信息请参阅MCP 规范的授权部分,但遗憾的是,这意味着您无法直接代理到 Google 或 GitHub 等不支持动态客户端注册的提供商(它们要求您在其 UI 中注册客户端)。

这给你留下了两个选择:

  1. 选择一个像 Auth0 这样的上游 OAuth 提供商,它允许你使用 Google 和 GitHub 等 OIDC IDP 进行身份验证,并且支持动态客户端注册,或者

  2. 在应用程序中自行实现动态客户端注册(即,Express 应用程序不再只是一个简单的 OAuth 代理,而是一个完整或部分完整的 OAuth 服务器)。Cloudflare 为其 Workers OAuth MCP 服务器实现了类似的功能,我们稍后可能会用它来扩展这个项目。您可以在这里找到它。

为了简单起见,我们选择了使用 Auth0 的前一个选项。

[!笔记]
由于此实现代理了上游 OAuth 服务器,因此将访问令牌从 OAuth 服务器转发到客户端的默认方法会将用户的上游访问令牌暴露给下游客户端和 MCP 主机。这在许多用例中并不适用,因此此方法重新实现了部分@modelcontextprotocol/typescript-sdk类来解决这个问题。

请注意,当我们代理上游授权服务器时,我们不会将最终用户的授权令牌返回给 MCP 客户端/主机——相反,我们会自行签发令牌,并允许客户端/主机使用该令牌向我们的服务器进行授权。这可以防止恶意客户端或主机滥用令牌,或在令牌泄露后被滥用。

使用 Auth0 设置 OAuth

要开始使用 Auth0:

  1. Auth0.com创建一个 Auth0 帐户。

  2. 创建至少一个与 IDP(例如 Google 或 GitHub)的连接。您可以点击此处了解如何操作

  3. 将连接提升为域级连接。由于每个 MCP 客户端都会注册新的 OAuth 客户端,因此您无法针对每个应用程序/客户端配置 IDP 连接。这意味着您的连接需要对域中的所有应用可用。您可以点击此处了解如何操作

  4. 启用动态客户端注册(auth0 也称之为“动态应用程序注册”)。您可以点击此处了解如何操作

完成所有这些设置后,您将需要以下信息:

  • 您的 Auth0 客户端 ID

  • 您的 Auth0 客户端密钥

  • 您的 Auth0 租户域

确保将此信息填写到你的.env中。复制.env.template ,然后使用你的配置和机密信息更新其中的值。

运行服务器

该存储库包括两个独立的服务器:

  • src/app.stateless.ts中提供了流式 HTTP 服务器的无状态实现。它仅支持流式 HTTP 传输,理论上适合无服务器部署。

  • src/app.stateful.ts中提供了 SSE 和可流式传输 HTTP 的状态实现。此应用同时提供这两种传输方式,但即使使用redis存储策略(连接必须持久化在内存中),状态仍会保留在内存中,因此不适用于无服务器部署或简单的水平扩展。

您可以使用bun运行其中任何一个:

bun run src/app.stateless.ts # or, bun run src/app.stateful.ts

整合起来

要测试我们的具有流式 HTTP 和 OAuth 支持的 MCP 服务器,您有几种选择。

如上所述,Python MCP SDK 不支持这些功能,因此目前您可以将我们的远程服务器插入 MCP 主机(如 Cursor 或 Claude Desktop),或者直接插入 TypeScript/JavaScript 应用程序 - 但不能插入 Python 应用程序。

将服务器插入 MCP 主机 (Cursor / Claude)

由于大多数 MCP 主机不支持可流式传输的 HTTP(在许多方面优于 SSE)OAuth,我们建议使用mcp-remote npm 包来处理 OAuth 授权,并将远程传输桥接到主机的 STDIO 传输中。

该命令将如下所示:

bunx mcp-remote --transport http-first https://some-domain.server.com/mcp # or, npx mcp-remote --transport http-first https://some-domain.server.com/mcp

对于--transport选项,您有几个选项:

  • http-first (默认):首先尝试 HTTP 传输,如果 HTTP 失败并出现 404 错误,则回退到 SSE

  • sse-first :首先尝试 SSE 传输,如果 SSE 失败并出现 405 错误,则回退到 HTTP

  • http-only :仅使用 HTTP 传输,如果服务器不支持则会失败

  • sse-only :仅使用 SSE 传输,如果服务器不支持则会失败

注意:如果使用src/app.stateless.ts启动无状态版本的服务器,则 SSE 传输不可用,因此应使用--transport http-only 。如果使用此入口点,SSE 传输将无法正常工作。

将服务器插入代理

您可以使用StreamableHTTPClientTransport将 Streamable HTTP 服务器插入 JS/TS 中的代理。但是,这不适用于受 OAuth 保护的服务器。您应该在客户端使用Authorization标头,并在服务器端使用有效的访问令牌。

您可以使用客户端凭据、API 密钥或其他方式来实现这一点。此存储库不支持该模式,但使用Vercel AI SDK看起来会像这样:

import { openai } from '@ai-sdk/openai'; import { experimental_createMCPClient as createMcpClient, generateText } from 'ai'; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const mcpClient = await createMcpClient({ transport: new StreamableHTTPClientTransport( new URL("http://localhost:5050/mcp"), { requestInit: { headers: { Authorization: "Bearer YOUR TOKEN HERE", }, }, // TODO add OAuth client provider if you want authProvider: undefined, }), }); const tools = await mcpClient.tools(); await generateText({ model: openai("gpt-4o"), prompt: "Hello, world!", tools: { ...(await mcpClient.tools()) } });
-
security - not tested
A
license - permissive license
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/NapthaAI/http-oauth-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server