turul_mcp_task_storage/lib.rs
1//! # Task Storage Abstractions and Implementations
2//!
3//! **Pluggable task storage backends for MCP servers with durable state machines.**
4//!
5//! MCP 2025-11-25 introduces Tasks — durable state machines for long-running operations
6//! (tool calls, sampling, elicitation). This crate provides the `TaskStorage` trait and
7//! an in-memory implementation for development and testing.
8//!
9//! ## Quick Start
10//!
11//! ```rust
12//! use turul_mcp_task_storage::prelude::*;
13//!
14//! # async fn example() -> Result<(), TaskStorageError> {
15//! let storage = InMemoryTaskStorage::new();
16//!
17//! // Create a task
18//! let task = TaskRecord {
19//! task_id: InMemoryTaskStorage::generate_task_id(),
20//! session_id: Some("session-123".to_string()),
21//! status: turul_mcp_protocol::TaskStatus::Working,
22//! status_message: Some("Processing...".to_string()),
23//! created_at: chrono::Utc::now().to_rfc3339(),
24//! last_updated_at: chrono::Utc::now().to_rfc3339(),
25//! ttl: Some(60_000),
26//! poll_interval: Some(5_000),
27//! original_method: "tools/call".to_string(),
28//! original_params: None,
29//! result: None,
30//! meta: None,
31//! };
32//!
33//! let created = storage.create_task(task).await?;
34//!
35//! // Update status with state machine enforcement
36//! let completed = storage.update_task_status(
37//! &created.task_id,
38//! turul_mcp_protocol::TaskStatus::Completed,
39//! Some("Done!".to_string()),
40//! ).await?;
41//! # Ok(())
42//! # }
43//! ```
44//!
45//! ## Architecture
46//!
47//! - **`TaskStorage` trait**: Core abstraction for task CRUD, status updates, pagination
48//! - **`TaskRecord`**: Persistence model (serializable, no runtime handles)
49//! - **`TaskOutcome`**: Success/Error result stored for `tasks/result` retrieval
50//! - **State machine**: Validates transitions per MCP spec lifecycle
51
52// Core modules
53pub mod error;
54#[cfg(feature = "in-memory")]
55pub mod in_memory;
56pub mod prelude;
57pub mod state_machine;
58pub mod traits;
59
60// Durable storage backends
61#[cfg(feature = "dynamodb")]
62pub mod dynamodb;
63#[cfg(feature = "postgres")]
64pub mod postgres;
65#[cfg(feature = "sqlite")]
66pub mod sqlite;
67
68// Parity test suite (shared across all backends)
69#[cfg(test)]
70#[allow(dead_code)]
71pub(crate) mod parity_tests;
72
73// Re-exports for convenience
74pub use error::TaskStorageError;
75#[cfg(feature = "in-memory")]
76pub use in_memory::{InMemoryTaskConfig, InMemoryTaskStorage};
77pub use state_machine::{is_terminal, validate_transition};
78pub use traits::{TaskListPage, TaskOutcome, TaskRecord, TaskStorage};
79
80#[cfg(feature = "dynamodb")]
81pub use dynamodb::{DynamoDbTaskConfig, DynamoDbTaskStorage};
82#[cfg(feature = "postgres")]
83pub use postgres::{PostgresTaskConfig, PostgresTaskStorage};
84#[cfg(feature = "sqlite")]
85pub use sqlite::{SqliteTaskConfig, SqliteTaskStorage};
86
87/// Create a default in-memory task storage instance for development and testing.
88#[cfg(feature = "in-memory")]
89pub fn create_default_storage() -> InMemoryTaskStorage {
90 InMemoryTaskStorage::new()
91}
92
93/// Create an in-memory task storage with custom configuration.
94#[cfg(feature = "in-memory")]
95pub fn create_memory_storage(config: InMemoryTaskConfig) -> InMemoryTaskStorage {
96 InMemoryTaskStorage::with_config(config)
97}