diff --git a/README.md b/README.md index bde1227..8b20245 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ fastmcpp is a C++ port of the Python [fastmcp](https://github.com/jlowin/fastmcp - Resources and prompts support. - Resource templates with URI pattern matching. - JSON Schema validation. -- McpApp high-level application class. +- FastMCP high-level application class. - ProxyApp for backend server proxying. - ServerSession for bidirectional communication, sampling, and server-initiated notifications. - Built-in middleware: Logging, Timing, Caching, RateLimiting, ErrorHandling. diff --git a/include/fastmcpp/app.hpp b/include/fastmcpp/app.hpp index ac7177d..59ad9e0 100644 --- a/include/fastmcpp/app.hpp +++ b/include/fastmcpp/app.hpp @@ -19,7 +19,7 @@ namespace fastmcpp struct MountedApp { std::string prefix; // Prefix for tools/prompts (e.g., "weather") - class McpApp* app; // Non-owning pointer to mounted app + class FastMCP* app; // Non-owning pointer to mounted app }; /// Proxy-mounted app with prefix (proxy mode) @@ -31,15 +31,15 @@ struct ProxyMountedApp /// MCP Application - bundles server metadata with managers /// -/// Similar to Python's FastMCP class. Provides: +/// Equivalent to Python's FastMCP class. Provides: /// - Server metadata (name, version, icons, etc.) /// - Tool, Resource, and Prompt managers /// - App mounting support with prefixes /// /// Usage: /// ```cpp -/// McpApp main_app("MainApp", "1.0"); -/// McpApp weather_app("WeatherApp", "1.0"); +/// FastMCP main_app("MainApp", "1.0"); +/// FastMCP weather_app("WeatherApp", "1.0"); /// /// // Register tools on sub-app /// weather_app.tools().register_tool(get_forecast_tool); @@ -49,13 +49,13 @@ struct ProxyMountedApp /// /// // Tools accessible as "weather_get_forecast" /// ``` -class McpApp +class FastMCP { public: /// Construct app with metadata - explicit McpApp(std::string name = "fastmcpp_app", std::string version = "1.0.0", - std::optional website_url = std::nullopt, - std::optional> icons = std::nullopt); + explicit FastMCP(std::string name = "fastmcpp_app", std::string version = "1.0.0", + std::optional website_url = std::nullopt, + std::optional> icons = std::nullopt); // Metadata accessors const std::string& name() const @@ -125,7 +125,7 @@ class McpApp /// @param app The app to mount (must outlive this app in direct mode) /// @param prefix Optional prefix (empty string = no prefix) /// @param as_proxy If true, mount in proxy mode (uses MCP handler for communication) - void mount(McpApp& app, const std::string& prefix = "", bool as_proxy = false); + void mount(FastMCP& app, const std::string& prefix = "", bool as_proxy = false); /// Get list of directly mounted apps const std::vector& mounted() const diff --git a/include/fastmcpp/mcp/handler.hpp b/include/fastmcpp/mcp/handler.hpp index 80c32fc..fefa482 100644 --- a/include/fastmcpp/mcp/handler.hpp +++ b/include/fastmcpp/mcp/handler.hpp @@ -14,7 +14,7 @@ namespace fastmcpp { -class McpApp; // Forward declaration +class FastMCP; // Forward declaration class ProxyApp; // Forward declaration } // namespace fastmcpp @@ -58,9 +58,9 @@ make_mcp_handler(const std::string& server_name, const std::string& version, const resources::ResourceManager& resources, const prompts::PromptManager& prompts, const std::unordered_map& descriptions = {}); -// MCP handler from McpApp - supports mounted apps with aggregation +// MCP handler from FastMCP - supports mounted apps with aggregation // Uses app's aggregated lists and routing for mounted sub-apps -std::function make_mcp_handler(const McpApp& app); +std::function make_mcp_handler(const FastMCP& app); // MCP handler from ProxyApp - supports proxying to backend server // Uses app's aggregated lists (local + remote) and routing @@ -73,11 +73,11 @@ using SessionAccessor = std::function(con /// The session_accessor callback is used to get ServerSession for sampling requests. /// Session ID is extracted from params._meta.session_id (injected by SSE server). std::function -make_mcp_handler_with_sampling(const McpApp& app, SessionAccessor session_accessor); +make_mcp_handler_with_sampling(const FastMCP& app, SessionAccessor session_accessor); -/// Convenience: create handler from McpApp + SseServerWrapper +/// Convenience: create handler from FastMCP + SseServerWrapper /// Uses the SSE server's get_session() method as the session accessor. std::function -make_mcp_handler_with_sampling(const McpApp& app, server::SseServerWrapper& sse_server); +make_mcp_handler_with_sampling(const FastMCP& app, server::SseServerWrapper& sse_server); } // namespace fastmcpp::mcp diff --git a/src/app.cpp b/src/app.cpp index 165968e..3805293 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -8,13 +8,13 @@ namespace fastmcpp { -McpApp::McpApp(std::string name, std::string version, std::optional website_url, - std::optional> icons) +FastMCP::FastMCP(std::string name, std::string version, std::optional website_url, + std::optional> icons) : server_(std::move(name), std::move(version), std::move(website_url), std::move(icons)) { } -void McpApp::mount(McpApp& app, const std::string& prefix, bool as_proxy) +void FastMCP::mount(FastMCP& app, const std::string& prefix, bool as_proxy) { if (as_proxy) { @@ -40,14 +40,14 @@ void McpApp::mount(McpApp& app, const std::string& prefix, bool as_proxy) // Prefix Utilities // ========================================================================= -std::string McpApp::add_prefix(const std::string& name, const std::string& prefix) +std::string FastMCP::add_prefix(const std::string& name, const std::string& prefix) { if (prefix.empty()) return name; return prefix + "_" + name; } -std::pair McpApp::strip_prefix(const std::string& name) +std::pair FastMCP::strip_prefix(const std::string& name) { auto pos = name.find('_'); if (pos == std::string::npos) @@ -55,7 +55,7 @@ std::pair McpApp::strip_prefix(const std::string& name return {name.substr(0, pos), name.substr(pos + 1)}; } -std::string McpApp::add_resource_prefix(const std::string& uri, const std::string& prefix) +std::string FastMCP::add_resource_prefix(const std::string& uri, const std::string& prefix) { if (prefix.empty()) return uri; @@ -73,7 +73,7 @@ std::string McpApp::add_resource_prefix(const std::string& uri, const std::strin return scheme + "://" + prefix + "/" + path; } -std::string McpApp::strip_resource_prefix(const std::string& uri, const std::string& prefix) +std::string FastMCP::strip_resource_prefix(const std::string& uri, const std::string& prefix) { if (prefix.empty()) return uri; @@ -93,7 +93,7 @@ std::string McpApp::strip_resource_prefix(const std::string& uri, const std::str return uri; } -bool McpApp::has_resource_prefix(const std::string& uri, const std::string& prefix) +bool FastMCP::has_resource_prefix(const std::string& uri, const std::string& prefix) { if (prefix.empty()) return true; // Empty prefix matches everything @@ -112,7 +112,7 @@ bool McpApp::has_resource_prefix(const std::string& uri, const std::string& pref // Aggregated Lists // ========================================================================= -std::vector> McpApp::list_all_tools() const +std::vector> FastMCP::list_all_tools() const { std::vector> result; @@ -153,7 +153,7 @@ std::vector> McpApp::list_all_tools() return result; } -std::vector McpApp::list_all_tools_info() const +std::vector FastMCP::list_all_tools_info() const { std::vector result; @@ -200,7 +200,7 @@ std::vector McpApp::list_all_tools_info() const return result; } -std::vector McpApp::list_all_resources() const +std::vector FastMCP::list_all_resources() const { std::vector result; @@ -247,7 +247,7 @@ std::vector McpApp::list_all_resources() const return result; } -std::vector McpApp::list_all_templates() const +std::vector FastMCP::list_all_templates() const { std::vector result; @@ -293,7 +293,7 @@ std::vector McpApp::list_all_templates() const return result; } -std::vector> McpApp::list_all_prompts() const +std::vector> FastMCP::list_all_prompts() const { std::vector> result; @@ -335,7 +335,7 @@ std::vector> McpApp::list_all_pro // Routing // ========================================================================= -Json McpApp::invoke_tool(const std::string& name, const Json& args) const +Json FastMCP::invoke_tool(const std::string& name, const Json& args) const { // Try local tools first try @@ -437,7 +437,7 @@ Json McpApp::invoke_tool(const std::string& name, const Json& args) const throw NotFoundError("tool not found: " + name); } -resources::ResourceContent McpApp::read_resource(const std::string& uri, const Json& params) const +resources::ResourceContent FastMCP::read_resource(const std::string& uri, const Json& params) const { // Try local resources first try @@ -562,8 +562,8 @@ resources::ResourceContent McpApp::read_resource(const std::string& uri, const J throw NotFoundError("resource not found: " + uri); } -std::vector McpApp::get_prompt(const std::string& name, - const Json& args) const +std::vector FastMCP::get_prompt(const std::string& name, + const Json& args) const { // Try local prompts first try diff --git a/src/mcp/handler.cpp b/src/mcp/handler.cpp index bd56f7b..67fa6ff 100644 --- a/src/mcp/handler.cpp +++ b/src/mcp/handler.cpp @@ -885,8 +885,8 @@ make_mcp_handler(const std::string& server_name, const std::string& version, }; } -// McpApp handler - supports mounted apps with aggregation -std::function make_mcp_handler(const McpApp& app) +// FastMCP handler - supports mounted apps with aggregation +std::function make_mcp_handler(const FastMCP& app) { return [&app](const fastmcpp::Json& message) -> fastmcpp::Json { @@ -1525,7 +1525,7 @@ static std::string extract_session_id(const fastmcpp::Json& params) } std::function -make_mcp_handler_with_sampling(const McpApp& app, SessionAccessor session_accessor) +make_mcp_handler_with_sampling(const FastMCP& app, SessionAccessor session_accessor) { return [&app, session_accessor](const fastmcpp::Json& message) -> fastmcpp::Json { @@ -1831,7 +1831,7 @@ make_mcp_handler_with_sampling(const McpApp& app, SessionAccessor session_access } std::function -make_mcp_handler_with_sampling(const McpApp& app, server::SseServerWrapper& sse_server) +make_mcp_handler_with_sampling(const FastMCP& app, server::SseServerWrapper& sse_server) { return make_mcp_handler_with_sampling(app, [&sse_server](const std::string& session_id) { return sse_server.get_session(session_id); }); diff --git a/tests/app/mounting.cpp b/tests/app/mounting.cpp index d2b12b1..a939aba 100644 --- a/tests/app/mounting.cpp +++ b/tests/app/mounting.cpp @@ -1,4 +1,4 @@ -// Unit tests for McpApp mounting functionality +// Unit tests for FastMCP mounting functionality #include "fastmcpp/app.hpp" #include "fastmcpp/exceptions.hpp" #include "fastmcpp/mcp/handler.hpp" @@ -58,7 +58,7 @@ void test_basic_app() { std::cout << "test_basic_app..." << std::endl; - McpApp app("TestApp", "1.0.0"); + FastMCP app("TestApp", "1.0.0"); assert(app.name() == "TestApp"); assert(app.version() == "1.0.0"); @@ -76,8 +76,8 @@ void test_basic_mounting() { std::cout << "test_basic_mounting..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tool on child child_app.tools().register_tool(make_echo_tool("say")); @@ -96,8 +96,8 @@ void test_tool_aggregation() { std::cout << "test_tool_aggregation..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -129,8 +129,8 @@ void test_tool_routing() { std::cout << "test_tool_routing..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -166,8 +166,8 @@ void test_resource_aggregation() { std::cout << "test_resource_aggregation..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register resources main_app.resources().register_resource(make_resource("file://main.txt", "main content")); @@ -199,8 +199,8 @@ void test_resource_routing() { std::cout << "test_resource_routing..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register resources main_app.resources().register_resource(make_resource("file://main.txt", "main content")); @@ -236,8 +236,8 @@ void test_prompt_aggregation() { std::cout << "test_prompt_aggregation..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register prompts main_app.prompts().register_prompt(make_prompt("greeting", "Hello from main!")); @@ -269,8 +269,8 @@ void test_prompt_routing() { std::cout << "test_prompt_routing..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register prompts main_app.prompts().register_prompt(make_prompt("greeting", "Hello from main!")); @@ -296,9 +296,9 @@ void test_nested_mounting() { std::cout << "test_nested_mounting..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp level1_app("Level1App", "1.0.0"); - McpApp level2_app("Level2App", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP level1_app("Level1App", "1.0.0"); + FastMCP level2_app("Level2App", "1.0.0"); // Register tools at each level main_app.tools().register_tool(make_echo_tool("main_tool")); @@ -339,8 +339,8 @@ void test_no_prefix_mounting() { std::cout << "test_no_prefix_mounting..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -375,8 +375,8 @@ void test_mcp_handler_integration() { std::cout << "test_mcp_handler_integration..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -423,9 +423,9 @@ void test_multiple_mounts() { std::cout << "test_multiple_mounts..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp weather_app("WeatherApp", "1.0.0"); - McpApp math_app("MathApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP weather_app("WeatherApp", "1.0.0"); + FastMCP math_app("MathApp", "1.0.0"); // Register tools weather_app.tools().register_tool(make_echo_tool("forecast")); @@ -457,8 +457,8 @@ void test_proxy_mode_basic() { std::cout << "test_proxy_mode_basic..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tool on child child_app.tools().register_tool(make_echo_tool("echo")); @@ -478,8 +478,8 @@ void test_proxy_mode_tool_aggregation() { std::cout << "test_proxy_mode_tool_aggregation..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -511,8 +511,8 @@ void test_proxy_mode_tool_routing() { std::cout << "test_proxy_mode_tool_routing..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -536,8 +536,8 @@ void test_proxy_mode_resource_aggregation() { std::cout << "test_proxy_mode_resource_aggregation..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register resources main_app.resources().register_resource(make_resource("file://main.txt", "main content")); @@ -569,8 +569,8 @@ void test_proxy_mode_resource_routing() { std::cout << "test_proxy_mode_resource_routing..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register resources main_app.resources().register_resource(make_resource("file://main.txt", "main content")); @@ -594,8 +594,8 @@ void test_proxy_mode_prompt_aggregation() { std::cout << "test_proxy_mode_prompt_aggregation..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register prompts main_app.prompts().register_prompt(make_prompt("greeting", "Hello from main!")); @@ -627,8 +627,8 @@ void test_proxy_mode_prompt_routing() { std::cout << "test_proxy_mode_prompt_routing..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register prompts main_app.prompts().register_prompt(make_prompt("greeting", "Hello from main!")); @@ -654,9 +654,9 @@ void test_mixed_direct_and_proxy_mounts() { std::cout << "test_mixed_direct_and_proxy_mounts..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp direct_app("DirectApp", "1.0.0"); - McpApp proxy_app("ProxyApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP direct_app("DirectApp", "1.0.0"); + FastMCP proxy_app("ProxyApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -692,8 +692,8 @@ void test_proxy_mode_mcp_handler() { std::cout << "test_proxy_mode_mcp_handler..." << std::endl; - McpApp main_app("MainApp", "1.0.0"); - McpApp child_app("ChildApp", "1.0.0"); + FastMCP main_app("MainApp", "1.0.0"); + FastMCP child_app("ChildApp", "1.0.0"); // Register tools main_app.tools().register_tool(make_add_tool()); @@ -727,7 +727,7 @@ void test_proxy_mode_mcp_handler() int main() { - std::cout << "=== McpApp Mounting Tests ===" << std::endl; + std::cout << "=== FastMCP Mounting Tests ===" << std::endl; test_basic_app(); test_basic_mounting();