api-patterns.mdc•4.53 kB
# API Patterns
Sentry API client usage, mocking, and testing patterns.
## API Client Usage
### Client Creation
```typescript
// Standard usage with context helper
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl
});
// Direct instantiation
const api = new SentryApiService({
host: "sentry.io",
accessToken: token
});
```
See: `packages/mcp-server/src/api-utils.ts` and `adding-tools.mdc#step-2-implement-the-handler` for usage in tools.
### Common Operations
```typescript
// List with filtering
const issues = await api.issues.list({
organizationSlug: "org",
query: "is:unresolved",
sort: "date"
});
// Get specific resource
const project = await api.projects.get({
organizationSlug: "org",
projectIdOrSlug: "frontend"
});
// Create/update
await api.issues.update({
issueId: "123",
status: "resolved"
});
```
### Multi-Region Support
Sentry uses region-specific URLs:
```typescript
// Auto-detect from organization
const orgs = await api.organizations.list();
// Returns: { region_url: "https://us.sentry.io" }
// Use region URL
const api = apiServiceFromContext(context, {
regionUrl: org.region_url
});
```
## Schema Patterns
### Flexible Sentry Models
```typescript
// Support ID variations
const IssueIdSchema = z.union([
z.string(), // "PROJ-123"
z.number() // 123456789
]);
// Partial with passthrough for unknowns
const FlexibleSchema = BaseSchema
.partial()
.passthrough();
// Nullable handling
z.union([DateSchema, z.null()])
```
See Zod patterns: `common-patterns.mdc#zod-schema-patterns`
### Type Safety
For testing API patterns, see `testing.mdc#mock-server-setup`
```typescript
// Derive types from schemas
export type Issue = z.infer<typeof IssueSchema>;
// Runtime validation
const issues = IssueListSchema.parse(response);
```
## Mock Patterns
### MSW Handler Structure
```typescript
export const handlers = [
{
method: "get",
path: "/api/0/organizations/:org/issues/",
fetch: async ({ request, params }) => {
// Validate parameters
if (!params.org) {
return HttpResponse.json("Invalid org", { status: 400 });
}
// Return fixture
return HttpResponse.json(issueListFixture);
}
}
];
```
See: `packages/mcp-server-mocks/src/handlers/`
### Request Validation
```typescript
fetch: async ({ request }) => {
const url = new URL(request.url);
const query = url.searchParams.get("query");
// Validate query parameters
if (query && !isValidQuery(query)) {
return HttpResponse.json("Invalid query", { status: 400 });
}
// Filter based on query
const filtered = fixtures.filter(item =>
matchesQuery(item, query)
);
return HttpResponse.json(filtered);
}
```
### Dynamic Responses
```typescript
// Support pagination
const limit = parseInt(url.searchParams.get("limit") || "100");
const cursor = url.searchParams.get("cursor");
const start = cursor ? parseInt(cursor) : 0;
const page = fixtures.slice(start, start + limit);
return HttpResponse.json(page, {
headers: {
"Link": `<...?cursor=${start + limit}>; rel="next"`
}
});
```
## Testing with Mocks
### Setup Pattern
```typescript
import { setupMockServer } from "@sentry-mcp/mocks";
const server = setupMockServer();
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
```
### Override Handlers
```typescript
it("handles errors", async () => {
server.use(
http.get("*/issues/", () =>
HttpResponse.json({ error: "Server error" }, { status: 500 })
)
);
await expect(api.issues.list(params))
.rejects.toThrow(ApiError);
});
```
## Error Patterns
### ApiError Handling
```typescript
try {
const data = await api.issues.list(params);
} catch (error) {
if (error instanceof ApiError) {
// Handle specific status codes
if (error.status === 404) {
throw new UserInputError("Organization not found");
}
}
throw error;
}
```
See error patterns: `common-patterns.mdc#error-handling`
## Best Practices
1. **Always use context helper** when in tools/prompts
2. **Handle region URLs** for multi-region support
3. **Validate schemas** at API boundaries
4. **Mock realistically** in tests
5. **Transform errors** for LLM consumption
## References
- API Client: `packages/mcp-server/src/api-client/`
- Mock handlers: `packages/mcp-server-mocks/src/handlers/`
- Fixtures: `packages/mcp-server-mocks/src/fixtures/`
- API Utils: `packages/mcp-server/src/api-utils.ts`