Skip to main content
CORE integrations connect external services to provide activity sync and MCP tools for AI agents. This reference covers integration architecture and event types.

Integration Capabilities

  1. Activity Sync - Capture events into knowledge graph
  2. MCP Tools - Expose service actions to AI agents (required)

File Structure

  • index.ts - Event router (SETUP, SYNC/PROCESS, GET_TOOLS, CALL_TOOL)
  • account-create.ts - OAuth handler
  • schedule.ts OR create-activity.ts + identify.ts - Activity sync
  • mcp/index.ts - MCP tool definitions and implementations

Integration Types

Webhook-Based - Real-time events (Slack, Discord)
  • Events: SETUP, IDENTIFY, PROCESS, GET_TOOLS, CALL_TOOL
  • Best for: Chat, real-time notifications
Schedule-Based - Periodic polling (GitHub, Linear)
  • Events: SETUP, SYNC, GET_TOOLS, CALL_TOOL
  • Best for: APIs without webhooks, batch processing
  • Frequency: 5-15 minute cron schedule

Spec Configuration

Returned by getSpec() in your CLI class:
{
  name: 'Service Name',
  key: 'service-key',
  description: 'Integration description',
  icon: 'icon-name',
  schedule: { frequency: '*/5 * * * *' },  // For schedule-based
  auth: {
    OAuth2: {
      token_url: 'https://api.service.com/oauth/token',
      authorization_url: 'https://api.service.com/oauth/authorize',
      scopes: ['read', 'write'],
      scope_separator: ',',
    }
  },
  mcp: { type: 'cli' }  // Always use 'cli' for custom tools
}

Event Types

All integrations handle:
case IntegrationEventType.SETUP:
  return await integrationCreate(eventPayload.eventBody);

case IntegrationEventType.GET_TOOLS:
  return await getTools();

case IntegrationEventType.CALL_TOOL:
  const { name, arguments: args } = eventPayload.eventBody;
  return await callTool(name, args, eventPayload.config.apiKey);
Schedule-based adds:
case IntegrationEventType.SYNC:
  return await handleSchedule(eventPayload.config, eventPayload.state);
Webhook-based adds:
case IntegrationEventType.IDENTIFY:
  return [{ type: 'identifier', data: eventPayload.eventBody.event.user }];

case IntegrationEventType.PROCESS:
  return await createActivityEvent(eventPayload.eventBody.eventData, eventPayload.config);

Return Types

SETUP - Account creation:
[{ type: 'account', data: { accountId, config, settings } }]
SYNC - Activity list + state:
[
  { type: 'activity', data: { text, sourceURL } },
  { type: 'state', data: { lastSyncTime, ...otherState } }
]
PROCESS - Activity list:
[{ type: 'activity', data: { text, sourceURL } }]
IDENTIFY - User identifier:
[{ type: 'identifier', data: 'user-id' }]
GET_TOOLS - Tool list:
[{ name: 'create_issue', description: '...', inputSchema: {...} }]
CALL_TOOL - Tool result:
{ content: [{ type: 'text', text: 'Result message' }] }

MCP Tools

All integrations must implement custom MCP tools using type: 'cli':
// src/mcp/index.ts
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';

const CreateIssueSchema = z.object({
  title: z.string().describe('Issue title'),
  description: z.string().optional(),
});

export async function getTools() {
  return [{
    name: 'create_issue',
    description: 'Create a new issue',
    inputSchema: zodToJsonSchema(CreateIssueSchema),
  }];
}

export async function callTool(name: string, args: any, apiKey: string) {
  if (name === 'create_issue') {
    const result = await yourApiCall(apiKey, args);
    return { content: [{ type: 'text', text: `Created #${result.id}` }] };
  }
  throw new Error(`Unknown tool: ${name}`);
}

Best Practices

Activity Messages:
  • Be descriptive with context
  • Always include sourceURL
  • Filter noise (only relevant events)
State Management:
  • Save lastSyncTime after each sync
  • Default to 24 hours on first sync
  • Use pagination for large datasets
Error Handling:
  • Return empty arrays on errors (don’t throw)
  • Continue processing if one item fails
  • Validate tokens early
MCP Tools:
  • Use clear descriptions
  • Validate all inputs
  • Return structured responses
  • Handle rate limiting

Reference Examples

Contributing

Want to build an integration? See our step-by-step contributor guide.