Forge documentation
Library referenceRust

forge-mcp

Model Context Protocol (MCP) client, server, and transport layer for the Forge SDK

Model Context Protocol (MCP) client, server, and transport layer for the Forge SDK

Package contract

FieldValue
Languagerust
Source version0.2.0
Manifestforge-rs/crates/forge-mcp/Cargo.toml
Source files7
EvidenceSource reference; registry publication and runtime conformance are separate checks

Import boundary

use forge_mcp;

Use a source checkout or your verified private registry. Manifest coordinates identify the package; they do not establish that a public registry release exists.

Crate boundary

The following entries are taken from src/lib.rs. Feature conditions in the exact source still apply.

pub mod auth;

#[cfg(not(target_arch = "wasm32"))]
pub mod client;

pub mod error;

#[cfg(not(target_arch = "wasm32"))]
pub mod server;

#[cfg(not(target_arch = "wasm32"))]
pub mod transport;

pub mod types;

pub mod prelude;

pub use crate::auth::{generate_pkce_challenge, OAuthConfig, PkceChallenge};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::client::{McpClient, McpClientConfig};

pub use crate::error::{ForgeMcpError, ForgeMcpResult};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::server::{McpServer, McpServerConfig};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::transport::{
        create_transport, HttpTransport, McpTransport, SseTransport, StdioTransport,
        TransportConfig,
    };

pub use crate::types::{
        McpCapabilities, McpErrorObject, McpPrompt, McpPromptArgument, McpRequest, McpRequestId,
        McpResource, McpResponse, McpToolDescriptor,
    };

Source reference

Download package reference JSON. Each original source file and generated declaration artifact has its own SHA-256 digest. Function bodies and constant values are omitted from downloads. These are source declaration inventories, not compiler-resolved rustdoc, TypeDoc, DocC, or Dokka output. Private modules can contain public declarations that are not reachable through the package boundary; consult the entry point before importing.

auth.rs

Read declaration text · 3 declaration entries

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OAuthConfig {
/// The OAuth client ID registered with the authorization server.

pub client_id: String,
/// The OAuth client secret, if the client is confidential.

///

/// Public clients (e.g., CLI tools) should leave this as `None`

/// and rely on PKCE for security.

pub client_secret: Option<String>,
/// The redirect URI for receiving the authorization code.

pub redirect_uri: String,
/// The authorization endpoint URL.

pub auth_url: String,
/// The token endpoint URL for exchanging codes for tokens.

pub token_url: String
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PkceChallenge {
/// The code verifier -- a high-entropy random string sent during

/// the token exchange.

pub verifier: String,
/// The code challenge -- the SHA-256 hash of the verifier, Base64url-encoded.

/// Sent during the authorization request.

pub challenge: String,
/// The challenge method (always "S256" for SHA-256).

pub method: String
}

pub fn generate_pkce_challenge(verifier_bytes: &[u8]) -> ForgeMcpResult<PkceChallenge>;

client.rs

Read declaration text · 11 declaration entries

#[derive(Debug, Clone)]
pub struct McpClientConfig {
/// Transport configuration (stdio, SSE, or HTTP).

pub transport: TransportConfig,
/// Optional OAuth configuration for authenticated servers.

pub auth: Option<OAuthConfig>
}

pub struct McpClient {

}

pub async fn connect(config: McpClientConfig) -> ForgeMcpResult<Self>;

pub fn capabilities(&self) -> &McpCapabilities;

pub async fn list_tools(&self) -> ForgeMcpResult<Vec<McpToolDescriptor>>;

pub async fn call_tool(
        &self,
        name: &str,
        arguments: serde_json::Value,
    ) -> ForgeMcpResult<serde_json::Value>;

pub async fn list_resources(&self) -> ForgeMcpResult<Vec<McpResource>>;

pub async fn get_resource(&self, uri: &str) -> ForgeMcpResult<serde_json::Value>;

pub async fn list_prompts(&self) -> ForgeMcpResult<Vec<McpPrompt>>;

pub async fn get_prompt(
        &self,
        name: &str,
        arguments: std::collections::HashMap<String, String>,
    ) -> ForgeMcpResult<serde_json::Value>;

pub async fn disconnect(&self) -> ForgeMcpResult<()>;

error.rs

Read declaration text · 2 declaration entries

#[derive(Debug, Error)]
pub enum ForgeMcpError {
    /// Failed to establish a connection to an MCP server.
    ///
    /// Check that the server is running, the transport configuration is correct,
    /// and the endpoint is reachable.
    #[error("MCP connection to '{endpoint}' failed: {reason}")]
    ConnectionFailed {
        /// The endpoint that was being connected to.
        endpoint: String,
        /// What went wrong during connection.
        reason: String,
    },

    /// A transport-level I/O error occurred.
    ///
    /// This covers read/write failures on the underlying transport (stdio, SSE, HTTP).
    #[error("MCP transport error on '{transport}': {reason}")]
    TransportError {
        /// The transport type (e.g., "stdio", "sse", "http").
        transport: String,
        /// Description of the I/O failure.
        reason: String,
    },

    /// The MCP protocol exchange contained invalid framing or unexpected content.
    ///
    /// This indicates a JSON-RPC framing error, an unrecognized method, or a
    /// protocol version mismatch.
    #[error("MCP protocol error (code={code}): {message}")]
    ProtocolError {
        /// The JSON-RPC error code, or -1 if not applicable.
        code: i64,
        /// Description of the protocol-level failure.
        message: String,
    },

    /// The requested tool was not found on the MCP server.
    ///
    /// Check the tool name spelling and call `list_tools()` to see available tools.
    #[error("MCP tool '{tool_name}' not found; available tools: {}", available.join(", "))]
    ToolNotFound {
        /// The tool name that was looked up.
        tool_name: String,
        /// The tools that are actually available.
        available: Vec<String>,
    },

    /// JSON serialization or deserialization of an MCP message failed.
    #[error("MCP serialization error: {reason}")]
    SerializationError {
        /// What went wrong during serialization.
        reason: String,
    },

    /// Authentication or authorization failed for the MCP connection.
    ///
    /// Check OAuth configuration, client credentials, and token validity.
    #[error("MCP auth error for endpoint '{endpoint}': {reason}")]
    AuthError {
        /// The endpoint that rejected authentication.
        endpoint: String,
        /// Why authentication failed.
        reason: String,
    },

    /// An error propagated from the Forge core layer.
    #[error("Forge core error: {0}")]
    Core(#[from] ForgeError),
}

pub type ForgeMcpResult<T> = Result<T, ForgeMcpError>;

lib.rs

Read declaration text · 13 declaration entries

pub mod auth;

#[cfg(not(target_arch = "wasm32"))]
pub mod client;

pub mod error;

#[cfg(not(target_arch = "wasm32"))]
pub mod server;

#[cfg(not(target_arch = "wasm32"))]
pub mod transport;

pub mod types;

pub mod prelude;

pub use crate::auth::{generate_pkce_challenge, OAuthConfig, PkceChallenge};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::client::{McpClient, McpClientConfig};

pub use crate::error::{ForgeMcpError, ForgeMcpResult};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::server::{McpServer, McpServerConfig};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::transport::{
        create_transport, HttpTransport, McpTransport, SseTransport, StdioTransport,
        TransportConfig,
    };

pub use crate::types::{
        McpCapabilities, McpErrorObject, McpPrompt, McpPromptArgument, McpRequest, McpRequestId,
        McpResource, McpResponse, McpToolDescriptor,
    };

server.rs

Read declaration text · 15 declaration entries

pub type ToolHandler =
    Box<dyn Fn(&str, &serde_json::Value) -> ForgeMcpResult<serde_json::Value> + Send + Sync>;

pub type ResourceHandler = Box<dyn Fn(&str) -> ForgeMcpResult<serde_json::Value> + Send + Sync>;

pub type PromptHandler =
    Box<dyn Fn(&str, &HashMap<String, String>) -> ForgeMcpResult<serde_json::Value> + Send + Sync>;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpServerConfig {
/// Human-readable server name.

pub name: String,
/// Server version string.

pub version: String,
/// Capabilities this server advertises.

pub capabilities: McpCapabilities
}

pub struct McpServer {

}

pub fn new(config: McpServerConfig) -> Self;

pub fn register_tool(&mut self, descriptor: McpToolDescriptor, handler: ToolHandler);

pub fn register_resource(&mut self, resource: McpResource, handler: ResourceHandler);

pub fn register_prompt(&mut self, prompt: McpPrompt, handler: PromptHandler);

pub fn handle_request(&self, request: &McpRequest) -> McpResponse;

pub async fn serve(&self, transport: &dyn McpTransport) -> ForgeMcpResult<()>;

pub fn config(&self) -> &McpServerConfig;

pub fn tool_count(&self) -> usize;

pub fn resource_count(&self) -> usize;

pub fn prompt_count(&self) -> usize;

transport.rs

Read declaration text · 14 declaration entries

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TransportConfig {
    /// Standard I/O transport (stdin/stdout).
    ///
    /// Used when the MCP server is spawned as a child process.
    Stdio,

    /// Server-Sent Events transport.
    ///
    /// The client receives responses via an SSE stream and sends requests
    /// via HTTP POST to a companion endpoint.
    Sse {
        /// The SSE endpoint URL.
        url: String,
    },

    /// HTTP POST transport.
    ///
    /// Both requests and responses use HTTP POST with JSON bodies. This
    /// is the simplest transport for stateless MCP servers.
    Http {
        /// The HTTP endpoint URL.
        url: String,
    },
}

pub fn transport_name(&self) -> &'static str;

pub fn endpoint_url(&self) -> Option<&str>;

#[async_trait]
pub trait McpTransport: Send + Sync {
    /// Sends a JSON-encoded message through the transport.
    ///
    /// # Arguments
    ///
    /// * `message` - The JSON string to send.
    ///
    /// # Errors
    ///
    /// Returns `ForgeMcpError::TransportError` if the write fails.
    async fn send(&self, message: &str) -> ForgeMcpResult<()>;

    /// Receives the next JSON-encoded message from the transport.
    ///
    /// This method blocks (asynchronously) until a message is available
    /// or the transport is closed.
    ///
    /// # Returns
    ///
    /// `Ok(Some(message))` if a message was received, `Ok(None)` if the
    /// transport has been cleanly closed.
    ///
    /// # Errors
    ///
    /// Returns `ForgeMcpError::TransportError` if the read fails.
    async fn receive(&self) -> ForgeMcpResult<Option<String>>;

    /// Closes the transport, releasing any held resources.
    ///
    /// After calling `close()`, subsequent `send()` and `receive()` calls
    /// should return errors.
    ///
    /// # Errors
    ///
    /// Returns `ForgeMcpError::TransportError` if the close fails.
    async fn close(&self) -> ForgeMcpResult<()>;
}

pub struct StdioTransport {

}

pub fn new() -> Self;

pub fn from_streams<R, W>(reader: R, writer: W) -> Self
    where
        R: AsyncRead + Send + 'static,
        W: AsyncWrite + Send + 'static,;

pub struct SseTransport {

}

pub fn new(url: impl Into<String>) -> Self;

pub fn url(&self) -> &str;

pub struct HttpTransport {

}

pub fn new(url: impl Into<String>) -> Self;

pub fn url(&self) -> &str;

pub fn create_transport(config: &TransportConfig) -> Box<dyn McpTransport>;

types.rs

Read declaration text · 14 declaration entries

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct McpToolDescriptor {
/// The unique tool name within the server.

pub name: String,
/// Human-readable description of what the tool does.

pub description: String,
/// JSON Schema for the tool's input parameters.

#[serde(rename = "inputSchema")]
pub input_schema: serde_json::Value
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct McpResource {
/// The resource URI (e.g., `file:///path` or `https://...`).

pub uri: String,
/// Human-readable resource name.

pub name: String,
/// Optional description of the resource.

#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// Optional MIME type of the resource content.

#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "mimeType")]
pub mime_type: Option<String>
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct McpPrompt {
/// Unique prompt name within the server.

pub name: String,
/// Optional description of the prompt's purpose.

#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// Arguments that the prompt template accepts.

#[serde(default)]
pub arguments: Vec<McpPromptArgument>
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct McpPromptArgument {
/// Argument name.

pub name: String,
/// Optional description of the argument.

#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// Whether this argument is required.

#[serde(default)]
pub required: bool
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct McpRequest {
/// JSON-RPC version string (always "2.0").

pub jsonrpc: String,
/// Request identifier for matching responses to requests.

pub id: McpRequestId,
/// The MCP method to invoke (e.g., `tools/list`, `tools/call`).

pub method: String,
/// Optional method parameters.

#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<serde_json::Value>
}

pub fn new(
        id: McpRequestId,
        method: impl Into<String>,
        params: Option<serde_json::Value>,
    ) -> Self;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct McpResponse {
/// JSON-RPC version string (always "2.0").

pub jsonrpc: String,
/// The request identifier this response corresponds to.

pub id: McpRequestId,
/// The successful result, if the request succeeded.

#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<serde_json::Value>,
/// The error object, if the request failed.

#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<McpErrorObject>
}

pub fn is_success(&self) -> bool;

pub fn is_error(&self) -> bool;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct McpErrorObject {
/// The JSON-RPC error code.

pub code: i64,
/// Human-readable error message.

pub message: String,
/// Optional additional error data.

#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum McpRequestId {
    /// Numeric request identifier.
    Number(u64),
    /// String request identifier.
    Str(String),
    /// Null identifier (for notifications).
    Null,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct McpCapabilities {
/// Whether tool listing and invocation is supported.

#[serde(default)]
pub tools: bool,
/// Whether resource listing and reading is supported.

#[serde(default)]
pub resources: bool,
/// Whether prompt listing and retrieval is supported.

#[serde(default)]
pub prompts: bool
}

pub fn all() -> Self;

pub fn none() -> Self;

Continue

On this page