# MCP Server Connection Lifecycle in 5ire: Managing stdio, SSE, and HTTP Streaming Transports

> Understand the 5ire MCP server connection lifecycle including stdio, SSE, and HTTP streaming transports. Learn how 5ire manages connections and events for UI sync.

- Repository: [Ironben/5ire](https://github.com/nanbingxyz/5ire)
- Tags: deep-dive
- Published: 2026-03-07

---

**The 5ire application handles the complete MCP server connection lifecycle through a unified state machine that discovers servers from the database, instantiates transport-specific clients, manages retry-aware connections, and emits discrete events for UI synchronization.**

The `MCPConnectionsManager` class in the nanbingxyz/5ire repository orchestrates Model Context Protocol server connections across three transport types: stdio, Server-Sent Events (SSE), and HTTP streaming. According to the source code in [`src/main/services/mcp-connections-manager.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/main/services/mcp-connections-manager.ts), the manager abstracts protocol differences behind a consistent interface while maintaining transport-specific optimizations for process spawning, stream handling, and connection teardown.

## Discovery and Initialization via Live Query

The lifecycle begins when `MCPConnectionsManager.init()` queries the database for all active MCP server records. This method, located at lines 420–432 in [`src/main/services/mcp-connections-manager.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/main/services/mcp-connections-manager.ts), establishes a live-query subscription that watches for inserts, updates, and deletes in real time.

Each database change triggers an automatic connect or disconnect operation. The server records include a `transport` field specifying either `"stdio"`, `"sse"`, or `"http"`, which determines the subsequent transport instantiation strategy. This reactive architecture ensures the application state remains synchronized with the database without requiring manual refresh cycles.

## Transport Creation and Protocol Abstraction

The private `#transport` method (lines 71–96) creates transport objects based on the server configuration. This abstraction layer allows the rest of the lifecycle to remain transport-agnostic.

**stdio transports** split the `endpoint` string into command and arguments, then instantiate `StdioClientTransport` from the MCP SDK:

```typescript
const args = server.endpoint.split(" ").filter(Boolean);
const command = args.shift()!;
const transport = new StdioClientTransport({
  command,
  args,
  env: server.config,
  stderr: "ignore",
});

```

**SSE and HTTP streaming transports** both use `StreamableHTTPClientTransport`, a unified class that handles both Server-Sent Events and plain HTTP streaming protocols. The endpoint is parsed as a URL and passed to the transport constructor:

```typescript
const url = new URL(server.endpoint);
const transport = new StreamableHTTPClientTransport(url, {
  requestInit: { headers: server.config },
});

```

This design eliminates the need for separate `SSEClientTransport` logic, consolidating streaming HTTP handling into a single implementation.

## Connection Establishment with Retry Logic

The `#connect` method (lines 103–193) implements the core connection handshake. It instantiates a `Client` with static implementation info (`CLIENT_IMPLEMENTATION`) and capabilities (`CLIENT_CAPABILITIES`), then attempts to connect using the previously created transport.

Connection attempts execute within a retry loop configured for maximum three attempts with exponential backoff via `setTimeout`. An `AbortController` provides cancellation semantics for in-flight connection attempts:

```typescript
const client = new Client({ name: "5ire", version: "1.0" });
await client.connect(transport, {});

```

If the server returns valid capabilities, the manager stores a `connected` state object. Failed attempts record error states and close the client to prevent resource leaks.

## State Management and Event Emission

The manager maintains connection state in a `Map<string, Connection>` where each entry tracks one of three statuses defined in the `MCPConnectionsManager.Connection` type (lines 66–88): `connecting`, `connected`, or `error`. State updates flow through the `Stateful` base class using the `update` method.

State transitions trigger specific events that UI components consume:

- **`server-connected`** (lines 165–168): Emitted when capability negotiation succeeds
- **`server-disconnected`** (lines 216–218): Emitted when a server is removed or explicitly disconnected

Listeners react to these high-level events without needing knowledge of the underlying transport implementation. This decoupling allows the frontend to display connection status consistently regardless of whether the backend uses stdio processes or HTTP streams.

## Graceful Disconnection and Resource Cleanup

The `#disconnect` method handles teardown through two pathways depending on connection status. For established connections, it invokes `client.close()`, which delegates to the transport-specific shutdown logic—terminating stdio processes or canceling HTTP streams. For connections still in the `connecting` phase, it aborts the pending attempt via the `AbortController`.

After cleanup, the manager removes the entry from the internal state map and emits the disconnection event, completing the lifecycle.

## Summary

- **Discovery**: `init()` queries active servers and subscribes to live database changes at startup
- **Transport selection**: The `#transport` method creates `StdioClientTransport` for local processes or `StreamableHTTPClientTransport` for SSE/HTTP endpoints (lines 71–96)
- **Resilient connections**: The `#connect` method implements 3-attempt retry logic with exponential backoff and abort capabilities (lines 103–193)
- **Unified state**: Three statuses (`connecting`, `connected`, `error`) managed through the `Stateful` base class
- **Event-driven architecture**: `server-connected` and `server-disconnected` events abstract transport details from UI components

## Frequently Asked Questions

### How does 5ire handle different MCP transport types internally?

The `MCPConnectionsManager` inspects the `transport` field in each server record. For stdio connections, it splits the endpoint into command arguments and creates a `StdioClientTransport`. For SSE and HTTP streaming, it parses the endpoint as a URL and instantiates `StreamableHTTPClientTransport`, which handles both protocols through a single implementation.

### What happens when an MCP server connection fails?

The connection routine in `#connect` implements a retry loop with a maximum of three attempts and exponential backoff. If all retries exhaust without receiving server capabilities, the manager closes the client, records an `error` state in the connection map, and prevents further connection attempts until the next database update triggers a fresh cycle.

### How does the application know when to connect or disconnect an MCP server?

The manager subscribes to a Supabase live query during initialization that monitors the MCP servers table. Insertions trigger automatic connection attempts, updates trigger reconnection cycles, and deletions trigger disconnection and cleanup. This reactive pattern ensures the connection state always reflects the current database configuration.

### What's the difference between SSE and HTTP streaming in 5ire's implementation?

There is no functional difference in the connection lifecycle. Both transport types use the same `StreamableHTTPClientTransport` class from the MCP SDK, which automatically negotiates the appropriate streaming mechanism based on server capabilities. The manager treats SSE and HTTP streaming as identical HTTP-based transports, eliminating the need for separate handling logic.