Skip to main content
Glama

Basecamp MCP Server

by jhliberty
utils.ts5.68 kB
import { vi } from 'vitest'; import type { AxiosResponse } from 'axios'; import type { BasecampProject, BasecampTodo, BasecampCardTable, BasecampCard, oAuthTokens, APIResponse } from '../types/basecamp.js'; /** * Test utilities for Vitest testing */ export const mockAxiosResponse = <T>(data: T, status = 200): AxiosResponse<T> => ({ data, status, statusText: status === 200 ? 'OK' : 'Error', headers: {}, config: {} as any, }); export const mockBasecampProject = (): BasecampProject => ({ id: '12345', name: 'Test Project', description: 'A test project for unit testing', created_at: '2025-01-01T00:00:00Z', updated_at: '2025-01-01T00:00:00Z', url: 'https://3.basecamp.com/12345/projects/67890', app_url: 'https://3.basecamp.com/12345/projects/67890', bookmarked: false, status: 'active', dock: [ { id: '111', name: 'todoset', enabled: true, position: 1, url: 'https://3.basecamp.com/12345/buckets/67890/todosets/111', app_url: 'https://3.basecamp.com/12345/buckets/67890/todosets/111' } ] }); export const mockBasecampTodo = (): BasecampTodo => ({ id: '54321', title: 'Test Todo', description: 'A test todo item', completed: false, created_at: '2025-01-01T00:00:00Z', updated_at: '2025-01-01T00:00:00Z', due_on: null, assignees: [], notes: '', url: 'https://3.basecamp.com/12345/buckets/67890/todos/54321', app_url: 'https://3.basecamp.com/12345/buckets/67890/todos/54321', comments_count: 0, parent: { id: '111', title: 'Test Todolist', type: 'Todolist', url: 'https://3.basecamp.com/12345/buckets/67890/todosets/111', app_url: 'https://3.basecamp.com/12345/buckets/67890/todosets/111' } }); export const mockBasecampCardTable = (): BasecampCardTable => ({ id: '98765', name: 'card_table', title: 'Card Table', type: 'Kanban::Tray', created_at: '2025-01-01T00:00:00Z', updated_at: '2025-01-01T00:00:00Z', url: 'https://3.basecamp.com/12345/buckets/67890/card_tables/98765', app_url: 'https://3.basecamp.com/12345/buckets/67890/card_tables/98765', columns: [], lists: [] }); export const mockBasecampCard = (): BasecampCard => ({ id: '13579', title: 'Test Card', content: 'Test card content', created_at: '2025-01-01T00:00:00Z', updated_at: '2025-01-01T00:00:00Z', url: 'https://3.basecamp.com/12345/buckets/67890/cards/13579', app_url: 'https://3.basecamp.com/12345/buckets/67890/cards/13579', status: 'active', due_on: null, assignees: [], comments_count: 0, steps: [], parent: { id: '98765', title: 'Card Table', type: 'Kanban::Tray', url: 'https://3.basecamp.com/12345/buckets/67890/card_tables/98765', app_url: 'https://3.basecamp.com/12345/buckets/67890/card_tables/98765' } }); export const mockOAuthToken = (): oAuthTokens => ({ access_token: 'test_access_token_123', token_type: 'Bearer', expires_in: 7200, refresh_token: 'test_refresh_token_456', scope: 'read write', created_at: Date.now(), account_id: '12345' }); /** * Mock environment variables for testing */ export const mockEnvironment = () => { vi.stubEnv('BASECAMP_CLIENT_ID', 'test_client_id'); vi.stubEnv('BASECAMP_CLIENT_SECRET', 'test_client_secret'); vi.stubEnv('BASECAMP_ACCOUNT_ID', '12345'); vi.stubEnv('USER_AGENT', 'Test Agent (test@example.com)'); }; /** * Create a mock MCP request */ export const mockMCPRequest = (method: string, params: any = {}, id: number = 1) => ({ jsonrpc: '2.0' as const, id, method, params }); /** * Create a mock MCP tool call request */ export const mockMCPToolCall = (toolName: string, arguments_: any = {}, id: number = 1) => ({ jsonrpc: '2.0' as const, id, method: 'tools/call', params: { name: toolName, arguments: arguments_ } }); /** * Helper to wait for async operations in tests */ export const waitFor = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); /** * Mock file system operations */ export const mockFileSystem = () => { const mockFiles: Record<string, string> = {}; return { readFile: vi.fn(async (path: string) => { if (mockFiles[path]) { return mockFiles[path]; } throw new Error(`File not found: ${path}`); }), writeFile: vi.fn(async (path: string, data: string) => { mockFiles[path] = data; }), exists: vi.fn(async (path: string) => { return mockFiles[path] !== undefined; }), getFiles: () => mockFiles, setFile: (path: string, data: string) => { mockFiles[path] = data; } }; }; /** * Mock HTTP server for OAuth testing */ export const mockHttpServer = () => { const handlers: Record<string, Function> = {}; return { listen: vi.fn((port: number, callback?: Function) => { if (callback) callback(); return { port }; }), get: vi.fn((path: string, handler: Function) => { handlers[`GET:${path}`] = handler; }), post: vi.fn((path: string, handler: Function) => { handlers[`POST:${path}`] = handler; }), close: vi.fn((callback?: Function) => { if (callback) callback(); }), request: (method: string, path: string, query: any = {}, body: any = {}) => { const handler = handlers[`${method.toUpperCase()}:${path}`]; if (handler) { const mockReq = { query, body }; const mockRes: APIResponse = { redirect: vi.fn(), send: vi.fn(), json: vi.fn(), status: vi.fn(() => mockRes) }; handler(mockReq, mockRes); return mockRes; } throw new Error(`No handler for ${method} ${path}`); } }; };

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/jhliberty/basecamp-mcp-server'

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