Skip to content

Feat/complete native mcp#194

Merged
Tuntii merged 4 commits into
mainfrom
feat/complete-native-mcp
Jun 13, 2026
Merged

Feat/complete native mcp#194
Tuntii merged 4 commits into
mainfrom
feat/complete-native-mcp

Conversation

@Tuntii

@Tuntii Tuntii commented Jun 13, 2026

Copy link
Copy Markdown
Owner

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:

  • Expanded and clarified documentation in auto_route.rs and auto_schema.rs to 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]
  • Added a warning in RustApi::auto() when no routes are discovered, helping users quickly diagnose missing handlers or linking issues.
  • Exposed 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:

  • Updated the README.md with 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]
  • Improved changelog and feature summary to highlight new MCP protocol support, cookbook recipes, and runnable examples. [1] [2] [3]

MCP Protocol and Crate Integration:

  • Added the new rustapi-mcp crate to the workspace and as a dependency, with corresponding public exports for protocol and runner functions. [1] [2] [3] [4]
  • Documented new MCP features, including end-to-end tests, cookbook recipes, and a runnable mcp_tools example. [1] [2] [3]

Macro and Procedural Macro Infrastructure:

  • Improved macro-generated code to ensure correct linkme usage when the crate is renamed, and clarified internal/private API boundaries for macro support. [1] [2] [3] [4]

General Codebase Maintenance:

  • Minor test and documentation cleanups to improve maintainability and ensure all public APIs are well-covered.

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

  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Test addition or update

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • If api/public/* snapshots changed, this PR has breaking or feature label

Testing

Please describe the tests that you ran to verify your changes:

  • Unit tests
  • Integration tests
  • Manual testing

Tuntii added 4 commits June 13, 2026 18:09
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.
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.
Copilot AI review requested due to automatic review settings June 13, 2026 16:22
@Tuntii
Tuntii merged commit 28b3f60 into main Jun 13, 2026
2 of 7 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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; exposed auto_route_count() for debugging.
  • Added a new rustapi-mcp workspace 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 {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants