Server

Struct Server 

Source
pub struct Server { /* private fields */ }
Available on non-WebAssembly only.
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

Source

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

Source

pub fn has_tool(&self, name: &str) -> bool

Check if a tool exists

Source

pub fn has_prompt(&self, name: &str) -> bool

Check if a prompt exists

Source

pub fn get_prompt(&self, name: &str) -> Option<&Arc<dyn PromptHandler>>

Get a prompt handler by name

Source

pub fn http_middleware(&self) -> Option<Arc<ServerHttpMiddlewareChain>>

Available on crate feature 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()
};
Source

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.

Source

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)?;
Source

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;
Source

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 initialized
  • None if the client hasn’t initialized yet
Source

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");
}
Source

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()?;
Source

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
Source

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
Source

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();
Source

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());
Source

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 to
  • client_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?;
Source

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 cancel
  • reason - 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?;
Source

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 from
  • client_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?;
Source

pub async fn notify_resource_updated(&self, uri: String) -> Result<usize>

Notify subscribers that a resource has been updated.

§Arguments
  • uri - The URI of the resource that was updated
§Returns

The number of subscribers that were notified.

Trait Implementations§

Source§

impl Debug for Server

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Server

§

impl !RefUnwindSafe for Server

§

impl Send for Server

§

impl Sync for Server

§

impl Unpin for Server

§

impl !UnwindSafe for Server

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more