mcp-oauth

📁 smithery-ai/skills 📅 5 days ago
3
总安装量
2
周安装量
#62443
全站排名
安装命令
npx skills add https://github.com/smithery-ai/skills --skill mcp-oauth

Agent 安装分布

claude-code 2
mcpjam 1
kilo 1
junie 1
windsurf 1
zencoder 1

Skill 文档

MCP OAuth Authentication Flow

Connect to any OAuth-protected MCP server using curl and bundled Node.js scripts. Execute steps in order. Stop and report on failure.

Store the user-provided MCP server URL as MCP_SERVER_URL.

1. Discover Protected Resource Metadata

curl -s "${MCP_SERVER_URL}/.well-known/oauth-protected-resource"

Extract resource and first authorization_servers entry as AUTH_SERVER.

Fallback: If 404, POST to ${MCP_SERVER_URL}/ unauthenticated and extract resource_metadata URL from the WWW-Authenticate header. Fetch that URL instead.

2. Fetch Authorization Server Metadata

curl -s "${AUTH_SERVER}/.well-known/oauth-authorization-server"

Save: authorization_endpoint, token_endpoint, registration_endpoint, code_challenge_methods_supported, scopes_supported.

3. Dynamic Client Registration

curl -s -X POST "${REGISTRATION_ENDPOINT}" \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "Claude Code MCP Client",
    "redirect_uris": ["http://localhost:9999/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"],
    "token_endpoint_auth_method": "none",
    "scope": "<scopes_supported joined by spaces>"
  }'

Save client_id. If registration unsupported (404), ask user for a client_id.

4. Generate PKCE Challenge

Run the bundled PKCE script:

PKCE_JSON=$(node scripts/pkce.js)
CODE_VERIFIER=$(echo "$PKCE_JSON" | node -e "process.stdin.on('data',d=>console.log(JSON.parse(d).code_verifier))")
CODE_CHALLENGE=$(echo "$PKCE_JSON" | node -e "process.stdin.on('data',d=>console.log(JSON.parse(d).code_challenge))")
STATE=$(echo "$PKCE_JSON" | node -e "process.stdin.on('data',d=>console.log(JSON.parse(d).state))")

The script path is relative to this skill’s directory.

5. Start Callback Server and Open Browser

Start the bundled callback server in background:

node scripts/callback_server.js 9999 &

The server listens on the given port, captures the OAuth redirect code, writes it to /tmp/mcp_oauth_code.txt and /tmp/mcp_oauth_state.txt, then exits.

Build and open the authorization URL:

REDIRECT_URI="http://localhost:9999/callback"
ENCODED_REDIRECT=$(node -e "console.log(encodeURIComponent('${REDIRECT_URI}'))")
AUTH_URL="${AUTHORIZATION_ENDPOINT}?response_type=code&client_id=${CLIENT_ID}&redirect_uri=${ENCODED_REDIRECT}&code_challenge=${CODE_CHALLENGE}&code_challenge_method=S256&state=${STATE}&scope=${SCOPES}&resource=${RESOURCE}"

open "${AUTH_URL}"

Tell the user: “I’ve opened the authorization page in your browser. Please authorize the app, then tell me when you’re done.”

Wait for user confirmation before continuing.

6. Exchange Code for Token

CODE=$(cat /tmp/mcp_oauth_code.txt)

curl -s -X POST "${TOKEN_ENDPOINT}" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=${CODE}" \
  -d "redirect_uri=http://localhost:9999/callback" \
  -d "client_id=${CLIENT_ID}" \
  -d "code_verifier=${CODE_VERIFIER}" \
  -d "resource=${RESOURCE}"

Save access_token and refresh_token (if present). Report expires_in to user.

7. Initialize MCP Session

curl -s -X POST "${MCP_SERVER_URL}/" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -d '{
    "jsonrpc": "2.0",
    "method": "initialize",
    "id": 1,
    "params": {
      "protocolVersion": "2025-03-26",
      "capabilities": {},
      "clientInfo": { "name": "claude-code", "version": "1.0.0" }
    }
  }'

Always include Accept: application/json, text/event-stream — required by Streamable HTTP MCP servers.

Save mcp-session-id from response headers if present (needed for subsequent requests).

8. List Tools

curl -s -X POST "${MCP_SERVER_URL}/" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  ${SESSION_HEADER} \
  -d '{ "jsonrpc": "2.0", "method": "tools/list", "id": 2, "params": {} }'

Include -H "mcp-session-id: ${SESSION_ID}" if a session ID was returned. Present tools to user (name + description).

9. Interactive Mode

Ask user if they want to call any tool:

curl -s -X POST "${MCP_SERVER_URL}/" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  ${SESSION_HEADER} \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "id": 3,
    "params": { "name": "<tool_name>", "arguments": { } }
  }'

Token Refresh

On 401 with a refresh_token available:

curl -s -X POST "${TOKEN_ENDPOINT}" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=${REFRESH_TOKEN}" \
  -d "client_id=${CLIENT_ID}" \
  -d "resource=${RESOURCE}"

Save new access_token and retry.

Cleanup

rm -f /tmp/mcp_oauth_code.txt /tmp/mcp_oauth_state.txt

Troubleshooting

Error Fix
Not Acceptable Add Accept: application/json, text/event-stream
invalid_token Refresh token or re-authorize
404 on .well-known Try unauthenticated POST, check WWW-Authenticate header
404 on registration Ask user for client_id
Port 9999 in use lsof -ti:9999 | xargs kill -9
PKCE mismatch Regenerate with scripts/pkce.js and retry