---
title: "Generic MCP client"
description: "Connect any MCP client to the broker over Streamable HTTP with OAuth discovery, using curl to check each step."
image: "https://docs.agentregistrar.dev/og/docs-default.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.agentregistrar.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Generic MCP client

**Tier 3: protocol-level instructions checked live against the broker on 2026-10-21.** This page makes no claim about a specific client. It is the fallback for a client that is not in the [support matrix](/agents/install/), and the reference for what a compliant client does under the hood.

## The transport

The broker serves MCP Streamable HTTP at one endpoint:

```text
https://agentregistrar.dev/mcp
```

- Requests are `POST` with a JSON-RPC 2.0 body.
- The client sends `Accept: application/json, text/event-stream`. A response may be a JSON body or an event stream.
- Every request needs `Authorization: Bearer <token>`, including `initialize`. An unauthenticated request gets `401` before any JSON-RPC method runs.
- The broker opens connections with the classic MCP `initialize` handshake. After initialization, clients send the negotiated protocol revision in `MCP-Protocol-Version`.
- The server advertises tools and resources. It does not advertise prompts.

The token is an MCP bearer token issued by the broker's OAuth server. It is not an agent assertion. An assertion is minted later by `identity_prove` and sent only to the relying party's `agent_signup` endpoint, never to `/mcp`.

## The OAuth chain

1. An unauthenticated request returns `401` with a `WWW-Authenticate` challenge naming the protected-resource metadata.
2. `GET /.well-known/oauth-protected-resource` names the resource (`https://agentregistrar.dev/mcp`) and the authorization server.
3. `GET /.well-known/oauth-authorization-server` gives the authorization, token, registration and JWKS endpoints, the supported grant types, `S256` PKCE and the supported scopes.
4. The client registers itself: a Client ID Metadata Document URL as `client_id`, or `POST /api/oauth/register` for dynamic registration.
5. The client opens `/oauth/authorize` with `response_type=code`, `code_challenge`, `code_challenge_method=S256`, its `client_id` and a loopback redirect URI, and the human approves.
6. The client exchanges the code at `/api/oauth/token` with the `code_verifier`, then calls `/mcp` with the bearer token.

The broker accepts loopback redirect URIs on any port, and HTTPS redirect URIs on any host, for dynamic registration. It supports public clients (`token_endpoint_auth_method: none`) and `client_secret_post`.

## Check the discovery documents

Start with the unauthenticated request and read the challenge:

```bash
curl -sS -D - -o /dev/null https://agentregistrar.dev/mcp
```

Live output, headers only:

```text
HTTP/2 401
www-authenticate: Bearer resource_metadata="https://agentregistrar.dev/.well-known/oauth-protected-resource", scope="mcp:tools tos:accept signup:free_tier"
```

Then read the two metadata documents:

```bash
curl -sS https://agentregistrar.dev/.well-known/oauth-protected-resource
curl -sS https://agentregistrar.dev/.well-known/oauth-authorization-server
```

Live output:

```json
{
  "resource": "https://agentregistrar.dev/mcp",
  "authorization_servers": ["https://agentregistrar.dev"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["mcp:tools", "tos:accept", "signup:free_tier"]
}
```

```json
{
  "issuer": "https://agentregistrar.dev",
  "authorization_endpoint": "https://agentregistrar.dev/oauth/authorize",
  "token_endpoint": "https://agentregistrar.dev/api/oauth/token",
  "registration_endpoint": "https://agentregistrar.dev/api/oauth/register",
  "jwks_uri": "https://agentregistrar.dev/.well-known/jwks.json",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_methods_supported": ["none", "client_secret_post"],
  "code_challenge_methods_supported": ["S256"],
  "client_id_metadata_document_supported": true,
  "scopes_supported": ["mcp:tools", "tos:accept", "signup:free_tier"]
}
```

Both returned `200 application/json` with `Access-Control-Allow-Origin: *`. The JWKS returned `200 application/json` with one key.

## Register a client

Dynamic registration takes a client name and at least one redirect URI:

```bash
curl -sS -X POST https://agentregistrar.dev/api/oauth/register \
  -H 'Content-Type: application/json' \
  -d '{
    "client_name": "my-mcp-client",
    "redirect_uris": ["http://127.0.0.1:49731/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"],
    "token_endpoint_auth_method": "none"
  }'
```

A live run on 2026-10-21 returned `201` with a body in this shape:

```json
{
  "client_id": "cli_<ulid>",
  "client_id_issued_at": 1792607788,
  "client_name": "my-mcp-client",
  "redirect_uris": ["http://127.0.0.1:49731/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
```

A redirect URI that is neither loopback nor HTTPS is rejected with `400`:

```json
{"error":"invalid_redirect_uri","error_description":"All redirect_uris must be loopback (http://127.0.0.1, http://localhost) or HTTPS URLs."}
```

A client that supports Client ID Metadata Documents skips this call and sends its metadata-document URL as the `client_id`; the broker fetches and caches it. The metadata advertises `client_id_metadata_document_supported: true`.

## Call the server

Without a token, `initialize` and `tools/list` both return `401`. That is the expected result, not a transport failure:

```bash
curl -sS -X POST https://agentregistrar.dev/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl-check","version":"0.0.0"}}}'
```

Live output:

```json
{"jsonrpc":"2.0","error":{"code":-32001,"message":"Unauthorized: Missing, invalid, expired, or revoked MCP Bearer token."},"id":null}
```

With a token from your own OAuth session, the same request returns the initialization result. Replace `<token>` with the bearer token the client obtained; never commit a real token:

```bash
curl -sS -X POST https://agentregistrar.dev/mcp \
  -H "Authorization: Bearer <token>" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl-check","version":"0.0.0"}}}'
```

List the tools:

```bash
curl -sS -X POST https://agentregistrar.dev/mcp \
  -H "Authorization: Bearer <token>" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

The result contains nine tools: `identity_register`, `identity_whoami`, `identity_signup`, `identity_prove`, `identity_record_signup`, `inbox_list`, `inbox_read`, `inbox_wait_for_email` and `inbox_send`. Input schemas are published by `tools/list`; the human-readable contract is in the [reference](/reference/).

A first identity call is:

```bash
curl -sS -X POST https://agentregistrar.dev/mcp \
  -H "Authorization: Bearer <token>" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"identity_whoami","arguments":{}}}'
```

The result names the agent bound to the session, its inbox address and its scopes. A bare `identity_whoami` auto-provisions the broker defaults, `opencode-agent` with `harness: "opencode-v2"`, when the session has no agent; call `identity_register` with a `name` and `harness` first to label the agent for this client. If the call returns `401`, the token is missing or expired; if it returns `403`, the human account has not signed the master agreement or is suspended.

## What remains unverified

The discovery documents, the `401` challenge, the DCR success and error responses, and the token endpoint's `invalid_grant` response were checked live. The authenticated half, `initialize` and `tools/list` with a real token, was not executed here, because completing OAuth requires a human in a browser. The tool names come from the broker's tool schema, not from a live authenticated response on this machine.

## Next step

For a client-specific path, return to the [support matrix](/agents/install/). For the failures that stop this chain, see [OAuth troubleshooting](/agents/install/oauth-troubleshooting/). For the full signup, see the [agent quickstart](/agents/quickstart/).

Source: https://docs.agentregistrar.dev/agents/install/generic-mcp/index.mdx
