MCP Resources
May 31, 2025 ยท View on GitHub
This guide explains how to use the Resources feature of the Model Context Protocol (MCP) with the Fast MCP library.
What are MCP Resources?
Resources in MCP are a way to share data between the server and clients. Unlike tools, which are used for executing actions, resources are used for sharing and synchronizing state. Resources can be:
- Static data (like configuration)
- Dynamic data that changes over time (like user data)
- Binary content (like images or files)
- Streaming data that updates frequently (like sensor readings)
Resources are identified by a unique URI and can be read, subscribed to, and updated.
Resource Features
The Fast MCP library supports the following resource features:
- Resource Registration: Register resources with the server
- Resource Reading: Read resource content from the client
- Resource Subscription: Subscribe to resource updates
- Resource Notifications: Receive notifications when resources change
- Binary Content: Support for both text and binary content
- Resource Metadata: Access resource metadata without reading the content
Server-Side Usage
Creating and Registering Resources
You can create resources by inheriting from the FastMcp::Resource class. Resources are stateless and generate content dynamically:
require 'fast_mcp'
# Create a server
server = FastMcp::Server.new(name: "my-mcp-server", version: "1.0.0")
# Create a resource by inheriting from FastMcp::Resource
class CounterResource < FastMcp::Resource
uri "example/counter"
resource_name "Counter"
description "A simple counter resource"
mime_type "application/json"
def content
# Read from file or database, or generate dynamically
count = File.exist?('counter.txt') ? File.read('counter.txt').to_i : 0
JSON.generate({ count: count })
end
end
# Register the resource with the server
server.register_resource(CounterResource)
Creating Resources from Files
You can create resources from files:
# Create a resource from a file
image_resource = FastMcp::Resource.from_file(
"path/to/image.png",
name: "Example Image",
description: "An example image resource"
)
# Register the resource with the server
server.register_resource(image_resource)
Updating Resources
Since resources are stateless, updates are typically handled through tools that modify external state (files, databases, etc.) and then notify about resource changes:
# Example tool that updates the counter
class IncrementCounterTool < FastMcp::Tool
description 'Increment the counter'
def call
# Read current value
current_count = File.exist?('counter.txt') ? File.read('counter.txt').to_i : 0
# Increment and save
new_count = current_count + 1
File.write('counter.txt', new_count.to_s)
# Notify that the resource has been updated
notify_resource_updated("example/counter")
{ count: new_count }
end
end
Removing Resources
You can remove resources from the server:
# Remove a resource
server.remove_resource("example/counter")
Custom Resource Types
You can create custom resource types by inheriting from FastMcp::Resource and implementing the required methods. Resources should be stateless and read from external sources:
# Custom resource type for weather data
class WeatherResource < FastMcp::Resource
uri "weather/current"
resource_name "Current Weather"
description "Current weather conditions"
mime_type "application/json"
def content
# Generate dynamic content or read from external source
JSON.generate({
temperature: rand(15..30),
condition: ['Sunny', 'Cloudy', 'Rainy'].sample,
humidity: rand(30..70),
wind_speed: rand(5..25),
updated_at: Time.now.to_s
})
end
end
# Register the resource
server.register_resource(WeatherResource)
# To update weather data, you would typically use a tool that
# writes to a file or database, then notifies about the update
This approach ensures that:
- Resources are stateless and don't hold in-memory state
- Content is generated dynamically from external sources
- Multiple instances can be created without conflicts
- Resources are more suitable for distributed environments
Integration with Web Frameworks
When integrating MCP resources with web frameworks like Rails, Sinatra, or Hanami, you can use the same approach as with tools. The resources will be exposed through the Rack middleware.
For more details on integrating with web frameworks, see:
Best Practices
-
Use Appropriate URIs: Use descriptive, hierarchical URIs for your resources (e.g., "users/profiles/123").
-
Set Correct MIME Types: Always set the correct MIME type for your resources to ensure proper handling.
-
Handle Binary Content Properly: When dealing with binary content, be careful with encoding and decoding.
-
Keep Resources Stateless: Resources should not maintain in-memory state. Instead, read from files, databases, or other external sources.
-
Use Tools for Updates: Use MCP tools to modify external state and notify about resource changes.
-
Error Handling: Implement proper error handling for resource operations, especially when dealing with external data sources.
-
Security: Be mindful of what data you expose through resources, especially in multi-tenant applications.
Conclusion
MCP Resources provide a powerful way to share and synchronize data between servers and clients. By keeping resources stateless and using tools for updates, you can build robust, scalable applications that work well in distributed environments.