Document MCP resources and prompts support
- MCP-Servers: new 'Interacting with MCP Servers' section covering the per-server meta-functions, the unified catalog (kind-aware search and describe, audience annotations), capability gating, mcp_read paging, pattern filtering and template expansion, blob sniff/spill behavior with size ceilings and eviction, bounded tool results, and prompts - REPL: .prompt command (usage, interactive args, result-as-chat-input, staged live tab-completion with silent-empty semantics, macro shadowing), .temp-role rename note, .list prompts row, completion bullet - Roles: temporary roles now use .temp-role (REPL) / --prompt (CLI) - Tools: MCP tool result bounding note and sanitized terminal error text - Home: MCP quick-link mentions resources and prompts - Sidebar: anchors for the new MCP sections
+1
-1
@@ -35,7 +35,7 @@ Coming from [AIChat](https://github.com/sigoden/aichat)? Follow the [migration g
|
|||||||
* [Create Custom TypeScript Tools](Custom-Tools#custom-typescript-based-tools)
|
* [Create Custom TypeScript Tools](Custom-Tools#custom-typescript-based-tools)
|
||||||
* [Create Custom Bash Tools](Custom-Bash-Tools)
|
* [Create Custom Bash Tools](Custom-Bash-Tools)
|
||||||
* [Bash Prompt Utilities](Bash-Prompt-Helpers)
|
* [Bash Prompt Utilities](Bash-Prompt-Helpers)
|
||||||
* [First-Class MCP Server Support](MCP-Servers): Easily connect and interact with MCP servers for advanced functionality.
|
* [First-Class MCP Server Support](MCP-Servers): Easily connect and interact with MCP servers for advanced functionality. Coyote supports all three MCP capabilities: tools, resources, and prompts, with capability-gated meta-tools for the model and a `.prompt` REPL command for invoking server prompts yourself.
|
||||||
* [Macros](Macros): Automate repetitive tasks and workflows with Coyote "scripts" (macros), and invoke them as your own custom REPL commands.
|
* [Macros](Macros): Automate repetitive tasks and workflows with Coyote "scripts" (macros), and invoke them as your own custom REPL commands.
|
||||||
* [RAG](RAG): Retrieval-Augmented Generation for enhanced information retrieval and generation.
|
* [RAG](RAG): Retrieval-Augmented Generation for enhanced information retrieval and generation.
|
||||||
* [Sessions](Sessions): Manage and persist conversational contexts and settings across multiple interactions.
|
* [Sessions](Sessions): Manage and persist conversational contexts and settings across multiple interactions.
|
||||||
|
|||||||
+140
@@ -544,6 +544,143 @@ To pick up new default servers added in a Coyote update, run `coyote --install m
|
|||||||
in the REPL). This **merges** the bundled template into your existing configuration: only servers not already present
|
in the REPL). This **merges** the bundled template into your existing configuration: only servers not already present
|
||||||
in your file are added; your existing servers and any custom secret references are left untouched.
|
in your file are added; your existing servers and any custom secret references are left untouched.
|
||||||
|
|
||||||
|
# Interacting with MCP Servers
|
||||||
|
|
||||||
|
Coyote does not flood the model's context with a separate function declaration for every tool an MCP server exposes.
|
||||||
|
Instead, each enabled server contributes a small set of **meta-functions** the model uses to discover and invoke the
|
||||||
|
server's capabilities on demand:
|
||||||
|
|
||||||
|
| Meta-function | Purpose |
|
||||||
|
|-------------------------|------------------------------------------------------------------------------------------------|
|
||||||
|
| `mcp_search_<server>` | Keyword search over the server's catalog of tools, resources, resource templates, and prompts |
|
||||||
|
| `mcp_describe_<server>` | Fetch the full schema or metadata for exactly one catalog item |
|
||||||
|
| `mcp_invoke_<server>` | Call a tool on the server |
|
||||||
|
| `mcp_read_<server>` | Read a resource (or expand a resource template) from the server |
|
||||||
|
| `mcp_prompt_<server>` | Fetch a server-defined prompt, rendered with the given arguments |
|
||||||
|
|
||||||
|
This keeps the per-server context cost small and constant no matter how large the server is: the model searches for
|
||||||
|
what it needs, describes the matching item to get its exact schema, and then invokes, reads, or fetches it.
|
||||||
|
|
||||||
|
## The Unified Catalog
|
||||||
|
|
||||||
|
`mcp_search_<server>` searches a single catalog spanning everything the server advertises: tools, resources, resource
|
||||||
|
templates, and prompts. Every search result carries a `kind` field (`tool`, `resource`, `resource_template`, or
|
||||||
|
`prompt`) so the model knows whether to follow up with `mcp_invoke`, `mcp_read`, or `mcp_prompt`. Listings follow
|
||||||
|
server-side pagination, so large servers are cataloged completely.
|
||||||
|
|
||||||
|
`mcp_describe_<server>` accepts the same `kind` as an optional parameter (default: `tool`). The `tool` parameter
|
||||||
|
carries the identifier for every kind: a tool name, a resource URI, a template's URI template, or a prompt name.
|
||||||
|
|
||||||
|
* `kind: "tool"` returns the tool's full invocation schema
|
||||||
|
* `kind: "resource"` returns the resource's catalog metadata (URI, MIME type, size)
|
||||||
|
* `kind: "resource_template"` returns the template and its variables
|
||||||
|
* `kind: "prompt"` returns the prompt's name, description, and arguments
|
||||||
|
|
||||||
|
Servers can annotate resources with an intended `audience` (`user` and/or `assistant`). Per the MCP spec this is
|
||||||
|
advisory metadata, not access control, and Coyote surfaces it on both search results and read results so the model
|
||||||
|
(and you) can see who the content was meant for.
|
||||||
|
|
||||||
|
## Capability Gating
|
||||||
|
|
||||||
|
Servers advertise which capabilities they support (tools, resources, prompts) during the connection handshake, and
|
||||||
|
Coyote only emits the meta-functions that make sense for each server:
|
||||||
|
|
||||||
|
| Meta-function | Emitted when... |
|
||||||
|
|----------------|------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `mcp_search` | Always (the catalog degrades per kind, so search works with whatever the server supports) |
|
||||||
|
| `mcp_describe` | Always (same reason) |
|
||||||
|
| `mcp_invoke` | The server advertises tools, **or** the handshake info is unavailable (fail-open: a handshake hiccup never strips a working server's tools) |
|
||||||
|
| `mcp_read` | The server advertises resources |
|
||||||
|
| `mcp_prompt` | The server advertises prompts |
|
||||||
|
|
||||||
|
So a resources-only server still gets `mcp_search`, `mcp_describe`, and `mcp_read`, and never wastes context on an
|
||||||
|
`mcp_invoke` or `mcp_prompt` that would always error.
|
||||||
|
|
||||||
|
## Reading Resources
|
||||||
|
|
||||||
|
`mcp_read_<server>` reads a resource by URI, or expands a resource template with variable values:
|
||||||
|
|
||||||
|
| Parameter | Required | Description |
|
||||||
|
|-------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `uri` | yes | The resource URI, or a resource template with `{var}` placeholders |
|
||||||
|
| `arguments` | no | Template variable values. Only [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570) Level 1 simple substitution is supported; values are percent-encoded |
|
||||||
|
| `pattern` | no | A regex applied to text content: only matching lines are returned, grep-style, with 2 lines of context and line-number prefixes |
|
||||||
|
| `offset` | no | Byte offset for paging text (default: `0`). When `pattern` is set, offsets refer to the **filtered** stream, not the raw resource |
|
||||||
|
| `max_bytes` | no | Maximum text bytes to return (default: `51200`, clamped to `204800`) |
|
||||||
|
|
||||||
|
Text content comes back as a structured result with paging metadata:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"uri": "file:///var/log/app.log",
|
||||||
|
"mime_type": "text/plain",
|
||||||
|
"text": "...",
|
||||||
|
"truncated": true,
|
||||||
|
"total_bytes": 1048576,
|
||||||
|
"next_offset": 51200,
|
||||||
|
"note": "Content truncated; re-call with offset=51200 to continue (max_bytes is clamped to 204800)"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `pattern` filter is applied before slicing, so paging walks the filtered stream: `total_bytes` and `next_offset`
|
||||||
|
describe the filtered content, and for a multi-megabyte log resource, "lines matching ERROR" is one call instead of
|
||||||
|
dozens of pages. When a read returns multiple content items, the paging parameters apply per text item and the whole
|
||||||
|
response is additionally capped at 204800 bytes; items beyond the cap are replaced with a marker naming how many were
|
||||||
|
omitted.
|
||||||
|
|
||||||
|
### Binary Content
|
||||||
|
|
||||||
|
Binary content is **never** inlined into model context. Instead:
|
||||||
|
|
||||||
|
1. Coyote first attempts a UTF-8 decode of the blob. If it decodes cleanly, it is treated as text and paged inline
|
||||||
|
regardless of the server's claimed MIME type (servers mislabel text constantly).
|
||||||
|
2. Genuinely binary content is decoded (up to a 50 MiB ceiling) and written to
|
||||||
|
`<cache_dir>/mcp-resources/<server>/<sha256>.<ext>` with `0600` permissions, and the read returns a
|
||||||
|
self-describing metadata object instead of the bytes:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"spilled": true,
|
||||||
|
"path": "/home/you/.cache/coyote/mcp-resources/github/3b0c44...98fb.png",
|
||||||
|
"uri": "resource://github/chart",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"sniffed": false,
|
||||||
|
"size_bytes": 204812,
|
||||||
|
"sha256": "3b0c44...98fb"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The path is actionable by you, by `execute_command`, by the `fs_*` tools, and by sub-agents, which is more useful
|
||||||
|
than base64 the model cannot act on anyway. The spill directory is bounded: when the `mcp-resources/` tree exceeds
|
||||||
|
512 MiB, the oldest files are evicted best-effort. Files are content-addressed by SHA-256, so re-reading the same
|
||||||
|
content regenerates the identical path. Spilled files are untrusted input: Coyote never executes or auto-opens them.
|
||||||
|
|
||||||
|
## Bounded Tool Results
|
||||||
|
|
||||||
|
The same content policy bounds `mcp_invoke` tool results before they reach the model:
|
||||||
|
|
||||||
|
* Text content larger than 204800 bytes is sliced at a UTF-8 boundary with a truncation note asking the model to
|
||||||
|
re-call with narrower arguments.
|
||||||
|
* Image, audio, and embedded binary content is routed through the same spill pipeline as resource reads: written to
|
||||||
|
disk, with the metadata object returned in its place.
|
||||||
|
* Oversized structured content (beyond the same 204800-byte ceiling once serialized) is replaced with a truncation
|
||||||
|
marker.
|
||||||
|
* Server-supplied metadata strings (URIs, MIME types, and similar) are clamped to 4096 bytes.
|
||||||
|
|
||||||
|
In-bounds results pass through byte-identical, so well-behaved servers are unaffected.
|
||||||
|
|
||||||
|
## Prompts
|
||||||
|
|
||||||
|
Servers that advertise the prompts capability expose named, parameterized message templates rendered server-side.
|
||||||
|
Coyote surfaces them in two places:
|
||||||
|
|
||||||
|
* **For you:** the [`.prompt` REPL command](REPL#prompt---invoke-an-mcp-server-prompt) invokes a prompt and submits
|
||||||
|
the result as your chat input, and `.list prompts` lists every prompt across enabled servers.
|
||||||
|
* **For the model:** the `mcp_prompt_<server>` meta-function takes a `prompt` name and an optional `arguments` object
|
||||||
|
(string values only; prompt arguments have no schemas per the MCP spec) and returns the rendered prompt text as the
|
||||||
|
tool result. Multi-message prompts are flattened into a single block with `[user]` / `[assistant]` labels, and
|
||||||
|
missing required arguments produce an error listing them.
|
||||||
|
|
||||||
# Coyote Configuration
|
# Coyote Configuration
|
||||||
MCP servers, like tools, can be used in a handful of contexts:
|
MCP servers, like tools, can be used in a handful of contexts:
|
||||||
* Inside a session
|
* Inside a session
|
||||||
@@ -553,6 +690,9 @@ MCP servers, like tools, can be used in a handful of contexts:
|
|||||||
|
|
||||||
Each of these has a different configuration and interaction with the global configuration.
|
Each of these has a different configuration and interaction with the global configuration.
|
||||||
|
|
||||||
|
Enabling a server in any of these contexts exposes its capability-gated meta-functions to the model; see
|
||||||
|
[Interacting with MCP Servers](#interacting-with-mcp-servers) above.
|
||||||
|
|
||||||
***Note:** The names of each MCP server referenced in the below configuration properties directly corresponds
|
***Note:** The names of each MCP server referenced in the below configuration properties directly corresponds
|
||||||
to the names given in the `functions/mcp.json` configuration file. So if you change the name of an MCP server
|
to the names given in the `functions/mcp.json` configuration file. So if you change the name of an MCP server
|
||||||
from `slack` to `lucem-slack`, then you need to also update your Coyote configuration accordingly.
|
from `slack` to `lucem-slack`, then you need to also update your Coyote configuration accordingly.
|
||||||
|
|||||||
+56
-3
@@ -18,6 +18,8 @@ things like
|
|||||||
* `.set key <tab>` to complete configuration values
|
* `.set key <tab>` to complete configuration values
|
||||||
* `.mcp auth <tab>` to complete remote MCP server names
|
* `.mcp auth <tab>` to complete remote MCP server names
|
||||||
* `.macro <tab>` to complete macro names and the `enable`/`disable` subcommands
|
* `.macro <tab>` to complete macro names and the `enable`/`disable` subcommands
|
||||||
|
* `.prompt <tab>` to complete MCP servers, then prompt names, then `key=` arguments, queried live from the
|
||||||
|
running servers (see [`.prompt`](#prompt---invoke-an-mcp-server-prompt) below)
|
||||||
* **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`)
|
||||||
@@ -71,12 +73,62 @@ Coyote offers the following commands to manage your roles:
|
|||||||
|
|
||||||
For more information about roles in Coyote and how to build them, refer to the [roles documentation](Roles).
|
For more information about roles in Coyote and how to build them, refer to the [roles documentation](Roles).
|
||||||
|
|
||||||
## `.prompt` - Set a temporary role using a prompt
|
## `.temp-role` - Set a temporary role using a prompt
|
||||||
If you need to create a temporary role that you want to discard after use, you use `.prompt`. `.prompt`-based roles
|
If you need to create a temporary role that you want to discard after use, you use `.temp-role`. `.temp-role`-based
|
||||||
cannot be persisted to a file and saved.
|
roles cannot be persisted to a file and saved.
|
||||||
|
|
||||||
|
> **Renamed from `.prompt`:** this command used to be called `.prompt`. That name now invokes MCP server prompts
|
||||||
|
> (see [`.prompt`](#prompt---invoke-an-mcp-server-prompt) below). If you have muscle memory or macros built around
|
||||||
|
> `.prompt <text>`, update them to `.temp-role <text>`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## `.prompt` - Invoke an MCP server prompt
|
||||||
|
MCP servers can expose [prompts](MCP-Servers#prompts): named, parameterized message templates that are rendered
|
||||||
|
server-side, so the server can embed live data the client never sees. `.prompt` invokes one and submits the rendered
|
||||||
|
result as your chat input:
|
||||||
|
|
||||||
|
```
|
||||||
|
.prompt <server> <name> [key=value ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
.prompt github summarize_pr repo=coyote number=42
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Arguments are named**, matching the prompt's declared argument names (MCP prompt arguments have no positional
|
||||||
|
order). Values containing spaces can be quoted: `key="some value"`.
|
||||||
|
* **Missing required arguments are prompted for interactively**, one at a time, before the prompt is fetched.
|
||||||
|
* **The result is submitted as your chat input**, exactly as if you had typed it. Multi-message prompts are flattened
|
||||||
|
into a single user message with `[user]` / `[assistant]` labels marking each original message's role. The flattened
|
||||||
|
text is never parsed as a REPL command or shell line, so prompt content beginning with `.` or `!` is chatted
|
||||||
|
verbatim, not executed.
|
||||||
|
* **Authentication errors surface here.** If the server's token has expired (or it was never authenticated),
|
||||||
|
`.prompt` reports the auth-required error the same way `mcp_invoke` does; run `.mcp auth <server>` to recover.
|
||||||
|
|
||||||
|
Discover available prompts with `.list prompts`, which prints a `server / name / description / args` table across
|
||||||
|
all enabled servers.
|
||||||
|
|
||||||
|
**Tab completion** is staged and queries the running MCP servers live on every TAB press (bounded by a 2-second
|
||||||
|
timeout per query):
|
||||||
|
|
||||||
|
| Input | Suggestions |
|
||||||
|
|----------------------------------|-----------------------------------------------------------------------------------------------|
|
||||||
|
| `.prompt <TAB>` | Enabled, running servers that advertise the prompts capability |
|
||||||
|
| `.prompt <server> <TAB>` | That server's prompt names, with descriptions |
|
||||||
|
| `.prompt <server> <name> <TAB>` | `key=` suggestions for the prompt's arguments, with required ones marked; keys you've already typed are excluded |
|
||||||
|
|
||||||
|
An empty completion list is silent by design: it means the server is not running or authenticated, or has no
|
||||||
|
prompts, and is not a bug. Completion never starts a server and never triggers an authentication flow; an
|
||||||
|
enabled-but-unauthenticated (or stopped) server simply shows nothing at TAB. Auth recovery happens at invocation,
|
||||||
|
where `.prompt` surfaces the actual error.
|
||||||
|
|
||||||
|
> **Macro shadowing:** built-in commands win name collisions, so a user macro named `prompt` is shadowed by this
|
||||||
|
> command. `.list macros` marks it `shadowed (built-in)`, and you can still run it explicitly with
|
||||||
|
> `.macro prompt [args...]`.
|
||||||
|
|
||||||
## `.skill` - Skill management
|
## `.skill` - Skill management
|
||||||
Skills are modular knowledge or capability packs the LLM can load and unload mid-conversation. Multiple skills can be
|
Skills are modular knowledge or capability packs the LLM can load and unload mid-conversation. Multiple skills can be
|
||||||
loaded at once; their instructions stack and their tools/MCP servers union with the active role/agent/session.
|
loaded at once; their instructions stack and their tools/MCP servers union with the active role/agent/session.
|
||||||
@@ -400,6 +452,7 @@ The `.list` command lists the assets of a given kind, making them discoverable w
|
|||||||
| `.list macros` | List all macros |
|
| `.list macros` | List all macros |
|
||||||
| `.list bundles` | List installed bundles with their source, version, ref pin, and drift status (see [Sharing Configurations](Sharing-Configurations)) |
|
| `.list bundles` | List installed bundles with their source, version, ref pin, and drift status (see [Sharing Configurations](Sharing-Configurations)) |
|
||||||
| `.list skills` | List skills available in this context, with descriptions and a `(loaded)` marker for active skills |
|
| `.list skills` | List skills available in this context, with descriptions and a `(loaded)` marker for active skills |
|
||||||
|
| `.list prompts` | List MCP prompts across all enabled servers (live listing), with each prompt's server, description, and arguments |
|
||||||
| `.list tools` | List the tools that can be enabled/disabled via `.tool [enable\|disable] <name>` (excludes internal tools; in an agent context, lists the agent's tool pool) |
|
| `.list tools` | List the tools that can be enabled/disabled via `.tool [enable\|disable] <name>` (excludes internal tools; in an agent context, lists the agent's tool pool) |
|
||||||
| `.list mcp-servers` | List the MCP servers that can be enabled/disabled via `.mcp [enable\|disable] <name>` (configured servers plus mapping aliases) |
|
| `.list mcp-servers` | List the MCP servers that can be enabled/disabled via `.mcp [enable\|disable] <name>` (configured servers plus mapping aliases) |
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -259,6 +259,7 @@ for more examples.
|
|||||||
|
|
||||||
# Temporary Roles
|
# Temporary Roles
|
||||||
Coyote also enables you to create temporary roles that will be discarded once you're finished with them. This is done via
|
Coyote also enables you to create temporary roles that will be discarded once you're finished with them. This is done via
|
||||||
the `.prompt/--prompt` command:
|
the `.temp-role` REPL command (previously named `.prompt`; that name now invokes [MCP server prompts](REPL#prompt---invoke-an-mcp-server-prompt))
|
||||||
|
or the `--prompt` CLI flag:
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
+9
@@ -204,6 +204,15 @@ the model receives:
|
|||||||
This allows the model to understand that an external service failed and take appropriate action (retry, use an
|
This allows the model to understand that an external service failed and take appropriate action (retry, use an
|
||||||
alternative approach, or inform the user).
|
alternative approach, or inform the user).
|
||||||
|
|
||||||
|
MCP error text shown in your terminal is sanitized (escape sequences are stripped so a misbehaving server cannot
|
||||||
|
drive your terminal); the JSON payload the model receives keeps the raw message.
|
||||||
|
|
||||||
|
## MCP Tool Result Bounding
|
||||||
|
MCP tool results are bounded before they reach the model: text larger than 200 KiB is sliced with a truncation
|
||||||
|
marker, images and binary blobs are written to disk (with a metadata object returned in their place) instead of
|
||||||
|
being inlined as base64, and oversized structured content is replaced with a truncation marker. In-bounds results
|
||||||
|
pass through unchanged. See [MCP Servers: Bounded Tool Results](MCP-Servers#bounded-tool-results) for details.
|
||||||
|
|
||||||
## Why This Matters
|
## Why This Matters
|
||||||
Without proper error propagation, models would only know that "something went wrong" without understanding *what*
|
Without proper error propagation, models would only know that "something went wrong" without understanding *what*
|
||||||
went wrong. By including stderr output and detailed error messages, models can:
|
went wrong. By including stderr output and detailed error messages, models can:
|
||||||
|
|||||||
+3
@@ -36,6 +36,9 @@
|
|||||||
- [Managing from CLI](MCP-Servers#managing-mcp-servers-from-the-cli)
|
- [Managing from CLI](MCP-Servers#managing-mcp-servers-from-the-cli)
|
||||||
- [Workspace-Local Servers](MCP-Servers#workspace-local-mcp-servers)
|
- [Workspace-Local Servers](MCP-Servers#workspace-local-mcp-servers)
|
||||||
- [OAuth Authentication](MCP-Servers#oauth-authentication)
|
- [OAuth Authentication](MCP-Servers#oauth-authentication)
|
||||||
|
- [Interacting with MCP Servers](MCP-Servers#interacting-with-mcp-servers)
|
||||||
|
- [Reading Resources](MCP-Servers#reading-resources)
|
||||||
|
- [Prompts](MCP-Servers#prompts)
|
||||||
- [Sandbox Compatibility](MCP-Servers#sandbox-compatibility)
|
- [Sandbox Compatibility](MCP-Servers#sandbox-compatibility)
|
||||||
|
|
||||||
## Agents
|
## Agents
|
||||||
|
|||||||
Reference in New Issue
Block a user