Skip to content
google-oauth-integration logo

Google OAuth Integration

google-oauth-integration

Complete Google OAuth integration architecture including token storage and debugging

SKILL.md

Full skill instructions

Google OAuth Integration

This skill documents the complete Google OAuth integration architecture in Orient, including token storage, tool registration, and debugging procedures.

Triggers

Use this skill when:

  • Setting up Google OAuth for a new package or service
  • Debugging "Unknown tool" errors for Google tools (Calendar, Gmail, Tasks)
  • Understanding token storage and refresh mechanics
  • Adding new Google service tools to the ToolExecutorRegistry

Token Storage Architecture

Token File Location

Google OAuth tokens are stored in JSON files at:

{cwd}/​data/​oauth-tokens/​google-oauth.json

CRITICAL: The path is resolved using process.cwd(), meaning different packages look in different locations:

  • Dashboard: packages/​dashboard/​data/​oauth-tokens/​google-oauth.json
  • Slack bot: packages/​bot-slack/​data/​oauth-tokens/​google-oauth.json
  • WhatsApp bot: packages/​bot-whatsapp/​data/​oauth-tokens/​google-oauth.json
  • Project root: data/​oauth-tokens/​google-oauth.json

Symlink Setup (Required for Multi-Package Access)

Since the dashboard is typically where users connect their Google accounts, other packages need symlinks to access the same tokens:

# For bot-slack
mkdir -p packages/​bot-slack/​data/​oauth-tokens
ln -sf $(pwd)/​packages/​dashboard/​data/​oauth-tokens/​google-oauth.json \
       packages/​bot-slack/​data/​oauth-tokens/​google-oauth.json

# For bot-whatsapp
mkdir -p packages/​bot-whatsapp/​data/​oauth-tokens
ln -sf $(pwd)/​packages/​dashboard/​data/​oauth-tokens/​google-oauth.json \
       packages/​bot-whatsapp/​data/​oauth-tokens/​google-oauth.json

# For project root (used by MCP servers)
mkdir -p data/​oauth-tokens
ln -sf $(pwd)/​packages/​dashboard/​data/​oauth-tokens/​google-oauth.json \
       data/​oauth-tokens/​google-oauth.json

Token File Structure

{
  "accounts": {
    "[email protected]": {
      "email": "[email protected]",
      "displayName": "User Name",
      "accessToken": "ya29...",
      "refreshToken": "1//...",
      "expiresAt": 1768578677699,
      "scopes": [
        "https://www.googleapis.com/​auth/​calendar",
        "https://www.googleapis.com/​auth/​gmail.modify"
      ],
      "connectedAt": 1768552923717,
      "lastRefreshAt": 1768575078699
    }
  },
  "pendingStates": {}
}

Environment Variables

Required environment variables in .env:

# OAuth Client Credentials (from Google Cloud Console)
GOOGLE_OAUTH_CLIENT_ID=<your-client-id>.apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=GOCSPX-<your-secret>

# Callback URL (must match Google Cloud Console)
GOOGLE_OAUTH_CALLBACK_URL=http://localhost/​api/​auth/​google/​callback

The OAuth service loads credentials in this priority order:

  1. Secrets database (GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET)
  2. Environment variables
  3. Credentials file: credentials/​client_secret_*.json

Tool Registration Architecture

Two Registration Systems

Orient has two tool registration systems:

  1. ToolRegistry (Discovery only)

    • Location: packages/​agents/​src/​services/​toolRegistry.ts
    • Used by: discover_tools for listing available tools
    • Does NOT execute tools
  2. ToolExecutorRegistry (Execution)

    • Location: packages/​agents/​src/​services/​toolRegistry.ts
    • Used by: executeToolCallFromRegistry() in packages/​mcp-servers/​src/​tool-executor.ts
    • Actually runs the tool code

Registering New Google Tools

To add a new Google tool, register it in the registerGoogleToolHandlers() function:

// In packages/​agents/​src/​services/​toolRegistry.ts

function registerGoogleToolHandlers(registry: ToolExecutorRegistry): void {
  const registerHandlers = async () => {
    const { getCalendarService, getGoogleOAuthService } =
      await import('@orientbot/​integrations/​google');

    // Register handler
    registry.registerHandler('google_calendar_list_events', async (args) => {
      const calendar = getCalendarService();
      const events = await calendar.listEvents(options, accountEmail);
      return createToolResult(JSON.stringify(events, null, 2));
    });
  };

  void registerHandlers();
}

Legacy vs Modern Registration

AspectLegacy (mcp-server.ts)Modern (ToolExecutorRegistry)
Locationpackages/​mcp-servers/​src/​mcp-server.tspackages/​agents/​src/​services/​toolRegistry.ts
PatternGiant switch statementHandler registration
Used byDirect MCP serverassistant-server via base-server
StatusDeprecatedPreferred

Important: The assistant-server (used by Slack/​WhatsApp bots) uses base-server.ts which ONLY uses ToolExecutorRegistry. It does NOT fall back to the legacy switch statement unless setLegacyExecutor() is called.

Token Refresh Mechanics

The OAuth service in packages/​integrations/​src/​google/​oauth.ts handles automatic token refresh:

async getAuthClient(email: string): Promise<Auth.OAuth2Client> {
  const account = this.data.accounts[email];

  // Check if token needs refresh (expired or expiring in < 5 min)
  if (Date.now() > account.expiresAt - 5 * 60 * 1000) {
    const { credentials } = await client.refreshAccessToken();
    account.accessToken = credentials.access_token;
    account.expiresAt = credentials.expiry_date;
    this.saveData();
  }

  return client;
}

Key points:

  • Tokens are refreshed automatically 5 minutes before expiration
  • Requires valid refresh_token from initial OAuth consent
  • Requires OAuth credentials (client ID/​secret) to be accessible

Debugging "Unknown Tool" Errors

When Google tools return {"error":"Unknown tool: google_calendar_list_events"}:

Step 1: Check Tool Discovery

# Tool should appear in discover_tools output
curl -X POST http://localhost:4099/​... -d '{"tool":"discover_tools","args":{"mode":"search","query":"calendar"}}'

If tool appears in discovery but not execution, it's registered in ToolRegistry but not ToolExecutorRegistry.

Step 2: Check ToolExecutorRegistry Registration

Look for the tool in packages/​agents/​src/​services/​toolRegistry.ts:

// Should see this in registerGoogleToolHandlers():
registry.registerHandler('google_calendar_list_events', async (args) => { ... });

Step 3: Verify Build and Restart

# Rebuild affected packages
pnpm --filter @orientbot/​agents build
pnpm --filter @orientbot/​mcp-servers build

# Copy to root dist (used by OpenCode)
cp packages/​mcp-servers/​dist/​*.js dist/​mcp-servers/

# Kill existing MCP server processes
ps aux | grep "assistant-server\|coding-server" | grep -v grep | awk '{print $2}' | xargs kill

# OpenCode will spawn fresh processes on next tool call

Step 4: Check MCP Server Logs

tail -f logs/​mcp-debug-*.log | grep -i "calendar\|google\|unknown"

Look for:

  • "Registered tool" - Tool was registered
  • "Unknown tool" - Tool not found in any executor
  • Error messages during handler registration

Common Issues

Issue: Tokens not found

Symptom: "No Google account connected" Cause: Token file not found at CWD path Fix: Create symlinks as documented above

Issue: Token refresh fails

Symptom: "Failed to refresh token" Cause: OAuth credentials not accessible Fix: Ensure GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET are set

Issue: Tool returns "Unknown tool"

Symptom: {"error":"Unknown tool: google_calendar_list_events"} Cause: Tool not registered in ToolExecutorRegistry Fix: Add handler in registerGoogleToolHandlers() and rebuild

Issue: Stale MCP server

Symptom: Changes not taking effect Cause: Old MCP server process still running Fix: Kill old processes, OpenCode will spawn new ones

Files Reference

FilePurpose
packages/​integrations/​src/​google/​oauth.tsOAuth service, token storage
packages/​integrations/​src/​google/​calendar.tsCalendar service implementation
packages/​agents/​src/​services/​toolRegistry.tsTool discovery + executor registration
packages/​mcp-servers/​src/​tool-executor.tsTool execution entry point
packages/​mcp-servers/​src/​base-server.tsMCP server using executor registry
packages/​mcp-servers/​src/​mcp-server.tsLegacy MCP server with switch statement

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View