How to Integrate OpenWork with Google Workspace and Microsoft 365 Connectors

OpenWork integrates Google Workspace and Microsoft 365 through native provider connectors in the Den backend, using MCP (Model Context Protocol) architecture with OAuth 2.0 delegation and scoped capability endpoints that AI agents can discover and execute on behalf of individual members.

The different-ai/openwork repository implements enterprise-grade connectors that let AI agents read calendar events, send emails, manage files, and interact with Teams—without ever storing user passwords. This guide explains the architecture, implementation files, and exact steps to configure both providers.


Architecture Overview

OpenWork's connector system spans four layers: the MCP client UI, the MCP server (Den backend), capability sources, and OAuth token management.

Layer Responsibility Key Implementation
MCP client (frontend) UI for adding connectors, displaying permission groups, and handling OAuth redirects GoogleWorkspaceDialog used in mcp-connections-screen.tsx at line 901; Microsoft365Dialog component
MCP server (Den) Stores connector configuration, registers native OAuth providers, resolves delegated access tokens registerGoogleWorkspaceRoutes in ee/apps/den-api/src/routes/org/google-workspace.ts; registerMicrosoft365Routes in ee/apps/den-api/src/routes/org/microsoft-365.ts
Capability Sources HTTP endpoints under /v1/capabilities/* auto-discovered by search_capabilities / execute_capability Google Workspace routes (e.g., GET /v1/capabilities/google-workspace/calendar-events); Microsoft 365 routes (e.g., GET /v1/capabilities/microsoft-365/mail-messages)
OAuth handling Fetches fresh tokens from native provider vault, translates missing credentials to needs_connection errors googleWorkspaceToken helper in google-workspace.ts; defaultAccessTokenResolver in microsoft-365.ts

When a member clicks Connect, OpenWork redirects to the provider's consent screen. After authorization, the native provider stores the encrypted credential ID in the Den vault. Subsequent capability calls use that delegated token, enabling the AI agent to act on the member's data without password access.


Core Implementation Files

Understanding the source structure is essential for debugging and extending these integrations.

Backend Routes

Provider File Path Purpose
Google Workspace ee/apps/den-api/src/routes/org/google-workspace.ts All capability endpoints, OAuth callbacks, token refresh, error handling
Microsoft 365 ee/apps/den-api/src/routes/org/microsoft-365.ts All capability endpoints, OAuth callbacks, token refresh, error handling

Frontend Components

Component File Path Purpose
Microsoft365Dialog ee/apps/den-web/app/(den)/dashboard/_components/microsoft-365-dialog.tsx Full UI for Microsoft 365 connection setup, including MICROSOFT_365_PERMISSION_GROUPS
GoogleWorkspaceDialog (used) ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-screen.tsx at line 901 Entry point where Google Workspace dialog is rendered

The connector-quick-add-grid.mdx documentation in the docs/start-here/ directory also shows these connectors in the quick-add interface row layout.


How the Integration Flow Works

Step 1: Adding a Connector

In Settings → Extensions, users click Add Custom App → Google Workspace or Microsoft 365. The dialog displays:

  • Google Workspace: Required redirect URI
  • Microsoft 365: Tenant registration steps

The browser redirects to:

  • Google: https://accounts.google.com/o/oauth2/v2/auth
  • Microsoft: Microsoft Entra consent endpoint

After authorization, OpenWork receives a code, exchanges it for tokens, and stores the encrypted secret via the native provider.

Step 3: Feature Selection

Admins toggle optional permission checkboxes:

Google Workspace permission groups:

  • Gmail (read, send)
  • Drive (read, write)
  • Calendar (read, write)

Microsoft 365 permission groups (MICROSOFT_365_PERMISSION_GROUPS):

  • Outlook mail (read, send)
  • Calendar (read, write)
  • OneDrive (read, write)
  • Teams chat (read, send)

These populate the connector's features array in the Den database.

Step 4: Capability Discovery

The agent calls search_capabilities against the MCP server:

POST https://api.openworklabs.com/mcp/agent/search_capabilities
Content-Type: application/json

{
  "query": "calendar events",
  "max_results": 10
}

Response includes deterministic tool names:

{
  "tools": [
    {
      "name": "native:google-workspace:getCapabilitiesGoogleWorkspaceCalendarEvents",
      "description": "List Google Calendar events in a time range as the calling member"
    },
    {
      "name": "native:microsoft-365:getCapabilitiesMicrosoft365CalendarEvents",
      "description": "List Microsoft 365 calendar events as the calling member"
    }
  ]
}

Step 5: Capability Execution

The agent invokes execute_capability with the tool name:

POST https://api.openworklabs.com/mcp/agent/execute_capability
Content-Type: application/json

{
  "name": "native:google-workspace:getCapabilitiesGoogleWorkspaceCalendarEvents",
  "query": {
    "timeMin": "2024-09-01T00:00:00Z",
    "timeMax": "2024-09-04T00:00:00Z",
    "maxResults": 5
  }
}

The Den route validates the member's token, checks enabled scopes via googleWorkspaceToken or defaultAccessTokenResolver, forwards to the Google/Microsoft Graph API, and returns typed JSON.


OAuth Token Management Deep Dive

Google Workspace Token Flow

The googleWorkspaceToken helper in google-workspace.ts:

  1. Retrieves the stored credential from the native provider vault
  2. Calls getValidAccessToken to refresh if expired
  3. Returns the access token for Graph API calls
  4. Throws needs_connection error if no credential exists

Microsoft 365 Token Flow

The defaultAccessTokenResolver in microsoft-365.ts:

  1. Resolves tenant ID from stored configuration
  2. Fetches delegated token for the specific member
  3. Validates required scopes against enabled features
  4. Returns token or missingPermissionMessage error

Both implementations use the needs_connection error pattern, surfaced to agents as:

{
  "error": "needs_connection",
  "message": "Connect your Microsoft work account first: open Settings > Connect and use Connect your account on the Microsoft 365 row, or connect from the OpenWork Cloud dashboard."
}

Error Handling Patterns

Error Type Source Agent Response
needs_connection Missing credential in vault Prompt user to complete OAuth flow
missingPermissionMessage Scope not enabled in features Request admin to toggle permission group
google_api_error Google API 4xx/5xx Surface specific error, suggest retry
microsoft_graph_error Microsoft Graph 4xx/5xx Surface specific error, suggest retry

The missingPermissionMessage helper generates human-readable guidance based on which permission group is absent.


Practical Code Examples

Creating a Microsoft 365 Email Draft

POST https://api.openworklabs.com/mcp/agent/execute_capability
Content-Type: application/json

{
  "name": "native:microsoft-365:mail-drafts",
  "json": {
    "to": ["alice@example.com"],
    "subject": "Project update",
    "body": "Here is the latest status …"
  }
}

Response:

{
  "ok": true,
  "draft": {
    "id": "draft-789",
    "subject": "Project update",
    "to": [{ "address": "alice@example.com", "name": "" }],
    "body": "Here is the latest status …"
  }
}

Handling Connection Errors in Agent Logic

// Example agent-side error handling
const result = await executeCapability('native:microsoft-365:mail-messages');

if (result.error === 'needs_connection') {
  // Show UI prompt with Settings deep link
  showConnectPrompt('microsoft-365');
} else if (result.error === 'microsoft_graph_error') {
  // Log and suggest retry
  logError(result.message);
  suggestRetry();
}

Admin Configuration Checklist

Step Google Workspace Microsoft 365
Create OAuth client Google Cloud Console → Credentials → OAuth 2.0 Client ID (Web) Microsoft Entra → App registrations → New registration
Set redirect URI https://api.openworklabs.com/mcp/agent/oauth/google-workspace/callback https://api.openworklabs.com/mcp/agent/oauth/microsoft-365/callback
Configure scopes Gmail, Calendar, Drive API scopes Microsoft Graph delegated permissions
Enter credentials Client ID, Client Secret in Google Workspace dialog Tenant ID, Client ID, Client Secret in Microsoft 365 dialog
Enable features Toggle permission groups (Gmail send, Drive write, etc.) Toggle permission groups (Outlook send, OneDrive write, Teams chat, etc.)
Member authorization Click Connect your account, consent to scopes Click Connect your account, consent to scopes

Restart OpenWork Desktop or reload the web UI to activate the connector under Your Connections.


Capability Endpoint Reference

Tool names follow the pattern native:<provider>:<capability>:

Provider Example Tool Endpoint
Google Workspace native:google-workspace:getCapabilitiesGoogleWorkspaceCalendarEvents GET /v1/capabilities/google-workspace/calendar-events
Google Workspace native:google-workspace:mail-send POST /v1/capabilities/google-workspace/mail-send
Microsoft 365 native:microsoft-365:getCapabilitiesMicrosoft365MailMessages GET /v1/capabilities/microsoft-365/mail-messages
Microsoft 365 native:microsoft-365:mail-drafts POST /v1/capabilities/microsoft-365/mail-drafts
Microsoft 365 native:microsoft-365:teams-chat-send POST /v1/capabilities/microsoft-365/teams-chat-send

These are registered automatically by registerGoogleWorkspaceRoutes and registerMicrosoft365Routes when the Den server starts.


Summary

  • OpenWork uses MCP-native provider architecture to connect Google Workspace and Microsoft 365, with OAuth delegation stored in the Den vault
  • Four layers implement the stack: MCP client UI (microsoft-365-dialog.tsx, mcp-connections-screen.tsx), MCP server registration functions, capability source endpoints, and token resolver helpers
  • Tool names are deterministic (native:<provider>:<capability>), enabling agent auto-discovery via search_capabilities
  • Scoped permissions are enforced at runtime—admins control which data sources agents can access
  • Connection errors are structured (needs_connection, missingPermissionMessage) so agents can guide users through resolution

Frequently Asked Questions

What is the MCP server URL for OpenWork?

The default MCP server endpoint is https://api.openworklabs.com/mcp/agent. Self-hosted deployments use their configured Den API URL with /mcp/agent path. All search_capabilities and execute_capability calls target this base URL.

How does OpenWork handle token expiration?

The getValidAccessToken function in the native provider automatically refreshes expired access tokens using stored refresh tokens. Implementations in googleWorkspaceToken and defaultAccessTokenResolver handle this transparently—agents never receive expired tokens.

Can I restrict which Microsoft 365 features my team can use?

Yes. During setup, admins toggle permission groups in the Microsoft365Dialog UI. These populate the connector's features array. The defaultAccessTokenResolver validates enabled features before executing capabilities, returning missingPermissionMessage if a disabled feature is requested.

What's the difference between Google Workspace and Microsoft 365 connector architecture?

Both use identical MCP patterns, but Microsoft 365 requires tenant ID configuration for multi-tenant apps, while Google Workspace uses universal OAuth 2.0 with client ID/secret only. Microsoft also supports more granular Teams-specific permissions not present in Google's workspace APIs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →