Connecting Remote MCP Servers to Flue Agents with Authentication

Use the connectMcpServer helper from @flue/sdk/client to establish authenticated connections to remote Model Context Protocol (MCP) servers, passing bearer tokens via the headers option and injecting discovered tools into your agent harness through init({ tools }).

Flue agents extend their capabilities by consuming tools hosted on remote MCP servers. According to the withastro/flue source code, the SDK provides a dedicated connection helper that handles transport negotiation, header injection, and tool discovery, enabling secure authenticated integrations with external tool providers.

How the Flue SDK Handles MCP Authentication

The authentication flow centers on the McpServerOptions interface defined in packages/sdk/src/mcp.ts (lines 8‑14). This configuration object accepts a headers field that allows you to inject any HTTP headers—including Authorization bearer tokens—into every request sent to the remote MCP server.

Header Injection and Merging

When you provide custom headers, the SDK merges them with any existing requestInit configuration using the internal mergeRequestInit utility (lines 13‑22 in packages/sdk/src/mcp.ts). This ensures your authentication tokens take precedence while preserving additional fetch options you might specify.

// From mcp.ts - merges headers ensuring auth tokens are preserved
const mergedInit = mergeRequestInit(
  { headers: { Authorization: `Bearer ${env.TOKEN}` } },
  userProvidedInit
);

The connectMcpServer function (lines 25‑55) then uses these merged options to build the transport layer, negotiate the connection, and return a McpServerConnection object containing the discovered tools.

Step-by-Step Implementation

1. Configure the Connection with Environment Variables

Never hardcode secrets. Instead, access tokens through the env object available in your Flue agent function. Call connectMcpServer with a descriptive name and the remote URL:

// .flue/agents/github-assist.ts
import { connectMcpServer } from '@flue/sdk/client';

const github = await connectMcpServer('github', {
  url: 'https://mcp.github.com/mcp',
  headers: {
    Authorization: `Bearer ${env.GITHUB_TOKEN}`, // Securely injected
  },
});

2. Initialize the Harness with Remote Tools

The connection object exposes a tools array containing the remote MCP tools formatted for Flue's harness system. Pass these to the init function alongside your model configuration:

const harness = await init({
  model: 'anthropic/claude-sonnet-4-6',
  tools: github.tools, // Remote tools become available to the LLM
});

3. Cleanup Resources After Execution

Remote connections hold active HTTP sessions and SSE streams. Always close the connection in a finally block to prevent resource leaks:

try {
  const session = await harness.session();
  return await session.prompt(payload.prompt);
} finally {
  await github.close(); // Releases underlying client resources
}

Transport Protocol Options

Streamable HTTP (Default)

The modern streamable‑http transport is the default in Flue. It uses standard HTTP requests with streaming response bodies for efficient bidirectional communication. This mode works automatically when you omit the transport option or set it explicitly to 'streamable-http'.

Legacy SSE Mode

For older MCP servers that require Server-Sent Events, force the transport by setting transport: 'sse' in your options:

const legacy = await connectMcpServer('legacy-server', {
  url: 'https://old-mcp.example.com/sse',
  transport: 'sse',
  headers: { Authorization: `Bearer ${env.TOKEN}` },
});

Advanced Configuration

Pass additional fetch parameters through the requestInit option. These are merged with your authentication headers via the internal mergeRequestInit logic:

const github = await connectMcpServer('github', {
  url: 'https://mcp.github.com/mcp',
  headers: { Authorization: `Bearer ${env.GITHUB_TOKEN}` },
  requestInit: { 
    mode: 'cors',
    cache: 'no-store' 
  },
});

Complete Working Example

Here is the canonical implementation from the withastro/flue repository demonstrating secure authentication and proper resource management:

// .flue/agents/github-assist.ts
import { connectMcpServer, type FlueContext } from '@flue/sdk/client';

export const triggers = { webhook: true };

export default async function ({ init, payload, env }: FlueContext) {
  // Establish authenticated connection
  const github = await connectMcpServer('github', {
    url: 'https://mcp.github.com/mcp',
    headers: {
      Authorization: `Bearer ${env.GITHUB_TOKEN}`,
    },
  });

  try {
    // Initialize harness with remote tools
    const harness = await init({
      model: 'anthropic/claude-sonnet-4-6',
      tools: github.tools,
    });

    // Execute agent logic
    const session = await harness.session();
    return await session.prompt(payload.prompt);
  } finally {
    // Critical: Release connection resources
    await github.close();
  }
}

Key Source Files

  • packages/sdk/src/mcp.ts – Core implementation of connectMcpServer, transport selection, and the mergeRequestInit utility (lines 8‑55).
  • packages/sdk/src/client.ts – Public API surface that re‑exports connectMcpServer for convenient importing (lines 59‑62).
  • README.md – Canonical usage examples in the "Remote MCP Tools" section (lines 93‑124).

Summary

  • connectMcpServer handles transport negotiation, authentication header injection, and tool discovery in a single async call.
  • Authentication tokens pass securely through the headers field of McpServerOptions, merged via mergeRequestInit to preserve precedence.
  • Remote tools integrate seamlessly into the Flue harness by passing the tools array from the connection to init({ tools }).
  • Resource management requires explicit close() calls to terminate underlying HTTP clients and SSE connections.
  • Environment variables (env) provide the secure mechanism for accessing secrets without exposing them in code.

Frequently Asked Questions

How do I securely store authentication tokens for MCP servers?

Store sensitive tokens as environment variables in your Flue project configuration. The env object injected into every agent function provides secure runtime access to these values. Never commit credentials to your repository or hardcode them in agent files.

What transport protocols does Flue support for MCP connections?

Flue supports streamable-http (modern default) and sse (legacy Server-Sent Events). The SDK automatically negotiates the appropriate transport unless you explicitly override it via the transport option in McpServerOptions.

Can I combine remote MCP tools with local custom tools?

Yes. The tools array accepted by init() accepts any combination of remote tools (from connectMcpServer) and local tool definitions. You can merge multiple remote connections and local implementations into a single tools array passed to the harness.

How do I handle connection errors and retries?

Wrap connectMcpServer calls in try-catch blocks to handle network failures. The underlying MCP client throws descriptive errors for connection timeouts, authentication failures (401/403), and transport negotiation issues. Implement retry logic around the initial connection call if your use case requires high availability.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →