Skip to main content

rustapi_mcp/
lib.rs

1//! # rustapi-mcp
2//!
3//! Native [Model Context Protocol (MCP)](https://modelcontextprotocol.io) support for RustAPI.
4//!
5//! This crate turns your RustAPI application into a first-class tool provider for LLMs
6//! and external AI agents (Claude, custom agent runtimes, etc.).
7//!
8//! ## Philosophy
9//!
10//! - **Embedded & opt-in**: Enable with the `protocol-mcp` feature.
11//! - **Zero duplication**: Tool definitions are derived from your existing routes,
12//!   `#[derive(Schema)]` types, and OpenAPI metadata.
13//! - **Security first**: Nothing is exposed as a tool unless you explicitly allow it
14//!   (tags, paths, or manual registration). Destructive operations are hidden by default via
15//!   `ToolPolicy::ReadOnly`.
16//! - **Respect the pipeline**: Every tool invocation goes through your normal middleware,
17//!   interceptors, extractors, validation, and error handling. No secret bypass paths.
18//! - **Permission metadata**: Tools declare "read" vs "write" and whether confirmation is needed.
19//!
20//! ## Current Status
21//!
22//! **Native MCP is implemented and functional** (discovery + real invocation + transport + concurrent runner).
23//!
24//! - Automatic tool discovery from your `#[rustapi_rs::get(...)]` routes + `#[derive(Schema)]` via OpenAPI.
25//! - Full respect for tags (`allowed_tags`) and path prefixes for safe exposure.
26//! - Framework-native permission scoping (`ToolPolicy::ReadOnly` default, `#[mcp(skip)]`, `#[mcp(write, require="confirm")]`).
27//! - Sidecar HTTP server speaking minimal MCP JSON-RPC (initialize, tools/list, tools/call).
28//! - Real `tools/call` execution: calls are proxied to your main RustAPI HTTP server → every layer, interceptor, extractor, validator, and error handler runs exactly as for normal traffic.
29//! - `run_rustapi_and_mcp` (and with shutdown) helpers to run your API + MCP endpoint side-by-side (auto-configures proxying).
30//!
31//! 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.
32//!
33//! ## Quick Example
34//!
35//! ```rust,ignore
36//! use rustapi_rs::prelude::*;
37//! use rustapi_rs::protocol::mcp::{McpConfig, McpServer, run_rustapi_and_mcp};
38//!
39//! #[rustapi_rs::get("/weather/{city}")]
40//! #[rustapi_rs::tag("public")]
41//! async fn get_weather(Path(city): Path<String>) -> Json<Weather> {
42//!     // ...
43//! }
44//!
45//! let app = RustApi::auto();
46//!
47//! let mcp = McpServer::from_rustapi(
48//!     &app,
49//!     McpConfig::new()
50//!         .name("weather-agent")
51//!         .allowed_tags(["public"]),
52//! );
53//!
54//! // Runs your normal HTTP API on :8080 and MCP server on :9090.
55//! // tool calls are automatically proxied back into the main API (full stack).
56//! run_rustapi_and_mcp(app, "0.0.0.0:8080", mcp, "0.0.0.0:9090").await?;
57//! ```
58
59#![warn(missing_docs)]
60#![warn(rustdoc::missing_crate_level_docs)]
61#![deny(clippy::unwrap_used)] // encourage proper error handling from day one
62
63pub mod config;
64pub(crate) mod discovery;
65pub mod error;
66pub mod runner;
67pub mod server;
68pub mod types;
69
70// Re-export the most important items at the crate root for convenience.
71pub use config::{InvocationMode, McpConfig, ToolPolicy};
72pub use error::{McpError, Result};
73pub use runner::{
74    run_concurrently, run_rustapi_and_mcp, run_rustapi_and_mcp_with_shutdown, BoxError,
75};
76pub use server::McpServer;
77pub use types::{McpCapability, McpTool, ToolCallRequest, ToolCallResponse};
78
79// Re-export OpenApiSpec for ergonomic attachment: users can pass app.openapi_spec().clone()
80pub use rustapi_openapi::OpenApiSpec;
81
82/// Prelude for common MCP types.
83pub mod prelude {
84    pub use crate::config::{InvocationMode, McpConfig, ToolPolicy};
85    pub use crate::error::{McpError, Result};
86    pub use crate::runner::{
87        run_concurrently, run_rustapi_and_mcp, run_rustapi_and_mcp_with_shutdown,
88    };
89    pub use crate::server::McpServer;
90    pub use crate::types::{McpTool, ToolCallRequest, ToolCallResponse};
91}
92
93/// Internal module for future transport implementations (HTTP+SSE, stdio, etc.).
94pub(crate) mod transport {
95    // Will contain SSE framing, JSON-RPC handling, etc.
96}
97
98/// Internal helpers for executing tool calls through the normal RustAPI stack.
99pub(crate) mod invocation;