pub struct Server { /* private fields */ }Expand description
MCP server implementation.
§Examples
use pmcp::{Server, ServerCapabilities, ToolHandler};
use async_trait::async_trait;
use serde_json::Value;
struct MyTool;
#[async_trait]
impl ToolHandler for MyTool {
async fn handle(&self, args: Value, _extra: pmcp::RequestHandlerExtra) -> pmcp::Result<Value> {
Ok(serde_json::json!({"result": "success"}))
}
}
let server = Server::builder()
.name("my-server")
.version("1.0.0")
.tool("my-tool", MyTool)
.build()?;
server.run_stdio().await?;Implementations§
Source§impl Server
impl Server
Sourcepub async fn handle_batch_request(
self: &Arc<Self>,
batch: BatchRequest,
) -> Result<BatchResponse>
pub async fn handle_batch_request( self: &Arc<Self>, batch: BatchRequest, ) -> Result<BatchResponse>
Handle a batch request.
Processes multiple JSON-RPC requests and returns their responses in the same order.
Source§impl Server
impl Server
Sourcepub fn has_prompt(&self, name: &str) -> bool
pub fn has_prompt(&self, name: &str) -> bool
Check if a prompt exists
Sourcepub fn get_prompt(&self, name: &str) -> Option<&Arc<dyn PromptHandler>>
pub fn get_prompt(&self, name: &str) -> Option<&Arc<dyn PromptHandler>>
Get a prompt handler by name
Sourcepub fn http_middleware(&self) -> Option<Arc<ServerHttpMiddlewareChain>>
Available on crate feature streamable-http only.
pub fn http_middleware(&self) -> Option<Arc<ServerHttpMiddlewareChain>>
streamable-http only.Get the HTTP middleware chain configured via ServerBuilder.
Returns the HTTP middleware chain that was set using
ServerBuilder::with_http_middleware(). This can be used when
creating a StreamableHttpServer.
§Examples
use pmcp::Server;
use pmcp::server::streamable_http_server::StreamableHttpServerConfig;
let server = Server::builder()
.name("my-server")
.version("1.0.0")
// ... with_http_middleware() called here
.build()?;
let config = StreamableHttpServerConfig {
http_middleware: server.http_middleware(),
..Default::default()
};Sourcepub fn get_auth_provider(&self) -> Option<Arc<dyn AuthProvider>>
pub fn get_auth_provider(&self) -> Option<Arc<dyn AuthProvider>>
Get the authentication provider configured via ServerBuilder.
Returns the authentication provider that was set using
ServerBuilder::auth_provider(). This can be used by transport
layers to validate incoming requests and extract auth context.
Sourcepub fn build_expansion_registries(
&self,
) -> (HashMap<Arc<str>, ToolInfo>, HashMap<Arc<str>, ResourceInfo>)
pub fn build_expansion_registries( &self, ) -> (HashMap<Arc<str>, ToolInfo>, HashMap<Arc<str>, ResourceInfo>)
Build tool and resource registries for workflow expansion.
Creates HashMap registries that can be used to build an ExpansionContext
for converting workflow prompts to protocol types. The registries are
automatically populated from all registered tools and resources.
Returns a tuple of (tools_map, resources_map) that can be used with
ExpansionContext.
§Examples
use pmcp::Server;
use pmcp::server::workflow::{InternalPromptMessage, ToolHandle, PromptContent, conversion::ExpansionContext};
use pmcp::types::Role;
let server = Server::builder()
.name("example-server")
.version("1.0.0")
.build()?;
// Build registries from registered tools/resources
let (tools, resources) = server.build_expansion_registries();
// Create expansion context
let ctx = ExpansionContext {
tools: &tools,
resources: &resources,
};
// Use it to convert workflow prompts to protocol types
let msg = InternalPromptMessage::new(
Role::System,
PromptContent::ToolHandle(ToolHandle::new("my_tool"))
);
let protocol_msg = msg.to_protocol(&ctx)?;Sourcepub async fn send_notification(&self, notification: ServerNotification)
pub async fn send_notification(&self, notification: ServerNotification)
Send a notification.
Sends a notification to the connected client. Notifications are one-way messages that don’t expect a response.
§Arguments
notification- The server notification to send
§Examples
use pmcp::{Server, ServerNotification, ProgressNotification, ProgressToken};
let server = Server::builder()
.name("example-server")
.version("1.0.0")
.build()?;
// Send a progress notification
let progress = ProgressNotification {
progress_token: ProgressToken::String("task-123".to_string()),
progress: 50.0,
total: None,
message: Some("Processing...".to_string()),
};
server.send_notification(ServerNotification::Progress(progress)).await;Sourcepub async fn get_client_capabilities(&self) -> Option<ClientCapabilities>
pub async fn get_client_capabilities(&self) -> Option<ClientCapabilities>
Get client capabilities.
Returns the capabilities that the client declared during initialization. This can be used to check if the client supports specific features.
§Examples
use pmcp::Server;
let server = Server::builder()
.name("example-server")
.version("1.0.0")
.build()?;
// Check client capabilities after initialization
if let Some(capabilities) = server.get_client_capabilities().await {
if capabilities.sampling.is_some() {
println!("Client supports LLM sampling requests");
}
if capabilities.elicitation.is_some() {
println!("Client supports user input requests");
}
}§Returns
Some(ClientCapabilities)if the client has been initializedNoneif the client hasn’t initialized yet
Sourcepub async fn is_initialized(&self) -> bool
pub async fn is_initialized(&self) -> bool
Check if the server is initialized.
Returns true if the initialization handshake with a client has completed. The server must be initialized before it can process most requests.
§Examples
use pmcp::Server;
let server = Server::builder()
.name("example-server")
.version("1.0.0")
.build()?;
if server.is_initialized().await {
println!("Server is ready to handle requests");
} else {
println!("Waiting for client initialization");
}Sourcepub fn builder() -> ServerBuilder
pub fn builder() -> ServerBuilder
Create a new server builder.
Returns a ServerBuilder for configuring and constructing a new MCP server.
The builder pattern allows you to set server information, capabilities,
and register handlers before building the final server instance.
§Examples
use pmcp::{Server, ToolHandler};
use async_trait::async_trait;
use serde_json::Value;
struct HelloTool;
#[async_trait]
impl ToolHandler for HelloTool {
async fn handle(&self, args: Value, _extra: pmcp::RequestHandlerExtra) -> pmcp::Result<Value> {
Ok(serde_json::json!({"message": "Hello, World!"}))
}
}
let server = Server::builder()
.name("greeting-server")
.version("1.0.0")
.tool("hello", HelloTool{})
.build()?;Sourcepub async fn run_stdio(self) -> Result<()>
pub async fn run_stdio(self) -> Result<()>
Run the server with stdio transport.
Starts the server using stdin/stdout for communication. This is the standard way to run MCP servers as they communicate via JSON-RPC over stdio.
§Examples
use pmcp::{Server, ToolHandler};
use async_trait::async_trait;
use serde_json::Value;
struct EchoTool;
#[async_trait]
impl ToolHandler for EchoTool {
async fn handle(&self, args: Value, _extra: pmcp::RequestHandlerExtra) -> pmcp::Result<Value> {
Ok(args) // Echo the input
}
}
let server = Server::builder()
.name("echo-server")
.version("1.0.0")
.tool("echo", EchoTool{})
.build()?;
// This will run indefinitely, handling client requests
server.run_stdio().await?;§Errors
Returns an error if:
- The stdio transport fails to initialize
- Communication with the client fails
- The server encounters an unrecoverable error
Sourcepub async fn run<T: Transport + 'static>(self, transport: T) -> Result<()>
pub async fn run<T: Transport + 'static>(self, transport: T) -> Result<()>
Run the server with a custom transport.
Starts the server using a custom transport implementation.
This allows for different communication mechanisms beyond stdio,
such as TCP sockets, WebSockets, or other protocols.
§Arguments
transport- The transport implementation to use for communication
§Examples
use pmcp::{Server, StdioTransport, ToolHandler};
use async_trait::async_trait;
use serde_json::Value;
struct CalculatorTool;
#[async_trait]
impl ToolHandler for CalculatorTool {
async fn handle(&self, args: Value, _extra: pmcp::RequestHandlerExtra) -> pmcp::Result<Value> {
let a = args["a"].as_f64().unwrap_or(0.0);
let b = args["b"].as_f64().unwrap_or(0.0);
Ok(serde_json::json!({"result": a + b}))
}
}
let server = Server::builder()
.name("calculator-server")
.version("1.0.0")
.tool("add", CalculatorTool{})
.build()?;
let transport = StdioTransport::new();
server.run(transport).await?;§Errors
Returns an error if:
- The transport fails to initialize or operate
- Communication with the client fails
- The server encounters an unrecoverable error
Sourcepub async fn register_root(
&self,
uri: impl Into<String>,
name: Option<String>,
) -> Result<impl FnOnce() + Send + 'static>
pub async fn register_root( &self, uri: impl Into<String>, name: Option<String>, ) -> Result<impl FnOnce() + Send + 'static>
Register a root directory or URI that the server has access to.
This method allows the server to announce to clients that it has access to specific file system roots or URIs. This is useful for resource handlers that need to expose filesystem access or other URI-based resources.
§Arguments
uri- The root URI to register (e.g.,file:///home/user/project)name- Optional human-readable name for the root
§Returns
An unregister function that can be called to remove the root registration.
§Examples
use pmcp::Server;
let server = Server::builder()
.name("file-server")
.version("1.0.0")
.build()?;
// Register a project root
let unregister = server.register_root(
"file:///home/user/project",
Some("My Project".to_string())
).await?;
// Later, unregister the root
unregister();Sourcepub async fn get_roots(&self) -> Vec<Root>
pub async fn get_roots(&self) -> Vec<Root>
Get the list of registered roots.
Returns a list of all currently registered root URIs and their associated names. Roots are directories or URIs that the server has announced access to.
§Returns
A vector of Root objects containing URI and optional name.
§Examples
use pmcp::Server;
let server = Server::builder()
.name("file-server")
.version("1.0.0")
.build()?;
// Register some roots
server.register_root("file:///home/user/project1", Some("Project 1".to_string())).await?;
server.register_root("file:///home/user/project2", None).await?;
// Get the list of roots
let roots = server.get_roots().await;
println!("Registered {} roots", roots.len());Sourcepub async fn subscribe_resource(
&self,
uri: String,
client_id: String,
) -> Result<()>
pub async fn subscribe_resource( &self, uri: String, client_id: String, ) -> Result<()>
Subscribe a client to resource updates.
This method allows the server to track which clients are interested in updates to specific resources. When a resource changes, the server can notify all subscribed clients.
§Arguments
uri- The resource URI to subscribe toclient_id- Identifier for the subscribing client
§Examples
use pmcp::Server;
let server = Server::builder()
.name("file-server")
.version("1.0.0")
.build()?;
// Subscribe client to resource updates
server.subscribe_resource(
"file:///project/file.txt".to_string(),
"client-123".to_string()
).await?;Sourcepub async fn cancel_request(
&self,
request_id: String,
reason: Option<String>,
) -> Result<()>
pub async fn cancel_request( &self, request_id: String, reason: Option<String>, ) -> Result<()>
Cancel a request that is currently being processed.
This method allows the server to cancel ongoing requests, which is useful for implementing request timeouts or client-requested cancellations.
§Arguments
request_id- The ID of the request to cancelreason- Optional reason for cancellation
§Examples
use pmcp::Server;
let server = Server::builder()
.name("cancel-server")
.version("1.0.0")
.build()?;
// Cancel a request
server.cancel_request(
"request-123".to_string(),
Some("User requested cancellation".to_string())
).await?;Sourcepub async fn unsubscribe_resource(
&self,
uri: String,
client_id: String,
) -> Result<()>
pub async fn unsubscribe_resource( &self, uri: String, client_id: String, ) -> Result<()>
Unsubscribe a client from resource updates.
This method removes a client’s subscription to a specific resource, so they will no longer receive notifications when that resource changes.
§Arguments
uri- The resource URI to unsubscribe fromclient_id- Identifier for the client to unsubscribe
§Examples
use pmcp::Server;
let server = Server::builder()
.name("file-server")
.version("1.0.0")
.build()?;
// Unsubscribe client from resource updates
server.unsubscribe_resource(
"file:///project/file.txt".to_string(),
"client-123".to_string()
).await?;