Building MCP Client with C#: A Beginner's Guide

1. Prerequisites

1.1 Understanding MCP (Model Context Protocol)

Overview

MCP (Model Context Protocol) is an open protocol that standardizes how applications provide context information to Large Language Models (LLMs). Think of MCP as the USB-C interface for AI applications. Just as USB-C provides a standardized way for devices to connect various peripherals and accessories, MCP offers a stendardized approach for AI models to connect to different data sources and tools.

In essence, Large Language Models function as our brains, but having just a "brain" isn't sufficient to accomplish all tasks. Previously, we typically interacted with AI models through manual conversations, giving instructions to complete tasks, and then analyzing and organizing the results ourselves. This undoubtedly increased our time costs significantly. Now, with MCP tools, models possess "hands and feet" - they can invoke different tools to execute tasks based on our commands. The MCP protocol serves as the bridge between models and these tools.

Why can models invoke different tools? This is thanks to Large Models now supporting Function Call (function calling) capabilities. Simply put, Function Call allows models to parse user requests and generate the parameters needed to call external functions, enabling more complex task processing.

Function Call Mechanism

  1. Semantic Understanding: The model parses user input and determines whether a function needs to be called.
  2. Tool Matching: Selects the appropriate tool from a predefined tool library (e.g., weather queries, mathematical calculations).
  3. Parameter Generation: Converts user descriptions into the required parameter format for functions (such as Fetch {Url:{address}}).
  4. Execution and Integration: Calls external tools to retrieve results and generates natural language responses.

For more detailed information, refer to the MCP Chinese documentation or official English documentation.

1.2 MCP Capabilities

  • Real-time Data Retrieval: Query dynamic information such as weather and stock data (since the LLM's own knowledge base is static).
  • Natural Language SQL Execution: Connect to databases to query local data and perform data analysis.
  • Private Domain Knowledge Expansion: Solve domain-specific problems using private data sources such as local knowledge bases and knowledge graphs.

2. Connecting to MCP Tools Using C#

2.1 Initial Setup

First, we need to select an AI model to use. In this tutorial, we utilize SiliconFlow's Qwen/QwQ-32B model. If you don't have a SiliconFlow account, you can register for a domestic account. By default, the platform provides 20 million tokens of free credit. After registration, you can select the model you need (such as Qwen/QwQ-32B). Ensure the selected model supports Function Call.

2.2 Creating a Console Project

In Visual Studio 2022, create a new console application project (for example, MCPClient). Then, install the required NuGet package:

dotnet add package ModelContextProtocol --prerelease

Now we can test MCP Client tool invocation using sample code from GitHub:

// Create MCP Client to connect to the corresponding MCP Server tool
#region适用于 0.1.0-preview.4 版本
var mcpClient = await McpClientFactory.CreateAsync(new()
{
    Id = "demo-server",
    Name = "DemoServer",
    TransportType = TransportTypes.StdIo,
    TransportOptions = new()
    {
        ["command"] = "npx",
        ["arguments"] = "-y @modelcontextprotocol/server-everything",
    }
});
#endregion

#region适用于 0.1.0-preview.9 版本
var clientTransport = new StdioClientTransport(
    new StdioClientTransportOptions
    {
        Name = "DemoServer",
        Command = "npx",
        Arguments = ["-y", "@modelcontextprotocol/server-everything"],
    }
);

var mcpClient = await McpClientFactory.CreateAsync(clientTransport);
#endregion

// Display the list of available tools on the MCP server
var availableTools = await mcpClient.ListToolsAsync();
foreach (var tool in availableTools)
{
    Console.WriteLine($"{tool.Name} - {tool.Description}");
}

// Execute a tool - using the echo function from the available tools
// The echo function returns the message you sent
var executionResult = await mcpClient.CallToolAsync(
    "echo",
    new Dictionary<string, object?>() { ["message"] = "Hello MCP!" },
    CancellationToken.None);

// echo always returns one and only one text content object
Console.WriteLine(executionResult.Content.First(c => c.Type == "text").Text);

The execution results appear as follows:

2.3 Performing Tool Invocation

After testing the basic MCP Client invocation, we can now implement a practical functionality: retrieving information from any webpage through the MCP Client and having the AI model summarize it. You can find suitable tools by visiting the official server tools list. For example, the Fetch tool can extract webpage content and convert it to Markdown format.

Let's examine the official server tools list to find the tool we want to invoke. Here we use the Fetch tool - clicking on the link provides detailed documentation for the corresponding tool.

Next, let's look at its configuration. It recommends using uvx for invocation, which we'll emulate. You can also install and run it using Python directly. To use uvx, you need to install the uvx environment. If you're unsure how to install it, refer to the documentation and download the corresponding uvx package. Since I already have Cherry Studio installed on my computer with the environment configured, I won't demonstrate that here. The uvx path is: C:\Users{Username}\.cherrystudio\bin. Keep this path in mind for later use.

{
  "mcpServers": {
    "fetch": {
      "command": "uvx",
      "args": ["mcp-server-fetch"]
    }
  }
}

Writing MCP Cleint Code

Since we need to use the model we just prepared and connect to the fetch tool to retrieve the webpage we want, we need to install some NuGet packages for convenient LLM integration:

dotnet add package Microsoft.Extensions.AI --prerelease
dotnet add package Microsoft.Extensions.AI.Abstractions --prerelease
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease

After installation, we begin writing our code:

using Microsoft.Extensions.AI;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol.Transport;
using OpenAI;
using System.ClientModel;


// Create MCP Client
#region适用于 0.1.0-preview.4 版本
var mcpClient = await McpClientFactory.CreateAsync(new()
{
    Id = "fetch",
    Name = "Fetch",
    TransportType = TransportTypes.StdIo,
    TransportOptions = new()
    {
        ["command"] = @"C:\Users\YourUsername\.cherrystudio\bin\uvx.exe",
        ["arguments"] = "mcp-server-fetch",
    }
});
#endregion

#region适用于 0.1.0-preview.9 版本
var clientTransport = new StdioClientTransport(
    new StdioClientTransportOptions
    {
        Name = "Fetch",
        Command = @"C:\Users\YourUsername\.cherrystudio\bin\uvx.exe",
        Arguments = ["mcp-server-fetch"],
    }
);

var mcpClient = await McpClientFactory.CreateAsync(clientTransport);
#endregion


var toolList = await mcpClient.ListToolsAsync();

// Display available tools on the server
foreach (var tool in toolList)
{
    Console.WriteLine($"{tool.Name} ({tool.Description})");
}

// Create API key credential
var apiKeyCredential = new ApiKeyCredential("your-api-key");

// Configure OpenAPI client options
var aiClientOptions = new OpenAIClientOptions();
aiClientOptions.Endpoint = new Uri("https://api.siliconflow.cn");


#region适用于 9.3.0-preview.1.25161.3
var aiClient = new OpenAIClient(apiKeyCredential, aiClientOptions)
    .AsChatClient("Qwen/QwQ-32B");

// Create ChatClient
var chatClient = new ChatClientBuilder(aiClient)
    .UseFunctionInvocation()
    .Build();
#endregion

#region适用于 9.4.0-preview.1.25207.5
// Create OpenAI client with specified model
IChatClient chatClient = new OpenAI.Chat.ChatClient(
    "Qwen/QwQ-32B",
    apiKeyCredential,
    aiClientOptions
)
    .AsIChatClient()
    .AsBuilder()
    .UseFunctionInvocation()
    .Build();
#endregion

// Create messages
IList<ChatMessage> messages = [
     new(ChatRole.System, "You are a helpful assistant helping us test MCP server functionality"),
     new(ChatRole.User, "I have a webpage I'd like you to analyze. The URL is: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.html"),
    ];

// Invoke fetch tool through LLM
var response = await chatClient.GetResponseAsync(
    messages,
    new() { Tools = [.. toolList] });

// Get tool usage messages
var toolUseMessage = response.Messages.Where(m => m.Role == ChatRole.Tool);
if (response.Messages[0].Contents.Count > 1)
{
    var functionCall = (FunctionCallContent)response.Messages[0].Contents[1];
}

Debug results appear as follows:

This completes our basic invocation of the Fetch tool - simple and effective!

3. Summary

This article introduced the fundamental concepts and operational patterns of MCP, then demonstrated how to create an MCP Client using the C# SDK to invoke MCP tools. Due to length constraints, I will cover MCP Server development and how MCP Client invokes our custom MCP Server in a follow-up article.

If you're a .NET developer interested in AI application development, explore the ecosystem components based on Microsoft.Extensions.AI and the MCP C# SDK.

Tags: C# MCP Model Context Protocol AI LLM

Posted on Mon, 01 Jun 2026 18:05:01 +0000 by point86