CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-google--genai

Google Gen AI JavaScript SDK for building applications powered by Gemini with content generation, image/video generation, function calling, caching, and real-time live sessions

Overview
Eval results
Files

mcp.mddocs/

MCP Integration (Experimental)

The MCP (Model Context Protocol) integration allows you to convert MCP clients and tools into Gemini-compatible tools for extended functionality and interoperability.

Capabilities

mcpToTool

Convert MCP clients or tools to Gemini CallableTool interface.

/**
 * Convert MCP clients/tools to Gemini tools
 * @param mcpClientOrTools - MCP client or tools array
 * @param config - Tool configuration
 * @returns Promise resolving to callable tool
 */
function mcpToTool(
  mcpClientOrTools: McpClient | McpTool[],
  config?: CallableToolConfig
): Promise<CallableTool>;

interface CallableToolConfig {
  /** Tool display name */
  displayName?: string;
  /** Tool description */
  description?: string;
  /** Additional configuration */
  [key: string]: unknown;
}

Usage Examples:

import { GoogleGenAI, mcpToTool } from '@google/genai';
import { McpClient } from '@modelcontextprotocol/sdk';

const client = new GoogleGenAI({ apiKey: 'YOUR_API_KEY' });

// Connect to MCP server
const mcpClient = new McpClient({
  serverUrl: 'http://localhost:3000'
});

await mcpClient.connect();

// Convert MCP client to Gemini tool
const mcpTool = await mcpToTool(mcpClient, {
  displayName: 'External MCP Tools',
  description: 'Tools provided by MCP server'
});

// Use in generation with automatic function calling
const response = await client.models.generateContent({
  model: 'gemini-2.0-flash',
  contents: 'Use the available tools to complete this task',
  config: {
    tools: [mcpTool],
    automaticFunctionCalling: {
      maximumRemoteCalls: 10
    }
  }
});

console.log('Response:', response.text);

// Close MCP connection
await mcpClient.disconnect();

Types

McpClient

MCP client interface (from @modelcontextprotocol/sdk).

interface McpClient {
  /** Connect to MCP server */
  connect(): Promise<void>;
  /** Disconnect from MCP server */
  disconnect(): Promise<void>;
  /** List available tools */
  listTools(): Promise<McpTool[]>;
  /** Call a tool */
  callTool(name: string, args: Record<string, unknown>): Promise<unknown>;
}

McpTool

MCP tool definition.

interface McpTool {
  /** Tool name */
  name: string;
  /** Tool description */
  description?: string;
  /** Input schema */
  inputSchema?: {
    type: string;
    properties?: Record<string, unknown>;
    required?: string[];
  };
}

CallableTool

Gemini callable tool interface.

interface CallableTool {
  /** Get tool declaration */
  tool(): Promise<Tool>;
  /** Execute function calls */
  callTool(functionCalls: FunctionCall[]): Promise<Part[]>;
}

Complete Examples

Connect to MCP Server

import { GoogleGenAI, mcpToTool } from '@google/genai';
import { McpClient } from '@modelcontextprotocol/sdk';

const client = new GoogleGenAI({ apiKey: 'YOUR_API_KEY' });

// Create and connect MCP client
const mcpClient = new McpClient({
  serverUrl: 'http://localhost:3000',
  apiKey: 'MCP_SERVER_KEY'
});

await mcpClient.connect();
console.log('Connected to MCP server');

// List available tools
const tools = await mcpClient.listTools();
console.log('Available MCP tools:');
tools.forEach(tool => {
  console.log(`  - ${tool.name}: ${tool.description}`);
});

// Convert to Gemini tool
const geminiTool = await mcpToTool(mcpClient);

// Use in generation
const response = await client.models.generateContent({
  model: 'gemini-2.0-flash',
  contents: 'Search for information about AI',
  config: {
    tools: [geminiTool]
  }
});

// Handle function calls manually
if (response.functionCalls) {
  console.log('MCP tools were called:', response.functionCalls);
}

// Cleanup
await mcpClient.disconnect();

Use Specific MCP Tools

import { McpTool } from '@modelcontextprotocol/sdk';

// Define specific MCP tools
const mcpTools: McpTool[] = [
  {
    name: 'search_database',
    description: 'Search the database',
    inputSchema: {
      type: 'object',
      properties: {
        query: { type: 'string' },
        limit: { type: 'number' }
      },
      required: ['query']
    }
  },
  {
    name: 'get_weather',
    description: 'Get weather information',
    inputSchema: {
      type: 'object',
      properties: {
        location: { type: 'string' }
      },
      required: ['location']
    }
  }
];

// Convert tools (not client)
const geminiTool = await mcpToTool(mcpTools, {
  displayName: 'Database and Weather Tools'
});

// Use in generation
const response = await client.models.generateContent({
  model: 'gemini-2.0-flash',
  contents: 'Search the database for AI papers and check weather in San Francisco',
  config: {
    tools: [geminiTool],
    automaticFunctionCalling: {
      maximumRemoteCalls: 5
    }
  }
});

console.log('Response:', response.text);

MCP with Streaming

// Connect MCP client
const mcpClient = new McpClient({
  serverUrl: 'http://localhost:3000'
});

await mcpClient.connect();

// Convert to tool
const mcpTool = await mcpToTool(mcpClient);

// Stream with MCP tools
const stream = await client.models.generateContentStream({
  model: 'gemini-2.0-flash',
  contents: 'Use the tools to gather information',
  config: {
    tools: [mcpTool]
  }
});

for await (const chunk of stream) {
  if (chunk.text) {
    process.stdout.write(chunk.text);
  }

  // Check for function calls
  if (chunk.functionCalls) {
    console.log('\nMCP tools invoked:', chunk.functionCalls);
  }
}

await mcpClient.disconnect();

MCP in Chat Session

// Setup MCP
const mcpClient = new McpClient({
  serverUrl: 'http://localhost:3000'
});

await mcpClient.connect();
const mcpTool = await mcpToTool(mcpClient);

// Create chat with MCP tools
const chat = client.chats.create({
  model: 'gemini-2.0-flash',
  config: {
    tools: [mcpTool],
    systemInstruction: 'You are a helpful assistant with access to external tools.'
  }
});

// Multi-turn conversation with MCP
const r1 = await chat.sendMessage({
  message: 'Search for recent AI developments'
});
console.log('Assistant:', r1.text);

const r2 = await chat.sendMessage({
  message: 'Get more details about the first result'
});
console.log('Assistant:', r2.text);

// Cleanup
await mcpClient.disconnect();

Multiple MCP Servers

// Connect to multiple MCP servers
const mcpClient1 = new McpClient({
  serverUrl: 'http://localhost:3000'
});

const mcpClient2 = new McpClient({
  serverUrl: 'http://localhost:4000'
});

await Promise.all([
  mcpClient1.connect(),
  mcpClient2.connect()
]);

// Convert each to tool
const [tool1, tool2] = await Promise.all([
  mcpToTool(mcpClient1, { displayName: 'Database Tools' }),
  mcpToTool(mcpClient2, { displayName: 'API Tools' })
]);

// Use both in generation
const response = await client.models.generateContent({
  model: 'gemini-2.0-flash',
  contents: 'Use both database and API tools to gather information',
  config: {
    tools: [tool1, tool2],
    automaticFunctionCalling: {
      maximumRemoteCalls: 10
    }
  }
});

console.log('Response:', response.text);

// Cleanup
await Promise.all([
  mcpClient1.disconnect(),
  mcpClient2.disconnect()
]);

MCP with Custom Tool Implementation

import { CallableTool, Tool, FunctionCall, Part } from '@google/genai';
import { McpClient } from '@modelcontextprotocol/sdk';

// Custom wrapper for MCP client
class CustomMcpTool implements CallableTool {
  constructor(private mcpClient: McpClient) {}

  async tool(): Promise<Tool> {
    // Get tools from MCP server
    const mcpTools = await this.mcpClient.listTools();

    // Convert to Gemini format
    const functionDeclarations = mcpTools.map(mcpTool => ({
      name: mcpTool.name,
      description: mcpTool.description,
      parametersJsonSchema: mcpTool.inputSchema
    }));

    return {
      functionDeclarations
    };
  }

  async callTool(functionCalls: FunctionCall[]): Promise<Part[]> {
    const results: Part[] = [];

    for (const fc of functionCalls) {
      try {
        console.log(`Calling MCP tool: ${fc.name}`);

        // Call MCP server
        const result = await this.mcpClient.callTool(fc.name!, fc.args || {});

        results.push({
          functionResponse: {
            name: fc.name,
            response: { result },
            id: fc.id
          }
        });
      } catch (error) {
        console.error(`MCP tool error: ${fc.name}`, error);

        results.push({
          functionResponse: {
            name: fc.name,
            response: {
              error: error.message
            },
            id: fc.id
          }
        });
      }
    }

    return results;
  }
}

// Use custom wrapper
const mcpClient = new McpClient({ serverUrl: 'http://localhost:3000' });
await mcpClient.connect();

const customTool = new CustomMcpTool(mcpClient);

const response = await client.models.generateContent({
  model: 'gemini-2.0-flash',
  contents: 'Use the tools',
  config: {
    tools: [customTool],
    automaticFunctionCalling: {
      maximumRemoteCalls: 5
    }
  }
});

Error Handling with MCP

// MCP connection with error handling
async function connectMcpWithRetry(
  config: { serverUrl: string },
  maxRetries: number = 3
): Promise<McpClient> {
  const mcpClient = new McpClient(config);

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      await mcpClient.connect();
      console.log('Connected to MCP server');
      return mcpClient;
    } catch (error) {
      console.error(`Connection attempt ${attempt} failed:`, error);

      if (attempt === maxRetries) {
        throw new Error('Failed to connect to MCP server after retries');
      }

      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  }

  throw new Error('Unexpected error');
}

// Use with error handling
try {
  const mcpClient = await connectMcpWithRetry({
    serverUrl: 'http://localhost:3000'
  });

  const mcpTool = await mcpToTool(mcpClient);

  const response = await client.models.generateContent({
    model: 'gemini-2.0-flash',
    contents: 'Use the MCP tools',
    config: {
      tools: [mcpTool]
    }
  });

  console.log('Response:', response.text);

  await mcpClient.disconnect();
} catch (error) {
  console.error('MCP error:', error);
}

MCP Tool Discovery

// Discover and document MCP tools
async function discoverMcpTools(mcpClient: McpClient): Promise<void> {
  await mcpClient.connect();

  const tools = await mcpClient.listTools();

  console.log(`Discovered ${tools.length} MCP tools:\n`);

  tools.forEach((tool, index) => {
    console.log(`${index + 1}. ${tool.name}`);
    console.log(`   Description: ${tool.description || 'N/A'}`);

    if (tool.inputSchema?.properties) {
      console.log('   Parameters:');
      Object.entries(tool.inputSchema.properties).forEach(([name, schema]: [string, any]) => {
        const required = tool.inputSchema?.required?.includes(name) ? '(required)' : '(optional)';
        console.log(`     - ${name}: ${schema.type} ${required}`);
        if (schema.description) {
          console.log(`       ${schema.description}`);
        }
      });
    }

    console.log('');
  });

  await mcpClient.disconnect();
}

// Discover tools
const mcpClient = new McpClient({
  serverUrl: 'http://localhost:3000'
});

await discoverMcpTools(mcpClient);

MCP with Function Calling Mode

import { FunctionCallingConfigMode } from '@google/genai';

// Connect MCP
const mcpClient = new McpClient({
  serverUrl: 'http://localhost:3000'
});

await mcpClient.connect();
const mcpTool = await mcpToTool(mcpClient);

// Force model to use MCP tools
const response = await client.models.generateContent({
  model: 'gemini-2.0-flash',
  contents: 'Get information',
  config: {
    tools: [mcpTool],
    toolConfig: {
      functionCallingConfig: {
        mode: FunctionCallingConfigMode.ANY // Must call at least one tool
      }
    }
  }
});

console.log('Response:', response.text);

await mcpClient.disconnect();

MCP Health Check

// Monitor MCP server health
class McpHealthMonitor {
  private mcpClient: McpClient;
  private isHealthy: boolean = false;

  constructor(serverUrl: string) {
    this.mcpClient = new McpClient({ serverUrl });
  }

  async check(): Promise<boolean> {
    try {
      await this.mcpClient.connect();

      // Try to list tools as health check
      const tools = await this.mcpClient.listTools();

      this.isHealthy = tools.length >= 0;

      await this.mcpClient.disconnect();

      return this.isHealthy;
    } catch (error) {
      console.error('MCP health check failed:', error);
      this.isHealthy = false;
      return false;
    }
  }

  async waitUntilHealthy(timeoutMs: number = 30000): Promise<void> {
    const startTime = Date.now();

    while (Date.now() - startTime < timeoutMs) {
      const healthy = await this.check();

      if (healthy) {
        console.log('MCP server is healthy');
        return;
      }

      await new Promise(resolve => setTimeout(resolve, 1000));
    }

    throw new Error('MCP server health check timeout');
  }

  isServerHealthy(): boolean {
    return this.isHealthy;
  }
}

// Use health monitor
const monitor = new McpHealthMonitor('http://localhost:3000');

await monitor.waitUntilHealthy();

if (monitor.isServerHealthy()) {
  // Proceed with MCP integration
  const mcpClient = new McpClient({
    serverUrl: 'http://localhost:3000'
  });

  await mcpClient.connect();
  const mcpTool = await mcpToTool(mcpClient);

  // Use tool...

  await mcpClient.disconnect();
}

Combined Native and MCP Tools

import { Type } from '@google/genai';

// Define native Gemini tool
const nativeTool = {
  functionDeclarations: [{
    name: 'calculate',
    description: 'Perform calculation',
    parameters: {
      type: Type.OBJECT,
      properties: {
        expression: { type: Type.STRING }
      }
    }
  }]
};

// Setup MCP tool
const mcpClient = new McpClient({
  serverUrl: 'http://localhost:3000'
});

await mcpClient.connect();
const mcpTool = await mcpToTool(mcpClient);

// Use both together
const response = await client.models.generateContent({
  model: 'gemini-2.0-flash',
  contents: 'Calculate 2+2 and search for information',
  config: {
    tools: [nativeTool, mcpTool],
    automaticFunctionCalling: {
      maximumRemoteCalls: 10
    }
  }
});

console.log('Response:', response.text);

await mcpClient.disconnect();

Notes

  • MCP integration is experimental and requires the @modelcontextprotocol/sdk package
  • MCP servers must implement the Model Context Protocol specification
  • Connection management and error handling are critical for reliable MCP integration
  • MCP tools are automatically converted to Gemini's function calling format
  • Supports both automatic and manual function calling modes
  • Can combine MCP tools with native Gemini tools in the same request

Install with Tessl CLI

npx tessl i tessl/npm-google--genai

docs

auth-tokens.md

batch.md

caching.md

chat.md

client.md

content-generation.md

embeddings.md

file-search-stores.md

files.md

function-calling.md

image-generation.md

index.md

live.md

mcp.md

models.md

operations.md

tuning.md

video-generation.md

tile.json