1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Cloudflare Durable Objects integration for MCP servers.
//!
//! This module provides first-class support for stateful patterns using
//! Cloudflare Durable Objects, enabling:
//!
//! - **Session Persistence**: Streamable HTTP sessions that survive Worker restarts
//! - **State Management**: Per-user/conversation persistent state
//! - **Rate Limiting**: Per-client rate limiting with sliding window
//! - **OAuth Token Storage**: Secure token storage with automatic expiration
//!
//! # Architecture
//!
//! Durable Objects are accessed through stub bindings. You configure the DO
//! binding in your `wrangler.toml`:
//!
//! ```toml
//! [[durable_objects.bindings]]
//! name = "MCP_SESSIONS"
//! class_name = "McpSessionObject"
//!
//! [[durable_objects.bindings]]
//! name = "MCP_STATE"
//! class_name = "McpStateObject"
//!
//! [[durable_objects.bindings]]
//! name = "MCP_RATE_LIMIT"
//! class_name = "McpRateLimitObject"
//! ```
//!
//! # Example: Session Store
//!
//! ```rust,ignore
//! use turbomcp_wasm::wasm_server::durable_objects::DurableObjectSessionStore;
//! use turbomcp_wasm::wasm_server::streamable::StreamableHandler;
//!
//! #[event(fetch)]
//! async fn fetch(req: Request, env: Env, _ctx: Context) -> Result<Response> {
//! let sessions = env.durable_object("MCP_SESSIONS")?;
//! let session_store = DurableObjectSessionStore::new(sessions);
//!
//! let server = MyServer::new()
//! .into_mcp_server()
//! .into_streamable()
//! .with_session_store(session_store);
//!
//! server.handle(req).await
//! }
//! ```
//!
//! # Example: State Store
//!
//! ```rust,ignore
//! use turbomcp_wasm::wasm_server::durable_objects::DurableObjectStateStore;
//!
//! async fn my_tool(ctx: Arc<RequestContext>, args: MyArgs) -> Result<String, ToolError> {
//! let state_store = DurableObjectStateStore::from_env(&env, "MCP_STATE")?;
//!
//! // Get conversation history
//! let history: Vec<Message> = state_store
//! .get(&ctx.session_id().unwrap(), "history")
//! .await
//! .unwrap_or_default();
//!
//! // Process and update
//! let mut history = history;
//! history.push(Message::user(&args.input));
//! state_store.set(&ctx.session_id().unwrap(), "history", &history).await?;
//!
//! Ok("Done".to_string())
//! }
//! ```
//!
//! # Example: Rate Limiting
//!
//! ```rust,ignore
//! use turbomcp_wasm::wasm_server::durable_objects::DurableObjectRateLimiter;
//!
//! let rate_limiter = DurableObjectRateLimiter::from_env(&env, "MCP_RATE_LIMIT")?
//! .with_limit(100) // 100 requests
//! .with_window(60000); // per minute
//!
//! // In middleware
//! if !rate_limiter.check(&client_id).await? {
//! return Err(ToolError::new("Rate limit exceeded"));
//! }
//! ```
pub use ;
pub use DurableObjectSessionStore;
pub use ;
pub use ;