docs: Added documentation for the new mcp OAuth flow

2026-07-02 14:57:35 -06:00
parent 8bf06911de
commit 78d26aea0b
2 changed files with 144 additions and 13 deletions
+118 -13
@@ -30,9 +30,9 @@ allows it to be omitted and infers `stdio` from the presence of a `command`). So
a new server, look at its docs and find the Claude Code configuration example. You should be able to use the
exact same configuration in your `functions/mcp.json` file. Just make sure every entry has an explicit `type`.
**Note:** Coyote does not support Claude Code's `"streamable-http"` alias (use `"http"` instead), nor extras
like `oauth` or `envFile`. For secrets, use [Coyote Vault](Vault) interpolation rather than Claude Code's `${VAR}`
shell-style expansion.
**Note:** Coyote does not support Claude Code's `"streamable-http"` alias (use `"http"` instead) or `envFile`.
For secrets, use [Coyote Vault](Vault) interpolation rather than Claude Code's `${VAR}` shell-style expansion.
OAuth-protected remote servers are supported natively (see [OAuth Authentication](#oauth-authentication) below).
Every server entry **must** include a `"type"` field set to one of: `"stdio"`, `"http"`, or `"sse"`.
@@ -93,11 +93,12 @@ For remote MCP servers that support the Streamable HTTP transport:
}
```
| Field | Required | Description |
|-----------|----------|--------------------------------------------------------|
| `type` | yes | Must be `"http"` |
| `url` | yes | The server endpoint URL |
| `headers` | no | Custom HTTP headers to include with every request |
| Field | Required | Description |
|-------------------|----------|------------------------------------------------------------------------------------------------|
| `type` | yes | Must be `"http"` |
| `url` | yes | The server endpoint URL |
| `headers` | no | Custom HTTP headers to include with every request |
| `oauth_client_id` | no | OAuth client ID. Omit to use Dynamic Client Registration (auto-registers on first `.mcp auth`) |
## SSE Servers
@@ -118,16 +119,120 @@ prefer `http` where the server supports it):
}
```
| Field | Required | Description |
|-----------|----------|--------------------------------------------------------|
| `type` | yes | Must be `"sse"` |
| `url` | yes | The server SSE endpoint URL |
| `headers` | no | Custom HTTP headers to include with every request |
| Field | Required | Description |
|-------------------|----------|------------------------------------------------------------------------------------------------|
| `type` | yes | Must be `"sse"` |
| `url` | yes | The server SSE endpoint URL |
| `headers` | no | Custom HTTP headers to include with every request |
| `oauth_client_id` | no | OAuth client ID. Omit to use Dynamic Client Registration (auto-registers on first `.mcp auth`) |
**Note:** Both `http` and `sse` types use the same underlying transport, which auto-negotiates the
protocol with the server. The `type` field primarily serves as documentation of which protocol the
server speaks. Neither type supports `command`, `args`, or `cwd` fields.
## OAuth Authentication
Some remote MCP servers require OAuth 2.0 authentication (e.g. Notion, Jira). Coyote supports these
natively, meaning no manual token management is required.
### Example: Notion
```json
{
"mcpServers": {
"notion": {
"type": "http",
"url": "https://mcp.notion.com/mcp"
}
}
}
```
That's it. Then in the REPL:
```
.mcp auth notion
```
Or from the command line:
```shell
coyote --auth-mcp notion
```
Your browser opens, you log into Notion, and the token is saved. On subsequent startups Coyote injects the token
automatically. When the token expires it is refreshed silently.
### How it works
1. **Discovery:** Coyote fetches `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`
to find the server's authorization and token endpoints (per RFC 9728 / RFC 8414). No manual endpoint configuration needed.
2. **Dynamic Client Registration (RFC 7591):** If the server supports it (the Notion MCP server used in this example does), Coyote
registers itself automatically and caches the client ID in `~/.cache/coyote/oauth/mcp_<name>_registration.json`. The
`oauth_client_id` field is only needed when DCR is unavailable.
3. **PKCE authorization code flow:** A localhost callback server is bound on an ephemeral port. Your browser opens for login.
The token is exchanged and stored in `<cache_dir>/oauth/mcp_<name>_oauth_tokens.json`.
4. **Token injection:** On every connection to the server, Coyote loads the stored token (refreshing if expired) and injects
it as an `Authorization: Bearer` header. No changes to `mcp.json` required.
### If authentication hasn't been run yet
If Coyote tries to connect to an OAuth-protected server at startup and gets an auth challenge, it
**warns and skips** the server rather than failing:
```
warn: MCP server 'notion' requires authentication. Run `.mcp auth notion` to authenticate.
```
Run `.mcp auth notion` (or `coyote --auth-mcp notion`) once to complete the flow, then restart Coyote.
### Using a pre-existing client ID
If your organization pre-registers a client with the server (this is rare, as DCR handles this automatically for most servers):
```json
{
"mcpServers": {
"my-server": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"oauth_client_id": "your-registered-client-id"
}
}
}
```
When `oauth_client_id` is set, DCR is skipped and the provided ID is used directly.
### Using a static token instead of OAuth
If the server issues long-lived tokens (e.g. Notion internal integrations), you can skip the OAuth flow
entirely and use a static `Authorization` header:
```json
{
"mcpServers": {
"notion": {
"type": "http",
"url": "https://mcp.notion.com/mcp",
"headers": {
"Authorization": "Bearer <your-notion-integration-token>"
}
}
}
}
```
Use [Coyote Vault](Vault) to avoid storing the token in plaintext:
```json
{
"headers": {
"Authorization": "Bearer {{notion_token}}"
}
}
```
## Secret Injection
As mentioned in the [Coyote Vault documentation](Vault), you can use Coyote Vault to inject secrets into your MCP configuration file.
+26
@@ -15,6 +15,7 @@ things like
* `.model <tab>` to complete chat models
* `.set <tab>` to complete configuration keys
* `.set key <tab>` to complete configuration values
* `.mcp auth <tab>` to complete remote MCP server names
* **Multi-Line Prompts:** You can also type prompts that span more than one line to help organize your thoughts. This
can be done in the following ways:
* `Ctrl-o` to open the current input buffer in your preferred editor (either the value of `editor` or `$EDITOR`)
@@ -338,6 +339,31 @@ The following entities are supported:
| `.info tools` | List every tool that would be sent in the next chat completion request (composed across role, agent, skills, and MCP filters). Errors when `function_calling_support` is disabled. |
| `.info todo` | Show the current todo list driving auto-continuation (goal, progress count, and per-task status). Only available when `auto_continue` is enabled. |
## `.mcp auth` - Authenticate with an OAuth-protected MCP server
Some remote MCP servers (such as Notion, Jira, etc.) require OAuth authentication before they can be used.
Run this command once per server to complete the authorization flow:
```
.mcp auth <server-name>
```
where `<server-name>` matches the key in your `mcp.json` file. Tab completion is available.
**What happens:**
1. Coyote discovers the server's OAuth endpoints automatically via [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728) metadata discovery.
2. If the server supports [Dynamic Client Registration (RFC 7591)](https://www.rfc-editor.org/rfc/rfc7591), Coyote registers itself automatically, meaning no `oauth_client_id` configuration is required.
3. Your browser opens to the server's authorization page. Log in and approve access.
4. The token is saved to `<cache_dir>/coyote/oauth/` and loaded automatically on subsequent startups.
5. Tokens are refreshed automatically when they expire.
**If a server requires authentication but you haven't run `.mcp auth` yet**, Coyote will skip that server at startup
with a warning rather than failing outright. The warning tells you exactly which command to run.
The same flow is available outside the REPL via `coyote --auth-mcp <server-name>`.
For full configuration options and an example for Notion, see the [MCP Servers documentation](MCP-Servers#oauth-authentication).
## `.authenticate` - Authenticate the current model client via OAuth
The `.authenticate` command will start the OAuth flow for the current model client if
* The client supports OAuth (See the [clients documentation](Clients#providers-that-support-oauth) for supported clients)