Skip to main content

Integrations Hub

Connect your existing tools to Trending Engine. Once connected, Jarvis can use these tools on your behalf.

How It Works

You connect Notion → Jarvis can "Create a page in my Notion"
You connect Slack → Jarvis can "Post to #general in my Slack"
You connect Linear → Jarvis can "Create issue in my Linear"
Each tenant manages their own connections. Credentials are encrypted and tenant-isolated.

Connection Types

OAuth Apps

Standard OAuth 2.0 flow for established apps:
IntegrationCapabilitiesOAuth Scopes
NotionCreate pages, search, read databasesread_content, update_content, insert_content
SlackPost messages, read channels, searchchat:write, channels:read, search:read
Google DriveRead, write, share filesdrive.file, drive.readonly
GitHubCreate issues, PRs, read reposrepo, read:org
LinearCreate issues, read projectsread, write
FigmaRead designs, export assetsfile_read
GmailSend, read, search emailsgmail.send, gmail.readonly
Google CalendarRead, create eventscalendar.events

MCP Servers

Model Context Protocol for custom integrations:
IntegrationTypeUse Case
SupabaseOfficial MCPDatabase queries
Custom InternalSelf-hostedYour internal tools
n8nWebhook MCPComplex workflows
MCP enables connecting any system with an MCP server—official or custom.

OAuth Integration Flow

1. User Initiates Connection

GET /api/integrations/notion/authorize
Redirects user to Notion’s OAuth consent screen.

2. User Grants Permission

User sees: “Trending Engine wants to access your Notion workspace”

3. Callback & Token Exchange

GET /api/integrations/callback?code=xxx&state=yyy
We exchange the auth code for access/refresh tokens.

4. Connection Stored

// Encrypted and stored in tenant_connections
{
  tenant_id: "xxx",
  integration_id: "notion-uuid",
  connection_type: "oauth",
  access_token_encrypted: "encrypted...",
  refresh_token_encrypted: "encrypted...",
  token_expires_at: "2025-02-15T00:00:00Z",
  scopes: ["read_content", "update_content"],
  external_account_name: "Jeff's Workspace"
}

5. Jarvis Can Now Use It

User: "Create a page in my Notion called 'Meeting Notes'"

Jarvis: [checks tenant_connections for Notion]
        [decrypts token]
        [calls Notion API]
        "Done! Created 'Meeting Notes' in your Notion workspace."

MCP Server Connections

Official MCP Servers

Connect to official MCP servers with one click:
// POST /api/integrations/connect
{
  "integration_id": "supabase-uuid",
  "connection_type": "mcp",
  "mcp_server_url": "https://mcp.supabase.com",
  "mcp_auth_type": "bearer",
  "mcp_auth_token": "your-supabase-key"
}

Custom MCP Servers

Connect your own MCP server:
// POST /api/integrations/connect
{
  "integration_id": "custom-uuid",
  "connection_type": "mcp",
  "display_name": "Internal CRM",
  "mcp_server_url": "https://mcp.yourcompany.com",
  "mcp_auth_type": "api_key",
  "mcp_auth_token": "your-api-key"
}

MCP Discovery

When connected, we discover available tools:
{
  "tools": [
    {
      "name": "notion:create_page",
      "description": "Create a new page in a Notion database",
      "inputSchema": {...}
    },
    {
      "name": "notion:search",
      "description": "Search across Notion workspace",
      "inputSchema": {...}
    }
  ]
}

Permission Control

Tool-Level Permissions

Enable/disable specific tools per connection:
// POST /api/connections/:id/permissions
{
  "tool_name": "slack:post_message",
  "allowed": true,
  "restrictions": {
    "channels": ["C123456", "C789012"]  // Only these channels
  }
}

Permission Examples

ToolRestriction TypeExample
slack:post_messageChannel allowlistOnly #general, #alerts
notion:create_pageDatabase allowlistOnly “Tasks” database
github:create_issueRepo allowlistOnly public repos
gmail:sendRecipient allowlistOnly @company.com

Usage Tracking

Every integration call is logged:
{
  "connection_id": "xxx",
  "tool_name": "notion:create_page",
  "action": "write",
  "triggered_by": "jarvis",
  "user_id": "xxx",
  "success": true,
  "response_time_ms": 234
}
View usage in the dashboard:
  • Total calls per integration
  • Success/failure rates
  • Average response times
  • Triggered by (Jarvis, automation, manual)

Security

Token Encryption

All tokens are encrypted using Supabase Vault (pgsodium):
-- Stored encrypted, never in plaintext
access_token_encrypted = vault.encrypt(access_token)

Token Refresh

OAuth tokens are refreshed automatically before expiration:
// Background job runs hourly
if (connection.token_expires_at < now + 1 hour) {
  const newTokens = await refreshOAuthToken(connection);
  await updateConnection(connection.id, newTokens);
}

Tenant Isolation

RLS ensures connections are tenant-isolated:
CREATE POLICY "tenant_connections_isolation" ON tenant_connections
  FOR ALL USING (
    tenant_id IN (SELECT get_user_tenant_ids())
  );

Available Integrations

Productivity

  • Notion - Pages, databases, search
  • Slack - Messages, channels, search
  • Linear - Issues, projects, cycles
  • Airtable - Records, bases, views

Development

  • GitHub - Issues, PRs, repos, actions
  • Vercel - Deployments, domains, env vars
  • Supabase - Database queries, storage

Google Workspace

  • Google Drive - Files, folders, sharing
  • Gmail - Send, read, search
  • Google Calendar - Events, availability
  • Google Docs - Documents, collaboration
  • Google Sheets - Spreadsheets, data

Communication

  • Slack - Team messaging
  • Discord - Server messaging

Storage

  • Dropbox - Files, sharing
  • OneDrive - Microsoft files

Design

  • Figma - Designs, components, exports
  • Canva - Graphics, templates

Analytics

  • Google Analytics - Traffic, conversions
  • Mixpanel - Events, funnels

CRM

  • HubSpot - Contacts, deals, pipelines
  • Salesforce - Leads, opportunities

Ecommerce

  • Shopify - Products, orders, customers

Custom

  • Webhook - Any HTTP endpoint
  • MCP Server - Any MCP-compatible server

Adding New Integrations

Request an integration or add your own MCP server:
  1. Request Official - Email [email protected]
  2. Add Custom MCP - Connect any MCP server URL
  3. Build Your Own - Use our MCP server template

MCP Server Template

// Minimal MCP server
import { Server } from '@modelcontextprotocol/sdk/server';

const server = new Server({
  name: 'my-integration',
  version: '1.0.0'
});

server.setRequestHandler('tools/list', async () => ({
  tools: [
    {
      name: 'my_tool',
      description: 'Does something useful',
      inputSchema: {
        type: 'object',
        properties: {
          input: { type: 'string' }
        }
      }
    }
  ]
}));

server.setRequestHandler('tools/call', async (request) => {
  if (request.params.name === 'my_tool') {
    return { result: 'Done!' };
  }
});

server.listen(3001);