Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
68 lines
2.5 KiB
Rust
68 lines
2.5 KiB
Rust
//! Integration test — `initialize` handshake response shape.
|
|
//!
|
|
//! Drives `dispatch` directly (library API) so the test does not depend on
|
|
//! spawning the binary. Verifies:
|
|
//! - `serverInfo.name` == "kei-mcp"
|
|
//! - `serverInfo.version` non-empty
|
|
//! - `capabilities.tools`, `.resources`, `.prompts` all present
|
|
//! - client-supplied `protocolVersion` is echoed back
|
|
|
|
use kei_mcp::{dispatch, JsonRpcRequest, ServerContext};
|
|
use serde_json::{json, Value};
|
|
|
|
fn make_request(method: &str, params: Value) -> JsonRpcRequest {
|
|
JsonRpcRequest {
|
|
jsonrpc: "2.0".into(),
|
|
id: Some(json!(1)),
|
|
method: method.into(),
|
|
params: Some(params),
|
|
}
|
|
}
|
|
|
|
fn empty_ctx() -> ServerContext {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let atoms = tmp.path().join("atoms-root");
|
|
let skills = tmp.path().join("skills-root");
|
|
std::fs::create_dir_all(&atoms).unwrap();
|
|
std::fs::create_dir_all(&skills).unwrap();
|
|
let ctx = ServerContext::new(atoms, skills);
|
|
std::mem::forget(tmp); // keep alive — server lifetime
|
|
ctx
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn initialize_returns_server_info() {
|
|
let ctx = empty_ctx();
|
|
let req = make_request("initialize", json!({ "protocolVersion": "2024-11-05" }));
|
|
let resp = dispatch(req, &ctx).await;
|
|
assert_eq!(resp.jsonrpc, "2.0");
|
|
assert_eq!(resp.id, Some(json!(1)));
|
|
let result = resp.result.expect("should have result");
|
|
assert_eq!(result["serverInfo"]["name"], "kei-mcp");
|
|
assert!(result["serverInfo"]["version"].as_str().unwrap().len() > 0);
|
|
assert_eq!(result["protocolVersion"], "2024-11-05");
|
|
assert!(result["capabilities"]["tools"].is_object());
|
|
assert!(result["capabilities"]["resources"].is_object());
|
|
assert!(result["capabilities"]["prompts"].is_object());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn initialize_falls_back_to_default_protocol_when_unset() {
|
|
let ctx = empty_ctx();
|
|
let req = make_request("initialize", json!({}));
|
|
let resp = dispatch(req, &ctx).await;
|
|
let result = resp.result.expect("should have result");
|
|
let pv = result["protocolVersion"].as_str().expect("protocolVersion string");
|
|
assert!(!pv.is_empty(), "default protocol version must not be empty");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn unknown_method_returns_method_not_found() {
|
|
let ctx = empty_ctx();
|
|
let req = make_request("totally/bogus", json!({}));
|
|
let resp = dispatch(req, &ctx).await;
|
|
assert!(resp.result.is_none());
|
|
let e = resp.error.expect("should have error");
|
|
assert_eq!(e.code, -32601);
|
|
assert!(e.message.contains("totally/bogus"));
|
|
}
|