62 lines
2.5 KiB
Rust
62 lines
2.5 KiB
Rust
mod support;
|
|
use hermes_grocy_mcp::{mcp::McpServer, model::AccessMode};
|
|
use rmcp::{ServiceExt, model::CallToolRequestParams};
|
|
use serde_json::json;
|
|
use std::sync::Arc;
|
|
use support::{MemoryStore, selection};
|
|
#[tokio::test]
|
|
async fn protocol_returns_data_and_policy() {
|
|
let app = axum::Router::new().fallback(|| async { axum::Json(json!([{"id":7,"amount":"2"}])) });
|
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
|
|
let port = listener.local_addr().unwrap().port();
|
|
let api = tokio::spawn(async move { axum::serve(listener, app).await.unwrap() });
|
|
for mode in [AccessMode::Full, AccessMode::ReadOnly] {
|
|
let store = Arc::new(MemoryStore {
|
|
url: format!("http://127.0.0.1:{port}"),
|
|
access: mode,
|
|
key: "synthetic-key".into(),
|
|
});
|
|
let server = McpServer::new(store, selection(), mode);
|
|
let (a, b) = tokio::io::duplex(65536);
|
|
let serving =
|
|
tokio::spawn(async move { server.serve(a).await.unwrap().waiting().await.unwrap() });
|
|
let client = ().serve(b).await.unwrap();
|
|
let tools = client.list_all_tools().await.unwrap();
|
|
assert!(tools.len() > 20);
|
|
if mode == AccessMode::ReadOnly {
|
|
assert!(!tools.iter().any(|t| t.name == "records_delete"));
|
|
} else {
|
|
let delete = tools.iter().find(|t| t.name == "records_delete").unwrap();
|
|
assert_eq!(
|
|
delete.annotations.as_ref().unwrap().destructive_hint,
|
|
Some(true)
|
|
);
|
|
}
|
|
let result = client
|
|
.call_tool(
|
|
CallToolRequestParams::new("stock_list")
|
|
.with_arguments(json!({}).as_object().unwrap().clone()),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
let text = result.content[0].as_text().unwrap();
|
|
let data: serde_json::Value = serde_json::from_str(&text.text).unwrap();
|
|
assert_eq!(Some(data.clone()), result.structured_content);
|
|
assert_eq!(data["data"]["items"][0]["id"], 7);
|
|
assert_ne!(result.is_error, Some(true));
|
|
let invalid = client
|
|
.call_tool(CallToolRequestParams::new("not_a_tool"))
|
|
.await
|
|
.unwrap();
|
|
assert_eq!(invalid.is_error, Some(true));
|
|
assert!(
|
|
!serde_json::to_string(&invalid)
|
|
.unwrap()
|
|
.contains("synthetic-key")
|
|
);
|
|
client.cancel().await.unwrap();
|
|
serving.await.unwrap();
|
|
}
|
|
api.abort();
|
|
}
|