Handler

Trait Handler 

Source
pub trait Handler:
    Send
    + Sync
    + 'static {
    type Input: JsonSchema + DeserializeOwned + Send;
    type Output: JsonSchema + Serialize + Send;
    type Error: Into<Error>;

    // Required method
    fn handle<'life0, 'async_trait>(
        &'life0 self,
        input: Self::Input,
    ) -> Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;

    // Provided methods
    fn input_schema() -> RootSchema { ... }
    fn output_schema() -> RootSchema { ... }
}
Expand description

Core handler abstraction - zero-cost, compatible with pmcp TypedTool.

The Handler trait provides a type-safe interface for implementing MCP tools. It leverages Rust’s type system for compile-time validation and automatic JSON Schema generation.

§Type Parameters

  • Input: The input type, must be deserializable and have a JSON schema
  • Output: The output type, must be serializable and have a JSON schema
  • Error: Error type that can be converted into pforge_runtime::Error

§Examples

§Basic Handler

use pforge_runtime::{Handler, Result};
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;

#[derive(Debug, Deserialize, JsonSchema)]
struct GreetInput {
    name: String,
}

#[derive(Debug, Serialize, JsonSchema)]
struct GreetOutput {
    message: String,
}

struct GreetHandler;

#[async_trait::async_trait]
impl Handler for GreetHandler {
    type Input = GreetInput;
    type Output = GreetOutput;
    type Error = pforge_runtime::Error;

    async fn handle(&self, input: Self::Input) -> Result<Self::Output> {
        Ok(GreetOutput {
            message: format!("Hello, {}!", input.name),
        })
    }
}

§Handler with Validation

use pforge_runtime::{Handler, Result, Error};
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;

#[derive(Debug, Deserialize, JsonSchema)]
struct AgeInput {
    age: i32,
}

#[derive(Debug, Serialize, JsonSchema)]
struct AgeOutput {
    category: String,
}

struct AgeHandler;

#[async_trait::async_trait]
impl Handler for AgeHandler {
    type Input = AgeInput;
    type Output = AgeOutput;
    type Error = Error;

    async fn handle(&self, input: Self::Input) -> Result<Self::Output> {
        if input.age < 0 {
            return Err(Error::Handler("Age cannot be negative".to_string()));
        }

        let category = match input.age {
            0..=12 => "child",
            13..=19 => "teenager",
            20..=64 => "adult",
            _ => "senior",
        }.to_string();

        Ok(AgeOutput { category })
    }
}

Required Associated Types§

Source

type Input: JsonSchema + DeserializeOwned + Send

Input type for the handler

Source

type Output: JsonSchema + Serialize + Send

Output type for the handler

Source

type Error: Into<Error>

Error type that can be converted to pforge_runtime::Error

Required Methods§

Source

fn handle<'life0, 'async_trait>( &'life0 self, input: Self::Input, ) -> Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Execute the handler with type-safe input.

This is the core method where tool logic is implemented. Input is automatically deserialized and output is automatically serialized.

Provided Methods§

Source

fn input_schema() -> RootSchema

Generate JSON schema for input (override for custom schemas).

By default, this derives the schema from the Input type using schemars. Override this method to provide custom validation rules or documentation.

Source

fn output_schema() -> RootSchema

Generate JSON schema for output.

By default, this derives the schema from the Output type using schemars.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§