DEV Community

Gunpal Jain
Gunpal Jain

Posted on

Supercharge Google Gemini with MCP: Connect Any Tool to Your AI!

Hey everyone!

If you've been working with AI and thought, "I wish my AI could access anything files, databases, APIs, custom tools..." you're in luck! Today, I'm excited to show you how to connect Google Gemini to the Model Context Protocol (MCP), unlocking a universe of external tools and services.

By the end of this article, you'll be able to connect Gemini to file systems, GitHub, databases, Slack, and practically any service that supports MCP. Let's dive in!


What is MCP?

Think of MCP as a universal adapter for AI models. Just like USB-C works with any compatible device, MCP provides a standardized way for AI models to connect to external tools and services.

Instead of building custom integrations for each service, MCP lets you:

  • Access file systems - Read, write, and search files
  • Connect to GitHub - Create issues, search repos, manage PRs
  • Query databases - Run SQL queries, fetch data
  • Integrate with Slack - Send messages, read channels
  • Use any MCP server - Hundreds of community servers available!

The best part? All with the same simple API. No need to learn different SDKs for each service!


Prerequisites

Before we begin, make sure you have:

  1. .NET 8.0 or later installed
  2. Google API Key from Google AI Studio
  3. Node.js (for running MCP servers)
  4. The Google_GenerativeAI.Tools NuGet package:
dotnet add package Google_GenerativeAI.Tools
Enter fullscreen mode Exit fullscreen mode

Part 1: Understanding MCP Integration

The Three Transport Types

MCP supports three ways to connect to servers:

1. Stdio (Subprocess)

Launch an MCP server as a child process. Perfect for local tools!

var transport = McpTransportFactory.CreateStdioTransport(
    name: "filesystem",
    command: "npx",
    arguments: new[] { "-y", "@modelcontextprotocol/server-filesystem", "/path/to/files" }
);
Enter fullscreen mode Exit fullscreen mode

When to use: Local file operations, running scripts, development

2. HTTP/SSE (Remote)

Connect to a remote MCP server over HTTP with Server-Sent Events.

var transport = McpTransportFactory.CreateHttpTransport(
    baseUrl: "https://api.example.com/mcp"
);
Enter fullscreen mode Exit fullscreen mode

When to use: Cloud services, shared tools, production deployments

3. HTTP with Authentication

Same as HTTP but with authentication headers.

var transport = McpTransportFactory.CreateHttpTransportWithAuth(
    baseUrl: "https://api.example.com/mcp",
    authToken: "your-secret-token"
);
Enter fullscreen mode Exit fullscreen mode

When to use: Protected APIs, enterprise services


Part 2: Building a Real Application

Let's build something practical: A Gemini-powered file assistant that can read, search, and summarize files on your computer!

Step 1: Create the Project

dotnet new console -n GeminiFileAssistant
cd GeminiFileAssistant
dotnet add package Google_GenerativeAI.Tools
Enter fullscreen mode Exit fullscreen mode

Step 2: Connect to the Filesystem MCP Server

Create a new file Program.cs:

using GenerativeAI;
using GenerativeAI.Tools.Mcp;
using GenerativeAI.Types;

// Configure the filesystem MCP server
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

var transport = McpTransportFactory.CreateStdioTransport(
    name: "filesystem",
    command: "npx",
    arguments: new[] {
        "-y",
        "@modelcontextprotocol/server-filesystem",
        documentsPath
    }
);

// Configure options
var options = new McpToolOptions
{
    ConnectionTimeoutMs = 30000,  // 30 second timeout
    AutoReconnect = true,          // Reconnect if connection drops
    IncludeDetailedErrors = true   // Show detailed errors
};

// Create the MCP tool
await using var mcpTool = await McpTool.CreateAsync(transport, options);

Console.WriteLine(" Connected to filesystem MCP server!");
Enter fullscreen mode Exit fullscreen mode

Step 3: Discover Available Tools

Let's see what the server can do:

// Get all available tools
var tools = mcpTool.GetAvailableFunctions();

Console.WriteLine($"\n Available tools: {tools.Count}");
foreach (var toolName in tools)
{
    var info = mcpTool.GetFunctionInfo(toolName);
    Console.WriteLine($"   {toolName}: {info.Description}");
}
Enter fullscreen mode Exit fullscreen mode

Output:

 Available tools: 5
   read_file: Read the complete contents of a file
   read_multiple_files: Read multiple files simultaneously
   write_file: Create a new file or overwrite existing
   list_directory: List all files and directories
   search_files: Search for files by name pattern
Enter fullscreen mode Exit fullscreen mode

Step 4: Integrate with Gemini

Now for the magic let's give Gemini access to these tools!

// Create Gemini model
var apiKey = Environment.GetEnvironmentVariable("GOOGLE_API_KEY")
    ?? throw new Exception("Please set GOOGLE_API_KEY environment variable");

var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini2Flash);

// Add the MCP tools
model.AddFunctionTool(mcpTool);

// Enable automatic function calling
model.FunctionCallingBehaviour.AutoCallFunction = true;
model.FunctionCallingBehaviour.AutoReplyFunction = true;

Console.WriteLine("\n Gemini is ready with filesystem access!");
Enter fullscreen mode Exit fullscreen mode

Step 5: Create an Interactive Chat

Let's build a conversational interface:

// Start chat session
var chat = model.StartChat();

// Helper method to chat with Gemini
async Task AskGemini(string prompt)
{
    Console.WriteLine($"\n You: {prompt}");
    Console.Write(" Gemini: ");

    var response = await chat.GenerateContentAsync(prompt);
    Console.WriteLine(response.Text());
}

// Example conversations
await AskGemini("What files are in my Documents folder?");
await AskGemini("Can you read my README.md file if it exists?");
await AskGemini("Search for all PDF files and tell me their names");
await AskGemini("Create a summary.txt file with a list of all text files");
Enter fullscreen mode Exit fullscreen mode

Step 6: Add System Instructions

Make Gemini even better with context:

var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini2Flash)
{
    SystemInstruction = @"
        You are a helpful file management assistant. When users ask about files:

        1. Always use the available filesystem tools
        2. Provide clear, concise summaries
        3. If you can't find something, suggest alternatives
        4. For large files, offer to summarize specific sections
        5. Be proactive - if you see related files, mention them

        Remember: You have access to read, write, list, and search files.
    "
};
Enter fullscreen mode Exit fullscreen mode

Part 3: Advanced Patterns

Pattern 1: Multiple MCP Servers

Connect to several services at once:

var transports = new List<IClientTransport>
{
    // Filesystem access
    McpTransportFactory.CreateStdioTransport(
        "filesystem",
        "npx",
        new[] { "-y", "@modelcontextprotocol/server-filesystem", "/path" }
    ),

    // GitHub integration
    McpTransportFactory.CreateStdioTransport(
        "github",
        "npx",
        new[] { "-y", "@modelcontextprotocol/server-github" }
    ),

    // Slack integration
    McpTransportFactory.CreateHttpTransportWithAuth(
        "https://slack-mcp.example.com",
        Environment.GetEnvironmentVariable("SLACK_TOKEN")
    )
};

// Create all tools
var mcpTools = await McpTool.CreateMultipleAsync(transports);

// Add all to Gemini
foreach (var tool in mcpTools)
{
    model.AddFunctionTool(tool);
}

// Now Gemini can use ALL services!
await model.GenerateContentAsync(
    "Check if there are any open GitHub issues, " +
    "read the project README, and post a summary to Slack"
);

// Cleanup
foreach (var tool in mcpTools)
{
    await tool.DisposeAsync();
}
Enter fullscreen mode Exit fullscreen mode

Pattern 2: Error Handling

Handle connection issues gracefully:

try
{
    var mcpTool = await McpTool.CreateAsync(transport, new McpToolOptions
    {
        ConnectionTimeoutMs = 10000,
        AutoReconnect = true,
        MaxReconnectAttempts = 3,
        ThrowOnToolCallFailure = false  // Don't crash on tool errors
    });

    // Use the tool
    var response = await model.GenerateContentAsync("List my files");
    Console.WriteLine(response.Text());
}
catch (TimeoutException)
{
    Console.WriteLine(" Connection timeout - is the MCP server running?");
}
catch (Exception ex)
{
    Console.WriteLine($" Error: {ex.Message}");
}
Enter fullscreen mode Exit fullscreen mode

Pattern 3: Streaming Responses

Stream Gemini's responses for better UX:

model.AddFunctionTool(mcpTool);

Console.Write(" Gemini: ");

await foreach (var chunk in model.StreamContentAsync(
    "Read the largest file and summarize its contents"))
{
    Console.Write(chunk.Text());
}

Console.WriteLine();
Enter fullscreen mode Exit fullscreen mode

Part 4: Real-World Examples

Example 1: Code Review Assistant

var transport = McpTransportFactory.CreateStdioTransport(
    "filesystem",
    "npx",
    new[] { "-y", "@modelcontextprotocol/server-filesystem", "./src" }
);

await using var mcpTool = await McpTool.CreateAsync(transport);

var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini2Flash)
{
    SystemInstruction = @"
        You are a code review assistant. Analyze source code files for:
        - Code quality issues
        - Potential bugs
        - Performance improvements
        - Security vulnerabilities

        Provide specific, actionable feedback.
    "
};

model.AddFunctionTool(mcpTool);

var response = await model.GenerateContentAsync(
    "Review all C# files in the current directory and identify potential issues"
);

Console.WriteLine(response.Text());
Enter fullscreen mode Exit fullscreen mode

Example 2: Documentation Generator

var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini2Flash);
model.AddFunctionTool(mcpTool);

var response = await model.GenerateContentAsync(@"
    Read all the code files in this project, understand the architecture,
    and create a comprehensive README.md with:
    - Project overview
    - Setup instructions
    - API documentation
    - Usage examples
");

Console.WriteLine(" Documentation generated!");
Console.WriteLine(response.Text());
Enter fullscreen mode Exit fullscreen mode

Example 3: Multi-Service Integration

// Connect to multiple services
var githubTransport = McpTransportFactory.CreateStdioTransport(
    "github", "npx", new[] { "-y", "@modelcontextprotocol/server-github" }
);

var filesystemTransport = McpTransportFactory.CreateStdioTransport(
    "filesystem", "npx",
    new[] { "-y", "@modelcontextprotocol/server-filesystem", "./" }
);

var tools = await McpTool.CreateMultipleAsync(new[]
{
    githubTransport,
    filesystemTransport
});

var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini2Flash);
foreach (var tool in tools) model.AddFunctionTool(tool);

// Gemini can now coordinate across services!
await model.GenerateContentAsync(@"
    1. Check for open GitHub issues labeled 'bug'
    2. For each issue, check if we have a test file covering it
    3. Create a report summarizing gaps in test coverage
    4. Save the report to 'test-coverage-gaps.md'
");
Enter fullscreen mode Exit fullscreen mode

Configuration Deep Dive

McpToolOptions Explained

var options = new McpToolOptions
{
    // How long to wait for connection (milliseconds)
    ConnectionTimeoutMs = 30000,

    // Automatically reconnect if connection drops
    AutoReconnect = true,

    // Maximum reconnection attempts before giving up
    MaxReconnectAttempts = 3,

    // Throw exception on tool call failures (vs. return error in response)
    ThrowOnToolCallFailure = false,

    // Include detailed error messages in responses
    IncludeDetailedErrors = true
};
Enter fullscreen mode Exit fullscreen mode

Transport Factory for Reconnection

For better reconnection handling, use a factory function:

var mcpTool = await McpTool.CreateAsync(
    transportFactory: () => McpTransportFactory.CreateStdioTransport(
        "my-server",
        "npx",
        new[] { "-y", "@modelcontextprotocol/server-everything" }
    ),
    options: new McpToolOptions
    {
        AutoReconnect = true,
        MaxReconnectAttempts = 5
    }
);
Enter fullscreen mode Exit fullscreen mode

The factory ensures a fresh transport is created for each reconnection attempt.


Available MCP Servers

Here are some popular MCP servers you can use right now:

Official Servers

Server Description Installation
filesystem File operations (read, write, search) npx -y @modelcontextprotocol/server-filesystem
github GitHub integration (issues, PRs, repos) npx -y @modelcontextprotocol/server-github
google-drive Google Drive access npx -y @modelcontextprotocol/server-google-drive
slack Slack messaging npx -y @modelcontextprotocol/server-slack
postgres PostgreSQL database queries npx -y @modelcontextprotocol/server-postgres
everything Demo server with multiple tools npx -y @modelcontextprotocol/server-everything

Community Servers

Browse hundreds more at: MCP Server Registry


Best Practices

1. Always Dispose Resources

// Good: Using statement
await using var mcpTool = await McpTool.CreateAsync(transport);

// Also good: Try-finally
var mcpTool = await McpTool.CreateAsync(transport);
try
{
    // Use mcpTool
}
finally
{
    await mcpTool.DisposeAsync();
}
Enter fullscreen mode Exit fullscreen mode

2. Set Appropriate Timeouts

// Local servers: Short timeout
var localOptions = new McpToolOptions
{
    ConnectionTimeoutMs = 5000  // 5 seconds
};

// Remote servers: Longer timeout
var remoteOptions = new McpToolOptions
{
    ConnectionTimeoutMs = 30000  // 30 seconds
};
Enter fullscreen mode Exit fullscreen mode

3. Enable Detailed Errors in Development

var options = new McpToolOptions
{
    IncludeDetailedErrors = true,  // Development
    // IncludeDetailedErrors = false  // Production
};
Enter fullscreen mode Exit fullscreen mode

4. Use System Instructions

Guide Gemini on how to use tools effectively:

var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini2Flash)
{
    SystemInstruction = @"
        When using filesystem tools:
        - Always verify file existence before reading
        - Summarize large files instead of dumping full content
        - Suggest file locations if not found
        - Be cautious with write operations
    "
};
Enter fullscreen mode Exit fullscreen mode

5. Implement Error Recovery

var options = new McpToolOptions
{
    AutoReconnect = true,
    MaxReconnectAttempts = 3,
    ThrowOnToolCallFailure = false  // Return errors gracefully
};
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

Problem: Server Won't Start

Error: Failed to connect to MCP server

Solutions:

# 1. Check if Node.js is installed
node --version

# 2. Try running the server manually
npx -y @modelcontextprotocol/server-filesystem /path

# 3. Increase timeout
var options = new McpToolOptions { ConnectionTimeoutMs = 60000 };
Enter fullscreen mode Exit fullscreen mode

Problem: Tools Not Discovered

Error: GetAvailableFunctions() returns empty

Solutions:

// 1. Refresh tools
await mcpTool.RefreshToolsAsync();

// 2. Check connection
Console.WriteLine($"Connected: {mcpTool.IsConnected}");

// 3. Inspect server logs
// Look for errors in the console output
Enter fullscreen mode Exit fullscreen mode

Problem: Function Calls Fail

Error: Tool returns errors

Solutions:

// 1. Enable detailed errors
var options = new McpToolOptions { IncludeDetailedErrors = true };

// 2. Inspect parameter schema
var info = mcpTool.GetFunctionInfo("tool-name");
Console.WriteLine(info.ParametersJsonSchema);

// 3. Test manually
var result = await mcpTool.CallAsync(new FunctionCall
{
    Name = "tool-name",
    Args = new JsonObject { ["param"] = "value" }
});
Enter fullscreen mode Exit fullscreen mode

Complete Working Example

Here's a full application you can run right now:

using System;
using System.Threading.Tasks;
using GenerativeAI;
using GenerativeAI.Tools.Mcp;
using GenerativeAI.Types;

namespace GeminiMcpDemo
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine(" Gemini MCP File Assistant\n");

            // 1. Setup MCP connection
            var docsPath = Environment.GetFolderPath(
                Environment.SpecialFolder.MyDocuments
            );

            var transport = McpTransportFactory.CreateStdioTransport(
                "filesystem",
                "npx",
                new[] { "-y", "@modelcontextprotocol/server-filesystem", docsPath }
            );

            var options = new McpToolOptions
            {
                ConnectionTimeoutMs = 30000,
                AutoReconnect = true,
                IncludeDetailedErrors = true
            };

            await using var mcpTool = await McpTool.CreateAsync(transport, options);
            Console.WriteLine(" Connected to filesystem MCP server");

            // 2. Show available tools
            Console.WriteLine("\n Available tools:");
            foreach (var tool in mcpTool.GetAvailableFunctions())
            {
                var info = mcpTool.GetFunctionInfo(tool);
                Console.WriteLine($"   {tool}: {info.Description}");
            }

            // 3. Create Gemini model
            var apiKey = Environment.GetEnvironmentVariable("GOOGLE_API_KEY");
            if (string.IsNullOrEmpty(apiKey))
            {
                Console.WriteLine("\n Please set GOOGLE_API_KEY environment variable");
                return;
            }

            var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini2Flash)
            {
                SystemInstruction = @"
                    You are a helpful file assistant. You can:
                    - List and search files
                    - Read file contents
                    - Write new files

                    Always be clear and concise in your responses.
                "
            };

            model.AddFunctionTool(mcpTool);
            model.FunctionCallingBehaviour.AutoCallFunction = true;
            model.FunctionCallingBehaviour.AutoReplyFunction = true;

            Console.WriteLine("\n Gemini ready! Type 'exit' to quit.\n");

            // 4. Interactive chat loop
            var chat = model.StartChat();

            while (true)
            {
                Console.Write(" You: ");
                var input = Console.ReadLine();

                if (string.IsNullOrEmpty(input) || input.ToLower() == "exit")
                    break;

                try
                {
                    Console.Write(" Gemini: ");
                    var response = await chat.GenerateContentAsync(input);
                    Console.WriteLine(response.Text() + "\n");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($" Error: {ex.Message}\n");
                }
            }

            Console.WriteLine("\n Goodbye!");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Run it:

dotnet run
Enter fullscreen mode Exit fullscreen mode

Try these prompts:

  • "What files are in my Documents folder?"
  • "Read my README.md file"
  • "Search for all .txt files"
  • "Create a file called 'test.txt' with 'Hello, MCP!'"
  • "Find all PDF files and list their names"

What's Next?

Now that you've mastered MCP integration, here are some ideas to explore:

  1. Build a knowledge base assistant - Connect to multiple document sources
  2. Create a DevOps helper - Integrate GitHub, databases, and file systems
  3. Make a personal assistant - Combine calendar, email, and task management
  4. Build an analytics tool - Query databases and generate reports
  5. Create custom MCP servers - Build your own tools and services!

Resources


Conclusion

MCP transforms Google Gemini from a chatbot into a powerful agent that can interact with real systems and services. Whether you're building a file assistant, a code reviewer, or a multi-service coordinator, MCP makes it incredibly simple.

The best part? The same API works for any MCP-compatible service. Learn it once, use it everywhere!

Got questions or built something cool? Drop a comment below! I'd love to hear what you're building with MCP!

Happy coding!


P.S. Want to see more examples? Check out the samples folder in the GitHub repo!

Found this helpful? Give the repository a on GitHub!

Top comments (0)