mcp-auth-proxy
by manio143
README.md
# mcp-auth-proxy
Stdio-to-HTTP MCP proxy with OAuth 2.1 authentication (PKCE + browser login).
Bridges the gap when your LLM harness only supports stdio MCP servers but the remote MCP server requires OAuth (e.g., Microsoft Entra ID).
```
LLM Harness (stdio only)
↕ stdin/stdout (JSON-RPC)
mcp-auth-proxy
↕ Streamable HTTP + Bearer token
Remote MCP Server (OAuth-protected)
```
## Features
- **RFC 9728 discovery** — auto-discovers authorization server and scopes from the MCP server's protected resource metadata
- **OAuth 2.1 + PKCE** — browser-based login, no client secrets needed (public client)
- **Random callback port** — each instance uses a random port, safe to run multiple instances simultaneously
- **Auto token refresh** — handled transparently by the SDK transport
- **In-memory only** — tokens are never written to disk
- **Full proxy** — tools, resources, and prompts are all proxied
## Installation
> ⚠️ **This package is not published on npm.** Install from source using `npm link`.
```bash
git clone https://github.com/manio143/mcp-stdio-proxy.git
cd mcp-stdio-proxy
npm install
npm run build
npm link
```
## Usage
```bash
# Basic — discovers client ID from server metadata
mcp-auth-proxy https://mcp.company.com/api
# With explicit client ID
mcp-auth-proxy https://mcp.company.com/api --clientId=my-app-client-id
```
### In MCP client config (e.g., Claude Desktop, VS Code)
```json
{
"mcpServers": {
"my-server": {
"command": "mcp-auth-proxy",
"args": ["https://mcp.company.com/api", "--clientId=my-app-id"]
}
}
}
```
## How authentication works
1. Proxy probes the remote MCP endpoint → gets `401`
2. Parses `WWW-Authenticate` header for resource metadata URL (RFC 9728)
3. Fetches protected resource metadata → finds authorization server + scopes
4. Fetches authorization server metadata (RFC 8414 / OIDC Discovery)
5. Opens browser for OAuth 2.1 authorization code flow with PKCE
6. Receives callback on `http://localhost:{random-port}/callback`
7. Exchanges code for tokens
8. All subsequent requests include `Authorization: Bearer <token>`
9. Token refresh happens automatically when tokens expire
## Client ID resolution
1. If `--clientId` is provided, uses that
2. If the server's protected resource metadata advertises a client ID, uses that
3. If the server supports dynamic client registration (RFC 7591), registers automatically
4. Otherwise, exits with an error
## Requirements
- Node.js ≥ 20
- A browser for the OAuth login flow
- The remote MCP server must support Streamable HTTP transport
## Security
- Tokens held in memory only — process exit clears them
- PKCE prevents authorization code interception
- Callback server binds to `127.0.0.1` only
- Random port prevents port conflicts and prediction
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues