npm package: @osiris-ai/notion-sdk
Description: Osiris Notion SDK
Latest version: 0.1.1

# @osiris-ai/notion-sdk

OAuth 2.0 Notion authenticator for building authenticated MCPs with Notion workspace integration.

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

## Overview

The Notion SDK provides seamless OAuth 2.0 authentication for Notion in the [Osiris](https://docs.osirislabs.xyz) ecosystem. Build powerful MCPs (Model Context Protocol) that can interact with Notion databases, pages, and workspaces with enterprise-grade security and zero-configuration authentication.

**Key Features:**
- 🔐 **Zero-config OAuth** - No client credentials or setup required
- 📊 **Workspace Integration** - Full access to Notion databases and pages
- 🤖 **Bot Support** - Integration bot capabilities for automated workflows
- 🔄 **Persistent Tokens** - Notion tokens don't expire, no refresh needed
- 🛡️ **Enterprise Security** - Built on Osiris Hub authentication
- 📝 **Full TypeScript** - Complete type safety and IDE support

## Installation

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

## Quick Start

### Hub Authentication (Recommended)

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

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

await createMcpServer({
  name: 'notion-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) => {
    // Create Notion page
    server.tool(
      'create_notion_page',
      'Create a new page in Notion',
      {
        parentId: z.string(),
        title: z.string(),
        content: z.string()
      },
      async ({ parentId, title, content }) => {
        try {
          const { token, context } = getAuthContext("osiris");
          if (!token || !context) {
            return createErrorResponse("User not authenticated");
          }

          const response = await fetch(`https://api.osirislabs.xyz/v1/hub/action/${context.deploymentId}/notion/v1/pages`, {
            method: 'POST',
            headers: {
              'Authorization': `Bearer ${token.access_token}`,
              'Content-Type': 'application/json',
              'Notion-Version': '2022-06-28'
            },
            body: JSON.stringify({
              parent: { page_id: parentId },
              properties: {
                title: {
                  title: [{ text: { content: title } }]
                }
              },
              children: [
                {
                  object: 'block',
                  type: 'paragraph',
                  paragraph: {
                    rich_text: [{ text: { content } }]
                  }
                }
              ]
            })
          });

          const result = await response.json();
          return createSuccessResponse('Page created successfully', {
            pageId: result.id,
            url: result.url
          });
        } catch (error) {
          return createErrorResponse(error);
        }
      }
    );
  }
});
```

### Available Notion Scopes

Configure your MCP to request specific Notion permissions:

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

## Local Authentication (Advanced)

For custom authentication flows or enterprise requirements:

```typescript
import { NotionAuthenticator } from '@osiris-ai/notion-sdk';
import { createMcpServer } from '@osiris-ai/sdk';

const notionAuth = new NotionAuthenticator(
  ['read', 'write'],
  {
    clientId: process.env.NOTION_CLIENT_ID!,
    clientSecret: process.env.NOTION_CLIENT_SECRET!,
    redirectUri: 'http://localhost:3000/notion/callback'
  }
);

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

## API Reference

### NotionAuthenticator

The main authenticator class for Notion OAuth integration.

```typescript
class NotionAuthenticator extends OAuthAuthenticator<NotionCallbackParams, NotionTokenResponse>
```

#### Constructor

```typescript
new NotionAuthenticator(allowedScopes: string[], config: NotionAuthenticatorConfig)
```

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

#### Methods

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

Generate Notion OAuth authorization URL with workspace owner support.

##### `callback(params: NotionCallbackParams): Promise<NotionTokenResponse>`

Handle OAuth callback and exchange code for tokens using Basic authentication.

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

Get authenticated user information.

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

Execute Notion API actions with automatic Notion-Version header.

**Note:** Notion tokens don't expire and don't support refresh - `refreshToken()` throws an error.



## Error Handling

The Notion authenticator provides robust error handling with detailed error messages:

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

    const response = await fetch(`https://api.osirislabs.xyz/v1/hub/action/${context.deploymentId}/notion/v1/users/me`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token.access_token}`,
        'Notion-Version': '2022-06-28'
      }
    });

    if (!response.ok) {
      if (response.status === 401) {
        return createErrorResponse("❌ Notion authentication invalid. Please reconnect your workspace.");
      }
      if (response.status === 403) {
        return createErrorResponse("❌ Insufficient Notion permissions. Please grant additional access.");
      }
      if (response.status === 404) {
        return createErrorResponse("❌ Notion resource not found. Check the page/database ID.");
      }
      return createErrorResponse(`Notion API error: ${response.statusText}`);
    }

    const result = await response.json();
    return createSuccessResponse('Notion data retrieved', result);
  } catch (error: any) {
    return createErrorResponse(`Notion 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 Notion MCP:**
   ```bash
   npx @osiris-ai/cli create-mcp my-notion-mcp
   ```

4. **Add Notion integration:**
   ```bash
   npm install @osiris-ai/notion-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.