An end-to-end example demonstrating how to use Model Context Protocol (MCP) over STDIO in .NET to expose server-side tools and consume them from a client, then feed tool results into a local Ollama-hosted LLM for reasoning and response generation.
This project is intentionally simple and educational: a C# MCP server exposes a GetCurrentTime tool, and a C# MCP client discovers and calls that tool, then passes the result into an Ollama chat model.
What this project shows:
- How to build an MCP server in .NET using STDIO transport
- How to expose tools using
[McpServerTool]attributes - How to build an MCP client that:
- Launches the server as a child process
- Discovers available tools
- Calls a tool with structured arguments
- How to integrate MCP tool output into an Ollama chat flow
- How to correctly handle STDOUT vs STDERR to avoid protocol corruption
- .NET 9.0 SDK or later
https://dotnet.microsoft.com/download/dotnet/9.0 - Ollama installed and running locally
https://ollama.ai/ - Required Ollama model:
ollama pull mistral:7b
- Clone the repository:
git clone https://github.com/your-username/mcp-stdio-ollama-time-demo.git cd mcp-stdio-ollama-time-demo - Restore NuGet packages:
dotnet restore
.
├── MCPClient/
│ ├── Program.cs # MCP client entry point
│ └── OllamaHttpChatClient.cs # Minimal Ollama HTTP chat client
│
└── MCPServer/
├── Program.cs # MCP server host & configuration
└── TimeTool.cs # MCP tool definition
The MCP server:
- Uses STDIO as its transport
- Exposes tools via attributes
- Writes NO logs to STDOUT
- STDOUT is reserved exclusively for MCP protocol messages
- ALL logs must go to STDERR
- Violating this will cause random client crashes or deserialization errors
// CRITICAL FOR MCP OVER STDIO:
// MCP uses STDOUT as a strict protocol channel.
// Any log output written to STDOUT will corrupt the MCP message stream.
builder.Logging.ClearProviders();
builder.Logging.AddConsole(options =>
{
options.LogToStandardErrorThreshold = LogLevel.Trace;
}); [McpServerToolType]
public static class TimeTool
{
[McpServerTool, Description("Get the current time for a city")]
public static string GetCurrentTime(string city) =>
$"It is {DateTime.Now:HH:mm} in {city}.";
}The MCP client is responsible for launching the MCP server, discovering available tools, invoking them with structured arguments, and forwarding the tool output to a local Ollama-hosted language model for reasoning and response generation.
The MCP client:
- Launches the MCP server executable as a child process using STDIO
- Establishes the MCP handshake and capability negotiation
- Discovers tools exposed by the server at runtime
- Invokes MCP tools with structured, named arguments
- Extracts and processes tool responses
- Passes tool output into an Ollama chat model for final response generation
Program.cs is the main entry point for the MCP client. It performs the following steps:
- Configures logging for diagnostics
- Starts the MCP server using the STDIO transport
- Creates and initializes the MCP client
- Discovers available MCP tools
- Calls the
GetCurrentTimetool - Forwards the tool result to Ollama
- Prints the final AI-generated response
Logging is enabled at Trace level to assist with debugging MCP protocol behavior.
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Trace);
});The MCP client:
- Launches the MCP server executable as a child process
- Discovers tools dynamically
- Calls tools with structured arguments
- Feeds tool output into an Ollama chat model
// IMPORTANT: Update the Command path to point to the MCP server executable
// on your own machine. This path is environment-specific.
Command = @"C:\Path\To\MCPServer\bin\Debug\net9.0\MCPServer.exe";Each developer or deployment environment must update this path.
- Ollama is used after MCP tool execution
- MCP performs the action (tool call)
- Ollama performs the reasoning / explanation
- Model used: mistral:7b
Make sure Ollama is running locally:
ollama serveMake sure Ollama is running and responding correctly:
curl http://localhost:11434/api/tagscd MCPServer
dotnet buildcd MCPClient
dotnet runThe client will:
- Launch the MCP server via STDIO
- Discover available MCP tools
- Call
GetCurrentTime - Pass the result into Ollama
- Print the final AI response
MCP tools discovered: GetCurrentTime — Get the current time for a city
MCP Tool Response: It is 14:32 in Illzach, France.
AI Response: The current time in Illzach, France is 14:32 CET.
- .NET 9.0 (C# Console Apps)
- Model Context Protocol (MCP)
- STDIO Transport
- Ollama (local LLM runtime)
- Mistral 7B (chat model)
- Microsoft.Extensions.Logging
MCP over STDIO is extremely strict:
- ✅ STDOUT → MCP protocol messages ONLY
- ✅ STDERR → logs, diagnostics, exceptions
- ❌ Any accidental
Console.WriteLinebreaks everything
This repository intentionally highlights correct setup to avoid subtle bugs.
See the LICENSE file for details.
Contributions are welcome.
If you want to extend this example:
- Async MCP tools
- Structured JSON tool outputs
- HTTP-based MCP transport
- Streaming responses
- Tool error handling
Open an issue or submit a Pull Request.