authorclover caruso <git@paperclover.net> 2026-10-06 23:11:12-07:00
committerclover caruso <git@paperclover.net> 2026-10-09 11:21:14-07:00
log2547169c7c14c468d646a4529194116b1adfb1ee
tree4e5289d7272390afa2421cd922f79340795b93c6
parent4e0a77820c14a4949c590a7beacb75a31502e9cf
signature Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU (~clover)

Disable shared caching of account-specific MCP tool lists


4 files changed, 15 insertions(+), 7 deletions(-)

dashboard/src/observability.rs+4-3
...@@ -2,8 +2,9 @@ use crate::*;...@@ -2,8 +2,9 @@ use crate::*;
2use rmcp::{2use rmcp::{
3 ErrorData, RoleServer, ServerHandler,3 ErrorData, RoleServer, ServerHandler,
4 model::{4 model::{
5 CallToolRequestParams, CallToolResponse, CallToolResult, ContentBlock, ListToolsResult,5 CacheScope, CallToolRequestParams, CallToolResponse, CallToolResult, ContentBlock,
6 PaginatedRequestParams, ServerCapabilities, ServerConfig, Tool, ToolAnnotations,6 ListToolsResult, PaginatedRequestParams, ServerCapabilities, ServerConfig, Tool,
7 ToolAnnotations,
7 },8 },
8 service::RequestContext,9 service::RequestContext,
9};10};
...@@ -27,7 +28,7 @@ impl ServerHandler for Observability {...@@ -27,7 +28,7 @@ impl ServerHandler for Observability {
27 let mut properties = json!({"service":{"type":"string"},"q":{"type":"string"},"limit":{"type":"integer","minimum":1,"maximum":500}});28 let mut properties = json!({"service":{"type":"string"},"q":{"type":"string"},"limit":{"type":"integer","minimum":1,"maximum":500}});
28 let required = if name=="get_trace" { properties=json!({"service":{"type":"string"},"trace_id":{"type":"string"}}); json!(["service","trace_id"]) } else {json!(["service"])};29 let required = if name=="get_trace" { properties=json!({"service":{"type":"string"},"trace_id":{"type":"string"}}); json!(["service","trace_id"]) } else {json!(["service"])};
29 Tool::new(name, description, json!({"type":"object","properties":properties,"required":required,"additionalProperties":false}).as_object().unwrap().clone()).with_annotations(ToolAnnotations::new().read_only(true))30 Tool::new(name, description, json!({"type":"object","properties":properties,"required":required,"additionalProperties":false}).as_object().unwrap().clone()).with_annotations(ToolAnnotations::new().read_only(true))
30 }).collect(), ..Default::default() })31 }).collect(), ttl_ms: Some(0), cache_scope: Some(CacheScope::Private), ..Default::default() })
31 }32 }
32 async fn call_tool(33 async fn call_tool(
33 &self,34 &self,
dashboard/src/relay.rs+5-2
...@@ -5,8 +5,9 @@ use mcp::{delete, get, hash, list, put, secret};...@@ -5,8 +5,9 @@ use mcp::{delete, get, hash, list, put, secret};
5use rmcp::{5use rmcp::{
6 ErrorData, RoleServer, ServerHandler,6 ErrorData, RoleServer, ServerHandler,
7 model::{7 model::{
8 CallToolRequestParams, CallToolResponse, CallToolResult, ContentBlock, ListToolsResult,8 CacheScope, CallToolRequestParams, CallToolResponse, CallToolResult, ContentBlock,
9 PaginatedRequestParams, ServerCapabilities, ServerConfig, Tool, ToolAnnotations,9 ListToolsResult, PaginatedRequestParams, ServerCapabilities, ServerConfig, Tool,
10 ToolAnnotations,
10 },11 },
11 service::RequestContext,12 service::RequestContext,
12};13};
...@@ -681,6 +682,8 @@ impl ServerHandler for Agents {...@@ -681,6 +682,8 @@ impl ServerHandler for Agents {
681 }).collect();682 }).collect();
682 Ok(ListToolsResult {683 Ok(ListToolsResult {
683 tools,684 tools,
685 ttl_ms: Some(0),
686 cache_scope: Some(CacheScope::Private),
684 ..Default::default()687 ..Default::default()
685 })688 })
686 }689 }
tools/dashboard-mcp-test.py+3-1
...@@ -133,7 +133,9 @@ def main():...@@ -133,7 +133,9 @@ def main():
133 http("/oauth/token", "POST", form, form=True, status=400)133 http("/oauth/token", "POST", form, form=True, status=400)
134 token = tokens["access_token"]134 token = tokens["access_token"]
135 assert rpc(token, "initialize", {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": marker, "version": "1"}})["capabilities"]["tools"] == {}135 assert rpc(token, "initialize", {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": marker, "version": "1"}})["capabilities"]["tools"] == {}
136 tools = rpc(token, "tools/list")["tools"]136 listed = rpc(token, "tools/list")
137 assert listed["ttlMs"] == 0 and listed["cacheScope"] == "private", listed
138 tools = listed["tools"]
137 assert {tool["name"] for tool in tools} == {"get_logs", "get_traces", "get_trace"}139 assert {tool["name"] for tool in tools} == {"get_logs", "get_traces", "get_trace"}
138 assert all(tool["annotations"]["readOnlyHint"] for tool in tools)140 assert all(tool["annotations"]["readOnlyHint"] for tool in tools)
139 refused = rpc(token, "tools/call", {"name": "get_logs", "arguments": {"service": denied}})141 refused = rpc(token, "tools/call", {"name": "get_logs", "arguments": {"service": denied}})
tools/dashboard-relay-test.py+3-1
...@@ -252,7 +252,9 @@ def main():...@@ -252,7 +252,9 @@ def main():
252 assert a1.machine == first["id"] and a2.machine == second["id"]252 assert a1.machine == first["id"] and a2.machine == second["id"]
253 init = rpc(control["key"], "initialize", {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": marker, "version": "1"}})253 init = rpc(control["key"], "initialize", {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": marker, "version": "1"}})
254 assert init["capabilities"]["tools"] == {}254 assert init["capabilities"]["tools"] == {}
255 tools = rpc(control["key"], "tools/list")["tools"]255 listed = rpc(control["key"], "tools/list")
256 assert listed["ttlMs"] == 0 and listed["cacheScope"] == "private", listed
257 tools = listed["tools"]
256 assert len(tools) == 7258 assert len(tools) == 7
257 assert next(t for t in tools if t["name"] == "send_message")["annotations"]["readOnlyHint"] is False259 assert next(t for t in tools if t["name"] == "send_message")["annotations"]["readOnlyHint"] is False
258 call(control["key"], "send_message", {"provider": "codex", "thread_id": str(uuid.uuid4()), "message": "ambiguous fixture"}, error=True)260 call(control["key"], "send_message", {"provider": "codex", "thread_id": str(uuid.uuid4()), "message": "ambiguous fixture"}, error=True)