Class BowireForwardingMcpTransport
- Namespace
- Kuestenlogik.Bowire.Mcp
- Assembly
- Kuestenlogik.Bowire.Mcp.dll
MCP-over-MCP forwarder (#286). Wraps an outbound ModelContextProtocol.Client.McpClient connected to a parent Bowire process's MCP endpoint so an incoming JSON-RPC request handled by this server is marshalled to the parent verbatim and the parent's response is relayed back to the caller.
public sealed class BowireForwardingMcpTransport : IAsyncDisposable
- Inheritance
-
BowireForwardingMcpTransport
- Implements
- Inherited Members
Remarks
Use case: a remote LLM agent talks to a thin Bowire process (e.g. on a
CI runner or in a container) that delegates the actual work to a heavier
Bowire running on the operator's workstation. bowire mcp serve
--attach <parent-addr> boots the server in forwarder mode —
no tools registered locally, every incoming MCP request is forwarded
to the parent.
The connection to the parent is established lazily on the first handler call so a child can boot even when the parent isn't reachable yet (e.g. the parent starts a moment later). Failures surface as MCP errors back to the child's caller; the connection is retried on the next handler call.
Lifecycle: DisposeAsync() closes the parent ModelContextProtocol.Client.McpClient + its transport so a graceful child shutdown (SIGTERM, Ctrl+C, host stop) doesn't leak the upstream connection.
Constructors
BowireForwardingMcpTransport(Uri, string?)
Build a forwarder targeting the given parent MCP endpoint URI.
public BowireForwardingMcpTransport(Uri parentEndpoint, string? bearerToken = null)
Parameters
parentEndpointUriHTTP(S) URI of the parent Bowire MCP endpoint (e.g.
http://localhost:5198/bowire/mcp).bearerTokenstringOptional bearer token to attach to every request to the parent (
Authorization: Bearer <secret>). Required when the parent was started with--token <secret>; ignored when the parent has no token configured.
Properties
HasBearerToken
Whether a bearer token was supplied at construction. Exposed for diagnostics — doesn't surface the token itself.
public bool HasBearerToken { get; }
Property Value
ParentEndpoint
The endpoint this forwarder was configured against. Exposed for diagnostics (the CLI banner, tests).
public Uri ParentEndpoint { get; }
Property Value
- Uri
Methods
DisposeAsync()
public ValueTask DisposeAsync()
Returns
GetClientAsync(CancellationToken)
Lazily establish + return the underlying MCP client. Repeated callers share the same client; if a previous call left the client in a faulted state the caller can call ResetAsync() before retrying. Thread-safe via an init semaphore.
public Task<McpClient> GetClientAsync(CancellationToken ct)
Parameters
Returns
- Task<McpClient>
ResetAsync()
Tear down the current client + transport so the next GetClientAsync(CancellationToken) call rebuilds them. Useful after a connection error so a transient parent restart doesn't sink the child for its remaining lifetime.
public Task ResetAsync()
Returns
TryParseAttachEndpoint(string?, out Uri?, out string)
Parse the documented --attach argument shapes into a
concrete parent MCP endpoint URI. Accepts:
host:port— expanded tohttp://host:port/bowire/mcp(the path Bowire's HTTP-bind serves MCP at).- An absolute
http(s)URI — used as-is.
Returns false + a human-readable reason for malformed input;
the caller surfaces the message to the operator.
public static bool TryParseAttachEndpoint(string? raw, out Uri? endpoint, out string error)