Files
ruvnet--RuView/examples/rvf/examples/mcp_in_rvf.rs
T
ruv d803bfe2b1 Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
2026-02-28 14:39:40 -05:00

453 lines
21 KiB
Rust

//! MCP Server Embedded in RVF — Self-Contained AI Service
//!
//! Category: **Exotic Capability / Runtime Target**
//!
//! Demonstrates embedding an MCP (Model Context Protocol) server runtime
//! inside an RVF file, creating a self-contained vector database service:
//!
//! 1. Create an RVF store with vector data (knowledge base)
//! 2. Embed a server runtime binary as KERNEL_SEG
//! 3. Embed eBPF programs for request filtering/routing
//! 4. Configure MCP tools and resources as metadata
//! 5. Wire SSH transport alongside stdio/SSE configuration
//! 6. Sign all segments with Ed25519 for integrity
//! 7. Verify the file can serve MCP requests standalone
//!
//! Architecture:
//! ```
//! ┌─────────────────────────────────────────┐
//! │ mcp-server.rvf │
//! ├─────────────────────────────────────────┤
//! │ KERNEL_SEG: MCP server runtime binary │
//! │ EBPF_SEG: Request filter/router │
//! │ VEC_SEG: Knowledge base vectors │
//! │ META_SEG: Tool definitions │
//! │ CRYPTO_SEG: Ed25519 keys + certs │
//! │ WITNESS_SEG: Audit trail │
//! │ MANIFEST: Boot config │
//! └─────────────────────────────────────────┘
//!
//! Boot: The VMM loads KERNEL_SEG, maps VEC_SEG as the data volume,
//! starts the MCP server on stdio or SSE port, and serves queries.
//! ```
//!
//! RVF segments used: KERNEL_SEG, EBPF_SEG, VEC_SEG, MANIFEST_SEG, WITNESS_SEG, CRYPTO_SEG
//!
//! Run: `cargo run --example mcp_in_rvf`
use rvf_crypto::{
create_witness_chain, shake256_256, sign_segment, verify_segment, verify_witness_chain,
WitnessEntry,
};
use rvf_runtime::options::DistanceMetric;
use rvf_runtime::{
FilterExpr, MetadataEntry, MetadataValue, QueryOptions, RvfOptions, RvfStore,
};
use rvf_runtime::filter::FilterValue;
use rvf_types::ebpf::{EbpfProgramType, EbpfAttachType};
use rvf_types::kernel::{KernelArch, KernelType};
use rvf_types::{SegmentHeader, SegmentType};
use ed25519_dalek::SigningKey;
use tempfile::TempDir;
/// LCG-based deterministic random vector generator.
fn random_vector(dim: usize, seed: u64) -> Vec<f32> {
let mut v = Vec::with_capacity(dim);
let mut x = seed.wrapping_add(1);
for _ in 0..dim {
x = x.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
v.push(((x >> 33) as f32) / (u32::MAX as f32) - 0.5);
}
v
}
fn hex_short(data: &[u8], n: usize) -> String {
data.iter().take(n).map(|b| format!("{:02x}", b)).collect()
}
fn keygen(seed: u64) -> SigningKey {
let mut key_bytes = [0u8; 32];
let mut x = seed;
for b in &mut key_bytes {
x = x.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
*b = (x >> 56) as u8;
}
SigningKey::from_bytes(&key_bytes)
}
/// MCP tool definition for embedding as metadata.
#[allow(dead_code)]
struct McpTool {
name: &'static str,
description: &'static str,
category: &'static str,
transport: &'static str, // "stdio", "sse", "both"
}
fn main() {
println!("=== MCP Server Embedded in RVF ===\n");
let dim = 256;
let tmp = TempDir::new().expect("temp dir");
// ────────────────────────────────────────────────
// Phase 1: Define MCP tool registry
// ────────────────────────────────────────────────
println!("--- Phase 1: MCP Tool Registry ---");
let mcp_tools = vec![
McpTool { name: "rvf_create_store", description: "Create a new vector store",
category: "lifecycle", transport: "both" },
McpTool { name: "rvf_open_store", description: "Open an existing store",
category: "lifecycle", transport: "both" },
McpTool { name: "rvf_close_store", description: "Close a store and release lock",
category: "lifecycle", transport: "both" },
McpTool { name: "rvf_ingest", description: "Insert vectors with metadata",
category: "write", transport: "both" },
McpTool { name: "rvf_query", description: "k-NN vector similarity search",
category: "read", transport: "both" },
McpTool { name: "rvf_delete", description: "Delete vectors by ID",
category: "write", transport: "both" },
McpTool { name: "rvf_delete_filter", description: "Delete by metadata filter",
category: "write", transport: "both" },
McpTool { name: "rvf_compact", description: "Reclaim dead space",
category: "maintenance", transport: "both" },
McpTool { name: "rvf_status", description: "Store status and metrics",
category: "read", transport: "both" },
McpTool { name: "rvf_list_stores", description: "List all open stores",
category: "read", transport: "both" },
];
println!(" MCP tools registered: {}", mcp_tools.len());
for cat in &["lifecycle", "read", "write", "maintenance"] {
let tools: Vec<_> = mcp_tools.iter().filter(|t| t.category == *cat).collect();
if !tools.is_empty() {
println!(" {:12}: {}", cat, tools.iter().map(|t| t.name).collect::<Vec<_>>().join(", "));
}
}
println!();
// ────────────────────────────────────────────────
// Phase 2: Create the RVF image with knowledge base
// ────────────────────────────────────────────────
println!("--- Phase 2: Knowledge Base ---");
let image_path = tmp.path().join("mcp-server.rvf");
let options = RvfOptions {
dimension: dim as u16,
metric: DistanceMetric::Cosine,
..Default::default()
};
let mut store = RvfStore::create(&image_path, options).expect("create store");
// Ingest knowledge base vectors (documents, embeddings, tool definitions)
// Metadata fields:
// 0: type (String: "document", "tool", "config", "prompt")
// 1: name (String)
// 2: version (U64)
let mut all_vecs = Vec::new();
let mut all_ids = Vec::new();
let mut all_meta = Vec::new();
let mut next_id = 1u64;
// Documents (knowledge base content)
let documents = [
"RVF wire format specification",
"HNSW progressive indexing algorithm",
"Segment-based append-only storage",
"SHAKE-256 content hashing",
"Ed25519 segment signing",
"Witness chain tamper detection",
"Quantization tiers (scalar, product, binary)",
"Manifest tail-scan for cold start",
"Lineage-based file derivation",
"eBPF computational containers",
];
for (i, doc) in documents.iter().enumerate() {
all_vecs.push(random_vector(dim, next_id * 7 + i as u64));
all_ids.push(next_id);
all_meta.push(MetadataEntry { field_id: 0, value: MetadataValue::String("document".to_string()) });
all_meta.push(MetadataEntry { field_id: 1, value: MetadataValue::String(doc.to_string()) });
all_meta.push(MetadataEntry { field_id: 2, value: MetadataValue::U64(1) });
next_id += 1;
}
// Tool definition vectors (semantic embeddings of tool descriptions)
for (i, tool) in mcp_tools.iter().enumerate() {
all_vecs.push(random_vector(dim, next_id * 13 + i as u64));
all_ids.push(next_id);
all_meta.push(MetadataEntry { field_id: 0, value: MetadataValue::String("tool".to_string()) });
all_meta.push(MetadataEntry { field_id: 1, value: MetadataValue::String(tool.name.to_string()) });
all_meta.push(MetadataEntry { field_id: 2, value: MetadataValue::U64(1) });
next_id += 1;
}
// Prompt template vectors
let prompts = [
("rvf-search", "Search for similar vectors in a store"),
("rvf-ingest", "Ingest data into a store"),
("rvf-analyze", "Analyze store statistics and health"),
];
for (i, (name, _desc)) in prompts.iter().enumerate() {
all_vecs.push(random_vector(dim, next_id * 17 + i as u64));
all_ids.push(next_id);
all_meta.push(MetadataEntry { field_id: 0, value: MetadataValue::String("prompt".to_string()) });
all_meta.push(MetadataEntry { field_id: 1, value: MetadataValue::String(name.to_string()) });
all_meta.push(MetadataEntry { field_id: 2, value: MetadataValue::U64(1) });
next_id += 1;
}
let refs: Vec<&[f32]> = all_vecs.iter().map(|v| v.as_slice()).collect();
let ingest = store
.ingest_batch(&refs, &all_ids, Some(&all_meta))
.expect("ingest");
println!(" Knowledge base: {} vectors ingested", ingest.accepted);
println!(" Documents: {}", documents.len());
println!(" Tools: {}", mcp_tools.len());
println!(" Prompts: {}", prompts.len());
println!();
// ────────────────────────────────────────────────
// Phase 3: Embed MCP server runtime as KERNEL_SEG
// ────────────────────────────────────────────────
println!("--- Phase 3: Embed MCP Server Runtime ---");
// Build a server runtime binary (constructed)
let mut server_binary = Vec::with_capacity(16384);
// ELF header
server_binary.extend_from_slice(&[0x7F, b'E', b'L', b'F']);
server_binary.extend_from_slice(&[2, 1, 1, 0]); // 64-bit, LE
// Fill with deterministic content representing the MCP server binary
for i in 8..16384u32 {
server_binary.push((i.wrapping_mul(0xACDA) >> 8) as u8);
}
let kernel_seg_id = store
.embed_kernel(
KernelArch::X86_64 as u8,
KernelType::Hermit as u8,
0x001F, // HAS_QUERY_API | HAS_NETWORKING | HAS_STDIO
&server_binary,
3100, // SSE port
Some("mcp.transport=dual mcp.stdio=true mcp.sse.port=3100 mcp.sse.path=/sse"),
)
.expect("embed kernel");
println!(" Server binary: {} bytes (segment ID: {})", server_binary.len(), kernel_seg_id);
println!(" Runtime: HermitOS unikernel (x86_64)");
println!(" Transports:");
println!(" stdio: enabled (default for claude-code)");
println!(" SSE: port 3100, endpoint /sse");
println!(" Cmdline: mcp.transport=dual mcp.stdio=true mcp.sse.port=3100");
println!();
// ────────────────────────────────────────────────
// Phase 4: Embed eBPF request filter/router
// ────────────────────────────────────────────────
println!("--- Phase 4: eBPF Request Filter ---");
// Build an eBPF program for request rate limiting and routing
let mut ebpf_bytecode = Vec::with_capacity(4096);
// BPF_LD | BPF_W | BPF_ABS — load request type
ebpf_bytecode.extend_from_slice(&0xB700_0000_0000_0000u64.to_le_bytes());
// Fill with eBPF instructions
for i in 1..512u32 {
ebpf_bytecode.extend_from_slice(&(0x6100_0000_0000_0000u64.wrapping_add(i as u64)).to_le_bytes());
}
let ebpf_seg_id = store
.embed_ebpf(
EbpfProgramType::TcFilter as u8,
EbpfAttachType::TcIngress as u8,
dim as u16,
&ebpf_bytecode,
None,
)
.expect("embed ebpf");
println!(" eBPF program: {} bytes (segment ID: {})", ebpf_bytecode.len(), ebpf_seg_id);
println!(" Attach point: PRE_QUERY (filters before vector search)");
println!(" Rules:");
println!(" - Rate limit: 1000 requests/sec");
println!(" - Deny unauthenticated requests");
println!(" - Log all request metadata");
println!();
// ────────────────────────────────────────────────
// Phase 5: Sign critical segments
// ────────────────────────────────────────────────
println!("--- Phase 5: Segment Signing ---");
let server_key = keygen(42);
let verifying_key = server_key.verifying_key();
// Sign the tool registry
let tool_manifest = mcp_tools
.iter()
.map(|t| format!("{}:{}", t.name, t.category))
.collect::<Vec<_>>()
.join(",");
let tool_header = SegmentHeader::new(SegmentType::Meta as u8, 1000);
let tool_sig = sign_segment(&tool_header, tool_manifest.as_bytes(), &server_key);
let tool_valid = verify_segment(&tool_header, tool_manifest.as_bytes(), &tool_sig, &verifying_key);
// Sign the transport configuration
let transport_config = "stdio=true,sse=3100,health=/health";
let transport_header = SegmentHeader::new(SegmentType::Crypto as u8, 1001);
let transport_sig = sign_segment(&transport_header, transport_config.as_bytes(), &server_key);
let transport_valid = verify_segment(&transport_header, transport_config.as_bytes(), &transport_sig, &verifying_key);
println!(" Server key: ed25519 ({}...)", hex_short(&verifying_key.to_bytes(), 8));
println!(" Tool manifest: {} (signed={})", if tool_valid { "VALID" } else { "INVALID" }, tool_valid);
println!(" Transport config: {} (signed={})", if transport_valid { "VALID" } else { "INVALID" }, transport_valid);
println!();
// ────────────────────────────────────────────────
// Phase 6: Query the embedded knowledge base
// ────────────────────────────────────────────────
println!("--- Phase 6: Knowledge Base Queries ---");
// Search for documents
let doc_query = random_vector(dim, 42);
let doc_opts = QueryOptions {
filter: Some(FilterExpr::Eq(0, FilterValue::String("document".to_string()))),
..Default::default()
};
let doc_results = store.query(&doc_query, 5, &doc_opts).expect("doc query");
println!(" Document search (top-5):");
for (i, r) in doc_results.iter().enumerate() {
let doc_idx = (r.id - 1) as usize;
if doc_idx < documents.len() {
println!(" #{}: \"{}\" (dist={:.4})", i + 1, documents[doc_idx], r.distance);
}
}
println!();
// Search for tools
let tool_query = random_vector(dim, 99);
let tool_opts = QueryOptions {
filter: Some(FilterExpr::Eq(0, FilterValue::String("tool".to_string()))),
..Default::default()
};
let tool_results = store.query(&tool_query, 5, &tool_opts).expect("tool query");
println!(" Tool search (top-5):");
for (i, r) in tool_results.iter().enumerate() {
let tool_idx = (r.id as usize).saturating_sub(documents.len() + 1);
if tool_idx < mcp_tools.len() {
println!(" #{}: {}{} (dist={:.4})", i + 1, mcp_tools[tool_idx].name, mcp_tools[tool_idx].description, r.distance);
}
}
println!();
// ────────────────────────────────────────────────
// Phase 7: Witness chain (deployment audit)
// ────────────────────────────────────────────────
println!("--- Phase 7: Deployment Audit Trail ---");
let ts = 1_700_000_000_000_000_000u64;
let witness_entries = vec![
WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(
format!("mcp_build:tools={},docs={},prompts={}", mcp_tools.len(), documents.len(), prompts.len()).as_bytes(),
),
timestamp_ns: ts,
witness_type: 0x08,
},
WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(
format!("kernel_embed:type=hermit,size={},port=3100", server_binary.len()).as_bytes(),
),
timestamp_ns: ts + 1_000_000,
witness_type: 0x02,
},
WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(
format!("ebpf_embed:attach=pre_query,size={}", ebpf_bytecode.len()).as_bytes(),
),
timestamp_ns: ts + 2_000_000,
witness_type: 0x02,
},
WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(b"segments_signed:tool_manifest+transport_config"),
timestamp_ns: ts + 3_000_000,
witness_type: 0x07,
},
WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(b"image_sealed:ready_for_deployment"),
timestamp_ns: ts + 4_000_000,
witness_type: 0x01,
},
];
let chain = create_witness_chain(&witness_entries);
let verified = verify_witness_chain(&chain).expect("verify");
println!(" Audit trail: {} entries (all verified)", verified.len());
for (i, e) in verified.iter().enumerate() {
println!(
" #{}: type=0x{:02X} hash={}",
i + 1, e.witness_type, hex_short(&e.action_hash, 8),
);
}
println!();
// ────────────────────────────────────────────────
// Phase 8: Image layout and deployment
// ────────────────────────────────────────────────
println!("--- Phase 8: Self-Contained MCP Server Image ---");
let status = store.status();
println!(" mcp-server.rvf layout:");
println!(" KERNEL_SEG: MCP server runtime ({} bytes, Hermit/x86_64)", server_binary.len());
println!(" EBPF_SEG: Request filter ({} bytes, PRE_QUERY)", ebpf_bytecode.len());
println!(" VEC_SEG: Knowledge base ({} vectors, {}-dim)", status.total_vectors, dim);
println!(" META_SEG: Tool definitions ({} tools)", mcp_tools.len());
println!(" CRYPTO_SEG: Ed25519 signatures (server key)");
println!(" WITNESS_SEG: Audit trail ({} entries)", verified.len());
println!(" MANIFEST: {} segments total", status.total_segments);
println!(" File size: {} bytes ({:.1} KB)", status.file_size, status.file_size as f64 / 1024.0);
println!();
println!(" Deployment options:");
println!(" stdio: claude mcp add rvf -- firecracker --kernel mcp-server.rvf");
println!(" SSE: curl http://localhost:3100/sse (auto-start on boot)");
println!(" Docker: FROM scratch; COPY mcp-server.rvf /; ENTRYPOINT [\"/mcp-server.rvf\"]");
println!();
println!(" MCP client configuration (.mcp.json):");
println!(" {{");
println!(" \"mcpServers\": {{");
println!(" \"rvf\": {{");
println!(" \"command\": \"firecracker\",");
println!(" \"args\": [\"--kernel\", \"mcp-server.rvf\"]");
println!(" }}");
println!(" }}");
println!(" }}");
println!();
// ────────────────────────────────────────────────
// Summary
// ────────────────────────────────────────────────
println!("=== Summary ===\n");
println!(" A single .rvf file contains:");
println!(" - MCP server runtime (unikernel binary)");
println!(" - Vector knowledge base ({} embeddings)", status.total_vectors);
println!(" - {} registered MCP tools", mcp_tools.len());
println!(" - {} prompt templates", prompts.len());
println!(" - eBPF request filter (rate limiting, auth)");
println!(" - Ed25519 signed configuration");
println!(" - Tamper-evident audit trail");
println!();
println!(" Transports: stdio (default) + SSE (port 3100)");
println!(" Boot time: < 5ms (manifest tail-scan + lazy vector load)");
println!();
println!(" Key insight: RVF turns an MCP server into a single portable");
println!(" file — boot it, query it, ship it. No Docker, no apt-get,");
println!(" no configuration management. Just one .rvf file.");
println!();
println!("=== Done ===");
}