# auth.md

The Portfolio MCP server supports anonymous agent registration for read-only portfolio access. The resource server and authorization server are both hosted at https://franzdomingo.dev. Agents register a public OAuth client, obtain a short-lived bearer token through OAuth authorization code with PKCE S256, then use that token with the MCP endpoint. Registration does not create a user account or issue a credential directly.

## Step 1: Discover

1. If the MCP endpoint returns 401, read the `resource_metadata` URL in its `WWW-Authenticate: Bearer` header. Otherwise, fetch https://franzdomingo.dev/.well-known/oauth-protected-resource.
2. Read `resource`, `authorization_servers`, `scopes_supported`, and `bearer_methods_supported` from the Protected Resource Metadata.
3. Fetch https://franzdomingo.dev/.well-known/oauth-authorization-server. Its `agent_auth` block is the source of truth for the registration method and credential type.

## Step 2: Pick a registration method

Only `anonymous` registration is supported. The issued credential is a bearer `access_token`. Identity assertions, verified email, account claim ceremonies, API keys, client secrets, and token revocation are not supported.

## Step 3: Register an anonymous public client

Send the client name and one or more exact redirect URIs to https://franzdomingo.dev/oauth/register. The registration endpoint accepts only public clients with `token_endpoint_auth_method` set to `none`.

```http
POST https://franzdomingo.dev/oauth/register
Content-Type: application/json

{ "client_name": "Example agent", "redirect_uris": ["https://agent.example/callback"] }
```

The response includes a `client_id`. Keep the redirect URI unchanged for the authorization and token requests.

## Step 4: Authorize and exchange

1. Generate a PKCE verifier and S256 challenge.
2. Direct the user to https://franzdomingo.dev/oauth/authorize with `response_type=code`, `client_id`, `redirect_uri`, `code_challenge`, `code_challenge_method=S256`, `scope=portfolio.read`, `state`, and `resource=https://franzdomingo.dev/api/mcp`.
3. After the user approves, exchange the returned code at https://franzdomingo.dev/oauth/token. Include the same `client_id`, `redirect_uri`, `code_verifier`, and `resource`.

## Step 5: Use the credential

Send the access token as `Authorization: Bearer TOKEN` when connecting to https://franzdomingo.dev/api/mcp. Tokens expire after one hour. On 401, discard the token and repeat authorization. There is no token revocation endpoint.

## Supported scope

- `portfolio.read`: Read public portfolio projects, skills, experience, certificates, contact details, and social links.

## Integration contact

For integration issues, use the portfolio contact form at https://franzdomingo.dev/#contact.
