Summary
LibreChat is the chat client we recommend for having an agent work on Linkr: open source, multi-user, and able to use a model hosted in your institution. It is installed next to Linkr and connected to its MCP server through one file, librechat.yaml. The address that goes in it depends on how the two run — under Docker or not —: this page gives the setup for each case.
Why LibreChat
Linkr does not host a chat: an agent runs in an external client, which holds the conversation, picks the model and asks for your approval before acting, and which acts on Linkr through the MCP server. Any MCP-compatible client works. We recommend LibreChat for use in an institution:
- Open source and self-hosted — it runs on your machines, and can use local models only: nothing leaves the institution.
- Multi-user — everyone signs in with their own account and gives Linkr their own API key: the agent acts as them, with their rights, never more.
- Configurable confirmation — the administrator decides which tools run straight away and which wait for your approval.
LibreChat is used in a tab next to Linkr. Every change the agent makes shows up in Linkr before your eyes, in the Notifications bell.
It needs an install with a backend
The MCP server acts on Linkr through its API: it only works with a Docker or manual install, not in client-only mode. The details are in Deployment modes.
Choosing your setup
Only one thing changes from one case to another: the address LibreChat uses to reach Linkr’s MCP server. Find your case, then pick the matching tab at each step — they stay in sync across the whole page.
| Linkr | LibreChat | MCP server address |
|---|---|---|
| Docker | Docker, same machine | http://linkr-mcp:3940/mcp |
| Manual install | Docker, same machine | http://host.docker.internal:3940/mcp |
| Docker or manual install | Without Docker, same machine | http://127.0.0.1:3940/mcp |
| On a server | On another machine | an https:// address, see below |
Why three addresses: inside a Docker container, 127.0.0.1 means the container itself, not your machine. Two containers reach each other through a shared Docker network; a container reaches your machine by the name host.docker.internal.
Installation
Start Linkr and its MCP server
Linkr must be running before LibreChat, with its MCP server — on port 3940.
The docker-compose.hub.yml file starts the MCP server with the rest of Linkr, as an mcp service. For LibreChat to reach it, both must share a Docker network. Create it once:
docker network create linkr-agentsThen, in docker-compose.hub.yml, attach the mcp service to that network under the name linkr-mcp, and declare the network at the end of the file:
mcp:
# … existing lines unchanged: image, ports, environment …
networks:
default:
linkr-agents:
aliases: [linkr-mcp]
networks:
linkr-agents:
external: trueThe default: line keeps the service on Linkr’s own network, through which it reaches the API. Restart Linkr: docker compose -f docker-compose.hub.yml up -d.
npm run dev:all starts the MCP server with the rest of Linkr. By default it only listens on 127.0.0.1 — the inside of your machine —, which a container cannot reach. Open it up by adding this line to packages/linkr-mcp/.env (create the file if it does not exist):
LINKR_MCP_HOST=0.0.0.0Restart npm run dev:all.
Port 3940 becomes reachable from your network
With 0.0.0.0, the MCP server also accepts connections from other machines, and API keys travel over it in cleartext. Keep this setting for a workstation behind a firewall, never for an exposed machine.
Nothing to change on the Linkr side: with Docker as with the manual install, the MCP server listens on http://127.0.0.1:3940/mcp, which LibreChat reaches directly since it runs on the same machine.
Install LibreChat
You need Git and Docker. In a separate folder, outside Linkr’s:
git clone https://github.com/LibreChat-AI/LibreChat.git
cd LibreChat
cp .env.example .env
cp librechat.example.yaml librechat.yamlThe .env file configures LibreChat itself; librechat.yaml will receive Linkr’s configuration in the next step.
You need Git and Docker. In a separate folder, outside Linkr’s:
git clone https://github.com/LibreChat-AI/LibreChat.git
cd LibreChat
cp .env.example .env
cp librechat.example.yaml librechat.yamlThe .env file configures LibreChat itself; librechat.yaml will receive Linkr’s configuration in the next step.
You need Git, Node.js 24 and a MongoDB database, which LibreChat uses for its accounts and conversations. LibreChat’s install guide without Docker covers installing MongoDB. Then:
git clone https://github.com/LibreChat-AI/LibreChat.git
cd LibreChat
cp .env.example .env
cp librechat.example.yaml librechat.yaml
npm run reinstallIn .env, set MONGO_URI to your MongoDB database’s address.
Port 3000 is already Linkr's
LibreChat’s Docker install also starts an admin panel, published by default on port 3000 — Linkr’s. In LibreChat’s .env file, uncomment the ADMIN_PANEL_PORT line and give it another port, for example ADMIN_PANEL_PORT=3090. That panel also needs a value for ADMIN_PANEL_SESSION_SECRET, which openssl rand -hex 32 generates.
Declare Linkr in librechat.yaml
Open librechat.yaml and add the two blocks below, at the top level of the file. If they already exist, complete them rather than duplicating them.
mcpSettings:
allowedAddresses:
- "linkr-mcp:3940"
mcpServers:
linkr:
type: streamable-http
url: http://linkr-mcp:3940/mcp
headers:
Authorization: "Bearer {{LINKR_API_KEY}}"
customUserVars:
LINKR_API_KEY:
title: "Linkr API key"
description: "In Linkr: User settings → API keys"
sensitive: true
requiresOAuth: false
serverInstructions: true
timeout: 300000 mcpSettings:
allowedAddresses:
- "host.docker.internal:3940"
mcpServers:
linkr:
type: streamable-http
url: http://host.docker.internal:3940/mcp
headers:
Authorization: "Bearer {{LINKR_API_KEY}}"
customUserVars:
LINKR_API_KEY:
title: "Linkr API key"
description: "In Linkr: User settings → API keys"
sensitive: true
requiresOAuth: false
serverInstructions: true
timeout: 300000 mcpSettings:
allowedAddresses:
- "127.0.0.1:3940"
mcpServers:
linkr:
type: streamable-http
url: http://127.0.0.1:3940/mcp
headers:
Authorization: "Bearer {{LINKR_API_KEY}}"
customUserVars:
LINKR_API_KEY:
title: "Linkr API key"
description: "In Linkr: User settings → API keys"
sensitive: true
requiresOAuth: false
serverInstructions: true
timeout: 300000 What each line does:
allowedAddresses— by default LibreChat refuses to contact a private address, a protection against requests diverted to the internal network. This line allows Linkr’s MCP server, and only it.{{LINKR_API_KEY}}andcustomUserVars— the key is not written in the file: LibreChat asks each user for it, and sends it to Linkr with every request.sensitivemasks it while typing.requiresOAuth: false— at startup, before any key has been entered, Linkr answers “unauthorized”. Without this line, LibreChat wrongly concludes the server expects an OAuth sign-in.serverInstructions— passes Linkr’s own introduction of its tools on to the model.timeout— five minutes, in milliseconds: a cohort or a script can take a while on a large warehouse.
allowedAddresses, not allowedDomains
LibreChat also knows mcpSettings.allowedDomains. That key works, but it turns the list into an exclusive list: any MCP server not on it is then blocked. allowedAddresses opens access to Linkr’s server alone, without touching anything else.
Choose a model
LibreChat needs at least one language model. For health data we very strongly recommend a model hosted in the institution — the Agents page explains why. With Ollama on the same machine, add to librechat.yaml:
endpoints:
allowedAddresses:
- "host.docker.internal:11434"
custom:
- name: "Ollama"
apiKey: "ollama"
baseURL: "http://host.docker.internal:11434/v1/"
models:
default: ["gpt-oss:20b"]
fetch: true
titleConvo: false
modelDisplayLabel: "Ollama" endpoints:
allowedAddresses:
- "host.docker.internal:11434"
custom:
- name: "Ollama"
apiKey: "ollama"
baseURL: "http://host.docker.internal:11434/v1/"
models:
default: ["gpt-oss:20b"]
fetch: true
titleConvo: false
modelDisplayLabel: "Ollama" endpoints:
allowedAddresses:
- "127.0.0.1:11434"
custom:
- name: "Ollama"
apiKey: "ollama"
baseURL: "http://127.0.0.1:11434/v1/"
models:
default: ["gpt-oss:20b"]
fetch: true
titleConvo: false
modelDisplayLabel: "Ollama" fetch: true lists every model installed in Ollama; default is the one offered first. The model must be able to call tools — gpt-oss, Qwen and Mistral can, not every model does. A vLLM server or any other OpenAI-compatible service is declared the same way, with its address. LibreChat’s documentation lists the other providers.
A remote model sees what the agent reads
Linkr does not filter what its tools send back to the model: query results, concept names, script contents. With a model run by an external provider, stick to open or synthetic data — MIMIC-IV Demo, an ATHENA vocabulary —, never real patient data.
Set up tool confirmation
By default, LibreChat runs tools without asking anything. To have it wait for your approval before any change, add under endpoints, next to custom:
endpoints:
agents:
recursionLimit: 60
toolApproval:
enabled: true
mode: default
allow:
- "get_*_mcp_linkr"
- "list_*_mcp_linkr"
- "describe_*_mcp_linkr"
- "search_*_mcp_linkr"
- "read_*_mcp_linkr"
- "preview_*_mcp_linkr"
- "run_sql_mcp_linkr"
- "find_linkr_tools_mcp_linkr"
- "run_linkr_read_tool_mcp_linkr"LibreChat names each tool <tool>_mcp_<server>. The tools in the allow list only read — list projects, describe a database, search for a concept, run a read-only query — and run without a question. All the others — create a cohort, add a widget, run code — wait for your approval, which LibreChat asks for in the conversation.
Less common tools go through three gateway tools: run_linkr_read_tool, run_linkr_write_tool and run_linkr_delete_tool, one per kind of action. Only the first is in allow: a change or a deletion always asks for your approval, even that way.
recursionLimit sets how many steps an agent can chain for a single reply; the default, 25, is quickly reached when a task takes several dozen tool calls.
Start LibreChat
Create a docker-compose.override.yml file in LibreChat’s folder, which Docker reads on top of LibreChat’s own file. It mounts librechat.yaml into the container and attaches it to Linkr’s network:
services:
api:
volumes:
- type: bind
source: ./librechat.yaml
target: /app/librechat.yaml
networks:
- default
- linkr-agents
networks:
linkr-agents:
external: trueThen start LibreChat:
docker compose up -d Create a docker-compose.override.yml file in LibreChat’s folder, which Docker reads on top of LibreChat’s own file. It mounts librechat.yaml into the container:
services:
api:
volumes:
- type: bind
source: ./librechat.yaml
target: /app/librechat.yamlThen start LibreChat:
docker compose up -d LibreChat reads librechat.yaml at the root of its folder. Start it:
npm run backend Open http://localhost:3080 and create an account: the first account created becomes LibreChat’s administrator. After any change to librechat.yaml, restart LibreChat — docker compose restart api under Docker — for it to take effect.
Give your API key
Each user does this step once, with their own account:
- In Linkr, create a key: your account menu → User settings → API keys tab → New API key. Copy it right away, it is shown only once. The details are in MCP server.
- In LibreChat, open the MCP Servers menu, below the input box, and click the settings icon next to
linkr: the Configure Variables for linkr window opens. Paste the key and save.
It is connected
Select linkr in the MCP Servers menu and ask: “Which Linkr projects can I open?”. The agent calls the tool that lists your projects and answers. Then ask for a change — “create a cohort of patients over 65 in this project” —: LibreChat asks for your approval, then the cohort appears in Linkr and in its Notifications bell.
Linkr and LibreChat on two machines
In an institution, LibreChat often runs on its own server, next to other tools. Linkr’s MCP server then only listens on its own machine — on purpose: API keys travel over it in plain HTTP, so in cleartext.
To open it to LibreChat, put a TLS terminator in front of it — the institution’s reverse proxy, nginx, Caddy… — that publishes it over https://, for example https://linkr-mcp.my-hospital.org/mcp. In librechat.yaml, put that address in url. If that name resolves to an internal network address, add it to allowedAddresses as well, with its port: "linkr-mcp.my-hospital.org:443".
The rest of the setup is unchanged. Production install describes deploying Linkr on a server.
Troubleshooting
LibreChat shows “Connection attempt to the provided MCP server failed”. Check in order: that Linkr and its MCP server are running; that the url address matches your case, in the table above; that the same address, with its port, is in mcpSettings.allowedAddresses; and that LibreChat has been restarted since.
LibreChat offers an OAuth sign-in instead of asking for the key. The requiresOAuth: false line is missing under linkr. Add it, then restart LibreChat.
Tools fail with “unauthorized”. The key entered has expired, been revoked, or was copied wrong. Create a new one in Linkr and enter it again in Configure Variables for linkr.
Linkr no longer answers on port 3000 since LibreChat was installed. LibreChat’s admin panel is holding it. Change ADMIN_PANEL_PORT in LibreChat’s .env, see the “Install LibreChat” step.
Under Docker, network linkr-agents declared as external, but could not be found. The shared network does not exist yet: docker network create linkr-agents, then start again.
The model never calls the tools. Check that linkr is selected in the conversation’s MCP Servers menu, and that the chosen model can call tools. A small model can also get lost: try the same request with a larger one.
After a Linkr update, new tools do not show up. LibreChat keeps the tool list it got when it connected. Reinitialise the linkr server in LibreChat; if you use a LibreChat agent, also tick the new tools in its configuration.
Going further
- Agents — what an agent can do in Linkr, and how you stay in control.
- MCP server — API keys, the server’s settings, and OpenCode as another client.
- Skills — installing the concept-mapping skill in LibreChat.
- LibreChat documentation — every
mcpServersoption.