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
| Field | Value |
|---|---|
| Language | rust |
| Source version | 0.2.0 |
| Manifest | forge-rs/crates/forge-mcp/Cargo.toml |
| Source files | 7 |
| Evidence | Source 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;