MCP
Model Context Protocol servers extend the agent with tools it doesn't have built in - a private wiki, a database, a browser that holds a login, an internal API.
Jan Agent reads the same mcp_config.json as Jan Desktop, so servers you configured in the app are
available in the terminal with nothing further to do. For what MCP is and how to add servers, see
Model Context Protocol.
At startup
Active servers connect in the background while the console opens, and announce themselves:
MCP ready: sequential-thinking, serper
A server that fails to come up says so in the transcript, with the reason:
MCP: failed to connect to 'fetch': connection closed: initialize response
The first turn waits for the connecting servers, so the model sees the full toolset rather than a half-connected one. A slow stdio server delays that first turn, not the whole session.
Managing servers
In the console
/mcp
Lists every configured server with its state. Space toggles the highlighted one; turning one on connects it in the background and the tools appear once it lands. Enter opens the server's detail screen (see below).
While the list is open you can also manage it:
- a opens an add form (
name, transport, then the transport-specific fields) - e edits the highlighted server, prefilled
- d removes the highlighted server after writing it out
The list opens even with nothing configured, so a is reachable on a fresh install.
Inside the form, arrow keys (or Tab) move between fields. k and j type as ordinary characters - URLs, paths, and header values contain them - so they no longer steer between fields as they did in earlier releases.
A newly added server defaults to inactive, so it is persisted but not connected until you toggle it on.
The change is written back to mcp_config.json, so it persists - and applies to Jan Desktop too.
The server detail screen
Enter on a row opens that server on its own screen: transport, endpoint or command, the
mcp_config.json path it came from, connection state, authentication state, the tool count, and the
name and version the server reported when it connected. Everything there is read from local state,
so it opens immediately; only the tool listing is a round trip and it fills in when it lands.
The actions below the info block are filtered to what the server can actually do - no sign-in rows
for a stdio server, no View tools while it is disconnected, no Reconnect while it is disabled:
View toolsprints the tool names into the conversation, where they scroll and persistAuthenticate/Re-authenticateruns the OAuth flow (see below)Clear authenticationforgets the stored tokens and drops the connection, which still holds the old one. The server stays enabled, so signing back in brings it up againReconnect,Enable/Disable,Edit configuration,Remove server
Esc steps back to the list rather than out of /mcp.
Signing in to a remote server
Remote (http / sse) servers that require OAuth are handled for you: Jan discovers the provider's
metadata, registers itself dynamically, and runs the authorization-code flow with PKCE against a
loopback redirect. Authenticate prints the consent URL into the conversation before it starts
waiting, and opens it in your browser - so a remote or headless session can still finish the sign-in
by opening the URL by hand. The wait times out after five minutes.
A server that fails to connect purely for want of a sign-in says so, rather than reporting a transport error: Jan asks the server whether it advertises OAuth instead of guessing from the failure.
Tokens are written to mcp_oauth.json, next to mcp_config.json in the Jan data folder, with
0600 permissions:
- not in
mcp_config.json, which is hand-edited, copied between machines and shared with Jan Desktop; bearer tokens have no business travelling with it - Access tokens are refreshed automatically, a minute before they expire, when the provider issued a refresh token
- Changing a server's
urlinvalidates its stored tokens rather than silently sending credentials issued for a different resource - Removing a server clears its tokens too, so a later server reusing the name does not inherit the authorization
If you set an Authorization header by hand, that wins: OAuth is never attempted and never reported
as missing, because wrapping it would put two credentials on one request.
From the command line
Add, list, edit, remove, and toggle servers headlessly with jan cli mcp ... - jan cli mcp add files --command npx --arg -y --arg my-mcp, jan cli mcp list, jan cli mcp remove files. See the
CLI reference.
Tool policy
MCP tools follow the project's [tools] policy:
default | Effect on MCP tools |
|---|---|
read-only | Available. The default |
deny | Locked down, except anything in allow |
allow | Available, except anything in deny |
[tools]default = "deny"allow = ["sequential-thinking"]
That exposes one server's tools and nothing else - useful for a project where you want reasoning help but no outside network access.
Choosing a model
Not every model is good at tool calling, and some can't do it at all. If MCP tools are connected but
never used, try a different model before debugging the server - /model switches without leaving
the session.