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
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user