| Crates.io | wasmcp |
| lib.rs | wasmcp |
| version | 0.2.8 |
| created_at | 2025-07-07 07:17:21.096286+00 |
| updated_at | 2025-08-26 02:14:37.834451+00 |
| description | Rust SDK for building MCP (Model Context Protocol) WebAssembly components |
| homepage | |
| repository | https://github.com/fastertools/wasmcp |
| max_upload_size | |
| id | 1740832 |
| size | 27,422 |
Rust SDK for MCP WebAssembly components. Zero WIT files, just a proc macro.
[dependencies]
wasmcp = "0.2"
use wasmcp::{mcp_handler, ToolHandler, AsyncToolHandler};
// Sync tool
struct EchoTool;
impl ToolHandler for EchoTool {
const NAME: &'static str = "echo";
const DESCRIPTION: &'static str = "Echo a message";
fn input_schema() -> serde_json::Value {
serde_json::json!({
"type": "object",
"properties": {
"message": { "type": "string" }
},
"required": ["message"]
})
}
fn execute(args: serde_json::Value) -> Result<String, String> {
Ok(format!("Echo: {}", args["message"]))
}
}
// Async tool
struct WeatherTool;
impl AsyncToolHandler for WeatherTool {
const NAME: &'static str = "weather";
const DESCRIPTION: &'static str = "Get weather for a location";
fn input_schema() -> serde_json::Value {
serde_json::json!({
"type": "object",
"properties": {
"location": { "type": "string" }
},
"required": ["location"]
})
}
async fn execute_async(args: serde_json::Value) -> Result<String, String> {
use spin_sdk::http::{Request, send};
let location = args["location"].as_str().ok_or("Missing location")?;
let request = Request::get(&format!("https://api.weather.com?q={}", location));
let response = send(request).await
.map_err(|e| format!("Request failed: {:?}", e))?;
Ok(format!("Weather data for {}", location))
}
}
// Register your tools - no WIT files needed!
#[mcp_handler(
tools(EchoTool, WeatherTool),
)]
mod handler {}
spin_sdk for HTTP, KV, and morestruct ConfigResource;
impl ResourceHandler for ConfigResource {
const URI: &'static str = "config://app";
const NAME: &'static str = "Application Config";
const MIME_TYPE: Option<&'static str> = Some("application/json");
fn read() -> Result<String, String> {
Ok(r#"{"version": "1.0.0"}"#.to_string())
}
}
// Add to handler
#[mcp_handler(
tools(EchoTool),
resources(ConfigResource),
)]
mod handler {}
struct GreetingPrompt;
impl PromptHandler for GreetingPrompt {
const NAME: &'static str = "greeting";
const DESCRIPTION: Option<&'static str> = Some("Generate greeting");
type Arguments = GreetingArgs;
fn resolve(args: serde_json::Value) -> Result<Vec<PromptMessage>, String> {
Ok(vec![
PromptMessage {
role: PromptRole::Assistant,
content: format!("Hello, {}!", args["name"]),
}
])
}
}
// Add to handler
#[mcp_handler(
tools(EchoTool),
prompts(GreetingPrompt),
)]
mod handler {}
cargo component build --release --target wasm32-wasip2
The resulting WASM component works with any MCP gateway (wasmcp-spin, custom, etc).
&'static strspin_executor handles async/awaitApache-2.0