# What are MCP resources?

# What are MCP resources?

MCP resources are read-only, addressable content entities exposed by the server. They allow MCP clients to retrieve structured, contextual data (such as logs, configuration data, or external documents) that can be passed to models for reasoning. Because resources are strictly observational and not actionable, they must be deterministic, idempotent, and free of side effects.

Resources can expose:

- Log files
- JSON config data
- Real-time market stats
- File contents
- Structured blobs (for example, PDFs or images)

Resources are accessed via URI schemes like `note://`, `config://`, or `stock://`, and read using the `resources/read` method.

## Resource lifecycles and request and response formats

Each resource lifecycle follows this pattern:

1.  The server registers a static resource or URI template (for example, `stock://{symbol}/earnings`).
2.  The client calls `resources/list` to discover available resources or templates.
3.  The client sends a `resources/read` request with a specific resource URI.
4.  The server loads the content for that resource.
5.  The server returns the content as either `text` or `blob`.

Here is an example of a resource read request:

```json
{
  "method": "resources/read",
  "params": {
    "uri": "stock://AAPL/earnings"
  },
  "id": 8
}
```

The server responds with a text resource:

```json
{
  "jsonrpc": "2.0",
  "id": 8,
  "result": {
    "contents": [
      {
        "uri": "stock://AAPL/earnings",
        "mimeType": "application/json",
        "text": "{ \"fiscalDateEnding\": \"2023-12-31\", \"reportedEPS\": \"3.17\" }"
      }
    ]
  }
}
```

Resources can also return `blob` values for binary content like base64-encoded PDFs or images.

## Declaring a resource in Python

Resources are regular functions marked with decorators that define their role:

- `@list_resources()` exposes static resources. You return a list of `types.Resource` items for static URIs.
- `@list_resource_templates()` exposes dynamic resources. You return a list of `types.ResourceTemplate` items for dynamic, parameterized URIs.
- `@read_resource()` implements logic for resolving a resource by URI.

Here's an example using the Alpha Vantage API to return earnings data. Since we want to support arbitrary stock symbols, we'll use a resource template to let clients specify the symbol.

```python

mcpServer.resource(
  "media",
  new ResourceTemplate("media://{messageId}", {
    list: () => {
      const allMedia = mediaRegistry.getAllMediaItems();
      const resources = [];
      for (const { mediaItems } of allMedia) {
        for (const mediaItem of mediaItems) {
          resources.push({
            uri: `media://${mediaItem.messageId}`,
            name: mediaItem.name,
            description: mediaItem.description,
            mimeType:
              mediaItem.mimetype !== "unknown" ? mediaItem.mimetype : undefined,
          });
        }
      }
      return { resources };
    },
  }),
  async (uri: URL, { messageId }) => {
    const messageIdRaw = Array.isArray(messageId) ? messageId[0] : messageId;
    const messageIdString = decodeURIComponent(messageIdRaw);
    const mediaData =
      await messageService.downloadMessageMedia(messageIdString);

    return {
      contents: [
        {
          uri: uri.href,
          blob: mediaData.data,
          mimeType: mediaData.mimetype,
        },
      ],
    };
  },
);
```

This code defines a resource called `media` that can be accessed by the MCP client. The resource has a `list` method that returns a list of all media items. The MCP client can then request a specific media item by its URI, and the MCP server will return the media data.

### Notifying clients about resource changes

The MCP server can send a `notifications/resources/list_changed` message to notify the MCP client that the list of resources has changed:

```typescript

// When the MCP server detects that a new media item has been added
mediaRegistry.onMediaListChanged((mediaItems: MediaItem[]) => {
  mcpServer.sendResourceListChanged();
});
```

You can also send a notification when a specific resource has changed:

```typescript
mediaRegistry.onMediaItemChanged((mediaItem: MediaItem) => {
  void mcpServer.server.sendResourceUpdated({
    uri: resourceUri,
  });
});
```

How the LLM client handles resources is up to the client implementation. The MCP server just needs to expose the resources and notify the client when they change.
