feat(mcp): add mcp_read meta-tool for resource reads
Implements plans/mcp-resources-prompts-design.md section 4.3 (T4): mcp_read_<server> declaration and handler wired to render.rs, RFC 6570 Level-1-only URI template expansion, defensive ResourceContents parsing, per-item text paging with pattern filtering, blob spill metadata, an overall 204800-byte multi-content ceiling, dispatch wiring on both eval chains, and a render_text paging-stall guard.
This commit is contained in:
+19
-2
@@ -1,8 +1,6 @@
|
||||
//! Content policy for MCP resource and tool content: UTF-8-boundary-safe text
|
||||
//! paging, grep-style pattern filtering, and spill-to-disk for binary blobs.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::config::paths;
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use base64::read::DecoderReader;
|
||||
@@ -136,6 +134,14 @@ pub fn render_text(
|
||||
while !stream.is_char_boundary(end) {
|
||||
end -= 1;
|
||||
}
|
||||
// A max_bytes smaller than one codepoint would produce an empty page with
|
||||
// next_offset == offset, stalling paging; always advance by at least one.
|
||||
if end == start && start < total_bytes {
|
||||
end += 1;
|
||||
while !stream.is_char_boundary(end) {
|
||||
end += 1;
|
||||
}
|
||||
}
|
||||
let truncated = end < total_bytes;
|
||||
Ok(RenderedText {
|
||||
text: stream[start..end].to_string(),
|
||||
@@ -428,6 +434,17 @@ mod tests {
|
||||
assert!(!rest.truncated);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_bytes_below_one_codepoint_still_advances() {
|
||||
// 'é' is 2 bytes; max_bytes 1 must not stall at next_offset == offset.
|
||||
let rendered = render_text("éa", None, 0, Some(1)).unwrap();
|
||||
|
||||
assert_eq!(rendered.text, "é");
|
||||
assert!(rendered.truncated);
|
||||
assert_eq!(rendered.total_bytes, 3);
|
||||
assert_eq!(rendered.next_offset, Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offset_past_eof_returns_empty() {
|
||||
let rendered = render_text("short", None, 100, None).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user