mctxdocs
Build Your MCP Server

Resources

Named data the MCP client can read. Learn URI patterns, handler signatures, mimeType, and when to use resources instead of tools.

Need help? Connect help.mctx.ai for instant answers.

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>
ParameterTypeNotes
paramsRecord<string, string>URI template parameters. Empty object {} for exact-URI resources.
askAskFunction | nullLLM sampling function. null when the client doesn't support sampling. Always guard before calling.
ctxMcpContextRequest 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:

PropertyTypeNotes
.namestringDisplay name shown to the client
.descriptionstringWhat this resource contains
.mimeTypestringHow 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 whenUse a tool when
The data is read-only and cacheableThe operation has side effects
You are exposing documents, schemas, or configurationYou are searching, creating, or modifying something
The client needs background context for a conversationThe AI needs to take an action
The content changes slowly or not at allThe 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.