Menu
Public repository / 1f1e9ee3a896111b3fb2dd86a7295dfd55c1d56a
AkurAI-Notes / crates/notes-mcp/tests/mcp_test.rs
Latest change b78e3a5270c5c5e1b0b04f1da8da4899aa5e4e22 - E06: HTTPS MCP server at /mcp — server.rs + tools.rs + cmd_mcp.rs + bearer auth by Claude Code
use akurai_storage::BTree;
use std::sync::{Arc, Mutex};
fn make_registry() -> notes_mcp::tools::ToolRegistry {
let dir = std::env::temp_dir().join(format!("notes-mcp-test-{}", std::process::id()));
let _ = std::fs::create_dir_all(&dir);
let unique = format!(
"test-{}.db",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
);
let db_path = dir.join(unique);
let db = BTree::open(&db_path).expect("create test db");
let owner_sub = "testuser@example.com".to_string();
notes_mcp::tools::ToolRegistry::new(Arc::new(Mutex::new(db)), None, None, owner_sub)
}
fn create_note_via_tool(
registry: ¬es_mcp::tools::ToolRegistry,
title: &str,
body: &str,
owner: &str,
) {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs() as i64;
let next_id = {
let mut db = registry.db.lock().unwrap();
let next = db
.get(b"_meta:next_note_id")
.ok()
.flatten()
.and_then(|b| String::from_utf8_lossy(&b).parse::<i64>().ok())
.unwrap_or(1);
db.insert(
b"_meta:next_note_id",
format!("{}", next + 1).as_bytes(),
)
.unwrap();
db.commit().unwrap();
next
};
let note = akurai_json::Value::Object(vec![
("id".into(), akurai_json::Value::Int(next_id)),
("title".into(), akurai_json::Value::Str(title.into())),
("body".into(), akurai_json::Value::Str(body.into())),
("ownerSub".into(), akurai_json::Value::Str(owner.into())),
("createdAt".into(), akurai_json::Value::Int(now)),
("updatedAt".into(), akurai_json::Value::Int(now)),
("archived".into(), akurai_json::Value::Bool(false)),
]);
let mut key = b"notes:".to_vec();
key.extend_from_slice(&(next_id as u64).to_be_bytes());
let mut db = registry.db.lock().unwrap();
db.insert(&key, note.to_json().as_bytes()).unwrap();
db.commit().unwrap();
}
#[test]
fn initialize_returns_server_info() {
let registry = make_registry();
let req = r#"{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}"#;
let resp = registry.handle_request(req);
assert!(resp.contains("\"jsonrpc\":\"2.0\""));
assert!(resp.contains("\"protocolVersion\":\"2024-11-05\""));
assert!(resp.contains("\"akurai-notes-mcp\""));
}
#[test]
fn tools_list_returns_all_notes_tools() {
let registry = make_registry();
let req = r#"{"jsonrpc":"2.0","id":2,"method":"tools/list"}"#;
let resp = registry.handle_request(req);
assert!(resp.contains("\"search_notes\""));
assert!(resp.contains("\"semantic_search\""));
assert!(resp.contains("\"get_note\""));
assert!(resp.contains("\"list_notebooks\""));
assert!(resp.contains("\"create_note\""));
assert!(resp.contains("\"update_note\""));
assert!(resp.contains("\"delete_note\""));
assert!(resp.contains("\"add_tag\""));
assert!(resp.contains("\"remove_tag\""));
}
#[test]
fn bad_json_returns_parse_error() {
let registry = make_registry();
let resp = registry.handle_request("not json");
assert!(resp.contains("\"code\":-32700"));
}
#[test]
fn search_notes_returns_owned_only() {
let registry = make_registry();
create_note_via_tool(®istry, "Meeting notes", "Discussed Q3 roadmap", "testuser@example.com");
create_note_via_tool(®istry, "Other note", "Not relevant", "other@example.com");
let req = r#"{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search_notes","arguments":{"query":"meeting"}}}"#;
let resp = registry.handle_request(req);
assert!(resp.contains("Meeting notes"));
}
#[test]
fn get_note_returns_full_note() {
let registry = make_registry();
create_note_via_tool(®istry, "Test Note", "Hello world", "testuser@example.com");
let req = r#"{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_note","arguments":{"id":1}}}"#;
let resp = registry.handle_request(req);
assert!(resp.contains("Test Note"));
assert!(resp.contains("Hello world"));
}
#[test]
fn create_note_inserts_and_returns_id() {
let registry = make_registry();
let req = r#"{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"create_note","arguments":{"title":"New Note","body":"Some body"}}}"#;
let resp = registry.handle_request(req);
assert!(resp.contains("\"result\""));
let get_req = r#"{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"get_note","arguments":{"id":1}}}"#;
let get_resp = registry.handle_request(get_req);
assert!(get_resp.contains("New Note"));
}
#[test]
fn unknown_tool_returns_error() {
let registry = make_registry();
let req = r#"{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"nonexistent","arguments":{}}}"#;
let resp = registry.handle_request(req);
assert!(resp.contains("\"code\":-32603"));
}
#[test]
fn unknown_method_returns_error() {
let registry = make_registry();
let req = r#"{"jsonrpc":"2.0","id":8,"method":"bogus"}"#;
let resp = registry.handle_request(req);
assert!(resp.contains("\"code\":-32601"));
}