npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@osiris-ai/sdk

v0.1.10

Published

MCP (Model Context Protocol) SDK for building AI-powered servers with authentication

Readme

Osiris MCP SDK

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

About Osiris

Osiris 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

npm install @osiris-ai/sdk

Gmail MCP with OAuth Authentication

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

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.osirislabs.xyz/v1

3. Configure Environment

Add your credentials to your environment variables:

# Osiris Configuration
HUB_BASE_URL=https://api.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.

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

// 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:

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

Layer 3: Enhanced Security Features

Automatic Token Refresh

// 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

// 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

// 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

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

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

Multiple Database Adapters

// 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)

const { token, context } = getAuthContext("osiris");
const response = await fetch("https://api.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

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

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

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:

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:

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:

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

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

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

// 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

// 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

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

// 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

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)

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

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

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

Redis

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

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

MongoDB

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

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

Connection Management Features

Session Management

// 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

// 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

# Core Configuration
HUB_BASE_URL=https://api.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

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

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

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

// ✅ 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

// ✅ 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

// ✅ 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!