Skip to main content
Glama

Sentry MCP

Official
by getsentry
resources.test.ts5.39 kB
import { describe, expect, it, beforeEach } from "vitest"; import { http, HttpResponse } from "msw"; import { mswServer } from "@sentry/mcp-server-mocks"; import { RESOURCES, isTemplateResource } from "./resources"; import { UserInputError } from "./errors"; import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js"; beforeEach(() => { mswServer.resetHandlers(); }); describe("resources", () => { describe("isTemplateResource", () => { it("should correctly identify template resources", () => { const templateResource = RESOURCES.find( (r) => r.name === "sentry-docs-platform", ); const guideResource = RESOURCES.find( (r) => r.name === "sentry-docs-platform-guide", ); const aboutResource = RESOURCES.find( (r) => r.name === "sentry-mcp-about", ); expect(templateResource).toBeDefined(); expect(guideResource).toBeDefined(); expect(aboutResource).toBeDefined(); expect(isTemplateResource(templateResource!)).toBe(true); expect(isTemplateResource(guideResource!)).toBe(true); expect(isTemplateResource(aboutResource!)).toBe(false); }); }); describe("aboutHandler", () => { it("should return about content", async () => { const aboutResource = RESOURCES.find( (r) => r.name === "sentry-mcp-about", ); expect(aboutResource).toBeDefined(); const result = await aboutResource!.handler( new URL("sentry://about"), {} as RequestHandlerExtra<any, any>, ); expect(result.contents).toHaveLength(1); expect(result.contents[0].uri).toBe("sentry://about"); expect(result.contents[0].mimeType).toBe("text/markdown"); expect(result.contents[0].text).toBeDefined(); expect(result.contents[0].text).toBeTruthy(); }); }); describe("sentryDocsHandler", () => { it("should fetch markdown version of Sentry docs", async () => { const mockContent = "# Sentry JavaScript SDK\n\nThis is the documentation..."; mswServer.use( http.get("https://docs.sentry.io/platforms/javascript.md", () => { return HttpResponse.text(mockContent); }), ); const docsResource = RESOURCES.find( (r) => r.name === "sentry-docs-platform", ); expect(docsResource).toBeDefined(); const result = await docsResource!.handler( new URL("https://docs.sentry.io/platforms/javascript/"), {} as RequestHandlerExtra<any, any>, ); expect(result.contents).toHaveLength(1); expect(result.contents[0]).toEqual({ uri: "https://docs.sentry.io/platforms/javascript/", mimeType: "text/markdown", text: mockContent, }); }); it("should handle trailing slashes correctly", async () => { const mockContent = "# Guide Content"; mswServer.use( http.get( "https://docs.sentry.io/platforms/javascript/guides/nextjs.md", () => { return HttpResponse.text(mockContent); }, ), ); const guideResource = RESOURCES.find( (r) => r.name === "sentry-docs-platform-guide", ); expect(guideResource).toBeDefined(); // Test with trailing slash const result = await guideResource!.handler( new URL("https://docs.sentry.io/platforms/javascript/guides/nextjs/"), {} as RequestHandlerExtra<any, any>, ); expect(result.contents[0].text).toBe(mockContent); }); it("should throw UserInputError for 404 responses", async () => { mswServer.use( http.get("https://docs.sentry.io/platforms/nonexistent.md", () => { return new HttpResponse(null, { status: 404 }); }), ); const docsResource = RESOURCES.find( (r) => r.name === "sentry-docs-platform", ); await expect( docsResource!.handler( new URL("https://docs.sentry.io/platforms/nonexistent/"), {} as RequestHandlerExtra<any, any>, ), ).rejects.toThrow(UserInputError); await expect( docsResource!.handler( new URL("https://docs.sentry.io/platforms/nonexistent/"), {} as RequestHandlerExtra<any, any>, ), ).rejects.toThrow( "Sentry documentation not found at /platforms/nonexistent/. Please check the URL is correct.", ); }); it("should throw regular Error for other HTTP errors", async () => { mswServer.use( http.get("https://docs.sentry.io/platforms/error.md", () => { return new HttpResponse(null, { status: 500, statusText: "Internal Server Error", }); }), ); const docsResource = RESOURCES.find( (r) => r.name === "sentry-docs-platform", ); await expect( docsResource!.handler( new URL("https://docs.sentry.io/platforms/error/"), {} as RequestHandlerExtra<any, any>, ), ).rejects.toThrow( "Failed to fetch Sentry docs: 500 Internal Server Error", ); // Ensure it's not a UserInputError await expect( docsResource!.handler( new URL("https://docs.sentry.io/platforms/error/"), {} as RequestHandlerExtra<any, any>, ), ).rejects.not.toThrow(UserInputError); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsentry/sentry-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server