Resources
Named data the MCP client can read. Learn URI patterns, handler signatures, mimeType, and when to use resources instead of tools.
A resource is a named piece of data the MCP client can read. The client sees the resource's URI and can include it as context in a conversation.
Register a resource with server.resource(uri, handler):
import { createServer } from "@mctx-ai/mcp";
const server = createServer();
const readme = () => "# My Project\n\nThis project does amazing things.";
readme.mimeType = "text/plain";
server.resource("docs://readme", readme);
export default { fetch: server.fetch };URI patterns
Resources are addressed by URI. The framework supports two patterns.
Exact URI
An exact URI matches one specific resource:
server.resource("docs://readme", readmeHandler);
server.resource("config://settings", settingsHandler);
server.resource("db://schema", schemaHandler);URI template
A URI template contains {param} placeholders following RFC 6570 syntax. The framework extracts the placeholder values and passes them to your handler:
server.resource("users://{userId}/profile", userProfileHandler);
server.resource("issues://{projectId}/{issueId}", issueHandler);When the client requests users://42/profile, the framework extracts { userId: "42" } and passes it as the params argument.
Handler signature
handler(params, ask?, ctx?) => data | Promise<data>| Parameter | Type | Notes |
|---|---|---|
params | Record<string, string> | URI template parameters. Empty object {} for exact-URI resources. |
ask | AskFunction | null | LLM sampling function. null when the client doesn't support sampling. Always guard before calling. |
ctx | McpContext | Request context. Contains ctx.userId — the authenticated subscriber identity injected by the mctx platform. |
The handler returns the resource content as a string, an object, or a Promise of either.
Handler properties
Set these properties on the handler function to describe the resource:
| Property | Type | Notes |
|---|---|---|
.name | string | Display name shown to the client |
.description | string | What this resource contains |
.mimeType | string | How to interpret the content. Default: text/plain |
const schema = () => JSON.stringify({ users: { id: "int", name: "text" } });
schema.name = "Database Schema";
schema.description = "Current production database schema";
schema.mimeType = "application/json";
server.resource("db://schema", schema);Example: user profile keyed by ctx.userId
ctx.userId is the authenticated subscriber identity the mctx platform injects on every request. Use it to scope a resource to the calling user:
const myProfile = (params, ask, ctx) => {
const userId = ctx?.userId;
if (!userId) {
return JSON.stringify({ error: "No authenticated user" });
}
// Fetch or build user-specific data using the stable userId
return JSON.stringify({
id: userId,
name: "Jane Smith",
plan: "pro",
});
};
myProfile.name = "My Profile";
myProfile.description = "Profile for the currently authenticated user";
myProfile.mimeType = "application/json";
server.resource("users://me/profile", myProfile);For resources keyed by a URI parameter instead, use a template:
const userProfile = (params) => {
const { userId } = params;
return JSON.stringify({
id: userId,
name: `User ${userId}`,
plan: "pro",
});
};
userProfile.name = "User Profile";
userProfile.description = "Profile for a user by ID";
userProfile.mimeType = "application/json";
server.resource("users://{userId}/profile", userProfile);Resources vs tools
| Use a resource when | Use a tool when |
|---|---|
| The data is read-only and cacheable | The operation has side effects |
| You are exposing documents, schemas, or configuration | You are searching, creating, or modifying something |
| The client needs background context for a conversation | The AI needs to take an action |
| The content changes slowly or not at all | The result depends on dynamic inputs or triggers an effect |
Resources are idempotent by nature — the client can read them multiple times and expect consistent results. If your handler writes data, triggers an external action, or produces different results on every call, it belongs as a tool.
See also
- Tools — actions the client can invoke
- Prompts — reusable conversation templates
- Concepts — handlers, the server object, and how it all fits together
- Framework API Reference — every export, type, and option
See something wrong? Report it or suggest an improvement — your feedback helps make these docs better.
Tools
Actions the MCP client can invoke. Learn handler signatures, the T schema system, annotations, mimeType, progress tracking, and error handling.
Prompts
Reusable conversation templates the MCP client can hydrate with variables. Learn handler signatures, the conversation() builder, and how to inject user context.