Use this file to discover all available pages before exploring further.
MCP clients connect to servers using transports. The C# SDK provides two main transport types: stdio for local process communication and HTTP for remote server connections.
using ModelContextProtocol.Client;IClientTransport transport = new StdioClientTransport(new(){ Command = "npx", Arguments = ["-y", "@modelcontextprotocol/server-everything"]});await using var client = await McpClient.CreateAsync(transport);
The client automatically performs the initialization handshake and negotiates capabilities with the server.
var transport = new StdioClientTransport(new StdioClientTransportOptions{ Command = "dotnet", Arguments = ["run", "--project", "../MyMcpServer"], Name = "My Local Server"});await using var client = await McpClient.CreateAsync(transport);
Streamable HTTP is the modern, bidirectional transport protocol:
var transport = new HttpClientTransport(new HttpClientTransportOptions{ Endpoint = new Uri("https://my-mcp-server.example.com/mcp"), TransportMode = HttpTransportMode.StreamableHttp});await using var client = await McpClient.CreateAsync(transport);
By default, the client auto-detects the transport mode, trying Streamable HTTP first and falling back to SSE:
var transport = new HttpClientTransport(new HttpClientTransportOptions{ Endpoint = new Uri("https://my-mcp-server.example.com/mcp") // TransportMode defaults to HttpTransportMode.AutoDetect});await using var client = await McpClient.CreateAsync(transport);
Add custom HTTP headers for authentication or other purposes:
var transport = new HttpClientTransport(new HttpClientTransportOptions{ Endpoint = new Uri("https://my-mcp-server.example.com/mcp"), AdditionalHeaders = new Dictionary<string, string> { ["X-API-Key"] = "your-api-key", ["X-Custom-Header"] = "value" }});await using var client = await McpClient.CreateAsync(transport);
Provide your own HttpClient instance for advanced scenarios:
var handler = new SocketsHttpHandler{ PooledConnectionLifetime = TimeSpan.FromMinutes(2), PooledConnectionIdleTimeout = TimeSpan.FromMinutes(1)};var httpClient = new HttpClient(handler);var transport = new HttpClientTransport( new HttpClientTransportOptions { Endpoint = new Uri("http://localhost:3001") }, httpClient, ownsHttpClient: false);await using var client = await McpClient.CreateAsync(transport);
Streamable HTTP supports session resumption for reconnecting to an existing server session:
// First session - capture session infovar transport = new HttpClientTransport(new HttpClientTransportOptions{ Endpoint = new Uri("https://my-mcp-server.example.com/mcp")});await using var client = await McpClient.CreateAsync(transport);var sessionId = /* capture from transport */;var serverCapabilities = client.ServerCapabilities;var serverInfo = client.ServerInfo;// Later - resume the sessionvar resumeTransport = new HttpClientTransport(new HttpClientTransportOptions{ Endpoint = new Uri("https://my-mcp-server.example.com/mcp"), KnownSessionId = sessionId});await using var resumedClient = await McpClient.ResumeSessionAsync( resumeTransport, new ResumeClientSessionOptions { ServerCapabilities = serverCapabilities, ServerInfo = serverInfo });
var options = new McpClientOptions{ ClientInfo = new Implementation { Name = "My MCP Client", Version = "1.0.0" }, Capabilities = new ClientCapabilities { Sampling = new SamplingCapability(), Roots = new RootsCapability { ListChanged = true } }, ProtocolVersion = null, // Use latest version InitializationTimeout = TimeSpan.FromSeconds(60)};await using var client = await McpClient.CreateAsync(transport, options);
After connection, access server capabilities and metadata:
await using var client = await McpClient.CreateAsync(transport);// Server capabilitiesServerCapabilities capabilities = client.ServerCapabilities;if (capabilities.Tools is not null){ Console.WriteLine("Server supports tools");}// Server implementation infoImplementation serverInfo = client.ServerInfo;Console.WriteLine($"Connected to {serverInfo.Name} v{serverInfo.Version}");// Server instructions (hints for LLMs)string? instructions = client.ServerInstructions;if (instructions is not null){ Console.WriteLine($"Server instructions: {instructions}");}
await using var client = await McpClient.CreateAsync(transport);// Wait for completion (in background task)_ = Task.Run(async () =>{ ClientCompletionDetails details = await client.Completion; if (details.Exception is null) { Console.WriteLine("Session closed gracefully"); } else { Console.WriteLine($"Session failed: {details.Exception.Message}"); }});// Use the client...