Expand description
§rustapi-mcp
Native Model Context Protocol (MCP) support for RustAPI.
This crate turns your RustAPI application into a first-class tool provider for LLMs and external AI agents (Claude, custom agent runtimes, etc.).
§Philosophy
- Embedded & opt-in: Enable with the
protocol-mcpfeature. - Zero duplication: Tool definitions are derived from your existing routes,
#[derive(Schema)]types, and OpenAPI metadata. - Security first: Nothing is exposed as a tool unless you explicitly allow it
(tags, paths, or manual registration). Destructive operations are hidden by default via
ToolPolicy::ReadOnly. - Respect the pipeline: Every tool invocation goes through your normal middleware, interceptors, extractors, validation, and error handling. No secret bypass paths.
- Permission metadata: Tools declare “read” vs “write” and whether confirmation is needed.
§Current Status
Native MCP is implemented and functional (discovery + real invocation + transport + concurrent runner).
- Automatic tool discovery from your
#[rustapi_rs::get(...)]routes +#[derive(Schema)]via OpenAPI. - Full respect for tags (
allowed_tags) and path prefixes for safe exposure. - Framework-native permission scoping (
ToolPolicy::ReadOnlydefault,#[mcp(skip)],#[mcp(write, require="confirm")]). - Sidecar HTTP server speaking minimal MCP JSON-RPC (initialize, tools/list, tools/call).
- Real
tools/callexecution: calls are proxied to your main RustAPI HTTP server → every layer, interceptor, extractor, validator, and error handler runs exactly as for normal traffic. run_rustapi_and_mcp(and with shutdown) helpers to run your API + MCP endpoint side-by-side (auto-configures proxying).
See memories/native_mcp_orchestration_plan.md for the original roadmap. Invocation currently uses a localhost proxy (correct & simple). An in-process RequestInvoker can be added later for zero network overhead.
§Quick Example
ⓘ
use rustapi_rs::prelude::*;
use rustapi_rs::protocol::mcp::{McpConfig, McpServer, run_rustapi_and_mcp};
#[rustapi_rs::get("/weather/{city}")]
#[rustapi_rs::tag("public")]
async fn get_weather(Path(city): Path<String>) -> Json<Weather> {
// ...
}
let app = RustApi::auto();
let mcp = McpServer::from_rustapi(
&app,
McpConfig::new()
.name("weather-agent")
.allowed_tags(["public"]),
);
// Runs your normal HTTP API on :8080 and MCP server on :9090.
// tool calls are automatically proxied back into the main API (full stack).
run_rustapi_and_mcp(app, "0.0.0.0:8080", mcp, "0.0.0.0:9090").await?;Re-exports§
pub use config::InvocationMode;pub use config::McpConfig;pub use config::ToolPolicy;pub use error::McpError;pub use error::Result;pub use runner::run_concurrently;pub use runner::run_rustapi_and_mcp;pub use runner::run_rustapi_and_mcp_with_shutdown;pub use runner::BoxError;pub use server::McpServer;pub use types::McpCapability;pub use types::McpTool;pub use types::ToolCallRequest;pub use types::ToolCallResponse;
Modules§
- config
- Configuration for the MCP server / integration.
- error
- MCP-specific error types.
- prelude
- Prelude for common MCP types.
- runner
- Concurrent execution helpers to run a normal RustAPI HTTP server side-by-side with an MCP server (on a separate address).
- server
- The main
McpServertype and lifecycle. - types
- Core MCP data types (tool definitions, requests, responses, capabilities).
Structs§
- Open
ApiSpec - OpenAPI 3.1.0 specification