Route CallToolResult content through the render.rs content policy per
plans/mcp-resources-prompts-design.md §6 (T8): oversized text sliced at
TEXT_MAX_BYTES_CLAMP with a self-explaining truncation note, image/audio/
embedded blob content spilled (or inlined when UTF-8-clean) instead of
shipping base64 into model context, and structuredContent subject to the
same ceiling. Clamp server-controlled uri/mime metadata strings to the new
METADATA_MAX_BYTES bound in both the read and tool-result paths, sanitize
the terminal rendering of MCP dispatch errors while keeping raw text in
the tool_call_error payload, and surface resource audience annotations in
both mcp_search results and mcp_read metadata via the catalog.
Implements plans/mcp-resources-prompts-design.md §5.1/§5.4 (T6):
- .prompt <server> <name> [key=value ...] fetches an MCP prompt and
submits the result as chat input via Input::from_str + ask(), never
through REPL line parsing; GetPromptResult messages are flattened
into one user-role block with unconditional [user]/[assistant] labels
- missing required prompt arguments are collected interactively
- .list prompts renders server/name/description/args via the unified
catalog (CatalogItem gains an arguments field), degrading per server
- staged live tab-completion: enabled+running+prompts-capable servers
(no RPC), then live prompt names, then key= argument suggestions with
(required) markers; 2s timeout per RPC, all errors degrade to silent
empty suggestions, ctx read guard dropped before blocking
- the enabled-server alias expansion is factored into a shared helper
used by both tool-scope rebuild and completion
- BREAKING: the former .prompt <text> temp-role builtin is renamed to
.temp-role <text> (behavior preserved); .prompt now belongs to MCP
prompts, and a user macro named prompt or temp-role is shadowed
Per-server McpServerFeatures (tools fail-open, resources/prompts
fail-closed) now drive which meta-functions are declared, with
gated_meta_function_prefixes as the single gating seam; read/prompt
declarations land together with their handlers. The server-enablement
sentinel keys on the always-emitted search name so resources-only
servers survive role filtering.
Implements plans/mcp-resources-prompts-design.md §4.4/D7 (T5).
Single content-policy module for MCP resource and tool content, per
plans/mcp-resources-prompts-design.md §4.5 (T3):
- render_text: UTF-8-boundary-safe paging with clamped max_bytes and
grep-style fancy-regex line filtering (2 lines of context, 1-based
line-number prefixes, merged hunks); offsets walk the filtered stream.
- render_blob/render_blob_at: streaming base64 decode with a 50 MiB
ceiling, UTF-8 sniff, sha256-named 0600 spill files under a sanitized
server dir with a fixed mime->ext allowlist, and best-effort
oldest-first eviction bounding the spill tree at 512 MiB.
Not yet wired to call sites; module carries #![allow(dead_code)] until
the read/prompt surfaces land.
Implements T1 of plans/mcp-resources-prompts-design.md (§4.1, §4.6):
- Replace list_tools(None) with cursor-following list_all_tools() at the
three call sites (start_server catalog build, catalog_items, describe)
so paginating servers no longer silently lose tools past page one.
- Add MCP_READ/MCP_PROMPT prefix constants (declared nowhere yet; wired
in T4/T7) plus centralized helpers MCP_META_FUNCTION_PREFIXES,
is_mcp_meta_function, and mcp_meta_function_names.
- Mechanically replace every hand-rolled 3-prefix starts_with triple
(partition in eval_tool_calls, 3 exclusion triples in
select_enabled_functions, 3 inclusion triples + per-server name
construction in select_enabled_mcp_servers) with the helpers,
preserving the existing lax starts_with matching semantics and the
mcp_invoke_* enablement sentinel (sentinel moves to search in T5).
- Behavior-neutral: dispatch chains keep their 3 arms, emission stays
at exactly 3 meta-functions per server, existing tests unmodified.
- Add unit tests: helper classification, prefix-soundness property,
lax-matching pin, ordered candidate-name construction.
Replace the spawn-time static Authorization header for OAuth-managed HTTP
MCP servers with McpOAuthClient, a custom implementation of rmcp's
StreamableHttpClient trait that resolves the bearer token on every
request via load_or_refresh_mcp_token. Tokens that expire mid-session
now refresh transparently instead of failing tool calls until restart.
On a 401 for an injected token, the wrapper force-refreshes (identity-
aware: a still-unexpired copy of the rejected token is not trusted) and
retries exactly once, matching Claude Code / official SDK semantics.
Both *_with_max_sse_event_size trait methods are overridden to preserve
the inner client's SSE size enforcement, and the inner reqwest client
mirrors rmcp's default (pool_max_idle_per_host(0), no redirects).
SSE, stdio, and static-header HTTP paths are unchanged; startup
warning semantics (McpAuthRequired reasons) are preserved. Verified
live: mid-session backdated token refreshed transparently during an
active atlassian session.
Distinguish why an OAuth MCP server was not started: never authenticated
(no stored credentials), stored token expired and refresh failed, or the
server rejected a token that looked valid. McpTokenStatus replaces the
Option<String> return of load_or_refresh_mcp_token, and McpAuthRequired
carries the reason across the error boundary via anyhow context.