adding-resources.mdc•5.8 kB
---
description: Guide for adding new resources that provide context, live data, and reference materials.
globs:
alwaysApply: false
---
# Adding New Resources
Guide for adding new resources that provide context, live data, and reference materials.
## What Are Resources?
Resources are **application-controlled** content that clients provide to LLMs proactively, unlike tools which are **model-controlled** (LLM decides when to call).
## Resource Structure
Each resource consists of:
1. **Definition** - Schema in `resources.ts`
2. **Handler** - Logic in `resources.ts`
3. **Tests** - Unit tests in `resources.test.ts`
4. **Integration** - Referenced by prompts and tools
## Resource Types
### 1. Context Management
Session state, user preferences, recent activity:
```typescript
{
name: "user-session-context",
uri: "sentry://session/current",
description: "Current user's session and preferences"
}
```
### 2. Live System Data
Real-time metrics, health snapshots:
```typescript
{
name: "project-health",
uri: "sentry://project/{projectSlug}/health",
description: "Real-time project error rates and performance"
}
```
### 3. Binary Content
Screenshots, logs, attachments:
```typescript
{
name: "issue-attachments",
uri: "sentry://issue/{issueId}/attachments",
description: "Binary attachments for an issue"
}
```
### 4. Documentation
Reference guides, API docs:
```typescript
{
name: "platform-docs",
uri: "sentry://docs/{platform}",
description: "Platform-specific documentation"
}
```
## Step 1: Define the Resource
Add to `packages/mcp-server/src/resources.ts`:
```typescript
const RESOURCE_HANDLERS: ResourceHandler[] = [
{
name: "your-resource-name",
uri: "sentry://your/path/{variable}", // Support templates
mimeType: "application/json", // or text/markdown, image/png
description: "Clear description for LLM understanding",
handler: yourResourceHandler
}
];
```
### Resource URI Design
- Use semantic paths: `sentry://entity/identifier/aspect`
- Support templates with `{variable}` placeholders
- Keep URIs predictable and consistent
## Step 2: Implement the Handler
```typescript
async function yourResourceHandler(url: URL): Promise<ReadResourceResult> {
// Extract parameters from URL
const pathParts = url.pathname.split('/');
const param = pathParts[2];
// Fetch or generate content
const data = await fetchData(param);
// Return formatted response
return {
contents: [{
uri: url.toString(),
mimeType: "application/json",
text: JSON.stringify(data, null, 2)
}]
};
}
```
## Step 3: Add Tests
```typescript
describe("resource: your-resource", () => {
it("returns expected content", async () => {
const handler = findHandler("sentry://your/path/123");
const result = await handler(new URL("sentry://your/path/123"));
expect(result.contents[0]).toMatchInlineSnapshot(`
{
"mimeType": "application/json",
"text": "{\"expected\": \"content\"}",
"uri": "sentry://your/path/123"
}
`);
});
});
```
## Advanced Patterns
### Handle Binary Content
For images, PDFs, or other binary data:
```typescript
async function binaryResourceHandler(url: URL): Promise<ReadResourceResult> {
const binary = await fetchBinaryData();
return {
contents: [{
uri: url.toString(),
mimeType: "image/png",
blob: binary.toString('base64')
}]
};
}
```
### Support Multiple Contents
Resources can return multiple content items:
```typescript
return {
contents: [
{
uri: url.toString(),
mimeType: "text/markdown",
text: "# Summary\n\nMarkdown content..."
},
{
uri: `${url.toString()}/data`,
mimeType: "application/json",
text: JSON.stringify(data)
}
]
};
```
### Resource Templates
Support dynamic URIs with placeholders:
```typescript
{
name: "issue-context",
uriTemplate: "sentry://issue/{issueId}/context",
handler: async (url: URL) => {
const issueId = extractIssueId(url);
// Implementation
}
}
```
The MCP server automatically generates:
- `sentry://issue/123/context` → Specific instance
- `sentry://issue/{issueId}/context` → Template for discovery
## Best Practices
### Clear Naming
- Use descriptive resource names
- Follow the pattern: `noun-context` (e.g., `issue-attachments`, `project-health`)
- Match naming conventions from tools
### Efficient Data
- Don't overload with unnecessary data
- Structure for LLM consumption
- Use appropriate mimeTypes
- Consider resource size limits
### Error Handling
- Return empty contents for missing data
- Use clear error messages
- Don't throw unless critical
- Log errors for debugging
### Security
- Validate access permissions
- Sanitize user input in URIs
- Don't expose sensitive data
- Use the same auth as tools
## Common Patterns
See `common-patterns.mdc` for:
- Response formatting
- Error handling
- Parameter extraction
- Binary content handling
- Multi-content resources
## Integration with Prompts
Resources are often referenced in prompts:
```typescript
// In prompt handler
const instructions = [
"Check available resources:",
"1. `user-session-context` for recent activity",
"2. `project-health` for current metrics",
];
```
## Checklist
- [ ] Resource defined in `resources.ts`
- [ ] Handler implemented with proper error handling
- [ ] Unit tests with snapshots added
- [ ] Resource documented in handler comments
- [ ] Referenced in relevant prompts
- [ ] Follows security best practices
## References
- Implementation: `packages/mcp-server/src/resources.ts`
- Tests: `packages/mcp-server/src/resources.test.ts`
- Common patterns: `docs/common-patterns.mdc`
- MCP spec: https://modelcontextprotocol.io/docs/concepts/resources