npm package: @osiris-ai/google-sdk
Description: Osiris Google SDK
Latest version: 0.1.1

# @osiris-ai/google-sdk

OAuth 2.0 Google authenticator for building authenticated MCPs with Google services integration.

[![npm version](https://badge.fury.io/js/@osiris-ai%2Fgoogle-sdk.svg)](https://badge.fury.io/js/@osiris-ai%2Fgoogle-sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Overview

The Google SDK provides seamless OAuth 2.0 authentication for Google services in the [Osiris](https://docs.osirislabs.xyz) ecosystem. Build powerful MCPs (Model Context Protocol) that can interact with Gmail, Drive, Calendar, Sheets, and more with enterprise-grade security and zero-configuration authentication.

**Key Features:**
- 🔐 **Zero-config OAuth** - No client credentials or setup required
- 📧 **Multi-Service Support** - Gmail, Drive, Calendar, Sheets, Docs, Slides, YouTube
- 🔄 **Auto Token Refresh** - Automatic token lifecycle management
- 🛡️ **Enterprise Security** - Built on Osiris Hub authentication
- 📝 **Full TypeScript** - Complete type safety with googleapis integration
- ⚡ **googleapis Integration** - Familiar Google API interface

## Installation

```bash
npm install @osiris-ai/google-sdk @osiris-ai/sdk
```

## Quick Start

### Hub Authentication (Recommended)

The Google authenticator works automatically through the Osiris Hub - no Google OAuth app setup required.

```typescript
import { createMcpServer, getAuthContext } from '@osiris-ai/sdk';
import { createHubGmailClient } from '@osiris-ai/google-sdk';
import { createSuccessResponse, createErrorResponse } from '../utils/types.js';
import { z } from 'zod';

await createMcpServer({
  name: 'google-mcp',
  version: '1.0.0',
  auth: {
    useHub: true,
    hubConfig: {
      baseUrl: process.env.HUB_BASE_URL!,
      clientId: process.env.OAUTH_CLIENT_ID!,
      clientSecret: process.env.OAUTH_CLIENT_SECRET!,
    }
  },
  configure: (server) => {
    // Send Gmail email
    server.tool(
      'send_email',
      'Send an email through Gmail',
      {
        to: z.string().email(),
        subject: z.string(),
        body: z.string()
      },
      async ({ to, subject, body }) => {
        try {
          const { token, context } = getAuthContext("osiris");
          if (!token || !context) {
            return createErrorResponse("User not authenticated");
          }

          // Create authenticated Gmail client
          const gmail = await createHubGmailClient({
            hubBaseUrl: process.env.HUB_BASE_URL!,
            token: token,
            context: context
          });

          // Send email using googleapis interface
          const emailContent = [
            `To: ${to}`,
            `Subject: ${subject}`,
            'MIME-Version: 1.0',
            'Content-Type: text/plain; charset=UTF-8',
            '',
            body
          ];

          const raw = Buffer.from(emailContent.join('\r\n'))
            .toString('base64')
            .replace(/\+/g, '-')
            .replace(/\//g, '_');

          const result = await gmail.users.messages.send({
            userId: 'me',
            requestBody: { raw }
          });

          return createSuccessResponse('Email sent successfully', {
            messageId: result.data.id,
            threadId: result.data.threadId
          });
        } catch (error) {
          return createErrorResponse(error);
        }
      }
    );
  }
});
```

### Available Google Services

The SDK provides dedicated clients for all major Google services:

```typescript
import {
  createHubGmailClient,      // Gmail API
  createHubDriveClient,      // Google Drive API
  createHubCalendarClient,   // Google Calendar API
  createHubSheetsClient,     // Google Sheets API
  createHubDocsClient,       // Google Docs API
  createHubSlidesClient,     // Google Slides API
  createHubYouTubeClient,    // YouTube API
  createHubPeopleClient,     // Google People (Contacts) API
} from '@osiris-ai/google-sdk';
```

### Available Google Scopes

Configure your MCP to request specific Google permissions:

All slack scopes are supported and they all need to prefixed with `google:`

## Local Authentication (Advanced)

For custom authentication flows or enterprise requirements:

```typescript
import { GoogleAuthenticator } from '@osiris-ai/google-sdk';
import { createMcpServer } from '@osiris-ai/sdk';

const googleAuth = new GoogleAuthenticator(
  ['openid', 'email', 'profile', 'gmail.send', 'drive.readonly'],
  {
    clientId: process.env.GOOGLE_CLIENT_ID!,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    redirectUri: 'http://localhost:3000/google/callback'
  }
);

await createMcpServer({
  name: 'google-mcp',
  version: '1.0.0',
  auth: {
    useHub: false,
    directAuth: {
      google: googleAuth
    }
  },
  configure: (server) => {
    // Your Google tools here
  }
});
```

## API Reference

### GoogleAuthenticator

The main authenticator class for Google OAuth integration.

```typescript
class GoogleAuthenticator extends OAuthAuthenticator<GoogleCallbackParams, GoogleTokenResponse>
```

#### Constructor

```typescript
new GoogleAuthenticator(allowedScopes: string[], config: GoogleAuthenticatorConfig)
```

**Parameters:**
- `allowedScopes`: Array of Google OAuth scopes your MCP requires
- `config`: Google OAuth application configuration

#### Methods

##### `getAuthenticationURL(scopes: string[], options: AuthenticationURLOptions): string`

Generate Google OAuth authorization URL.

##### `callback(params: GoogleCallbackParams): Promise<GoogleTokenResponse>`

Handle OAuth callback and exchange code for tokens.

##### `refreshToken(refreshToken: string): Promise<GoogleTokenResponse>`

Refresh an expired access token.

##### `getUserInfo(accessToken: string): Promise<GoogleUserInfo>`

Get authenticated user information.

##### `getEmailFromIdToken(idToken: string): Promise<string | undefined>`

Extract email from verified ID token using JWT verification.

##### `action(params: ActionParams, accessToken: string, refreshToken?: string): Promise<ActionResponse>`

Execute Google API actions with automatic token refresh.

### Google Service Clients

All service clients follow the same pattern and provide full googleapis functionality:

```typescript
// Create any Google service client
const gmail = await createHubGmailClient({ hubBaseUrl, token, context });
const drive = await createHubDriveClient({ hubBaseUrl, token, context });
const calendar = await createHubCalendarClient({ hubBaseUrl, token, context });
const sheets = await createHubSheetsClient({ hubBaseUrl, token, context });
```

## Usage Examples

### Google Calendar Integration

```typescript
server.tool(
  'create_calendar_event',
  'Create a new calendar event',
  {
    summary: z.string(),
    start: z.string(),
    end: z.string(),
    description: z.string().optional()
  },
  async ({ summary, start, end, description }) => {
    const { token, context } = getAuthContext("osiris");
    if (!token || !context) {
      return createErrorResponse("User not authenticated");
    }

    const calendar = await createHubCalendarClient({
      hubBaseUrl: process.env.HUB_BASE_URL!,
      token: token,
      context: context
    });

    const event = await calendar.events.insert({
      calendarId: 'primary',
      requestBody: {
        summary,
        description,
        start: { dateTime: start },
        end: { dateTime: end }
      }
    });

    return createSuccessResponse('Event created', {
      eventId: event.data.id,
      eventLink: event.data.htmlLink
    });
  }
);
```

### Google Drive File Management

```typescript
server.tool(
  'search_drive_files',
  'Search for files in Google Drive',
  {
    query: z.string(),
    mimeType: z.string().optional()
  },
  async ({ query, mimeType }) => {
    const { token, context } = getAuthContext("osiris");
    if (!token || !context) {
      return createErrorResponse("User not authenticated");
    }

    const drive = await createHubDriveClient({
      hubBaseUrl: process.env.HUB_BASE_URL!,
      token: token,
      context: context
    });

    const searchQuery = mimeType ? `name contains '${query}' and mimeType='${mimeType}'` : `name contains '${query}'`;

    const files = await drive.files.list({
      q: searchQuery,
      fields: 'files(id,name,mimeType,webViewLink,modifiedTime)'
    });

    return createSuccessResponse('Files found', {
      files: files.data.files?.map(file => ({
        id: file.id,
        name: file.name,
        type: file.mimeType,
        link: file.webViewLink,
        modified: file.modifiedTime
      }))
    });
  }
);
```

### Google Sheets Data Access

```typescript
server.tool(
  'read_sheet_data',
  'Read data from a Google Sheet',
  {
    spreadsheetId: z.string(),
    range: z.string()
  },
  async ({ spreadsheetId, range }) => {
    const { token, context } = getAuthContext("osiris");
    if (!token || !context) {
      return createErrorResponse("User not authenticated");
    }

    const sheets = await createHubSheetsClient({
      hubBaseUrl: process.env.HUB_BASE_URL!,
      token: token,
      context: context
    });

    const response = await sheets.spreadsheets.values.get({
      spreadsheetId,
      range
    });

    return createSuccessResponse('Sheet data retrieved', {
      values: response.data.values,
      range: response.data.range
    });
  }
);
```

## Error Handling

The Google authenticator provides robust error handling with automatic retries and detailed error messages:

```typescript
server.tool('resilient_google_tool', 'Google tool with error handling', schema, async (params) => {
  try {
    const { token, context } = getAuthContext("osiris");
    if (!token || !context) {
      return createErrorResponse("🔐 Please connect your Google account first");
    }

    const gmail = await createHubGmailClient({
      hubBaseUrl: process.env.HUB_BASE_URL!,
      token: token,
      context: context
    });

    // Google API call with automatic error handling
    const result = await gmail.users.messages.list({ userId: 'me' });
    return createSuccessResponse('Gmail messages retrieved', result.data);
  } catch (error: any) {
    if (error.message.includes('Authentication failed')) {
      return createErrorResponse("❌ Google authentication expired. Please reconnect your account.");
    }
    if (error.message.includes('Access denied')) {
      return createErrorResponse("❌ Insufficient Google permissions. Please grant additional scopes.");
    }
    if (error.status === 404) {
      return createErrorResponse("❌ Google resource not found. Check the resource ID and permissions.");
    }
    return createErrorResponse(`Google error: ${error.message}`);
  }
});
```

## Getting Started

1. **Install the Osiris CLI:**
   ```bash
   npm install -g @osiris-ai/cli
   ```

2. **Set up authentication:**
   ```bash
   npx @osiris-ai/cli register
   npx @osiris-ai/cli create-client
   npx @osiris-ai/cli connect-auth
   ```

3. **Create your Google MCP:**
   ```bash
   npx @osiris-ai/cli create-mcp my-google-mcp
   ```

4. **Add Google integration:**
   ```bash
   npm install @osiris-ai/google-sdk
   ```

## Contributing

We welcome contributions! Please see our [Contributing Guide](https://github.com/fetcchx/osiris-ai/blob/main/CONTRIBUTING.md) for details.

## Support

- **Documentation:** [https://docs.osirislabs.xyz](https://docs.osirislabs.xyz)
- **GitHub Issues:** [https://github.com/fetcchx/osiris-ai/issues](https://github.com/fetcchx/osiris-ai/issues)
- **Discord Community:** [Join our Discord](https://discord.osirislabs.xyz)

## License

MIT License - see [LICENSE](LICENSE) file for details.

---

Built with ❤️ by the [Osiris Labs](https://osirislabs.xyz) team.