npm package: @osiris-ai/sdk
Description: MCP (Model Context Protocol) SDK for building AI-powered servers with authentication
Latest version: 0.2.0

# Osiris MCP SDK

A comprehensive framework to build authenticated, stateful, and policy-driven MCPs (Model Context Protocol) with enterprise-grade security.

## About Osiris

[Osiris](https://osirislabs.xyz) provides secure authentication, wallet management, and policy enforcement for MCPs. Built with privacy-first principles, Osiris enables developers to create sophisticated MCPs that can safely interact with external services, manage user data, and execute blockchain transactions—all while maintaining user sovereignty and control.

The Osiris SDK leverages Osiris's robust infrastructure to provide seamless multi-tenant authentication, embedded wallet security with policy engines, and persistent state management across AI interactions.

## What Problem Does This Solve?

Building production-ready MCP servers requires solving multiple complex challenges:

- **Multi-layered Authentication**: Securing both User ↔ MCP and LLM ↔ MCP connections
- **Heterogeneous Auth Types**: Supporting OAuth, secret sharing, and embedded wallets with different security models
- **Policy Enforcement**: Embedded wallets need intelligent guardrails to prevent invalid transactions
- **Stateful Operations**: MCPs need persistent state beyond simple API proxying
- **Multi-tenant Isolation**: Each deployment requires isolated authentication and data
- **Blockchain Integration**: Secure wallet management with policy-based transaction validation

The Osiris SDK handles all of this automatically, with an advanced policy engine for wallet security, letting you focus on building intelligent MCP tools.

## 🚀 Quick Start

### Installation

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

### Gmail MCP with OAuth Authentication

```typescript
import { createMcpServer, getAuthContext } from '@osiris-ai/sdk';
import { PostgresDatabaseAdapter } from '@osiris-ai/postgres-sdk';
import { createHubGmailClient } from '@osiris-ai/google-sdk';

class GmailMCP {
    private hubBaseUrl: string;

    constructor(hubBaseUrl: string) {
        this.hubBaseUrl = hubBaseUrl;
    }

    getGmailClient() {
        const context = getAuthContext();

        if (!context.tokens) {
            throw new Error('No Google token available. Please authenticate with Google first.');
        }

        return createHubGmailClient({
            hubBaseUrl: this.hubBaseUrl,
        });
    }

    configureServer(server) {
        server.tool(
            'send_email',
            'Send an email through Gmail',
            {
                to: { type: 'string', description: 'Recipient email' },
                subject: { type: 'string', description: 'Email subject' },
                body: { type: 'string', description: 'Email content' },
            },
            async ({ to, subject, body }) => {
                const gmail = this.getGmailClient();

                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 {
                    content: [
                        {
                            type: 'text',
                            text: `✅ Email sent successfully! Message ID: ${result.data.id}`,
                        },
                    ],
                };
            }
        );
    }
}

// Start server
const gmailMcp = new GmailMCP(process.env.HUB_BASE_URL!);

await createMcpServer({
    name: 'gmail-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!,
        },
        database: new PostgresDatabaseAdapter({
            connectionString: process.env.DATABASE_URL!,
        }),
    },

    server: {
        port: 3001,
        mcpPath: '/mcp',
        callbackBasePath: '/callback',
        osirisConfigPath: './osiris.json', // Optional: path to osiris config
        logger: (msg) => console.log(msg),
    },

    configure: (server) => {
        gmailMcp.configureServer(server);
    },
});
```

### Blockchain/Wallet MCP with Policy Engine

```typescript
import { createMcpServer, getAuthContext } from '@osiris-ai/sdk';
import { EVMWalletClient } from '@osiris-ai/web3-evm-sdk';

class Web3MCP {
    configureServer(server) {
        server.tool(
            'sign_message',
            'Sign a blockchain message with policy validation',
            {
                chain: { type: 'string', description: 'Blockchain (ethereum, polygon, etc.)' },
                data: { type: 'string', description: 'Data to be signed' },
            },
            async ({ chain, to, value, data }) => {
                const { token, context } = getAuthContext('osiris');

                // Policy engine automatically validates transaction
                const client = new EVMWalletClient(
                    process.env.HUB_BASE_URL!,
                    token.access_token,
                    context.deploymentId
                );

                const addresses = await client.getWalletRecords();
                const address = addresses[0].accounts[0].address;

                const signature = await walletClient.signMessage(data, chainId, address);

                return {
                    content: [
                        {
                            type: 'text',
                            text: `✅ Message signed: ${signature}\n🛡️ Policy validated: Safe to proceed`,
                        },
                    ],
                };
            }
        );
    }
}
```

## 🔑 Getting Osiris Credentials

To use the Osiris SDK with Osiris authentication, you'll need to obtain your OAuth client credentials:

### 1. Request Access

Use `@osiris-ai/cli` to receive credentials and get started with building world class MCPs

Refer Osiris CLI documentation here

### 2. Receive Credentials

Once approved, you'll receive:

- `OAUTH_CLIENT_ID` - Your application's unique identifier
- `OAUTH_CLIENT_SECRET` - Your application's secret key
- Access to the Osiris Hub at `https://api.bk.osirislabs.xyz/v1`

### 3. Configure Environment

Add your credentials to your environment variables:

```bash
# Osiris Configuration
HUB_BASE_URL=https://api.bk.osirislabs.xyz/v1
OAUTH_CLIENT_ID=your-client-id-here
OAUTH_CLIENT_SECRET=your-client-secret-here

# Database
DATABASE_URL=your-database-connection-string
```

### 4. Development vs Production

- **Development**: Use the demo hub for testing and prototyping
- **Production**: Contact Osiris Labs for production deployment guidance

**Important**: Keep your client secret secure and never commit it to version control. Use environment variables or secure secret management systems.

## 🏗️ Authentication Architecture

Osiris SDK provides **dual-layer authentication** that secures both user access and LLM interactions:

### Layer 1: User ↔ MCP Authentication

Three authentication types for different use cases:

#### 1. OAuth Authentication (Hub-Based)

**Best for**: API integrations with Google, GitHub, Discord, etc.

```typescript
auth: {
    useHub: true,
    hubConfig: {
        baseUrl: 'https://hub.osiris.dev/v1',
        clientId: process.env.OAUTH_CLIENT_ID!,
        clientSecret: process.env.OAUTH_CLIENT_SECRET!,
    }
}

// In your tools
const context = getAuthContext();
const googleToken = context.getToken(); // OAuth token from hub
const gmail = createHubGmailClient({ hubBaseUrl: process.env.HUB_BASE_URL! });
```

**Security Model**: OAuth scopes define what your MCP can access

- ✅ Centralized token management through hub
- ✅ Automatic token refresh and retry logic
- ✅ User controls permissions via OAuth scopes
- ✅ Rich error messages with actionable guidance

#### 2. Secret Sharing (Hub Access)

**Best for**: Database connections, API keys, internal services

**Security Model**: Encrypted secret management

- ✅ Encrypted storage with connection-level isolation
- ✅ Secret validation and schema enforcement
- ✅ Automatic credential rotation support

#### 3. Embedded Wallets (Policy Engine Security)

**Best for**: Blockchain interactions, financial operations

```typescript
// From Uniswap MCP example
const { token, context } = getAuthContext('osiris');
const client = new EVMWalletClient(hubBaseUrl, token.access_token, context.deploymentId, chainId);
const walletRecords = await client.getWalletRecords();
const account = await client.getViemAccount(walletRecords[0].metadata.wallet.addresses[0]);
```

**Security Model**: **Policy engine enforced at wallet level**

- ✅ **User sets policies in their wallet**
- ✅ **MCP/LLM cannot execute invalid transactions**
- ✅ User chooses wallet provider (Turnkey, etc.)
- ✅ Policy rules prevent unauthorized actions
- ✅ Multi-signature and hardware wallet support

### Layer 2: LLM ↔ MCP Authentication

Prevents unauthorized LLM access to your MCP:

```typescript
server: {
    port: 3001,
    mcpPath: '/mcp',
    callbackBasePath: '/callback',
}
```

### Layer 3: Enhanced Security Features

#### Automatic Token Refresh

```typescript
// SDK automatically handles token refresh
const context = getAuthContext();
const token = context.getToken('google'); // Always fresh token

// Manual refresh if needed
const newToken = await authManager.refreshToken('google', oldRefreshToken);
```

#### Rich Error Handling

```typescript
// Enhanced error responses with actionable guidance
try {
    const result = await performAction();
} catch (error) {
    if (error instanceof AuthenticationError) {
        // Rich error with actionable resolution
        console.log(`Error: ${error.message}`);
        console.log(`Resolution: ${error.resolution.description}`);
        console.log(`Auth URL: ${error.authorizationUrl}`);
    }
}
```

## 🧠 Osiris Policy Engine

The **Osiris Policy Engine** is specifically designed for **embedded wallet security**, providing dynamic transaction validation:

### Policy Engine Scope

**Important**: The policy engine is **only active for embedded wallets**, not for OAuth or secret sharing authentication. Users set wallet policies to prevent MCPs and LLMs from executing invalid or unauthorized transactions.

### Wallet-Level Policy Enforcement

```typescript
// MCP attempts transaction - policy engine validates
const { token, context } = getAuthContext('osiris');
const client = new EVMWalletClient(hubBaseUrl, token.access_token, context.deploymentId, chainId);

// Policy engine automatically checks transaction against user's rules
const transaction = await client.signTransaction(abi, serializedTx, address);
// ✅ Approved if within policy bounds
// ❌ Rejected if violates user's policies
```

### Why Wallet Policies Matter

Unlike traditional APIs, blockchain transactions are:

- **Irreversible** - once confirmed, cannot be undone
- **Financial** - directly involve user's assets
- **Complex** - smart contract interactions can have unexpected consequences
- **High-stakes** - mistakes can result in total loss of funds

The policy engine prevents MCPs and LLMs from:

- 🚫 Transferring more than daily limits
- 🚫 Sending to blocked/suspicious addresses
- 🚫 Paying excessive gas fees
- 🚫 Interacting with unauthorized contracts
- 🚫 Executing transactions during off-hours

## 🗃️ Stateful MCP Architecture

Osiris MCPs maintain persistent state across conversations:

### Enhanced Database Management

#### Connection-Based Storage

```typescript
import { PostgresDatabaseAdapter } from '@osiris-ai/sdk';

// Production setup with connection pooling
const database = new PostgresDatabaseAdapter({
    connectionString: process.env.DATABASE_URL!,
});
```

#### Multiple Database Adapters

```typescript
// Memory (development)
import { MemoryDatabaseAdapter } from '@osiris-ai/sdk';
database: new MemoryDatabaseAdapter();

// PostgreSQL (production recommended)
import { PostgresDatabaseAdapter } from '@osiris-ai/postgres-sdk';
database: new PostgresDatabaseAdapter({ connectionString: process.env.DATABASE_URL! });

// MongoDB (document-based)
import { MongoDBDatabaseAdapter } from '@osiris-ai/mongodb-sdk';
database: new MongoDBDatabaseAdapter({ connectionString: process.env.MONGODB_URL! });

// Redis (cache + session)
import { RedisDatabaseAdapter } from '@osiris-ai/redis-sdk';
database: new RedisDatabaseAdapter({ host: 'localhost', port: 6379 });

// SQLite (file-based)
import { SQLiteDatabaseAdapter } from '@osiris-ai/sqlite-sdk';
database: new SQLiteDatabaseAdapter({ filepath: './data/mcp.db' });
```

### State Storage Options

#### Option 1: User's Database (Recommended)

```typescript
const { token, context } = getAuthContext('osiris');
const response = await fetch(
    'https://api.bk.osirislabs.xyz/v1/hub/action/${deploymentId}/postgres',
    {
        method: 'POST',
        body: JSON.stringify({
            sql: `INSERT INTO user_preferences (user_id, settings) VALUES ($1, $2)`,
            params: [context.userId, JSON.stringify(userSettings)],
        }),
    }
);
```

#### Option 2: MCP's Database

```typescript
database: new PostgresDatabaseAdapter({
    connectionString: process.env.MCP_DATABASE_URL!, // Your database
});

// Automatic connection-level isolation
const context = getAuthContext();
// All queries automatically scoped to context.deploymentId
```

### Real-World Examples

#### Gmail MCP with State Tracking

```typescript
export class GmailMCP {
    async fetchEmailsWithQuery(query: string, maxResults: number = 10) {
        const gmail = this.getGmailClient();

        const messagesResponse = await gmail.users.messages.list({
            userId: 'me',
            maxResults,
            q: query,
        });

        // Store query patterns for learning
        const context = getAuthContext();
        await this.storeQueryPattern(context.userId, {
            query,
            resultCount: messagesResponse.data.messages?.length || 0,
            timestamp: new Date(),
        });

        return {
            totalFound: messagesResponse.data.messages?.length || 0,
            emails: emailDetails,
            query,
        };
    }
}
```

#### Blockchain MCP with Transaction History

```typescript
export class UniswapClass {
    async swap(params: SwapTransactionParams): Promise<CallToolResult> {
        const { token, context } = getAuthContext('osiris');
        const client = new EVMWalletClient(
            this.hubBaseUrl,
            token.access_token,
            context.deploymentId,
            this.chainId
        );

        // Policy engine validates transaction at wallet level
        const walletRecords = await client.getWalletRecords();
        const account = await client.getViemAccount(walletRecords[0].metadata.wallet.addresses[0]);

        // Execute swap (policy engine automatically validates)
        const transaction = await this.executeSwap(params, account);

        // Store transaction for future reference
        await this.storeTransactionHistory(context.userId, {
            hash: transaction.hash,
            tokenIn: params.tokenIn,
            tokenOut: params.tokenOut,
            amountIn: params.amountIn,
            timestamp: new Date(),
        });

        return createSuccessResponse('Successfully swapped tokens', {
            hash: result.data.hash,
        });
    }
}
```

## 🌟 Real-World Use Cases

Here are compelling examples of what you can build with Osiris SDK's authenticated, stateful architecture:

### 1. LLM-Powered Multiplayer D&D

**AI Dungeon Master** - A sophisticated multiplayer Dungeons & Dragons experience where the LLM serves as an intelligent, persistent dungeon master for cross-conversation campaigns.

**Core Architecture:**

- **LLM Game Engine**: AI dungeon master that creates dynamic campaigns, NPCs, and story arcs
- **Persistent Campaign State**: Game sessions, character sheets, and world state survive across conversations
- **Multi-Player Coordination**: Real-time multiplayer coordination across different LLM conversations
- **Cross-Platform Notifications**: Player updates via Discord, Gmail, Telegram, and Osiris mobile app

**Key Features:**

- **Intelligent Dungeon Master**: LLM generates dynamic quests, NPCs, and story branches based on player actions
- **Persistent Characters**: Character sheets, inventory, and progression persist across LLM sessions
- **Real-Time Multiplayer**: Players can join/leave campaigns seamlessly across different AI conversations
- **Cross-Conversation Campaigns**: Start a campaign in ChatGPT, continue in Claude, invite friends via Discord
- **Notifications**: When it's your turn, get notified via Discord DM, email, Telegram, or mobile push

**Example Campaign Flow:**

```
Player 1 (ChatGPT): "I want to start a D&D campaign as a wizard"
AI DM: "Welcome to the Mystic Realms! You're in the village of Eldertree..."

Player 2 (Claude): "I want to join campaign #12345 as a rogue"
AI DM: "A mysterious rogue approaches the wizard's table at the tavern..."

[Discord notification to Player 1]: "🎲 It's your turn in campaign #12345! The rogue wants to join your party."

Player 1: "I invite the rogue to join our quest"
AI DM: "The party is formed! Your first quest awaits..."
```

**MCP Server Setup:**

```typescript
import { createMcpServer, PostgresDatabaseAdapter } from '@osiris-ai/sdk';

const dndMcp = {
    name: 'ai-dungeon-master',
    version: '1.0.0',

    configureServer(server: McpServer) {
        server.tool(
            'create_campaign',
            'Start a new D&D campaign',
            {
                campaign_name: z.string(),
                max_players: z.number().default(4),
                setting: z.string().optional(),
            },
            async ({ campaign_name, max_players, setting }) => {
                const campaign = await gameEngine.createCampaign({
                    name: campaign_name,
                    dmId: 'ai-dungeon-master',
                    maxPlayers: max_players,
                    setting: setting || 'fantasy',
                });

                return {
                    content: [
                        {
                            type: 'text',
                            text:
                                `🏰 **CAMPAIGN CREATED: ${campaign_name}**\n\n` +
                                `Campaign ID: ${campaign.id}\n` +
                                `Setting: ${campaign.setting}\n` +
                                `Max Players: ${max_players}\n\n` +
                                `Share this campaign ID with friends to invite them!`,
                        },
                    ],
                };
            }
        );

        server.tool(
            'take_action',
            'Perform an action in the campaign',
            {
                campaign_id: z.string(),
                action: z.string(),
                dice_roll: z.number().optional(),
            },
            async ({ campaign_id, action, dice_roll }) => {
                const result = await gameEngine.processAction({
                    campaignId: campaign_id,
                    playerId: getAuthContext().userId,
                    action: action,
                    diceRoll: dice_roll,
                });

                // Notify other players
                await notificationService.notifyOtherPlayers(campaign_id, {
                    message: `${result.playerName} ${action}`,
                    channels: ['discord', 'telegram', 'mobile'],
                });

                return {
                    content: [
                        {
                            type: 'text',
                            text:
                                `🎲 **ACTION RESULT**\n\n${result.outcome}\n\n` +
                                `Next: ${result.nextPlayer || 'Continue your adventure!'}`,
                        },
                    ],
                };
            }
        );
    },
};
```

**Notification System:**

```typescript
class NotificationService {
    async notifyOtherPlayers(
        campaignId: string,
        notification: {
            message: string;
            channels: ('discord' | 'telegram' | 'gmail' | 'mobile')[];
        }
    ) {
        const campaign = await getCampaign(campaignId);
        const otherPlayers = campaign.players.filter((p) => p.id !== currentPlayerId);

        for (const player of otherPlayers) {
            // Discord notification
            if (notification.channels.includes('discord')) {
                await discordClient.sendDM(
                    player.discordId,
                    `🎲 ${notification.message} in campaign "${campaign.name}"`
                );
            }

            // Email notification
            if (notification.channels.includes('gmail')) {
                await gmailClient.sendEmail(player.email, {
                    subject: `Your D&D Campaign Update`,
                    body: `${notification.message}\n\nContinue playing: ${campaign.continueUrl}`,
                });
            }

            // Mobile push notification
            if (notification.channels.includes('mobile')) {
                await osirisApp.sendPushNotification(player.deviceId, {
                    title: 'D&D Campaign Update',
                    body: notification.message,
                    deepLink: `osiris://campaign/${campaignId}`,
                });
            }
        }
    }
}
```

**Why This Showcases Osiris SDK:**

- **Multi-Tenant Authentication**: Each player authenticated securely across different LLM platforms
- **Persistent State**: Campaign data survives across conversations and AI platforms
- **Cross-Platform Notifications**: Since MCPs can't directly notify LLMs, Osiris enables rich notification systems
- **OAuth Integration**: Connect Discord, Gmail, Telegram for seamless multiplayer coordination
- **Mobile App Integration**: Deep linking back to campaigns via Osiris mobile app

**Player Experience:**

1. **Start Campaign**: Create a D&D campaign in any LLM conversation
2. **Invite Friends**: Share campaign ID, friends join from any AI platform
3. **Cross-Platform Play**: Continue campaigns across ChatGPT, Claude, etc.
4. **Smart Notifications**: Get notified when it's your turn via your preferred channel
5. **Persistent Progress**: Characters and campaigns persist indefinitely

This demonstrates the unique power of authenticated, stateful MCPs with cross-platform notification capabilities that only Osiris SDK can provide.

### 2. LLM based Hyperliquid trader

**Policy-Enforced Trading** - Intelligent trading assistant with built-in safety guardrails through Osiris's policy engine.

**Core Implementation:**

```typescript
import { getAuthContext, EVMWalletClient } from '@osiris-ai/sdk';

export class HyperliquidTrader {
    async executeMarketOrder(params: {
        asset: 'ETH' | 'SOL';
        amount: number;
        side: 'buy' | 'sell';
    }) {
        // Get wallet context - policy engine validates transactions
        const { token, context } = getAuthContext('osiris');
        if (!token || !context) {
            throw new Error('Wallet authentication required');
        }

        const client = new EVMWalletClient(
            this.hubBaseUrl,
            token.access_token,
            context.deploymentId,
            this.chainId
        );

        // Policy engine automatically validates transaction
        const transaction = await client.signTransaction(abi, serializedTx, account.address);

        // Store trade for portfolio tracking
        await this.storeTradeHistory(context.userId, {
            asset: params.asset,
            amount: params.amount,
            side: params.side,
            hash: transaction.hash,
            timestamp: new Date(),
        });

        return transaction;
    }
}
```

**Features:**

- **Asset Restrictions**: Only whitelisted tokens, enforced at wallet policy level
- **Trade Limits**: Maximum trade sizes and daily limits via policy engine
- **Risk Management**: Slippage protection and MEV prevention
- **Portfolio Tracking**: Persistent state for P&L analysis and performance metrics
- **Multi-DEX Support**: Uniswap, SushiSwap, 1inch with best price routing

### 3. Structured State Tracker

**Persistent Data Architecture** - Helps LLMs maintain organized, queryable data structures across conversations.

**Example: Nutrition Tracker**

```typescript
interface NutritionEntry {
    timestamp: Date;
    mealType: 'breakfast' | 'lunch' | 'dinner' | 'snack';
    foods: FoodItem[];
    macroBreakdown: MacroBreakdown;
}

export class NutritionTracker {
    async logMeal(userId: string, entry: NutritionEntry) {
        // Store in structured format
        await this.database.nutritionEntries.create({
            userId,
            ...entry,
            calculatedCalories: entry.foods.reduce(
                (sum, food) => sum + food.calories * food.quantity,
                0
            ),
        });

        // Update daily totals
        await this.updateDailyTotals(userId, entry.timestamp);
    }

    async getWeeklyAnalysis(userId: string): Promise<WeeklyNutrition> {
        const entries = await this.database.nutritionEntries.findMany({
            where: {
                userId,
                timestamp: { gte: sevenDaysAgo },
            },
        });

        return {
            avgCalories: entries.reduce((sum, e) => sum + e.calculatedCalories, 0) / 7,
            macroBreakdown: this.calculateMacroBreakdown(entries),
            adherenceRate: this.calculateAdherenceToGoals(entries),
        };
    }
}
```

**Key Benefits:**

- **Persistent Memory**: Structured data survives conversation resets
- **Intelligent Queries**: "Show me last week's protein intake" gets accurate responses
- **Trend Analysis**: Track patterns and provide data-driven recommendations
- **Goal Tracking**: Monitor progress with real metrics instead of LLM memory

## Why These Use Cases Matter

Each example showcases Osiris SDK's core strengths:

- 🔐 **Authenticated**: User data stays private and secure with Osiris authentication
- 🧠 **Stateful**: MCPs learn and improve from every interaction
- 🔄 **Persistent**: Data accumulates value over time, creating personalized experiences
- 🚀 **Scalable**: Handle complex workflows across multiple services
- 🛡️ **Policy-Safe**: Wallet transactions protected by user-defined policies
- 🌐 **Social**: Build community features with shared leaderboards and challenges

These aren't just tools—they're **intelligent assistants** that grow smarter with every use, creating compound value for users while maintaining complete privacy and security.

## ⚙️ Enhanced Context System

The Osiris SDK provides request-scoped authentication context with improved error handling:

### Basic Context Usage

```typescript
import { getAuthContext } from '@osiris-ai/sdk';

server.tool('context_example', 'Shows how to use auth context', schema, async (params) => {
    // For OAuth services
    const context = getAuthContext();
    if (!context.tokens) {
        throw new Error('No tokens available. Please authenticate first.');
    }

    // For embedded wallets
    const { token, context: walletContext } = getAuthContext('osiris');
    if (!token || !walletContext) {
        throw new Error('No wallet token or context found');
    }

    return { content: [{ type: 'text', text: 'Context accessed successfully' }] };
});
```

### Advanced Context Features

#### Multi-Tenant Isolation

```typescript
// Context is automatically scoped to current deployment
const context = getAuthContext();
console.log('User ID:', context.userId);
console.log('Deployment ID:', context.deploymentId);
console.log('Package ID:', context.packageId);
console.log('Session ID:', context.sessionId);

// All database operations are automatically deployment-scoped
const userEmails = await fetchUserEmails(context.userId);
const userTransactions = await fetchUserTransactions(context.userId);
```

#### Enhanced Token Management

```typescript
// Get tokens with automatic refresh
const context = getAuthContext();
const googleToken = context.getToken('google'); // Automatically refreshed if expired
const githubToken = context.getToken('github');

// Check token expiration
if (context.isTokenExpired('google')) {
    // SDK automatically handles refresh
    const refreshedToken = await context.refreshToken('google');
}
```

#### Improved Error Handling

```typescript
const context = getAuthContext();

// Rich deployment validation errors
if (context.deploymentValidationError) {
    throw new Error(`Deployment validation failed: ${context.deploymentValidationError}`);
}

// Service availability checking
const hasGoogleAccess = context.hasService('google');
```

### Service Client Creation

```typescript
// OAuth services - automatic token injection with refresh
const gmail = createHubGmailClient({
    hubBaseUrl: process.env.HUB_BASE_URL!,
    // Token automatically managed by context
});

const github = createHubGitHubClient({
    hubBaseUrl: process.env.HUB_BASE_URL!,
});

// Wallet services - explicit authenticator access
const { token, context } = getAuthContext('osiris');
const walletAuth = EVMWalletClient(hubBaseUrl, token.access_token, context.deploymentId);
if (walletAuth) {
    const wallet = await walletAuth.getWalletRecords();
}
```

## 📦 Enhanced Service Integration

### OAuth Services (Hub-Based) with Improved Error Handling

```typescript
export class GmailMCP {
    getGmailClient() {
        const context = getAuthContext();

        if (!context.tokens || !context.getToken('google')) {
            throw new AuthenticationError({
                code: 'GOOGLE_AUTH_REQUIRED',
                message: 'Google authentication required for Gmail access',
                authorizationUrl: context.getAuthorizationUrl('google', [
                    'https://www.googleapis.com/auth/gmail.modify',
                ]),
                service: 'google',
                category: 'reauthorization_required',
                resolution: {
                    type: 'reauthorize',
                    description: 'Click the link above to authenticate with Google',
                    estimatedTime: '1-2 minutes',
                },
            });
        }

        return createHubGmailClient({
            hubBaseUrl: this.hubBaseUrl,
        });
    }

    async sendEmail(emailData) {
        try {
            const gmail = this.getGmailClient();

            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 result;
        } catch (error) {
            // SDK automatically attempts token refresh on 401 errors
            if (error.status === 401) {
                // Refresh handled automatically, retry once
                const gmail = this.getGmailClient();
                return await gmail.users.messages.send({
                    userId: 'me',
                    requestBody: { raw },
                });
            }
            throw error;
        }
    }
}
```

### Embedded Wallet Services (Policy-Enforced)

```typescript
export class UniswapClass {
    async swap(params: SwapTransactionParams) {
        // Get wallet context - policy engine validates transactions
        const { token, context } = getAuthContext('osiris');
        if (!token || !context) {
            throw new Error('No token or context found');
        }

        const client = new EVMWalletClient(
            this.hubBaseUrl,
            token.access_token,
            context.deploymentId,
            this.chainId
        );

        const walletRecords = await client.getWalletRecords();
        const account = await client.getViemAccount(walletRecords[0].metadata.wallet.addresses[0]);

        // Policy engine automatically validates transaction
        const signedTx = await client.signTransaction(abi, serializedTx, account.address);
        const hash = await walletClient.sendRawTransaction({
            serializedTransaction: signedTx as `0x${string}`,
        });

        return hash;
    }
}
```

## 🗄️ Database Adapters

#### PostgreSQL with Connection Pooling

```typescript
import { PostgresDatabaseAdapter } from '@osiris-ai/postgres-sdk';

database: new PostgresDatabaseAdapter({
    connectionString: process.env.DATABASE_URL!,
});
```

#### Redis

```typescript
import { RedisDatabaseAdapter } from '@osiris-ai/redis-sdk';

database: new RedisDatabaseAdapter({
    host: process.env.REDIS_HOST || 'localhost',
    port: parseInt(process.env.REDIS_PORT || '6379'),
});
```

#### MongoDB

```typescript
import { MongoDBDatabaseAdapter } from '@osiris-ai/mongodb-sdk';

database: new MongoDBDatabaseAdapter({
    connectionString: process.env.MONGODB_URL!,
});
```

### Connection Management Features

#### Session Management

```typescript
// Enhanced session management with cleanup
const sessionId = await database.storeSession({
    id: randomUUID(),
    status: 'active',
    packageId: 'my-mcp',
    name: 'User Session',
    description: 'Active user session',
    expiresAt: new Date(Date.now() + 30 * 60 * 1000), // 30 minutes
    connectedServices: new Map([
        ['google', { authenticated: true, scopes: ['gmail.modify'] }],
        ['github', { authenticated: true, scopes: ['repo'] }],
    ]),
    isDirectAuth: false,
});

// Automatic cleanup of expired sessions
await database.cleanupExpiredSessions(); // Returns count of cleaned sessions
```

#### Connection-Level Isolation

```typescript
// All data automatically isolated by connection/deployment ID
const context = getAuthContext();

// Authentications scoped to this deployment
const auths = await database.getAuthenticationsForConnection(context.deploymentId);

// Secrets scoped to this deployment
const secrets = await database.getSecretsForConnection(context.deploymentId);

// Connections scoped to package
const connections = await database.getConnectionsForPackage(context.packageId);
```

## ⚙️ Advanced Configuration

### Environment Variables

```bash
# Core Configuration
HUB_BASE_URL=https://api.bk.osirislabs.xyz/v1
PORT=3001

# OAuth Authentication
OAUTH_CLIENT_ID=your-oauth-client-id
OAUTH_CLIENT_SECRET=your-oauth-client-secret

# Database Configuration
DATABASE_URL=postgresql://user:pass@localhost:5432/mcp_db
REDIS_URL=redis://localhost:6379
MONGODB_URL=mongodb://localhost:27017/mcp_data

# Wallet Configuration (if using direct auth)
TURNKEY_API_BASE_URL=https://api.turnkey.com
TURNKEY_ORGANIZATION_ID=your-turnkey-org-id

# Security & Deployment
MCP_DEPLOYMENT_SECRET=your-deployment-secret
NODE_ENV=production

# Osiris Configuration
OSIRIS_CONFIG_PATH=./osiris.json # Path to osiris config file
```

### Complete Production MCP Server

```typescript
import { createMcpServer } from '@osiris-ai/sdk';
import { PostgresDatabaseAdapter } from '@osiris-ai/postgres-sdk';

await createMcpServer({
    name: 'production-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!,
        },
        database: new PostgresDatabaseAdapter({
            connectionString: process.env.DATABASE_URL!,
        }),
    },

    server: {
        port: parseInt(process.env.PORT || '3001'),
        mcpPath: '/mcp',
        callbackBasePath: '/callback',
        osirisConfigPath: './osiris.json',
        baseUrl: `http://localhost:${port}`,
        logger: (msg: string) => console.log(msg),
    },

    analytics: {
        enabled: process.env.LEGION_ANALYTICS_DISABLED !== 'true',
        shareDetailedData: process.env.NODE_ENV === 'production',
    },

    configure: (server, authManager) => {
        // Tool implementations with enhanced error handling
        server.tool('send_email', 'Send email via Gmail', emailSchema, async (params) => {
            try {
                const context = getAuthContext();
                const gmail = createHubGmailClient({ hubBaseUrl: process.env.HUB_BASE_URL! });

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

                return {
                    content: [
                        {
                            type: 'text',
                            text: `✅ Email sent successfully! Message ID: ${result.data.id}`,
                        },
                    ],
                };
            } catch (error) {
                if (error instanceof AuthenticationError) {
                    return {
                        content: [
                            {
                                type: 'text',
                                text: `🔐 ${error.message}\n\nPlease authenticate: ${error.authorizationUrl}`,
                            },
                        ],
                        isError: true,
                    };
                }

                throw error;
            }
        });

        server.tool(
            'crypto_transfer',
            'Transfer cryptocurrency',
            transferSchema,
            async (params) => {
                try {
                    const context = getAuthContext();
                    const walletAuth = context.getWalletAuthenticator('turnkey');

                    if (!walletAuth) {
                        throw new Error('Wallet authentication required');
                    }

                    const result = await walletAuth.action({
                        method: 'POST',
                        url: 'sign-transaction',
                        data: {
                            method: 'signTransaction',
                            chain: params.chain,
                            walletAddress: context.userId,
                            payload: params.transaction,
                            metadata: {
                                description: `Transfer ${params.amount} ${params.token}`,
                                riskLevel: params.amount > 1000 ? 'high' : 'medium',
                                estimatedGas: '21000',
                            },
                        },
                    });

                    return {
                        content: [
                            {
                                type: 'text',
                                text: `✅ Transfer completed! Transaction: ${result.data.hash}`,
                            },
                        ],
                    };
                } catch (error) {
                    if (error.message.includes('policy')) {
                        return {
                            content: [
                                {
                                    type: 'text',
                                    text: `🚫 Transaction blocked by wallet policy: ${error.message}`,
                                },
                            ],
                            isError: true,
                        };
                    }

                    throw error;
                }
            }
        );
    },
});
```

## 🛠️ Error Handling

### Rich Authentication Errors

```typescript
import { AuthContextError } from '@osiris-ai/sdk';

server.tool('robust_tool', 'Tool with error handling', schema, async (params) => {
    try {
        const gmail = createHubGmailClient({ hubBaseUrl: process.env.HUB_BASE_URL! });
        const result = await gmail.users.messages.list({ userId: 'me' });

        return {
            content: [{ type: 'text', text: 'Success!' }],
        };
    } catch (error) {
        if (error instanceof AuthContextError) {
            return {
                content: [
                    {
                        type: 'text',
                        text: `🔐 Authentication required: ${error.authorizationUrl}`,
                    },
                ],
                isError: true,
            };
        }

        return {
            content: [
                {
                    type: 'text',
                    text: `❌ Error: ${error.message}`,
                },
            ],
            isError: true,
        };
    }
});
```

### Wallet Transaction Errors

```typescript
server.tool('wallet_tool', 'Wallet operation', schema, async (params) => {
    try {
        const { token, context } = getAuthContext('osiris');
        if (!token || !context) {
            throw new Error('Wallet authentication required');
        }

        // Wallet operation - policy engine validates automatically
        const result = await performWalletOperation();

        return {
            content: [{ type: 'text', text: `✅ Transaction: ${result.hash}` }],
        };
    } catch (error) {
        if (error.message.includes('policy')) {
            return {
                content: [
                    {
                        type: 'text',
                        text: `🚫 Transaction blocked by wallet policy: ${error.message}`,
                    },
                ],
                isError: true,
            };
        }

        return {
            content: [
                {
                    type: 'text',
                    text: `💳 Wallet error: ${error.message}`,
                },
            ],
            isError: true,
        };
    }
});
```

## 🎯 Best Practices

### 1. Choose the Right Authentication Strategy

**OAuth (Hub-Based)** for external APIs:

- ✅ Google, GitHub, Discord APIs
- ✅ Centralized token management with automatic refresh
- ✅ User controls permissions via OAuth scopes
- ✅ Rich error messages with actionable guidance

**Secret Sharing** for infrastructure:

- ✅ Database connections, API keys, internal services
- ✅ Encrypted storage with connection-level isolation
- ✅ Schema validation for credential security

**Embedded Wallets** for blockchain:

- ✅ DeFi interactions, token transfers
- ✅ **Policy engine prevents invalid transactions**
- ✅ Multi-chain support with hardware-backed security
- ✅ Risk assessment and transaction metadata

### 2. Implement Robust Error Handling

```typescript
// ✅ GOOD: Comprehensive error handling with user guidance
const handleMcpError = (error: any) => {
    if (error instanceof AuthenticationError) {
        return {
            content: [{
                type: 'text',
                text: `🔐 **${error.service?.toUpperCase()} Authentication Required**\n\n` +
                      `${error.resolution.description}\n\n` +
                      `[Authenticate Now](${error.authorizationUrl})`
            }],
            isError: true
        };
    }

    if (error.message.includes('policy')) {
        return {
            content: [{
                type: 'text',
                text: `🛡️ **Security Policy Protection**\n\n` +
                      `Your transaction was blocked by your wallet policy for your protection.\n\n` +
                      `This prevents unauthorized or risky transactions.`
            }],
            isError: true
        };
    }

    // Generic fallback with helpful context
    return {
        content: [{
            type: 'text',
            text: `❌ **Error:** ${error.message}\n\n` +
                  `If this persists, please check your configuration or contact support.`
        }],
        isError: true
    };
};

// ❌ BAD: Generic error messages without guidance
catch (error) {
    return { content: [{ type: 'text', text: 'Error occurred' }], isError: true };
}
```

### 3. Implement Stateful Patterns

```typescript
// ✅ GOOD: Store user state for learning
server.tool('smart_tool', 'Learns user patterns', schema, async (params) => {
    const context = getAuthContext();

    // Load user history
    const history = await getUserHistory(context.userId);

    // Make decision based on history
    const result = await makeDecision(params, history);

    // Store for future learning
    await storeUserAction(context.userId, { params, result, timestamp: new Date() });

    return result;
});
```

### 4. Use Proper Error Messages

```typescript
// ✅ GOOD: Actionable error messages
catch (error) {
    if (error instanceof AuthContextError) {
        return {
            content: [{
                type: 'text',
                text: `🔐 Please authenticate: ${error.authorizationUrl}`
            }],
            isError: true
        };
    }
}

// ❌ BAD: Generic error messages
catch (error) {
    return { content: [{ type: 'text', text: 'Error' }], isError: true };
}
```

---

**Ready to build the future of AI automation?** 🚀

The Osiris SDK v0.1.8 provides everything you need to create authenticated, stateful MCPs with wallet-level policy enforcement, enhanced error handling, and comprehensive analytics. Start building intelligent assistants that grow smarter with every interaction while maintaining complete security and user control!