Resources Overview
Managing external data sources and APIs with MCP Framework resources
Resources
What are Resources?
Resources are data sources that AI models can read or subscribe to. Think of them as a way to provide context, data, or state to your AI interactions!
Understanding Resources
Resources can be:
- Files
- API endpoints
- Database queries
- Real-time data streams
- Configuration data
Here's a simple example:
import { MCPResource } from "mcp-framework";
class ConfigResource extends MCPResource {
uri = "resource://config";
name = "Configuration";
description = "System configuration settings";
mimeType = "application/json";
async read() {
return [
{
uri: this.uri,
mimeType: this.mimeType,
text: JSON.stringify({
version: "1.0.0",
environment: "production",
features: ["analytics", "reporting"],
}),
},
];
}
}Creating Resources
Using the CLI
mcp add resource my-resourceThis creates a new resource in src/resources/MyResource.ts.
Resource Structure
Every resource has:
- Metadata
uri = "resource://my-data";
name = "My Data Resource";
description = "Provides access to my data";
mimeType = "application/json";- Read Method
async read(): Promise<ResourceContent[]> {
// Fetch or generate your data
return [{
uri: this.uri,
mimeType: this.mimeType,
text: JSON.stringify(data)
}];
}Resource Types
Static Resources
class DocumentationResource extends MCPResource {
uri = "resource://docs";
name = "Documentation";
mimeType = "text/markdown";
async read() {
return [
{
uri: this.uri,
mimeType: this.mimeType,
text: "# API Documentation\n\nWelcome to our API...",
},
];
}
}Dynamic Resources
class MarketDataResource extends MCPResource {
uri = "resource://market-data";
name = "Market Data";
mimeType = "application/json";
async read() {
const data = await this.fetch("https://api.market.com/latest");
return [
{
uri: this.uri,
mimeType: this.mimeType,
text: JSON.stringify(data),
},
];
}
}Real-time Resources
Real-time Updates
Use subscription methods to handle real-time data streams!
class StockTickerResource extends MCPResource {
uri = "resource://stock-ticker";
name = "Stock Ticker";
mimeType = "application/json";
private ws: WebSocket | null = null;
async subscribe() {
this.ws = new WebSocket("wss://stocks.example.com");
this.ws.on("message", this.handleUpdate);
}
async unsubscribe() {
if (this.ws) {
this.ws.close();
this.ws = null;
}
}
async read() {
const latestData = await this.getLatestStockData();
return [
{
uri: this.uri,
mimeType: this.mimeType,
text: JSON.stringify(latestData),
},
];
}
}Title, Icons, Size, and Annotations
Resources now support additional metadata fields per MCP spec 2025-11-25, enabling richer display in client UIs and providing behavioral hints to clients.
import { MCPResource } from "mcp-framework";
class ProjectResource extends MCPResource {
uri = "resource://project/readme";
name = "README";
title = "Project Documentation"; // Human-readable display name
description = "Project README file";
mimeType = "text/markdown";
size = 4096; // Optional: size in bytes
// Optional: icons for client UI
icons = [{ src: "https://example.com/doc-icon.png", mimeType: "image/png" }];
// Optional: annotations for client behavior hints
resourceAnnotations = {
audience: ["user", "assistant"], // Who this is for
priority: 0.8, // 0.0 (optional) to 1.0 (critical)
lastModified: "2025-01-12T15:00:58Z",
};
async read() {
return [{
uri: this.uri,
mimeType: this.mimeType,
text: "# My Project\n\nProject documentation...",
}];
}
}Field Reference
title— Optional human-readable name for display in client UIs. Falls back tonameif not set.icons— Optional array of icon objects withsrc(URL or data URI), optionalmimeType, and optionalsizes.size— Optional size in bytes. This is a hint; actual content returned fromread()may differ.resourceAnnotations— Optional metadata hints for client behavior:audience— Array of"user"and/or"assistant"indicating who the resource is intended for.priority— Number from 0.0 to 1.0 indicating importance (1.0 = most important, 0.0 = least important).lastModified— ISO 8601 timestamp of the last modification.
Annotations Are Hints
Annotations are purely informational. Clients may use them for display ordering, filtering, or UI hints, but they do not enforce any behavior.
Resource Templates with Metadata
When using resource templates, title and icons defined on the class also apply to the template definition:
class FileResource extends MCPResource {
uri = "resource://files/{path}";
name = "Project Files";
title = "Project File Browser";
icons = [{ src: "https://example.com/file-icon.png", mimeType: "image/png" }];
protected template = {
uriTemplate: "resource://files/{path}",
description: "Access project files",
};
// title and icons on the class also apply to the template definition
async read() {
// ...
}
}Best Practices
- URI Naming
uri = "resource://domain/type/identifier";
// Example: "resource://finance/stocks/AAPL"- Error Handling
async read() {
try {
const data = await this.fetchData();
return [{
uri: this.uri,
mimeType: this.mimeType,
text: JSON.stringify(data)
}];
} catch (error) {
throw new Error(`Failed to read resource: ${error.message}`);
}
}- Caching
class CachedResource extends MCPResource {
private cache: any = null;
private lastFetch: number = 0;
private TTL = 60000; // 1 minute
async read() {
if (this.cache && Date.now() - this.lastFetch < this.TTL) {
return this.cache;
}
const data = await this.fetchFreshData();
this.cache = data;
this.lastFetch = Date.now();
return data;
}
}Advanced Usage
Combining with Tools
class DataResource extends MCPResource {
uri = "resource://data";
name = "Data Store";
async read() {
return [
{
uri: this.uri,
mimeType: "application/json",
text: JSON.stringify(await this.getData()),
},
];
}
}
class DataProcessor extends MCPTool {
async execute(input) {
const resource = new DataResource();
const [data] = await resource.read();
return this.processData(JSON.parse(data.text));
}
}Next Steps
- Learn about Tools
- Learn about Prompts
- Get Started