Sample: stdio-to-HTTP bridge for AI clients that only support stdio transport
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 68/100
Direzione di ricerca
Inizia con l’entry point proposto samples/StdioToHttpBridge e l’utilizzo raw di ITransport descritto nell’issue. Eseguilo con un endpoint HTTP MCP e un client stdio, verificando l’inoltro bidirezionale dei messaggi, gli header API-key, le variabili d’ambiente e l’avviso di insicurezza. Il lavoro è completato quando il sample connette entrambi i transport in modo trasparente senza implementare direttamente la gestione del protocollo.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Is your feature request related to a problem?
Many AI clients (Claude Desktop, Cursor, VS Code, etc.) only support stdio MCP servers configured as local processes. When the actual MCP server runs over Streamable HTTP (e.g. a remote or self-hosted server with API key authentication), users need a lightweight bridge process to proxy messages between the two transports.
Today there is no sample showing this pattern, so developers end up implementing HTTP manually (handling mcp-session-id, SSE parsing, notifications, error mapping, etc.) without knowing the SDK already provides everything needed.
Describe the solution you'd like
Add a samples/StdioToHttpBridge sample showing how to proxy messages transparently between StdioServerTransport and HttpClientTransport using the raw ITransport layer:
using System.CommandLine;
using ModelContextProtocol.Client;
using ModelContextProtocol.Server;
var urlOption = new Option<string>("--url", ["-u"])
{
Description = "MCP server endpoint URL. Env: MCP_URL",
DefaultValueFactory = (_) => Environment.GetEnvironmentVariable("MCP_URL") ?? string.Empty
};
var apiKeyOption = new Option<string>("--api-key", ["-k"])
{
Description = "API key for authentication. Env: MCP_API_KEY",
DefaultValueFactory = (_) => Environment.GetEnvironmentVariable("MCP_API_KEY") ?? string.Empty
};
var insecureOption = new Option<bool>("--insecure", ["-i"])
{
Description = "Disable SSL certificate validation. DANGEROUS: use only in development. Env: MCP_INSECURE",
DefaultValueFactory = (_) => Environment.GetEnvironmentVariable("MCP_INSECURE") is "1" or "true"
};
var rootCommand = new RootCommand("stdio-to-HTTP MCP bridge") { urlOption, apiKeyOption, insecureOption };
rootCommand.SetAction(async action =>
{
var mcpUrl = action.GetValue(urlOption);
var apiKey = action.GetValue(apiKeyOption);
var insecure = action.GetValue(insecureOption);
if (string.IsNullOrWhiteSpace(mcpUrl) || string.IsNullOrWhiteSpace(apiKey))
{
if (string.IsNullOrWhiteSpace(mcpUrl)) Console.Error.WriteLine("Error: --url is required.");
if (string.IsNullOrWhiteSpace(apiKey)) Console.Error.WriteLine("Error: --api-key is required.");
Environment.Exit(1);
}
if (insecure) Console.Error.WriteLine("WARNING: SSL validation is DISABLED");
var handler = insecure
? new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }
: new HttpClientHandler();
var httpTransport = new HttpClientTransport(
new HttpClientTransportOptions
{
Endpoint = new Uri(mcpUrl!),
AdditionalHeaders = new Dictionary<string, string> { ["X-API-Key"] = apiKey! },
TransportMode = HttpTransportMode.StreamableHttp
},
new HttpClient(handler));
await using var remoteTransport = await httpTransport.ConnectAsync();
await using var stdioTransport = new StdioServerTransport("mcp-bridge");
// Proxy stdio → remote
var stdioToRemote = Task.Run(async () =>
{
await foreach (var message in stdioTransport.MessageReader.ReadAllAsync())
await remoteTransport.SendMessageAsync(message);
});
// Proxy remote → stdio
var remoteToStdio = Task.Run(async () =>
{
await foreach (var message in remoteTransport.MessageReader.ReadAllAsync())
await stdioTransport.SendMessageAsync(message);
});
await Task.WhenAny(stdioToRemote, remoteToStdio);
});
return await rootCommand.Parse(args).InvokeAsync();
Why this approach
- Transparent proxy: works at raw
ITransportlevel — all JSON-RPC messages (includinginitialize/initialized) are forwarded as-is, no double handshake - SDK handles complexity:
HttpClientTransportmanagesmcp-session-id, Streamable HTTP protocol, reconnections automatically - Authentication via
AdditionalHeaders: clean way to inject API keys or bearer tokens - Environment variable support:
MCP_URL,MCP_API_KEY,MCP_INSECUREfor container/CI use - Distributable: can be published as
PublishSingleFile=trueself-contained executable
Additional context
This is the pattern we use in cv4pve-admin to let Claude Desktop connect to our self-hosted Proxmox VE MCP server over HTTPS with API key authentication.
- Lingua principale
- C#
- Stelle
- 4.5k
- Fork
- 814
- Merge medio
- 9g 19h
- PR unite (30g)
- 4
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di modelcontextprotocol/csharp-sdk
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
modelcontextprotocol/csharp-sdk#1867 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
modelcontextprotocol/csharp-sdk#1840 · 1 commento ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
modelcontextprotocol/csharp-sdk#1836 ·
-
enhancement needs confirmation
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
modelcontextprotocol/csharp-sdk#678 · 1 commento ·
-
enhancement needs confirmation P3 ready for work
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
modelcontextprotocol/csharp-sdk#515 · 6 commenti · 3 reazioni ·
Tutte le issue di modelcontextprotocol/csharp-sdk
Issue simili
-
untriaged
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
dotnet/dotnet-api-docs#13095 ·
-
area-deployment area-integrations triage:bot-seen
Difficoltà 2/5 Mezza giornata Idoneità per principianti 86/100
-
type/automation type/tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
-
bug
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
newrelic/newrelic-dotnet-agent#3850 · 1 commento ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
LuckyPennySoftware/AutoMapper#4660 ·