docs: Added documentation for the new mcp OAuth flow
+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
|
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`.
|
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
|
**Note:** Coyote does not support Claude Code's `"streamable-http"` alias (use `"http"` instead) or `envFile`.
|
||||||
like `oauth` or `envFile`. For secrets, use [Coyote Vault](Vault) interpolation rather than Claude Code's `${VAR}`
|
For secrets, use [Coyote Vault](Vault) interpolation rather than Claude Code's `${VAR}` shell-style expansion.
|
||||||
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"`.
|
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 |
|
| Field | Required | Description |
|
||||||
|-----------|----------|--------------------------------------------------------|
|
|-------------------|----------|------------------------------------------------------------------------------------------------|
|
||||||
| `type` | yes | Must be `"http"` |
|
| `type` | yes | Must be `"http"` |
|
||||||
| `url` | yes | The server endpoint URL |
|
| `url` | yes | The server endpoint URL |
|
||||||
| `headers` | no | Custom HTTP headers to include with every request |
|
| `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
|
## SSE Servers
|
||||||
|
|
||||||
@@ -118,16 +119,120 @@ prefer `http` where the server supports it):
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
| Field | Required | Description |
|
| Field | Required | Description |
|
||||||
|-----------|----------|--------------------------------------------------------|
|
|-------------------|----------|------------------------------------------------------------------------------------------------|
|
||||||
| `type` | yes | Must be `"sse"` |
|
| `type` | yes | Must be `"sse"` |
|
||||||
| `url` | yes | The server SSE endpoint URL |
|
| `url` | yes | The server SSE endpoint URL |
|
||||||
| `headers` | no | Custom HTTP headers to include with every request |
|
| `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
|
**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
|
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.
|
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
|
## Secret Injection
|
||||||
As mentioned in the [Coyote Vault documentation](Vault), you can use Coyote Vault to inject secrets into your MCP configuration file.
|
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
|
* `.model <tab>` to complete chat models
|
||||||
* `.set <tab>` to complete configuration keys
|
* `.set <tab>` to complete configuration keys
|
||||||
* `.set key <tab>` to complete configuration values
|
* `.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
|
* **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:
|
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`)
|
* `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 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. |
|
| `.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
|
## `.authenticate` - Authenticate the current model client via OAuth
|
||||||
The `.authenticate` command will start the OAuth flow for the current model client if
|
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)
|
* The client supports OAuth (See the [clients documentation](Clients#providers-that-support-oauth) for supported clients)
|
||||||
|
|||||||
Reference in New Issue
Block a user