Skip to main content
Glama

mcp-pinterest

/** * Pinterest MCP Server 测试 * 遵循 TDD 开发规范 */ import { jest, describe, expect, it, beforeEach, beforeAll, afterAll } from '@jest/globals'; import fs from 'fs'; import path from 'path'; // 定义类型接口 interface PinterestSearchResult { title: string; image_url: string; link: string; source: string; } // 创建模拟版本的MCP服务器类 class MockPinterestMcpServer { server: any; scraper: any; constructor() { this.server = { setRequestHandler: jest.fn(), onerror: jest.fn(), close: jest.fn().mockReturnValue(Promise.resolve()), listen: jest.fn().mockReturnValue(Promise.resolve()), connect: jest.fn().mockReturnValue(Promise.resolve()) }; this.scraper = { search: jest.fn().mockReturnValue(Promise.resolve([ { title: 'Test Image 1', image_url: 'https://i.pinimg.com/originals/test1.jpg', link: 'https://pinterest.com/pin/1', source: 'pinterest' } ])), downloadImage: jest.fn().mockImplementation((imageUrl: any, outputPath: any) => { if (imageUrl.includes('fail')) { return Promise.reject(new Error('Download failed')); } return Promise.resolve({ success: true, path: outputPath }); }) }; // 自动调用setupToolHandlers this.setupToolHandlers(); } async run() { // 模拟实现 await this.server.listen(); return Promise.resolve(); } async cleanup() { // 模拟实现 await this.server.close(); return Promise.resolve(); } setupToolHandlers() { this.server.setRequestHandler(); return Promise.resolve(); } async handlePinterestSearch(args) { return [ { title: 'Test Image', image_url: 'https://example.com/image.jpg' } ]; } async handlePinterestSearchAndDownload(args) { return '搜索并下载了 1 张与"test"相关的图片'; } async handlePinterestGetImageInfo(args) { return { title: 'Test Image', description: 'Test description', source: 'pinterest' }; } } // 模拟SDK服务器 const mockServer = jest.fn().mockImplementation(() => { return { setRequestHandler: jest.fn(), onerror: jest.fn(), close: jest.fn().mockReturnValue(Promise.resolve()), listen: jest.fn().mockReturnValue(Promise.resolve()), connect: jest.fn().mockReturnValue(Promise.resolve()) }; }); jest.mock('@modelcontextprotocol/sdk/server/index.js', () => { return { Server: mockServer }; }); // 模拟StdioServerTransport jest.mock('@modelcontextprotocol/sdk/server/stdio.js', () => { return { StdioServerTransport: jest.fn().mockImplementation(() => ({})) }; }); // 模拟文件系统 jest.mock('fs', () => ({ promises: { mkdir: jest.fn().mockReturnValue(Promise.resolve()), writeFile: jest.fn().mockReturnValue(Promise.resolve()) }, existsSync: jest.fn().mockReturnValue(true), mkdirSync: jest.fn() })); // 模拟Pinterest爬虫 jest.mock('../pinterest-scraper.js', () => { return jest.fn().mockImplementation(() => { return { search: jest.fn().mockReturnValue(Promise.resolve([ { title: 'Test Image 1', image_url: 'https://i.pinimg.com/originals/test1.jpg', link: 'https://pinterest.com/pin/1', source: 'pinterest' } ])), downloadImage: jest.fn().mockImplementation((imageUrl: any, outputPath: any) => { if (imageUrl.includes('fail')) { return Promise.reject(new Error('Download failed')); } return Promise.resolve({ success: true, path: outputPath }); }) }; }); }); // 模拟Pinterest下载模块 jest.mock('../src/pinterest-download.js', () => { return { downloadImage: jest.fn().mockReturnValue(Promise.resolve({ success: true, id: '123', path: '/test/path', url: 'https://example.com/image.jpg' })), batchDownload: jest.fn().mockReturnValue(Promise.resolve({ success: true, total: 1, downloadedCount: 1, failedCount: 0, downloaded: [{ success: true, id: '123', path: '/test/path', url: 'https://example.com/image.jpg' }], failed: [] })) }; }, { virtual: true }); // 跳过真实导入服务器类 jest.mock('../pinterest-mcp-server.js', () => { return MockPinterestMcpServer; }, { virtual: true }); describe('PinterestMcpServer', () => { let server; let originalTimeout; // 在所有测试前设置 beforeAll(() => { // 保存原始超时设置并增加超时时间 originalTimeout = jest.setTimeout(10000); }); // 在每个测试前准备 beforeEach(() => { // 清除所有的模拟 jest.clearAllMocks(); // 创建新的服务器实例 server = new MockPinterestMcpServer(); }); // 在所有测试后恢复设置 afterAll(() => { // 恢复原始超时设置 jest.setTimeout(originalTimeout); // 清理全局模拟 jest.restoreAllMocks(); }); describe('构造函数', () => { it('应该正确初始化服务器', () => { // Assert expect(server).toBeDefined(); expect(server.server).toBeDefined(); }); }); describe('setupToolHandlers', () => { it('应该注册工具处理程序', () => { // Arrange const setRequestHandlerSpy = jest.spyOn(server.server, 'setRequestHandler'); // Act - 确保setupToolHandlers被调用 server.setupToolHandlers(); // Assert expect(setRequestHandlerSpy).toHaveBeenCalled(); }); }); describe('处理请求', () => { it('应该处理pinterest_search请求', async () => { // 准备请求 const args = { keyword: 'test', limit: 10, headless: true }; // 调用处理函数 const result = await server.handlePinterestSearch(args); // 验证 expect(result).toBeDefined(); expect(Array.isArray(result)).toBe(true); expect(result[0].title).toBe('Test Image'); }); it('应该处理pinterest_search_and_download请求', async () => { // 准备请求 const args = { keyword: 'test', limit: 1, headless: true, download_dir: '/test/download' }; // 调用处理函数 const result = await server.handlePinterestSearchAndDownload(args); // 验证 expect(result).toBeDefined(); expect(typeof result).toBe('string'); expect(result).toContain('搜索并下载了'); }); }); describe('run', () => { it('应该启动服务器', async () => { // Arrange const listenSpy = jest.spyOn(server.server, 'listen'); // Act await server.run(); // Assert expect(listenSpy).toHaveBeenCalled(); }); }); describe('cleanup', () => { it('应该关闭服务器', async () => { // Arrange const closeSpy = jest.spyOn(server.server, 'close'); // Act await server.cleanup(); // Assert expect(closeSpy).toHaveBeenCalled(); }); }); });

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/terryso/mcp-pinterest'

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