Resources
Resources are application-driven, read-only data sources that provide context to AI models from files, APIs, databases, and other sources.
For the complete documentation index, see llms.txt. Markdown variants of every page are available by appending .md to the URL.xmcp automatically detects and registers files under the /src/resources/ directory as resources. This path can be configured in your xmcp.config.ts file.
Each resource file should export three elements:
- Schema: Input parameters defined using Zod schemas
- Metadata: The resource's identity and behavior configuration
- Default: The resource handler function
There are two types of resources: static and dynamic. When creating resources, it's important to understand how the folder structure determines the resource URI.
URI composition rules
Each resource is uniquely identified by a URI composed from its file path using these rules:
- The URI scheme is detected from folders with parentheses. For example, a parent folder named
(users)creates the URI schemeusers. - Static folders become literal path segments.
- Brackets
[]indicate dynamic parameters.
For example, the following file path:
src/resources/(users)/[userId]/profile.tsWill result in the URI users://{userId}/profile.
1. Static resource
Static resources are files that don't require any parameters. Following the composition rules above, the resource below will have the URI config://app:
import { type ResourceMetadata } from "xmcp";
export const metadata: ResourceMetadata = {
name: "app-config",
title: "Application Config",
description: "Application configuration data",
};
export default function handler() {
return "App configuration here";
}2. Dynamic resource
Dynamic resources accept parameters. The example below creates a resource with the URI users://{userId}/profile:
import { z } from "zod";
import { type ResourceMetadata, type InferSchema } from "xmcp";
export const schema = {
userId: z.string().describe("The ID of the user"),
};
export const metadata: ResourceMetadata = {
name: "user-profile",
title: "User Profile",
description: "User profile information",
};
export default function handler({ userId }: InferSchema<typeof schema>) {
return `Profile data for user ${userId}`;
}References
Schema (optional)
The schema object defines the resource's parameters with:
- Key: Parameter name.
- Value: Zod schema with
.describe()for documentation and resource inspection. This will be visible through the inspector. - Purpose: Type validation and automatic parameter documentation.
This is the exact same as the schema object for tools and prompts.
Metadata (optional)
The metadata object provides:
- Name: Unique identifier for the resource
- Title: Human-readable title for the resource
- Description: Brief explanation of what the resource does
- MimeType: The MIME type of the resource
- Size: The size of the resource
Implementation (required)
The default export function that performs the actual work.
- Parameters: Automatically typed from your schema using the built-in
InferSchema. - Returns: MCP-compatible response with content type.
Troubleshooting
Resource Loading Errors
When xmcp starts, it loads every file under your resources directory.
- Empty resource files are skipped with a friendly warning
- Files without a
defaultexport are skipped with a friendly warning - Real syntax or import errors still fail normally so you can see the full stack trace
For example, if src/resources/(drafts)/latest.ts is empty, startup will log:
[xmcp] Failed to load resource file: src/resources/(drafts)/latest.ts
-> File is empty.
[xmcp] 1 resource skipped due to empty files or missing default exportsIf the file exists but does not export a default handler, startup will log:
[xmcp] Failed to load resource file: src/resources/(drafts)/latest.ts
-> File does not export a default resource handler.