Testing Guide for Attio MCP Server

October 2, 2025 ยท View on GitHub

This guide explains how to set up and run tests for the Attio MCP Server, including unit tests and integration tests that interact with the Attio API.

๐Ÿ† Current Test Status

โœ… 100% Integration Test Pass Rate Achieved (15/15 tests passing)

Recent Testing Improvements (August 2025)

  • Critical Bug Fixes: All P0 API failures resolved with robust error handling
  • Enhanced Validation: Complete email validation consistency between create/update operations
  • Resource Mapping: Fixed all resource type mappings and JSON response handling
  • Tasks API Special Handling: Implemented workaround for missing /objects/tasks/attributes endpoint
  • Build Integration: All TypeScript compilation errors resolved
  • Error Handling: Comprehensive error mocking and fallback patterns implemented

Test Coverage

  • Integration Tests: 15/15 passing (100% pass rate)
  • Unit Tests: All offline tests passing
  • E2E Tests: Comprehensive error handling and API contract validation
  • Build Tests: TypeScript compilation validation included

Table of Contents

Quick Start

# 1. Set up your Attio API key in .env
echo "ATTIO_API_KEY=your_api_key_here" > .env

# 2. Copy test configuration template
cp .env.test.example .env.test

# 3. Edit .env.test with your workspace-specific IDs
# Or run the setup script to create test data:
npm run setup:test-data

# 4. Run all tests
npm test

# 5. Run integration tests only
npm run test:integration

Test Types

Unit Tests

Unit tests run without requiring an API connection and test individual functions in isolation.

# Run all unit tests
npm test

# Run unit tests in watch mode
npm test:watch

# Run offline tests only (no API calls)
npm test:offline

Integration Tests (IT-XXX)

Integration tests make real API calls to verify individual API operations, edge cases, and platform services against the live Attio API.

ID Prefix: IT-XXX (Integration Test) Location: test/integration/ Focus: API operations, validation, error handling

# Run all integration tests
npm run test:integration

# Run specific integration test
npm run test:integration -- test/integration/lists/add-record-to-list.integration.test.ts

# Run integration tests in watch mode
npm run test:integration:watch

Documentation:

E2E Tests (TC-XXX)

End-to-end tests validate complete user workflows through the MCP protocol, testing the full integration chain from client tools to Attio API.

ID Prefix: TC-XXX (Test Case) Location: test/e2e/ Focus: Complete workflows, user scenarios, MCP tool orchestration

# Run all E2E tests
npm run test:e2e

# Run MCP protocol tests
npm run test:e2e:mcp

# Run with diagnostics
npm run e2e:diagnose

Documentation:

Test Taxonomy: IT-XXX vs TC-XXX

AspectIntegration (IT-XXX)E2E (TC-XXX)
ScopeIndividual API operationsComplete workflows
ProtocolDirect Attio APIMCP โ†’ Attio API
NumberingIT-001, IT-105, IT-201...TC-001, TC-L01, TC-D01...
ExamplesRate limiting, batch CRUD, validationSearch workflow, deal creation, list management
Run Commandnpm run test:integrationnpm run test:e2e

Setting Up Integration Tests

1. Configure API Access

Create a .env file in the project root with your Attio API key:

ATTIO_API_KEY=your_api_key_here

2. Configure Test Data

Integration tests need specific records in your workspace to test against. You have two options:

Option A: Use Existing Records

  1. Copy the test configuration template:

    cp .env.test.example .env.test
    
  2. Edit .env.test with IDs from your workspace:

    # Required test data
    TEST_COMPANY_ID=198abdd2-a0d9-4c95-93b6-29bc4154953a
    TEST_PERSON_ID=f3503402-85fc-41b6-9427-819d05e8813e
    TEST_LIST_ID=b352b506-5d1f-43b2-9623-dc2e31c751f7
    
    # Optional test data
    TEST_DEAL_ID=93a7631d-8586-4471-ac56-881a6030a2ce
    

Option B: Create Test Data Automatically

Run the setup script to create test data in your workspace:

npm run setup:test-data

This will:

  • Create test companies and people with identifiable names (prefixed with E2E_TEST_)
  • Find available lists in your workspace
  • Output the IDs to add to your .env.test file

3. Finding Record IDs

To find IDs for existing records:

  1. Via Attio Web Interface:

    • Open a record in Attio
    • Look at the URL: https://app.attio.com/workspaces/.../objects/.../records/rec_abc123
    • The ID is the part starting with rec_, list_, etc.
  2. Via API Discovery:

    # Build the project first
    npm run build
    
    # Discover available resources
    npm run discover
    

Running Tests

All Tests

# Run all tests once
npm test

# Run tests in watch mode
npm test:watch

# Run tests with coverage
npm test:coverage

Integration Tests Only

# Run all integration tests
npm run test:integration

# Run a specific integration test file
npm run test:integration -- test/integration/lists/add-record-to-list.integration.test.ts

# Run integration tests matching a pattern
npm run test:integration -- -t "should add record to list"

Offline Tests Only

# Run tests that don't require API access
npm test:offline

# Watch mode for offline tests
npm test:watch:offline

Test Configuration

Environment Variables

The following environment variables control test behavior:

VariableDescriptionDefault
ATTIO_API_KEYYour Attio API keyRequired
SKIP_INTEGRATION_TESTSSkip all integration testsfalse
TEST_COMPANY_IDID of test company recordRequired for integration tests
TEST_PERSON_IDID of test person recordRequired for integration tests
TEST_LIST_IDID of test listRequired for list tests
SKIP_INCOMPLETE_TESTSSkip tests missing optional IDstrue
CLEANUP_TEST_DATAClean up created test datatrue
TEST_DATA_PREFIXPrefix for test data namesE2E_TEST_

Test Configuration File Structure

.env.test structure:

# Required test data
TEST_COMPANY_ID=your_company_id
TEST_PERSON_ID=your_person_id
TEST_LIST_ID=your_list_id

# Optional test data
TEST_EMPTY_LIST_ID=
TEST_DEAL_ID=
TEST_TASK_ID=
TEST_NOTE_ID=

# Test data values
TEST_COMPANY_NAME="Integration Test Company"
TEST_PERSON_EMAIL="integration-test@example.com"
TEST_PERSON_FIRST_NAME="Integration"
TEST_PERSON_LAST_NAME="Test"
TEST_DOMAIN="integration-test.com"

# Test behavior
SKIP_INCOMPLETE_TESTS=true
CLEANUP_TEST_DATA=true
TEST_DATA_PREFIX="E2E_TEST_"

Troubleshooting

Common Issues

"No API key found"

Ensure your .env file exists and contains:

ATTIO_API_KEY=your_actual_api_key

"Test configuration missing"

  1. Check that .env.test exists
  2. Verify it contains the required IDs
  3. Run npm run setup:test-data to create test data

"Record not found" errors

The test records may have been deleted. Either:

  • Update .env.test with new IDs
  • Run npm run setup:test-data to create new test records

Rate limiting errors

The tests include retry logic, but if you see rate limiting:

  • Reduce the number of concurrent tests
  • Add delays between test runs
  • Use a dedicated test workspace

Debugging Tests

# Run tests with verbose output
npm test -- --reporter=verbose

# Run a single test with debugging
npm test -- test/integration/lists/add-record-to-list.integration.test.ts --reporter=verbose

# Check test configuration
cat .env.test

Best Practices

1. Test Data Management

  • Use identifiable prefixes: Test data should be clearly marked (e.g., E2E_TEST_)
  • Clean up after tests: Enable CLEANUP_TEST_DATA=true
  • Use dedicated test records: Don't test against production data
  • Document test dependencies: Note which features require specific workspace setup

2. Writing Integration Tests

import { setupIntegrationTests } from '../helpers/integration-test-setup';

describe('My Integration Test', () => {
  // Setup with configuration requirement
  const setup = setupIntegrationTests({
    requireTestConfig: true,
    verbose: true,
  });

  if (setup.shouldSkip) {
    test.skip('Skipping - ' + setup.skipReason, () => {});
    return;
  }

  test('should interact with API', async () => {
    // Use test configuration
    const { companyId, listId } = setup.testConfig!;

    // Your test logic here
  });
});

3. CI/CD Considerations

For CI/CD pipelines:

# Example GitHub Actions setup
env:
  ATTIO_API_KEY: ${{ secrets.ATTIO_API_KEY }}
  TEST_COMPANY_ID: ${{ secrets.TEST_COMPANY_ID }}
  TEST_PERSON_ID: ${{ secrets.TEST_PERSON_ID }}
  TEST_LIST_ID: ${{ secrets.TEST_LIST_ID }}

4. Performance Tips

  • Run offline tests during development: npm test:offline
  • Use watch mode for faster feedback: npm test:watch:offline
  • Run integration tests before commits: npm run test:integration
  • Consider using separate test workspaces for parallel CI runs

Advanced Topics

Custom Test Configurations

Create workspace-specific test suites by extending the base configuration:

// test/config/my-workspace.ts
export const workspaceTestConfig = {
  customFields: {
    companies: ['industry', 'size'],
    people: ['department', 'role'],
  },
  lists: {
    prospecting: 'list_abc123',
    customers: 'list_def456',
  },
};

Test Data Factories

Use the test data generators for consistent test data:

import { generateTestData } from '../helpers/integration-test-setup';

const testData = generateTestData(Date.now());
// Creates timestamped test data for uniqueness

Mocking Strategies

For unit tests that need to mock API responses:

vi.mock('../../src/api/attio-client', () => ({
  getAttioClient: vi.fn(() => ({
    post: vi.fn().mockResolvedValue({ data: mockResponse }),
  })),
}));

Contributing

When adding new integration tests:

  1. Follow the existing pattern in test/integration/
  2. Use the setupIntegrationTests helper
  3. Add any new required test data to .env.test.example
  4. Update this documentation if adding new test types
  5. Ensure tests clean up after themselves

For more information, see the main README and Contributing Guide.