Feat/complete native mcp#194
Merged
Merged
Conversation
Introduces a new internal crate (rustapi-mcp) that turns RustAPI applications into first-class MCP tool providers for LLMs and AI agents (Claude, Cursor, custom agents, etc.). Key features: - McpConfig with fine-grained exposure control (allowed_tags, allowed_path_prefixes, admin_token, max_tools) - Automatic tool discovery from OpenAPI spec + annotated routes (reuses existing #[derive(Schema)] and route metadata) - Minimal JSON-RPC-over-HTTP transport (supports initialize + tools/list) - Real tool invocation: calls are proxied as normal HTTP requests back to the main RustAPI server → guarantees that the full middleware stack, interceptors, extractors, validation, and error handling run exactly as for regular traffic - Ergonomic attachment: McpServer::from_rustapi(&app, config), .with_openapi(spec), .with_http_base(...) - Public types: McpTool, ToolCallRequest/Response, InitializeResult, etc. This completes the core of the "Native MCP Orchestration" roadmap item (discovery + invocation + basic transport + runner helpers). See memories/native_mcp_orchestration_plan.md for the original plan.
…er + invocation proxy
- Add rustapi-mcp as workspace member and dependency
- Wire `protocol-mcp` feature in rustapi-rs (and legacy `mcp` alias)
- Expose under `rustapi_rs::protocol::mcp` and in prelude
- Add concurrent runner helpers (run_rustapi_and_mcp, with_shutdown) modeled after rustapi-grpc
- McpServer now supports real `tools/call` via HTTP proxy to main server (when http_base configured)
- Runner automatically configures the proxy base URL
- Linkme registration improvements and diagnostics (warning on 0 routes, public auto_route_count, better docs)
- Updated READMEs and sub-crate docs with recommended short alias usage (`api = { package = rustapi-rs }`) and Native MCP examples
This makes Native MCP actually usable end-to-end:
`McpServer::from_rustapi(...)` + `run_rustapi_and_mcp(...)` gives you a working MCP endpoint that can discover and invoke your routes safely.
…s (reqwest for invocation proxy)
Introduce native MCP (Model Context Protocol) support and developer tooling: add a runnable mcp_tools example, comprehensive end-to-end MCP tests, and cookbook/docs entries for MCP integration. Implement tools/call in the MCP server to proxy invocations through the main RustAPI pipeline and shape responses per the MCP convention (including isError semantics). Export run_rustapi_and_mcp helpers and protocol::mcp in the public API, update dev-dependencies (reqwest, serde) for rustapi-mcp tests, and enable the tokio "signal" feature for rustapi-rs. Update README and CHANGELOG to document the new example, tests, and cookbook recipe.
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request extends RustAPI’s link-time auto-registration documentation and diagnostics, and introduces a new native MCP (Model Context Protocol) integration via a new rustapi-mcp crate, including a concurrent runner, example, and end-to-end tests.
Changes:
- Expanded auto-route/auto-schema documentation and added an explicit warning when
RustApi::auto()collects 0 routes; exposedauto_route_count()for debugging. - Added a new
rustapi-mcpworkspace crate and facade exports to support MCP tool discovery and proxied tool invocation. - Updated README/cookbook/docs to describe recommended crate aliasing (
api::...) and MCP progress, plus added an MCP runnable example and e2e tests.
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates quickstart and feature status notes; recommends api alias and mentions MCP progress. |
| docs/cookbook/src/SUMMARY.md | Adds rustapi-mcp deep-dive + MCP recipe links (currently includes duplicates / missing targets). |
| docs/cookbook/src/recipes/README.md | Adds MCP recipe link (currently duplicated / missing target). |
| docs/cookbook/src/recipes/ai_integration.md | Cross-links TOON guidance to MCP recipe (currently missing target). |
| crates/rustapi-rs/tests/auto_route.rs | Adds notes about linkme flakiness in tests and clarifies assertions/logging. |
| crates/rustapi-rs/src/lib.rs | Re-exports auto_route_count and adds protocol mcp module exports behind feature flags. |
| crates/rustapi-rs/README.md | Expands quickstart with Turkish + aliasing guidance. |
| crates/rustapi-rs/examples/README.md | Documents the new mcp_tools example and how to run it. |
| crates/rustapi-rs/examples/mcp_tools.rs | New runnable example for HTTP + MCP sidecar and tag-based tool exposure. |
| crates/rustapi-rs/Cargo.toml | Adds optional rustapi-mcp dependency + protocol-mcp feature; enables tokio signal for dev targets. |
| crates/rustapi-openapi/src/lib.rs | Re-exports Components (needed by MCP discovery). |
| crates/rustapi-mcp/tests/mcp_e2e.rs | Adds end-to-end MCP tests for initialize/list/call and tag filtering. |
| crates/rustapi-mcp/src/types.rs | Introduces MCP tool/call types and capability model. |
| crates/rustapi-mcp/src/server.rs | Implements minimal JSON-RPC-over-HTTP MCP transport and HTTP-proxy tool execution. |
| crates/rustapi-mcp/src/runner.rs | Adds helpers to run RustAPI HTTP + MCP concurrently (with shutdown). |
| crates/rustapi-mcp/src/lib.rs | Crate root, re-exports, and lint policy for the new MCP crate. |
| crates/rustapi-mcp/src/error.rs | Defines MCP-specific error types. |
| crates/rustapi-mcp/src/discovery.rs | Converts OpenAPI operations into MCP tools + builds input schemas. |
| crates/rustapi-mcp/src/config.rs | Defines McpConfig for tool exposure and transport/auth toggles. |
| crates/rustapi-mcp/Cargo.toml | New crate manifest and dependencies. |
| crates/rustapi-macros/tests/renamed_dependency_support.rs | Adds clarification about renamed-crate + linkme registration behavior. |
| crates/rustapi-macros/src/lib.rs | Improves linkme usage comments and ensures correct #[linkme(crate=...)] emission. |
| crates/rustapi-core/src/lib.rs | Exposes auto_route_count and expands internal macro-support module docs. |
| crates/rustapi-core/src/auto_schema.rs | Expands internal documentation for auto-schema registration. |
| crates/rustapi-core/src/auto_route.rs | Expands internal documentation; formalizes auto_route_count as public API. |
| crates/rustapi-core/src/app.rs | Emits a clear warning when RustApi::auto() collects 0 routes. |
| CHANGELOG.md | Adds entries for MCP example/tests/recipe and docs updates. |
| Cargo.toml | Adds crates/rustapi-mcp to the workspace and workspace dependencies. |
| Cargo.lock | Locks new dependencies/crate graph including rustapi-mcp. |
| api/public/rustapi-rs.all-features.txt | Updates public API snapshot to include MCP exports. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+10
to
+13
| keywords = ["web", "framework", "api", "mcp", "llm", "ai", "agents"] | ||
| categories = ["web-programming::http-server", "network-programming"] | ||
| rust-version.workspace = true | ||
| readme = "README.md" |
Comment on lines
26
to
29
| - [rustapi-ws: The Live Wire](crates/rustapi_ws.md) | ||
| - [rustapi-grpc: The Bridge](crates/rustapi_grpc.md) | ||
| - [rustapi-mcp: The Agent Bridge](crates/rustapi_mcp.md) | ||
| - [cargo-rustapi: The Architect](crates/cargo_rustapi.md) |
Comment on lines
53
to
57
| - [Real-time Chat](recipes/websockets.md) | ||
| - [Server-Side Rendering (SSR)](recipes/server_side_rendering.md) | ||
| - [AI Integration (TOON)](recipes/ai_integration.md) | ||
| - [MCP Integration (Agent Tools)](recipes/mcp_integration.md) | ||
| - [Production Tuning](recipes/high_performance.md) |
| - [Deployment](recipes/deployment.md) | ||
| - [HTTP/3 (QUIC)](recipes/http3_quic.md) | ||
| - [gRPC Integration](recipes/grpc_integration.md) | ||
| - [MCP Integration (Agent Tools)](recipes/mcp_integration.md) |
Comment on lines
33
to
35
| - [AI Integration (TOON)](ai_integration.md) | ||
| - [MCP Integration (Agent Tools)](mcp_integration.md) | ||
| - [Production Tuning](high_performance.md) |
Comment on lines
+477
to
+487
| fn jsonrpc_success_response(id: serde_json::Value, result: serde_json::Value) -> Response<Full<Bytes>> { | ||
| let body = serde_json::json!({ | ||
| "jsonrpc": "2.0", | ||
| "id": id, | ||
| "result": result | ||
| }); | ||
| Response::builder() | ||
| .header("content-type", "application/json") | ||
| .body(Full::new(Bytes::from(serde_json::to_vec(&body).unwrap()))) | ||
| .unwrap() | ||
| } |
Comment on lines
+489
to
+506
| fn jsonrpc_error_response( | ||
| id: serde_json::Value, | ||
| code: i32, | ||
| message: &str, | ||
| ) -> Response<Full<Bytes>> { | ||
| let body = serde_json::json!({ | ||
| "jsonrpc": "2.0", | ||
| "id": id, | ||
| "error": { | ||
| "code": code, | ||
| "message": message | ||
| } | ||
| }); | ||
| Response::builder() | ||
| .header("content-type", "application/json") | ||
| .body(Full::new(Bytes::from(serde_json::to_vec(&body).unwrap()))) | ||
| .unwrap() | ||
| } |
Comment on lines
+459
to
+471
| Err(e) => { | ||
| // Surface execution errors as a successful JSON-RPC but with isError inside the result | ||
| // (this is the MCP convention so the client knows it was a tool-level failure). | ||
| let result = serde_json::json!({ | ||
| "content": [{ | ||
| "type": "text", | ||
| "text": format!("Tool execution error: {}", e) | ||
| }], | ||
| "isError": true | ||
| }); | ||
| Ok(jsonrpc_success_response(id, result)) | ||
| } | ||
| } |
Comment on lines
+93
to
+95
| let http_addr = "0.0.0.0:8080"; | ||
| let mcp_addr = "0.0.0.0:9090"; | ||
|
|
Comment on lines
+545
to
+551
| /// Substitute {param} placeholders in the path template using values from the MCP arguments. | ||
| fn substitute_path_params(template: &str, args: &std::collections::HashMap<String, serde_json::Value>) -> String { | ||
| let mut result = template.to_string(); | ||
| for (key, value) in args { | ||
| let placeholder = format!("{{{}}}", key); | ||
| if result.contains(&placeholder) { | ||
| let val_str = match value { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This pull request introduces several improvements and clarifications to the auto-registration system in the RustAPI framework, enhances documentation for best practices, and adds support for the new MCP protocol and crate. The most significant changes are grouped below:
Auto-Registration System Improvements:
auto_route.rsandauto_schema.rsto explain the link-time registration mechanism, its limitations, and best practices for debugging and manual fallback. The documentation now explicitly warns users about common pitfalls and provides guidance for test and library scenarios. [1] [2] [3] [4]RustApi::auto()when no routes are discovered, helping users quickly diagnose missing handlers or linking issues.auto_route_count()in the public API for easier debugging and introspection, and updated tests to ensure safe behavior even without registered routes. [1] [2] [3]Documentation and Usage Experience:
README.mdwith a recommended short macro prefix (api::get,api::main, etc.) for a cleaner, FastAPI-like experience, including Turkish-language tips for crate aliasing. [1] [2] [3]MCP Protocol and Crate Integration:
rustapi-mcpcrate to the workspace and as a dependency, with corresponding public exports for protocol and runner functions. [1] [2] [3] [4]mcp_toolsexample. [1] [2] [3]Macro and Procedural Macro Infrastructure:
linkmeusage when the crate is renamed, and clarified internal/private API boundaries for macro support. [1] [2] [3] [4]General Codebase Maintenance:
These changes collectively make the framework easier to use, more robust in different build environments, and ready for advanced agent integration scenarios.
References: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20]
Type of Change
Checklist
api/public/*snapshots changed, this PR hasbreakingorfeaturelabelTesting
Please describe the tests that you ran to verify your changes: