Local connectors¶
For users who run MCP servers on their own computer
Offering the MCP servers installed on your laptop or server to your chat,
without opening a port to the internet. For servers reachable on the web, see
Connectors; for the coding-agent side of galopin, see
Agent computers.
A local connector is an MCP server that
runs on a computer you control (a filesystem server over your notes, a database
tool, a CRM that listens on 127.0.0.1). galopin, the same binary that links
a computer to the Agents panel, dials out to the chat and passes the server's
traffic through, so the assistant can use its tools while the server, its files
and its secrets stay where they are. Nothing on the link adds a server or starts
a command: the computer's own file lists what it offers, and the chat uses that.
Who may use it¶
On a deployment with the Pystino gateway, local connectors are their own per-group
capability, local_connectors (set in the gateway console under Groups, on by default for new
groups; separate from code_agents). A connectors computer needs it, an agent computer needs
code_agents, and the computer's kind is only known at its first message, so it is checked there
and again every minute. Without it the On your computers section of Workspace → Connectors says "Your administrator has not
enabled local connectors for your groups" instead of the how-to, the computer is closed with
4404 and its MCP channels with it, and nothing is revoked: it reconnects by itself once a group
grants the flag. If the gateway reports neither capability because it has no chat configured
(GATEWAY_CHAT__ENABLED unset on a standalone Pystino), the section and the computer say the gateway
is not configured for the chat. Without a gateway nothing changes.
Enroll a connectors-only computer¶
A computer that only serves connectors needs no coding agent, no opencode and no
billing group. Install galopin as for an agent computer,
then enroll with --connectors-only and run it. Sign in to the chat in your
browser once first: Cerea only accepts a computer for an account it has seen, and
until then galopin run is refused with "Sign in to Cerea once before
connecting a computer".
enroll opens your browser to sign in (or prints a link and code for another
device), stores the refresh credential in <config-dir>/galopin/credentials.json
and writes nothing else: no opencode config, no gateway, no policy file. It
records that this is a connectors computer, so a plain galopin run starts no
backend. The computer then appears under
On your computers (Workspace → Connectors), where you approve it
(a connectors computer is never listed in the Agents panel).
A computer that already runs a coding agent needs no second enrollment: it offers
connectors too as soon as it has an mcp.json. To run only the connectors on
such a computer, for one run, use galopin run --connectors-only.
mcp.json¶
Put the file in galopin's config directory, beside credentials.json
(~/.config/galopin/mcp.json on Linux, ~/Library/Application
Support/galopin/mcp.json on macOS). It is the format Claude Desktop and Claude
Code use, so an existing file can be copied as is. To use a file where it
already is instead, point galopin at it:
galopin run --mcp-config /path/to/claude_desktop_config.json (also
galopin connectors list|test|login --mcp-config ..., or the environment
variable GALOPIN_MCP_CONFIG; the flag wins). ~ works, and a relative path is
taken from the directory galopin is started in. The file must exist, and it gets
the same live reload, ${VAR} expansion and per-server checks as the default;
galopin logs which file it uses at start. A Claude Code ~/.claude.json works
too: only its top-level mcpServers is read, everything else in it is ignored,
and a server galopin cannot run is listed as invalid.
{
"mcpServers": {
"notes": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/me/notes"],
"env": { "LOG_LEVEL": "warn" },
"cwd": "/home/me",
"description": "My notes folder",
"allowedTools": ["read_file", "list_directory", "search_files"]
},
"crm": {
"type": "http",
"url": "http://127.0.0.1:9000/mcp",
"headers": { "Authorization": "Bearer ${CRM_TOKEN}" }
},
"old": {
"type": "sse",
"url": "https://tools.example.org/sse",
"disabled": true
}
}
}
| Entry | Meaning |
|---|---|
command, args, env, cwd |
A stdio server: galopin starts the process when the chat opens it and talks newline-delimited JSON-RPC over its stdin and stdout. |
"type": "http" and url |
A server speaking MCP Streamable HTTP ("streamable-http" is accepted too), with the headers you list sent on every request. |
"type": "sse" and url |
A server on the older HTTP+SSE transport. |
${VAR}, ${VAR:-default} |
Expanded in command, args, env, url and headers from galopin's own environment, as Claude Code does. A variable that is unset and has no default makes the entry invalid; the chat is told the variable's name, never a value. |
description |
Shown in the chat's MCP panel. Ignored by Claude. |
disabled: true |
Listed in the chat but not startable. Ignored by Claude. |
allowedTools |
The computer's ceiling, below. Ignored by Claude. |
A server name is letters, digits, - and _ (at most 64, starting with a letter
or digit); another name is listed as invalid. Keys galopin does not know are
ignored, so a file written for Claude works unchanged. galopin re-reads the file
when it changes (checked every few seconds): a server whose entry was removed or
changed has its open channels closed, and a changed one starts afresh the next
time the chat opens it. A file that stops parsing leaves the servers as they
were, and says why in galopin's log.
Check what galopin makes of the file without the chat:
galopin connectors list # name, transport, state, and whether you are signed in
galopin connectors test notes # start it, initialize, list its tools, stop it
What the chat may do: allowedTools¶
When allowedTools is present, it is a ceiling the chat cannot change.
galopin removes every other tool from the server's tools/list answer, and
answers a tools/call for any tool outside the list itself, with the JSON-RPC
error -32001 ("this tool is not allowed on this computer"), without ever
forwarding it. An empty list allows no tool; with no allowedTools key, every
tool the server offers is available. The chat's own per-chat tool
choices work inside this list.
Every tools/call adds one line to audit.log in galopin's config directory:
when, which server, which tool, and the outcome (ok, error, refused).
Never the arguments or the result, which stay between the chat and the server.
Coding agents on the same computer¶
On a computer that also runs coding agents, a session can use its own computer's connectors without going through Cerea: switch them on for the session (the Connectors switches in its Permissions sheet, "on this computer"; see Connectors for an agent). galopin runs the call itself, in-process, with the same ceiling as the chat: allowedTools still applies, a server that needs a sign-in is refused until you sign in, and each call adds its line to audit.log. The call is also a tools call for the session's permissions (Plan refuses it, Ask raises a card, the computer's tools limit caps it). Switching a server on for a session is separate from its Workspace switch for the chat.
Signing in to an http server¶
Secrets for a stdio server belong in its env, which never leaves the computer,
and an http server can be given a token in headers. A server that asks for
OAuth (it answers 401 with a WWW-Authenticate challenge, per the MCP
authorization specification) is listed in the chat as needs login. Sign in
from the chat: its Sign in button sends your browser to the provider and back,
and galopin, not the chat, exchanges the code and keeps the tokens in
<config-dir>/galopin/connectors/NAME.json (mode 0600), refreshing them
automatically. The chat never sees a token.
A provider that accepts only pre-registered redirect addresses cannot be signed in that way. Sign in on the computer instead:
It prints a URL and tries to open a browser; the answer comes back to 127.0.0.1
at a random port, so on a remote computer open the URL somewhere that can reach
that port (for example through an SSH -L forward). Both ways use the standard
authorization-code flow with PKCE, discover the server's authorization server and
register galopin by dynamic client registration when the server offers it (a
server that offers none cannot be signed in to). A sign-in made while galopin runs
takes effect without a restart.
Lifecycle and limits¶
- A stdio server starts when the chat opens it, in its own process group, and stops when the chat closes it, when the link to the chat drops, or after 10 minutes without traffic. galopin asks the kernel to kill it if galopin itself dies. Its standard error goes to galopin's log, never to the chat; the last line of it is in the message when the server fails to start or crashes.
- Each open is a new process (or a new HTTP session): at most 4 channels per server at a time.
- A message over 1 MiB does not cross the link: a request that cannot be forwarded is answered with a JSON-RPC error, anything else is dropped and logged.
- Nothing else on the computer is offered: the chat sees the servers of
mcp.jsonand nothing it did not list.
Running it as a service¶
A connectors computer runs exactly like any galopin: keep galopin run up with
the user service in Keeping it running.
The unit's PATH must include whatever the servers' commands need (npx,
uvx, your own binaries), and any ${VAR} an entry uses must be in the unit's
environment (Environment=CRM_TOKEN=..., or an EnvironmentFile= with mode
0600), because a service does not read your shell profile. Edits to the connectors file
take effect without a restart; a change to the environment needs one
(systemctl --user restart galopin). To use another file, add
--mcp-config /path/to/file.json to the unit's ExecStart= line.
If something is off¶
| In the chat | Why |
|---|---|
| The computer is offline | galopin run is not running, or cannot reach the chat. galopin auth status shows the credential; journalctl --user -u galopin -f its log. |
| The server is invalid | The reason is shown: an unset ${VAR} (its name), an unknown type, a missing command or url, a bad name. |
| The server is needs login | Sign in from the chat, or run galopin connectors login NAME on that computer. |
| Unavailable when the chat opens it | The process could not start or exited at once (the exit status and the last stderr line are in the message), the HTTP server could not be reached, or 4 channels are open already. |
| A tool is missing | It is outside the entry's allowedTools. |
| A tool call fails with "not allowed" (-32001) | The same ceiling; edit allowedTools on the computer. |