1pub mod auth;
2pub mod common;
3pub mod diagnostics;
4pub mod embeddings;
5pub mod engine;
6pub mod handlers;
7pub mod http;
8pub mod lifecycle;
9pub mod mcp_core;
10pub mod mcp_protocol;
11mod mcp_runtime;
12pub mod path_utils;
13pub mod preprocessing;
14pub mod query;
15pub mod rag;
16pub mod recovery;
17pub mod search;
18pub mod security;
19pub mod startup;
20pub mod storage;
21#[cfg(test)]
22mod tests;
23pub mod tools;
24
25#[cfg(feature = "cli")]
27pub mod progress;
28#[cfg(feature = "cli")]
29pub mod tui;
30
31use anyhow::Result;
32pub use memex_contracts as contracts;
33use tracing::Level;
34
35pub use auth::{
37 AuthDenial, AuthManager, AuthResult, Scope, TokenEntry, TokenStoreFile, TokenStoreV2,
38};
39pub use embeddings::{
40 DEFAULT_REQUIRED_DIMENSION, DimensionAdapter, EmbeddingClient, EmbeddingConfig, MLXBridge,
41 MlxConfig, MlxMergeOptions, ProviderConfig, RerankerConfig, TokenConfig,
42 cross_dimension_search_adapt, estimate_tokens, safe_chunk_size, truncate_to_token_limit,
43 validate_batch_tokens, validate_chunk_tokens,
44};
45pub use handlers::{MCPServer, create_server};
46pub use mcp_core::{
47 McpCore, McpDispatch, McpTransport, shared_initialize_result, shared_tools_list_result,
48};
49pub use mcp_core::{dispatch_mcp_jsonrpc_request, dispatch_mcp_payload, dispatch_mcp_request};
50pub use mcp_runtime::build_mcp_core;
51pub use preprocessing::{
52 IntegrityRecommendation, Message, PreprocessingConfig, PreprocessingStats, Preprocessor,
53 TextIntegrityMetrics,
54};
55pub use query::{
56 LoctreeSuggestion, QueryIntent, QueryRouter, RecommendedSearchMode, RoutingDecision,
57 SearchModeRecommendation, TemporalHints, detect_intent,
58};
59pub use rag::{
60 Chunk as PipelineChunk,
61 ChunkOpts,
62 ChunkProvider,
63 ChunkerKind,
64 ContextPrefixConfig,
65 CrossStoreRecoveryBatchReport,
66 CrossStoreRecoveryReport,
67 CrossStoreRecoveryState,
68 EmbeddedChunk,
69 EnrichedChunk,
70 FileContent,
71 IndexResult,
72 OnionSlice,
73 OnionSliceConfig,
74 OuterSynthesis,
75 PipelineConfig,
76 PipelineEvent,
77 PipelineGovernorConfig,
78 PipelineResult,
79 PipelineSnapshot,
80 PipelineStats,
81 RAGPipeline,
82 SearchOptions,
83 SearchResult,
84 SliceLayer,
85 SliceMode,
86 compute_content_hash,
87 create_enriched_chunks,
88 create_onion_slices,
89 detect_default_chunker,
90 inspect_cross_store_recovery,
91 repair_cross_store_recovery,
92 run_pipeline,
94};
95pub use recovery::{
96 MaintenanceExecution, MergeExecution, RepairExecution, cleanup_versions, collect_garbage,
97 compact_database, merge_databases, repair_writes,
98};
99pub use search::{
100 BM25Config, BM25Index, HybridConfig, HybridSearchResult, HybridSearcher, SearchMode,
101 StemLanguage,
102};
103pub use security::NamespaceSecurityConfig;
104pub use startup::{StartupSchemaGuard, guard_daemon_startup_schema};
105pub use storage::{
106 ChromaDocument, CrossStoreRecoveryBatch, CrossStoreRecoveryDocumentRef,
107 CrossStoreRecoveryStatus, DEFAULT_TABLE_NAME, GcConfig, GcStats, SchemaMigrationReport,
108 SchemaMismatchWriteError, SchemaVersion, StorageManager, TableStats, parse_duration_string,
109 required_columns_for,
110};
111
112pub use engine::{BatchResult, MemexConfig, MemexEngine, MetaFilter, StoreItem};
114pub use lifecycle::{
115 ExportRecord, ImportOutcome, NamespaceMigrationOutcome, ReindexJob, ReindexOutcome,
116 ReprocessJob, ReprocessOutcome, default_reindexed_namespace, export_namespace_jsonl_stream,
117 import_jsonl_bytes_stream, import_jsonl_file, import_jsonl_reader, migrate_namespace_atomic,
118 reindex_namespace, reprocess_jsonl_file,
119};
120
121pub use tools::{
123 ToolDefinition, ToolResult, delete_document, delete_documents_by_filter, get_document,
124 search_documents, store_document, store_documents_batch, tool_definitions,
125};
126
127#[cfg(feature = "cli")]
129pub use progress::IndexProgressTracker;
130#[cfg(feature = "cli")]
131pub use tui::{
132 CheckStatus, HealthCheckItem, HealthCheckResult, HealthChecker, HostDetection, HostKind,
133 WizardConfig, detect_hosts, run_wizard,
134};
135
136#[derive(Debug, Clone)]
137pub struct ServerConfig {
138 pub cache_mb: usize,
140
141 pub db_path: String,
143
144 pub max_request_bytes: usize,
146
147 pub log_level: Level,
149
150 pub allowed_paths: Vec<String>,
154
155 pub security: NamespaceSecurityConfig,
157
158 pub embeddings: EmbeddingConfig,
160
161 pub hybrid: HybridConfig,
163}
164
165impl Default for ServerConfig {
166 fn default() -> Self {
167 Self {
168 cache_mb: 4096,
169 db_path: "~/.rmcp-servers/rust-memex/lancedb".to_string(),
170 max_request_bytes: 5 * 1024 * 1024,
171 log_level: Level::INFO,
172 allowed_paths: vec![],
173 security: NamespaceSecurityConfig::default(),
174 embeddings: EmbeddingConfig::default(),
175 hybrid: HybridConfig::default(),
176 }
177 }
178}
179
180impl ServerConfig {
181 #[doc(alias = "with_db_path")]
182 pub fn with_storage_path(mut self, db_path: impl Into<String>) -> Self {
183 self.db_path = db_path.into();
184 self
185 }
186
187 #[deprecated(note = "use with_storage_path")]
188 pub fn with_db_path(self, db_path: impl Into<String>) -> Self {
189 self.with_storage_path(db_path)
190 }
191}
192
193pub async fn run_stdio_server(config: ServerConfig) -> Result<()> {
195 let server = create_server(config).await?;
196 server.run_stdio().await
197}
198
199#[cfg(test)]
200mod lib_tests {
201 use super::*;
202 use serde_json::json;
203
204 #[test]
205 fn default_config_has_expected_values() {
206 let cfg = ServerConfig::default();
207 assert_eq!(cfg.cache_mb, 4096);
208 assert_eq!(cfg.db_path, "~/.rmcp-servers/rust-memex/lancedb");
209 assert_eq!(cfg.max_request_bytes, 5 * 1024 * 1024);
210 }
211
212 #[test]
213 fn contracts_are_reachable_through_main_crate() {
214 let audit = contracts::audit::AuditResult {
215 namespace: "animals".to_string(),
216 document_count: 4,
217 avg_chunk_length: 256,
218 sentence_integrity: 0.92,
219 word_integrity: 0.94,
220 chunk_quality: 0.9,
221 overall_score: 0.91,
222 recommendation: contracts::audit::AuditRecommendation::Good,
223 passes_threshold: true,
224 };
225 let storage = contracts::stats::StorageMetrics::default();
226 let timeline = contracts::timeline::TimelineFilter {
227 namespace: Some("animals".to_string()),
228 since: Some("2026-04-19".to_string()),
229 gaps_only: false,
230 };
231 let progress = contracts::progress::SseEvent {
232 event: "done".to_string(),
233 id: Some("evt-1".to_string()),
234 data: json!({ "status": "ok" }),
235 };
236
237 let _: rag::AuditResult = audit.clone();
238 let _: http::AuditResult = audit;
239 let _: http::StorageMetrics = storage;
240 let _: http::TimelineFilter = timeline;
241 let _: http::SseEvent = progress;
242 }
243}