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:
- .NET 8.0 or later installed
- Google API Key from Google AI Studio
- Node.js (for running MCP servers)
- The Google_GenerativeAI.Tools NuGet package:
dotnet add package Google_GenerativeAI.Tools
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" }
);
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"
);
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"
);
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
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!");
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}");
}
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
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!");
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");
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.
"
};
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();
}
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}");
}
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();
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());
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());
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'
");
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
};
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
}
);
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();
}
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
};
3. Enable Detailed Errors in Development
var options = new McpToolOptions
{
IncludeDetailedErrors = true, // Development
// IncludeDetailedErrors = false // Production
};
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
"
};
5. Implement Error Recovery
var options = new McpToolOptions
{
AutoReconnect = true,
MaxReconnectAttempts = 3,
ThrowOnToolCallFailure = false // Return errors gracefully
};
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 };
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
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" }
});
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!");
}
}
}
Run it:
dotnet run
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:
- Build a knowledge base assistant - Connect to multiple document sources
- Create a DevOps helper - Integrate GitHub, databases, and file systems
- Make a personal assistant - Combine calendar, email, and task management
- Build an analytics tool - Query databases and generate reports
- Create custom MCP servers - Build your own tools and services!
Resources
- MCP Integration Guide - Complete documentation
- SDK Repository - Source code and examples
- MCP Documentation - Official MCP docs
- MCP Servers Registry - Browse available servers
- Sample Projects - Working examples
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)