.github/skills/mcp-testing/SKILL.md
MCP Testing Strategies with Vitest, Inspector, and Integration Tests
npx skillsauth add adeze/raindrop-mcp mcp-testingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Modern testing strategies for Model Context Protocol (MCP) servers developed in VS Code using TypeScript, Bun, and Vitest.
import { describe, it, expect, beforeEach } from "vitest";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { InMemoryTransport } from "@modelcontextprotocol/sdk/testing/inMemoryTransport.js";
import { RaindropMCPService } from "../src/services/raindropmcp.service.js";
describe("RaindropMCPService Tools", () => {
let service: RaindropMCPService;
let transport: InMemoryTransport;
let client: Client;
beforeEach(async () => {
service = new RaindropMCPService();
transport = new InMemoryTransport(service.getServer());
client = new Client(
{
name: "test-client",
version: "1.0.0",
},
{ capabilities: {} },
);
await client.connect(transport);
});
it("should list available tools", async () => {
const tools = await client.listTools();
expect(tools.tools.length).toBeGreaterThan(0);
expect(tools.tools.map((t) => t.name)).toContain("collection_list");
});
it("should call a tool with valid input", async () => {
const result = await client.callTool({
name: "collection_list",
arguments: {},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
});
});
RaindropService for isolated tool testingTerminal > Run Task > "Debug HTTP Server with Inspector" (or STDIO variant)
http://localhost:3000 (or via auto-opened browser)Manual Inspection Flow:
diagnostics tool → view server version and enabled toolscollection_list → see resource links to collectionsRecord & Replay:
import { describe, it, expect } from "vitest";
import { RaindropMCPService } from "../src/services/raindropmcp.service.js";
describe("Tool Schema Snapshots", () => {
let service: RaindropMCPService;
beforeEach(() => {
service = new RaindropMCPService();
});
it("should maintain consistent tool schemas", async () => {
const tools = await service.listTools();
expect(tools).toMatchSnapshot();
});
});
bun run test:coverage
Generates coverage reports showing:
bun test --watch
it("should handle concurrent tool calls", async () => {
const promises = Array.from({ length: 10 }, () =>
client.callTool({
name: "collection_list",
arguments: {},
}),
);
const results = await Promise.all(promises);
expect(results).toHaveLength(10);
expect(results.every((r) => r.content)).toBe(true);
});
it("should respond within acceptable latency", async () => {
const start = performance.now();
await client.callTool({
name: "bookmark_search",
arguments: { search: "test" },
});
const duration = performance.now() - start;
expect(duration).toBeLessThan(5000); // 5s timeout for API calls
});
it("should fetch and validate collection resources", async () => {
const resources = await client.listResources();
const collectionPattern = resources.resources.find((r) =>
r.uri.includes("mcp://collection/"),
);
expect(collectionPattern).toBeDefined();
// Read a specific collection
const resourceData = await client.readResource({
uri: "mcp://collection/12345",
});
expect(resourceData).toBeDefined();
expect(Array.isArray(resourceData)).toBe(true);
expect(resourceData[0].text).toBeDefined();
});
it("should handle invalid resource URIs gracefully", async () => {
expect(async () => {
await client.readResource({ uri: "mcp://invalid/xyz" });
}).rejects.toThrow();
});
{
"devDependencies": {
"vitest": "^4.0.0",
"@vitest/coverage-v8": "^1.0.0",
"@vitest/ui": "^1.0.0",
"happy-dom": "^13.0.0"
}
}
{
"devDependencies": {
"eslint": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"eslint-config-prettier": "^9.0.0",
"prettier": "^3.0.0"
}
}
{
"devDependencies": {
"@modelcontextprotocol/inspector": "^1.0.0"
}
}
tools
# Raindrop.io MCP Server Connect Raindrop.io to your AI assistant with a simple MCP server. Use it to organize, search, and manage bookmarks with natural language. ## Capabilities - **Bookmark Management**: Create, update, and delete collections and bookmarks. - **Search & Filtering**: Advanced search by tags, domain, type, date, and more. - **Tag Management**: List, rename, merge, and delete tags. - **Highlights**: Read and manage highlights from bookmarks. - **Organization**: AI-powered sug
tools
Publishing and release workflow with semantic-release and GitHub Actions
tools
Refactoring MCP Tools for Better LLM Integration and Usability
tools
MCP Protocol Inspection and Debugging with Inspector CLI