DEV Community

Seey
Seey

Posted on

MCPSDK vs Smithery

Comparing Smithery and MCPSDK integration approaches for Vercel AI SDK

Both Smithery and MCPSDK provide hosted MCP servers, eliminating the need to manage local processes. The core differences lie in integration approach and developer experience.

One-sentence summary: Smithery requires manual MCP client management, while MCPSDK provides zero-config tool functions.

1. At a Glance

Dimension Smithery MCPSDK
Core Positioning Hosted MCP Server + Registry Hosted MCP Server + Developer API
Server Hosting Cloud-hosted (HTTP) Cloud-hosted (API)
Server State Local MCP needs preloading / Remote MCP direct Always-on / No type distinction
Integration Method experimental_createMCPClient getAISDKTool() / getOpenAISDKTool()
Authentication OAuth Provider API Key
Multi-tool Management Manual aggregation of clients Unified API client
Client Lifecycle Manual close() required Automatic management
API Key Management Handled in OAuth Configured in package() call
Tool Invocation AI invocation only AI invocation + Direct developer invocation

2. Deep Dive

2.1 Smithery: Hosted MCP Server + HTTP Integration

Smithery provides hosted MCP servers (server.smithery.ai) accessible via HTTP transport protocol, suitable for use with Vercel AI SDK.

Advantages:

  • ☁️ No need to manage local processes (cloud-hosted)
  • 🌐 HTTP access (suitable for Serverless environments)
  • 📚 Beautiful tool registry and documentation
  • 🔒 OAuth authentication mechanism

Architecture Characteristics:

  • 🔄 MCP Type Separation: Distinguishes between Local MCP and Remote MCP
    • Local MCP: Requires preloading to server, cannot be invoked directly (cold start)
    • Remote MCP: Direct access via dedicated endpoints (e.g., server.smithery.ai/exa)
  • ⚠️ Invocation Complexity: Developers need to understand and distinguish between different MCP types

Vercel AI SDK Integration Code:

import { experimental_createMCPClient as createMCPClient } from '@ai-sdk/mcp';
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

// 1. Create MCP client (experimental API)
const mcpClient = await createMCPClient({
  transport: {
    type: 'http',
    url: 'https://server.smithery.ai/exa',
    authProvider: myOAuthClientProvider,  // OAuth configuration required
  },
});

// 2. Get tool list
const tools = await mcpClient.tools();

// 3. Use in AI calls
const result = await streamText({
  model: openai('gpt-4o-mini'),
  tools,
  prompt: 'Search the web for the latest AI news',
  onFinish: async () => {
    await mcpClient.close();  // Manual client closure required
  },
});
Enter fullscreen mode Exit fullscreen mode

Multi-tool Integration (Manual Aggregation Required):

import { experimental_createMCPClient as createMCPClient } from '@ai-sdk/mcp';

// Need to create separate clients for each server
const servers = [
  'https://server.smithery.ai/exa',
  'https://server.smithery.ai/@anthropics/brave-search',
];

const clients = await Promise.all(
  servers.map(url =>
    createMCPClient({
      transport: { type: 'http', url, authProvider: myOAuthClientProvider },
    })
  )
);

// Manually aggregate all tools
const allTools = Object.assign(
  {}, 
  ...(await Promise.all(clients.map(c => c.tools())))
);
Enter fullscreen mode Exit fullscreen mode

Key Considerations:

  • ⚠️ Uses experimental_createMCPClient (experimental API, subject to change)
  • ⚠️ Requires OAuth Provider configuration (additional authentication complexity)
  • ⚠️ Manual management of multiple clients for multiple tools
  • ⚠️ Manual close() calls required for lifecycle management
  • ⚠️ Third-party tool API keys (e.g., Exa) handled in OAuth (opaque)
  • ⚠️ Local MCP requires preloading: Cannot be invoked directly, slower response
  • ⚠️ MCP type distinction required: Local MCP and Remote MCP have different invocation patterns

2.2 MCPSDK: Hosted MCP Server + Developer-Friendly API

MCPSDK also provides hosted MCP servers, but with higher-level API wrapping optimized for developer experience.

Advantages:

  • 🎯 Stable API (non-experimental)
  • 🔑 Simple API key authentication
  • 🛠️ Zero-config tool function generation
  • 🔄 Automatic client lifecycle management
  • 📦 Unified third-party tool API key management
  • 🎮 Flexible invocation: Supports both AI invocation and direct developer invocation

Architecture Characteristics:

  • All MCP Servers Always-On: No installation or startup needed, use on demand
  • 🚀 Zero Cold Start: All tool packages preloaded in cloud, faster response
  • 🔌 Unified API Gateway: Access all tool packages through single entry point
  • 🎯 No Type Distinction: Local MCP and Remote MCP handled uniformly, transparent to developers

Vercel AI SDK Integration Code:

import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { MCPSDKApiClient } from 'toolsdk/api';

// 1. Initialize MCPSDK (simple API key)
const toolSDK = new MCPSDKApiClient({ 
  apiKey: process.env.TOOLSDK_API_KEY 
});

// 2. Get tool (chained call, one line)
const searchTool = await toolSDK
  .package('tavily-mcp', { TAVILY_API_KEY: process.env.TAVILY_API_KEY })
  .getAISDKTool('tavily-search');

// 3. Use directly (no manual close)
const result = await generateText({
  model: openai('gpt-4o'),
  tools: { searchTool },
  prompt: 'What is the latest news about AI?'
});
Enter fullscreen mode Exit fullscreen mode

Direct Developer Tool Invocation (No AI Required):

import { MCPSDKApiClient } from 'toolsdk/api';

const toolSDK = new MCPSDKApiClient({ apiKey: 'xxx' });

// Invoke tool directly without AI
const result = await toolSDK
  .package('github', { GITHUB_TOKEN: 'xxx' })
  .run({
    toolKey: 'create-issue',
    inputData: {
      title: 'New Issue',
      body: 'Issue description'
    }
  });

console.log(result); // Get tool execution result directly
Enter fullscreen mode Exit fullscreen mode

Multi-tool Integration (Unified Client):

import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { MCPSDKApiClient } from 'toolsdk/api';

const toolSDK = new MCPSDKApiClient({ apiKey: 'xxx' });

// Parallel tool fetching (Promise.all + chaining)
const [searchTool, emailTool] = await Promise.all([
  toolSDK
    .package('tavily-mcp', { TAVILY_API_KEY: 'xxx' })
    .getAISDKTool('tavily-search'),
  toolSDK
    .package('@mcpsdk.dev/mcp-send-email', { RESEND_API_KEY: 'xxx' })
    .getAISDKTool('send-email'),
]);

// Use directly
const result = await generateText({
  model: openai('gpt-4o'),
  tools: { searchTool, emailTool },
  prompt: 'Search AI news and send to john@example.com'
});
Enter fullscreen mode Exit fullscreen mode

Developer Experience Advantages:

  • ✅ Stable API (not experimental_)
  • ✅ No OAuth Provider configuration required
  • ✅ Unified API client manages all tools
  • ✅ Transparent third-party API key management
  • ✅ Automatic client lifecycle management (no close())
  • ✅ Better TypeScript type inference
  • No MCP type distinction: Local and Remote MCP handled uniformly
  • Flexible invocation: Can be used by AI or invoked directly by developers

3. Code Comparison: Side by Side

Let's compare implementing the same functionality: Using a search tool to query the latest AI news

3.1 Smithery Approach

import { experimental_createMCPClient as createMCPClient } from '@ai-sdk/mcp';
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

// 1. Create MCP client (experimental API)
const mcpClient = await createMCPClient({
  transport: {
    type: 'http',
    url: 'https://server.smithery.ai/exa',
    authProvider: myOAuthClientProvider,  // ⚠️ OAuth configuration required
  },
});

// 2. Get tools
const tools = await mcpClient.tools();

// 3. Use tool
const result = await streamText({
  model: openai('gpt-4o-mini'),
  tools,
  prompt: 'Search the web for the latest AI news',
  onFinish: async () => {
    await mcpClient.close();  // ⚠️ Manual closure required
  },
});
Enter fullscreen mode Exit fullscreen mode

Lines of Code: 18 lines

Configuration Required: OAuth Provider

Manual Management: Client lifecycle (close)

3.2 MCPSDK Approach

import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { MCPSDKApiClient } from 'toolsdk/api';

// 1. Initialize (simple API key)
const toolSDK = new MCPSDKApiClient({ apiKey: 'xxx' });

// 2. Get tool (chained call)
const searchTool = await toolSDK
  .package('tavily-mcp', { TAVILY_API_KEY: 'xxx' })
  .getAISDKTool('tavily-search');

// 3. Use tool
const result = await generateText({
  model: openai('gpt-4o'),
  tools: { searchTool },
  prompt: 'Search the web for the latest AI news'
});
Enter fullscreen mode Exit fullscreen mode

Lines of Code: 12 lines

Configuration Required: API Key (standard)

Manual Management: None


3.3 Additional Scenario: Direct Developer Tool Invocation

Sometimes you need to invoke tools directly without AI.

Smithery Approach

Does not support direct developer tool invocation

Smithery's MCP client can only pass tools to AI SDK, cannot execute tools directly.

MCPSDK Approach

Supports direct tool invocation

import { MCPSDKApiClient } from 'toolsdk/api';

const toolSDK = new MCPSDKApiClient({ apiKey: 'xxx' });

// Invoke tool directly (no AI)
const result = await toolSDK
  .package('github', { GITHUB_TOKEN: 'xxx' })
  .run({
    toolKey: 'create-issue',
    inputData: {
      title: 'New Issue',
      body: 'Issue description'
    }
  });

console.log(result); // Get tool execution result directly
Enter fullscreen mode Exit fullscreen mode

Lines of Code: 8 lines

Use Cases: Background tasks, scheduled jobs, webhook handlers, and other non-AI scenarios

4. When to use which?

4.1 Choose Smithery if...

  • ✅ You prefer OAuth authentication (over API keys)
  • ✅ You're comfortable using experimental APIs (experimental_createMCPClient)
  • ✅ You need specific tools from the Smithery registry (e.g., Brave Search)
  • ✅ You need to use tools in both Claude Desktop and code

4.2 Choose MCPSDK if...

  • ✅ You want to use stable APIs (non-experimental)
  • ✅ You need to manage multiple tools uniformly (no need to create clients for each)
  • ✅ You want transparent third-party API key management (e.g., Tavily, Resend)
  • ✅ You don't want to handle client lifecycle (automatic management)
  • ✅ You need better TypeScript type support
  • ✅ You want to uniformly invoke all MCP types (no Local/Remote distinction, no cold start)
  • ✅ You need direct developer tool invocation (background tasks, scheduled jobs, webhooks, and other non-AI scenarios)

5. The Core Difference

Smithery MCPSDK
Design Philosophy Hosted server + Low-level MCP client Hosted server + High-level developer API
MCP Types Distinguishes Local MCP and Remote MCP Handles all MCP types uniformly
Server Architecture Local MCP needs preloading, Remote MCP dedicated endpoints All always-on, unified gateway
Startup Method Local MCP has cold start, Remote MCP direct Preloaded always-on (zero cold start)
Invocation Method AI invocation only AI invocation + Direct developer invocation
Integration Layer Protocol layer (createMCPClient) Application layer (getAISDKTool / run)
Complexity Requires understanding MCP types, clients, transport, lifecycle One line to get/execute tool
Use Cases Deep MCP integration customization AI apps + Background tasks + Automation

Analogy:

  • Smithery is like AWS SDK (you manage clients, connections, authentication)
  • MCPSDK is like Firebase (you just call simple APIs)

Server Architecture Analogy:

  • Smithery is like hybrid cloud (Local MCP = on-premise deployment needs preloading, Remote MCP = cloud direct)
  • MCPSDK is like unified fully-managed service (all MCPs always-on in cloud, instant response)

6. Try MCPSDK

Experience zero-config MCP tool integration:

npm install toolsdk
Enter fullscreen mode Exit fullscreen mode

2 lines of code to integrate search + email tools:

const toolSDK = new MCPSDKApiClient({ apiKey: 'xxx' });
const [searchTool, emailTool] = await Promise.all([
  toolSDK.package('tavily-mcp', {...}).getAISDKTool('tavily-search'),
  toolSDK.package('@mcpsdk.dev/mcp-send-email', {...}).getAISDKTool('send-email'),
]);
Enter fullscreen mode Exit fullscreen mode

View complete examples →

Top comments (0)