Skip to main content

mcpkit_core/
lib.rs

1//! # mcp-core
2//!
3//! Core types and traits for the Model Context Protocol (MCP) SDK.
4//!
5//! This crate provides the foundational building blocks for the MCP SDK:
6//!
7//! - **Protocol types**: JSON-RPC 2.0 request/response/notification types
8//! - **MCP types**: Tools, resources, prompts, tasks, content, sampling, elicitation
9//! - **Capability negotiation**: Client and server capabilities
10//! - **Error handling**: Unified `McpError` type with rich diagnostics
11//! - **Typestate connection**: Compile-time enforced connection lifecycle
12//!
13//! This crate is runtime-agnostic and does not depend on any async runtime.
14//! It can be used with Tokio, smol, or any other executor.
15//!
16//! # Protocol Version
17//!
18//! This crate implements MCP protocol version **2025-11-25**.
19//!
20//! # Example
21//!
22//! ```rust
23//! use mcpkit_core::{
24//!     types::{Tool, ToolOutput, Content},
25//!     capability::{ServerCapabilities, ServerInfo},
26//!     state::Connection,
27//! };
28//!
29//! // Create a tool definition
30//! let tool = Tool::new("search")
31//!     .description("Search the database")
32//!     .input_schema(serde_json::json!({
33//!         "type": "object",
34//!         "properties": {
35//!             "query": { "type": "string" }
36//!         },
37//!         "required": ["query"]
38//!     }));
39//!
40//! // Create server capabilities
41//! let caps = ServerCapabilities::new()
42//!     .with_tools()
43//!     .with_resources()
44//!     .with_tasks();
45//!
46//! // Create server info
47//! let info = ServerInfo::new("my-server", "1.0.0");
48//! ```
49//!
50//! # Feature Flags
51//!
52//! - **`fancy-errors`**: Enable miette's fancy error reporting with terminal
53//!   colors and formatting.
54//!
55//! - **`jwt`**: Enable JWT validation helpers with JWKS fetching. This adds
56//!   the `auth::jwt` module with functions for validating JWT access tokens
57//!   and fetching JSON Web Key Sets from authorization servers.
58
59#![deny(missing_docs)]
60
61pub mod auth;
62pub mod capability;
63pub mod debug;
64pub mod error;
65pub mod extension;
66pub mod methods;
67pub mod pagination;
68pub mod protocol;
69pub mod protocol_version;
70pub mod schema;
71pub mod state;
72pub mod tasks;
73pub mod types;
74
75// Re-export commonly used types at the crate root
76pub use capability::{
77    ClientCapabilities, ClientInfo, InitializeRequest, InitializeResult, PROTOCOL_VERSION,
78    SUPPORTED_PROTOCOL_VERSIONS, ServerCapabilities, ServerInfo, VersionNegotiationResult,
79    is_version_supported, negotiate_version, negotiate_version_detailed,
80};
81pub use error::{JsonRpcError, McpError, McpResultExt};
82pub use protocol::{Message, Notification, ProgressToken, Request, RequestId, Response};
83pub use protocol_version::ProtocolVersion;
84pub use state::{Closing, Connected, Connection, Disconnected, Initializing, Ready};
85
86/// Prelude module for convenient imports.
87///
88/// # Example
89///
90/// ```rust
91/// use mcpkit_core::prelude::*;
92/// ```
93pub mod prelude {
94    // Re-export common serde types for convenience
95    pub use serde::{Deserialize, Serialize};
96    pub use serde_json::json;
97
98    pub use crate::capability::{
99        ClientCapabilities, ClientInfo, InitializeRequest, InitializeResult, PROTOCOL_VERSION,
100        SUPPORTED_PROTOCOL_VERSIONS, ServerCapabilities, ServerInfo, VersionNegotiationResult,
101        is_version_supported, negotiate_version, negotiate_version_detailed,
102    };
103    pub use crate::error::{McpError, McpResultExt};
104    pub use crate::protocol::{Message, Notification, ProgressToken, Request, RequestId, Response};
105    pub use crate::protocol_version::ProtocolVersion;
106    pub use crate::schema::{Schema, SchemaBuilder, SchemaType};
107    pub use crate::state::{Closing, Connected, Connection, Disconnected, Initializing, Ready};
108    pub use crate::types::{
109        Annotations,
110        // Tool types
111        CallToolResult,
112        // Task types
113        CancelTaskRequest,
114        // Content types
115        Content,
116        // Sampling types
117        CreateMessageRequest,
118        CreateMessageResult,
119        CreateTaskResult,
120        // Elicitation types
121        ElicitAction,
122        ElicitRequest,
123        ElicitResult,
124        ElicitationSchema,
125        // Prompt types
126        GetPromptResult,
127        GetTaskPayloadRequest,
128        GetTaskRequest,
129        ListTasksRequest,
130        ListTasksResult,
131        ModelPreferences,
132        // The JSON object map used by object-typed spec fields
133        Object,
134        Prompt,
135        PromptArgument,
136        PromptMessage,
137        PromptOutput,
138        PropertySchema,
139        // Resource types
140        Resource,
141        ResourceContents,
142        ResourceTemplate,
143        Role,
144        SamplingMessage,
145        StopReason,
146        Task,
147        TaskId,
148        TaskMetadata,
149        TaskProgress,
150        TaskStatus,
151        Tool,
152        ToolAnnotations,
153        ToolOutput,
154    };
155}
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_prelude_imports() {
163        use crate::prelude::*;
164
165        // Just verify that all the types are accessible
166        let _tool = Tool::new("test");
167        let _caps = ServerCapabilities::new().with_tools();
168        let _conn: Connection<Disconnected> = Connection::new();
169    }
170
171    #[test]
172    fn test_protocol_version() {
173        assert_eq!(PROTOCOL_VERSION, "2025-11-25");
174    }
175
176    #[test]
177    fn test_error_context() {
178        use crate::error::McpResultExt;
179
180        fn might_fail() -> Result<(), McpError> {
181            Err(McpError::InternalMessage {
182                message: "something went wrong".to_string(),
183            })
184        }
185
186        let result = might_fail().context("while doing something important");
187        assert!(result.is_err());
188
189        let err = result.unwrap_err();
190        assert!(err.to_string().contains("while doing something important"));
191    }
192}