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).
15//! - **Respect the pipeline**: Every tool invocation goes through your normal middleware,
16//!   interceptors, extractors, validation, and error handling. No secret bypass paths.
17//!
18//! ## Current Status
19//!
20//! **Native MCP is implemented and functional** (discovery + real invocation + transport + concurrent runner).
21//!
22//! - Automatic tool discovery from your `#[rustapi_rs::get(...)]` routes + `#[derive(Schema)]` via OpenAPI.
23//! - Full respect for tags (`allowed_tags`) and path prefixes for safe exposure.
24//! - Sidecar HTTP server speaking minimal MCP JSON-RPC (initialize, tools/list, tools/call).
25//! - 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.
26//! - `run_rustapi_and_mcp` (and with shutdown) helpers to run your API + MCP endpoint side-by-side (auto-configures proxying).
27//!
28//! 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.
29//!
30//! ## Quick Example
31//!
32//! ```rust,ignore
33//! use rustapi_rs::prelude::*;
34//! use rustapi_rs::protocol::mcp::{McpConfig, McpServer, run_rustapi_and_mcp};
35//!
36//! #[rustapi_rs::get("/weather/{city}")]
37//! #[rustapi_rs::tag("public")]
38//! async fn get_weather(Path(city): Path<String>) -> Json<Weather> {
39//!     // ...
40//! }
41//!
42//! let app = RustApi::auto();
43//!
44//! let mcp = McpServer::from_rustapi(
45//!     &app,
46//!     McpConfig::new()
47//!         .name("weather-agent")
48//!         .allowed_tags(["public"]),
49//! );
50//!
51//! // Runs your normal HTTP API on :8080 and MCP server on :9090.
52//! // tool calls are automatically proxied back into the main API (full stack).
53//! run_rustapi_and_mcp(app, "0.0.0.0:8080", mcp, "0.0.0.0:9090").await?;
54//! ```
55
56#![warn(missing_docs)]
57#![warn(rustdoc::missing_crate_level_docs)]
58#![deny(clippy::unwrap_used)] // encourage proper error handling from day one
59
60pub mod config;
61pub(crate) mod discovery;
62pub mod error;
63pub mod runner;
64pub mod server;
65pub mod types;
66
67// Re-export the most important items at the crate root for convenience.
68pub use config::{InvocationMode, McpConfig};
69pub use error::{McpError, Result};
70pub use runner::{
71    run_concurrently, run_rustapi_and_mcp, run_rustapi_and_mcp_with_shutdown, BoxError,
72};
73pub use server::McpServer;
74pub use types::{McpCapability, McpTool, ToolCallRequest, ToolCallResponse};
75
76// Re-export OpenApiSpec for ergonomic attachment: users can pass app.openapi_spec().clone()
77pub use rustapi_openapi::OpenApiSpec;
78
79/// Prelude for common MCP types.
80pub mod prelude {
81    pub use crate::config::{InvocationMode, McpConfig};
82    pub use crate::error::{McpError, Result};
83    pub use crate::runner::{
84        run_concurrently, run_rustapi_and_mcp, run_rustapi_and_mcp_with_shutdown,
85    };
86    pub use crate::server::McpServer;
87    pub use crate::types::{McpTool, ToolCallRequest, ToolCallResponse};
88}
89
90/// Internal module for future transport implementations (HTTP+SSE, stdio, etc.).
91pub(crate) mod transport {
92    // Will contain SSE framing, JSON-RPC handling, etc.
93}
94
95/// Internal helpers for executing tool calls through the normal RustAPI stack.
96pub(crate) mod invocation;