Skip to content

Resources

A resource is something the agent reads (not invokes). Each one is identified by a URI — opaque to the agent, structured to your server.

import { defineResource } from '@mcify/core';
export const config = defineResource({
uri: 'config://current',
name: 'Server config',
description: 'The mcify server config in JSON form',
mimeType: 'application/json',
read: async () => ({
contents: [
{ uri: 'config://current', text: JSON.stringify({ name: 'weather', version: '0.1.0' }) },
],
}),
});

Wire it the same way as a tool:

defineConfig({ resources: [config], ... });

The agent calls resources/list to discover them, then resources/read with a URI.

Templated resources

URIs can be templated. The runtime extracts path parameters and passes them to your handler:

export const userProfile = defineResource({
uri: 'user://{userId}',
name: 'User profile',
read: async (params) => {
// params.userId — typed via the schema below
const user = await fetchUser(params.userId);
return {
contents: [{ uri: `user://${params.userId}`, text: JSON.stringify(user) }],
};
},
paramsSchema: z.object({ userId: z.string().uuid() }),
});

When the agent calls resources/read with user://550e8400-e29b-41d4-a716-446655440000, the runtime pattern-matches against user://{userId}, validates with paramsSchema, and invokes read({ userId: '550e...' }).

Resource vs tool

Use a resourceUse a tool
Read-only. Idempotent.Causes side effects. Writes, sends, charges.
The agent wants to see something.The agent wants to do something.
Result is large enough that pagination matters.Result fits in a JSON object.

Most connectors lean tool-heavy. Resources are useful for read-only catalog APIs (a list of products, a knowledge base article, a config dump).

Next