Add a Remote MCP Server to LibreChat: librechat.yaml, OAuth and Fixes | MCP Hunter

Add a Remote MCP Server to LibreChat: librechat.yaml, OAuth and Fixes

How to add a remote MCP server to LibreChat: the mcpServers block in librechat.yaml or the Add MCP form, why a missing type means SSE, per-user keys with customUserVars, OAuth sign-in, timeouts, private addresses, and fixing a server that will not connect.

MCP Hunter team 6 min read

An admin adds a remote MCP server to LibreChat as one entry under mcpServers in librechat.yaml [1]:

mcpServers:
  my-server:
    type: streamable-http
    url: https://mcp.example.com/mcp

Restart LibreChat afterwards: servers in librechat.yaml are set up at startup, so a change to the file needs a restart [1]. If your role allows it, you can also add a server from the chat UI under MCP Settings, and it works at once [1][2].

Everything below is checked against LibreChat's documentation on 2 November 2026 [1][2].

TL;DR:

  • Always write type: streamable-http. Without a type, an https:// URL is read as the older SSE transport [1].
  • Each user can bring their own key through customUserVars, entered in the UI and stored per user [1].
  • OAuth works without a client ID: leave it out and LibreChat registers itself with the server [1].
  • timeout is in milliseconds, default 60000. Connecting has its own initTimeout, default 30000 [1].

Add the server in librechat.yaml

A fuller entry, with the fields you are most likely to need [1]:

mcpServers:
  my-server:
    type: streamable-http
    url: https://mcp.example.com/mcp
    headers:
      Authorization: "Bearer ${MY_SERVER_TOKEN}"
      X-User-ID: "{{LIBRECHAT_USER_ID}}"
    timeout: 120000
    serverInstructions: true
Field What it does [1]
type streamable-http (or its alias http), sse, or websocket
url The MCP endpoint; https:// for HTTP transports, wss:// for websocket
headers Sent with every request; takes ${ENV_VAR} and {{LIBRECHAT_USER_*}} placeholders
timeout Milliseconds per request, tool calls included; default 60000
initTimeout Milliseconds to connect; default 30000
serverInstructions true passes the server's own instructions to the model
startup false skips connecting when LibreChat starts
chatMenu false hides it from the chat composer; agents can still use it

${MY_SERVER_TOKEN} comes from the LibreChat server's environment, so the key lives in your .env, not in the YAML [1]. {{LIBRECHAT_USER_ID}} is filled with the signed-in user's ID, which lets the MCP server tell your users apart [1].

Why the type field matters

LibreChat infers the transport when type is missing, and it infers the old one: an http:// or https:// URL becomes sse, a ws:// or wss:// URL becomes websocket [1]. A server that only speaks Streamable HTTP then fails to connect even though the URL is right. Writing type: streamable-http removes the guess.

Let each user bring their own key

When every user has their own account on the MCP server, declare the key as a user variable and put it in a header [1]:

mcpServers:
  my-server:
    type: streamable-http
    url: https://mcp.example.com/mcp
    headers:
      Authorization: "Bearer {{MY_SERVER_API_KEY}}"
    customUserVars:
      MY_SERVER_API_KEY:
        title: "My Server API key"
        description: "Create one under Settings, API keys in My Server"

Each variable needs a title and a description [1]. Users enter the value the first time they connect, can change it later from Configure in the chat composer or in MCP Settings, and it is stored per user and per server [1].

Sign in to a server that needs it

Every oauth subkey is optional. With no client_id and client_secret, LibreChat uses Dynamic Client Registration [1]:

mcpServers:
  my-server:
    type: streamable-http
    url: https://mcp.example.com/mcp
    oauth:
      scope: "read write"

For a server that wants a pre-registered client, add client_id, client_secret, and if needed authorization_url, token_url and redirect_uri [1]. LibreChat detects sign-in on its own; set requiresOAuth: false for a server protected by a fixed Authorization header [1].

What the user sees: a Connect dialog with Continue with OAuth, which opens the server's sign-in page in a new tab. After approving, the server shows Connected [2]. They have 10 minutes to finish unless the admin changes it [2]. Revoke on the server's card in MCP Settings drops the stored tokens [2]. MCP OAuth covers what a server has to publish for the sign-in to work.

Add the server from the UI

In MCP Settings in the side panel, click + ("Add MCP") [2]. The form asks for a name, the MCP Server URL, the transport (Streamable HTTPS or SSE), and how it authenticates: auto-detect, API key or OAuth [2]. Tick "I trust this application" and click Create [2]. The interface.mcpServers setting decides who may create and share servers [2].

A server added this way can only reach a remote URL, and it cannot use the server's environment variables or the user placeholders [2]. Anything that needs ${ENV_VAR} or {{LIBRECHAT_USER_ID}} belongs in librechat.yaml.

To use the tools in a chat, open the composer's + menu, pick the server under MCP Servers, and it shows as a chip on the composer [2]. For an agent, add it from Tools in the Agent Builder [2]. The model has to support tool calls, or it never calls the server [2].

When it will not connect

What you see Usual cause Fix
A known-good server fails to connect No type, so LibreChat spoke SSE Add type: streamable-http
A change to the YAML does nothing The file is read at startup Restart LibreChat [1]
A server on 192.168.x.x or host.docker.internal is refused Private addresses must be allowed explicitly [1] Add it to mcpSettings.allowedAddresses [1]
401 with a ${...} header The variable is not set where LibreChat runs Add it to the server's environment and restart
The server stays on Needs Auth Nobody has signed in yet Click it and finish the OAuth sign-in [2]
A shared API-key server stuck on Needs Auth Stale stored metadata Edit and save the server once [1]
Long tool calls are cut off A reverse proxy's timeout, or timeout Raise the proxy timeout and timeout [1]
The server's tools never get called The model does not support tool calls Switch to a model that does [2]
Two servers, one set of tools missing Names that normalise to the same value Rename one [1]

For what the server's own error codes mean, see MCP server errors and MCP server connection failed.

Check it from outside before you share it

LibreChat calls the server from wherever LibreChat runs, so an address that works from your laptop can still fail from the LibreChat host. Our MCP connection test calls your server from our network, runs the handshake and tools/list, and reports what a stranger on the internet gets back, with a dated URL you can share. If it passes there and fails in LibreChat, look at the YAML and the address rules first.

The same setup in other clients is in OpenCode, Warp, Claude Desktop, ChatGPT, LM Studio, Claude Code, Cursor, VS Code and Cline, and remote MCP server vs stdio covers whether your server should have a public address at all.

Sources

  1. MCP Servers object structure, LibreChat docs
  2. MCP, LibreChat docs