cpp-mcp/include/mcp_resource.h

309 lines
8.2 KiB
C++

/**
* @file mcp_resource.h
* @brief Resource implementation for MCP
*
* This file defines the base resource class and common resource types for the MCP protocol.
* Follows the 2024-11-05 protocol specification.
*/
#ifndef MCP_RESOURCE_H
#define MCP_RESOURCE_H
#include "mcp_message.h"
#include "base64.hpp"
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include <map>
namespace mcp {
/**
* @class resource
* @brief Base class for MCP resources
*
* The resource class defines the interface for resources that can be
* accessed through the MCP protocol. Each resource is identified by a URI.
*/
class resource {
public:
virtual ~resource() = default;
/**
* @brief Get resource metadata
* @return Metadata as JSON
*/
virtual json get_metadata() const = 0;
/**
* @brief Read the resource content
* @return The resource content as JSON
*/
virtual json read() const = 0;
/**
* @brief Check if the resource has been modified
* @return True if the resource has been modified since last read
*/
virtual bool is_modified() const = 0;
/**
* @brief Get the URI of the resource
* @return The URI as string
*/
virtual std::string get_uri() const = 0;
};
/**
* @class text_resource
* @brief Resource containing text content
*
* The text_resource class provides a base implementation for resources
* that contain text content.
*/
class text_resource : public resource {
public:
/**
* @brief Constructor
* @param uri The URI of the resource
* @param name The name of the resource
* @param mime_type The MIME type of the resource
* @param description Optional description of the resource
*/
text_resource(const std::string& uri,
const std::string& name,
const std::string& mime_type,
const std::string& description = "");
/**
* @brief Get resource metadata
* @return Metadata as JSON
*/
json get_metadata() const override;
/**
* @brief Read the resource content
* @return The resource content as JSON
*/
json read() const override;
/**
* @brief Check if the resource has been modified
* @return True if the resource has been modified since last read
*/
bool is_modified() const override;
/**
* @brief Get the URI of the resource
* @return The URI as string
*/
std::string get_uri() const override;
/**
* @brief Set the text content of the resource
* @param text The text content
*/
void set_text(const std::string& text);
/**
* @brief Get the text content of the resource
* @return The text content
*/
std::string get_text() const;
protected:
std::string uri_;
std::string name_;
std::string mime_type_;
std::string description_;
std::string text_;
mutable bool modified_;
};
/**
* @class binary_resource
* @brief Resource containing binary content
*
* The binary_resource class provides a base implementation for resources
* that contain binary content.
*/
class binary_resource : public resource {
public:
/**
* @brief Constructor
* @param uri The URI of the resource
* @param name The name of the resource
* @param mime_type The MIME type of the resource
* @param description Optional description of the resource
*/
binary_resource(const std::string& uri,
const std::string& name,
const std::string& mime_type,
const std::string& description = "");
/**
* @brief Get resource metadata
* @return Metadata as JSON
*/
json get_metadata() const override;
/**
* @brief Read the resource content
* @return The resource content as JSON with base64-encoded data
*/
json read() const override;
/**
* @brief Check if the resource has been modified
* @return True if the resource has been modified since last read
*/
bool is_modified() const override;
/**
* @brief Get the URI of the resource
* @return The URI as string
*/
std::string get_uri() const override;
/**
* @brief Set the binary content of the resource
* @param data Pointer to the binary data
* @param size Size of the binary data
*/
void set_data(const uint8_t* data, size_t size);
/**
* @brief Get the binary content of the resource
* @return The binary content
*/
const std::vector<uint8_t>& get_data() const;
protected:
std::string uri_;
std::string name_;
std::string mime_type_;
std::string description_;
std::vector<uint8_t> data_;
mutable bool modified_;
};
/**
* @class file_resource
* @brief Resource for file system operations
*
* The file_resource class provides access to files as resources.
*/
class file_resource : public text_resource {
public:
/**
* @brief Constructor
* @param file_path The path to the file
* @param mime_type The MIME type of the file (optional, will be guessed if not provided)
* @param description Optional description of the resource
*/
file_resource(const std::string& file_path,
const std::string& mime_type = "",
const std::string& description = "");
/**
* @brief Read the resource content
* @return The resource content as JSON
*/
json read() const override;
/**
* @brief Check if the resource has been modified
* @return True if the resource has been modified since last read
*/
bool is_modified() const override;
private:
std::string file_path_;
mutable time_t last_modified_;
/**
* @brief Guess the MIME type from file extension
* @param file_path The file path
* @return The guessed MIME type
*/
static std::string guess_mime_type(const std::string& file_path);
};
/**
* @class resource_manager
* @brief Manager for MCP resources
*
* The resource_manager class provides a central registry for resources
* and handles resource operations.
*/
class resource_manager {
public:
/**
* @brief Get the singleton instance
* @return Reference to the singleton instance
*/
static resource_manager& instance();
/**
* @brief Register a resource
* @param resource Shared pointer to the resource
*/
void register_resource(std::shared_ptr<resource> resource);
/**
* @brief Unregister a resource
* @param uri The URI of the resource to unregister
* @return True if the resource was unregistered
*/
bool unregister_resource(const std::string& uri);
/**
* @brief Get a resource by URI
* @param uri The URI of the resource
* @return Shared pointer to the resource, or nullptr if not found
*/
std::shared_ptr<resource> get_resource(const std::string& uri) const;
/**
* @brief List all registered resources
* @return JSON array of resource metadata
*/
json list_resources() const;
/**
* @brief Subscribe to resource changes
* @param uri The URI of the resource to subscribe to
* @param callback The callback function to call when the resource changes
* @return Subscription ID
*/
int subscribe(const std::string& uri, std::function<void(const std::string&)> callback);
/**
* @brief Unsubscribe from resource changes
* @param subscription_id The subscription ID
* @return True if the subscription was removed
*/
bool unsubscribe(int subscription_id);
/**
* @brief Notify subscribers of resource changes
* @param uri The URI of the resource that changed
*/
void notify_resource_changed(const std::string& uri);
private:
resource_manager() = default;
~resource_manager() = default;
resource_manager(const resource_manager&) = delete;
resource_manager& operator=(const resource_manager&) = delete;
std::map<std::string, std::shared_ptr<resource>> resources_;
std::map<int, std::pair<std::string, std::function<void(const std::string&)>>> subscriptions_;
int next_subscription_id_ = 1;
};
} // namespace mcp
#endif // MCP_RESOURCE_H