authful-mcp-proxy 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of authful-mcp-proxy might be problematic. Click here for more details.
- authful_mcp_proxy/__init__.py +9 -0
- authful_mcp_proxy/__main__.py +180 -0
- authful_mcp_proxy/config.py +27 -0
- authful_mcp_proxy/external_oidc.py +435 -0
- authful_mcp_proxy/mcp_proxy.py +74 -0
- authful_mcp_proxy-0.1.0.dist-info/METADATA +646 -0
- authful_mcp_proxy-0.1.0.dist-info/RECORD +10 -0
- authful_mcp_proxy-0.1.0.dist-info/WHEEL +4 -0
- authful_mcp_proxy-0.1.0.dist-info/entry_points.txt +2 -0
- authful_mcp_proxy-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OIDC OAuth-enabled MCP Proxy with stdio transport.
|
|
3
|
+
|
|
4
|
+
This module provides the main proxy server that bridges remote HTTP MCP servers
|
|
5
|
+
protected by token validation to local stdio transport for MCP clients like Claude
|
|
6
|
+
Desktop. It handles:
|
|
7
|
+
|
|
8
|
+
- OIDC authentication via external authorization servers
|
|
9
|
+
- HTTP-to-stdio transport bridging
|
|
10
|
+
- Session management and token refresh
|
|
11
|
+
- Transparent request forwarding to the backend MCP server
|
|
12
|
+
|
|
13
|
+
The proxy uses ExternalOIDCAuth to obtain access tokens through the OAuth 2.0
|
|
14
|
+
authorization code flow and attaches them as Bearer tokens to all backend requests.
|
|
15
|
+
This enables MCP clients to connect to token-protected MCP servers without
|
|
16
|
+
implementing OIDC authentication themselves.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from fastmcp import Client
|
|
22
|
+
from fastmcp.server import FastMCP
|
|
23
|
+
|
|
24
|
+
from .config import OIDCConfig
|
|
25
|
+
from .external_oidc import ExternalOIDCAuth
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def run_async(
|
|
29
|
+
backend_url: str,
|
|
30
|
+
oidc_config: OIDCConfig,
|
|
31
|
+
show_banner: bool = True,
|
|
32
|
+
**transport_kwargs: Any,
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
Run the MCP proxy server with OIDC authentication.
|
|
36
|
+
|
|
37
|
+
Creates an authenticated connection to the backend MCP server using OIDC
|
|
38
|
+
authentication, then proxies all requests through stdio transport for
|
|
39
|
+
local MCP clients.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
backend_url: URL of the remote backend MCP server to proxy.
|
|
43
|
+
oidc_config: OIDC authentication configuration with issuer, client credentials,
|
|
44
|
+
and scopes.
|
|
45
|
+
show_banner: Whether to display the server startup banner (default: True).
|
|
46
|
+
**transport_kwargs: Additional keyword arguments passed to the transport layer
|
|
47
|
+
(e.g., log_level).
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
ValueError: If required OIDC parameters (issuer_url, client_id) are missing.
|
|
51
|
+
RuntimeError: If authentication or connection to backend server fails.
|
|
52
|
+
"""
|
|
53
|
+
# Create OIDC auth provider
|
|
54
|
+
auth = ExternalOIDCAuth(
|
|
55
|
+
issuer_url=oidc_config.issuer_url,
|
|
56
|
+
client_id=oidc_config.client_id,
|
|
57
|
+
client_secret=oidc_config.client_secret,
|
|
58
|
+
scopes=oidc_config.scopes,
|
|
59
|
+
redirect_url=oidc_config.redirect_url,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Create a client that authenticates (once) with the configured OIDC auth provider
|
|
63
|
+
# and connects to the backend MCP server
|
|
64
|
+
async with Client(transport=backend_url, auth=auth) as authenticated_client:
|
|
65
|
+
# Create FastMCP proxy server that reuses the connected session for all requests
|
|
66
|
+
# Warning: Sharing the same backend session for all requests may cause context mixing
|
|
67
|
+
# and race conditions in concurrent scenarios. When running this MCP proxy with stdio
|
|
68
|
+
# transport inside MCP clients like Claude Desktop this is generally not the case.
|
|
69
|
+
mcp_proxy = FastMCP.as_proxy(backend=authenticated_client)
|
|
70
|
+
|
|
71
|
+
# Run via stdio for MCP clients like Claude Desktop
|
|
72
|
+
await mcp_proxy.run_async(
|
|
73
|
+
transport="stdio", show_banner=show_banner, **transport_kwargs
|
|
74
|
+
)
|