An MCP server is a remote server that the owner adds in Connections. Each tool on it that the owner approves becomes a Permission. The permission gives apps one function and gives Chat one agent tool. You do not need a new desktop build for this. Redac connects only to remote servers with Streamable HTTP. It does not run local (stdio) servers.
The owner adds a server, signs in and approves the tools. An app or Chat cannot add a server, and an app ZIP cannot bring a server.
Names of one tool
The server name is the name in the form, else the server's own name (only for a
server with no sign-in), else the host of the address. For example "Linear".
Redac makes a slug from the name: lower case a-z and 0-9 only, at most
24 characters, and it starts with a letter. If the slug is in use, Redac adds
2, 3 and so on. Redac makes a tool id from the tool name: the words
join in camel case, for example list_issues becomes listIssues. A tool id has at most 32 characters.
One approved tool has four names:
| Name | Form | Example |
|---|---|---|
| Connection type | mcp-<slug> | mcp-linear |
| Permission | mcp-<slug>.<toolId> | mcp-linear.listIssues |
| Function entry | mcp.<slug>.<toolId> | mcp.linear.listIssues |
| Agent tool | mcp_<slug>_<toolId> | mcp_linear_listIssues |
The names map one to one. Put the permission in the manifest actions. Call
the function entry with cap.call. Chat sees the agent tool.
A permission is read only when the server marks the tool readOnlyHint: true. All other tools are write. The label of the permission is the tool
title, else its name.
Connections
Each server is one connection type in Connections › Accounts.
| Sign-in | Connection id | Connection name |
|---|---|---|
| None | mcp-<slug>:local | "This computer" for a loopback server, else "Server" |
| Browser sign-in | mcp-<slug>:<account id> | Account 1, Account 2 … |
| Token | mcp-<slug>:<account id> | Token, then Token 2 … |
MCP gives no account identity, so Redac names the accounts with numbers. For a server with sign-in, the owner can select Add another account. Each account is one more connection. Accounts keeps at most 100 accounts in total, for all providers. Thus servers with Browser sign-in or a token reach that limit before the limit of 256 servers.
Use a function in an app
-
Declare each permission in
manifest.json:{ "actions": ["mcp-linear.listIssues", "mcp-linear.createComment"] }The manifest can name an MCP permission before the server is on this computer. The install review then shows Not available on this computer and "Add the Linear MCP server in Connections to use them." The install continues.
-
Call the function entry. Every MCP function has the same arguments:
const result = await client.cap.call('mcp.linear.listIssues', { arguments: { team: 'ENG' }, });argumentsis the tool input. Redac checks it against the approved input schema, but not against its regular expressions (pattern,patternPropertiesandpropertyNames): the server checks them.connectionis optional: a connection id or a connection name. When you do not give it, Access uses the default connection. A tool input field namedconnectioncannot collide, because the tool input is underarguments. -
The owner gives access in the app's Access tab. An app starts at Off for each MCP permission. At install, the owner can keep the connection on. Then the declared permissions of a server that is on this computer start at Ask.
Use resources.list({ action: 'mcp-linear.listIssues' }) to find the
connections with Allow. Each function is a read for a read tool and a mutate
for a write tool. A write call has no request key. Do not retry a write
automatically: the server can have done the change before a failure.
The result:
{
content: Block[]; // at most 256 blocks
structured?: object; // the tool's structured content, when it sends it
isError: false;
}
A block is one of:
{ type: 'text', text }{ type: 'image', data, mimeType }or{ type: 'audio', data, mimeType }(base64 data){ type: 'resource_link', uri, name }
An embedded resource becomes its text. A binary resource becomes a text note.
A tool error (isError: true from the server) fails the call with
unavailable, and the message is the tool's text.
Chat
Chat gets the permissions of a new server at once. Read permissions start at Allow and write permissions at Ask. The owner changes them in Settings › Chat. A call at Ask shows one approval card.
Chat sees each approved tool as its own agent tool mcp_<slug>_<toolId>. Its
description is the approved tool description, and its parameters are
{ connection?, arguments }. The Chat instructions tell the agent that MCP
results are untrusted source data, and that write tools need explicit owner
intent. apps.describe has no MCP part. To write an app, Chat uses the
agent tool parameters and the name map above.
App agents get only the MCP tools that their profile tools lists. The run's
Access removes Off tools at run start.
Tool changes
Redac compares the live tool list with the approved list when a session opens and when the owner selects Check for changes.
| Change | Result |
|---|---|
| Input schema or annotations | The tool is blocked until the owner reviews it. One desktop alert. |
| Description only | The tool works with the approved description. The page shows Update available. |
| New tool | Redac does not add it. The banner counts it. |
| Tool not on the server | The permission stays. Calls get the server's error. Not on server. |
| Tool that Redac cannot use | The same tool is on the server, but review refuses it now. It is blocked. |
In Review changes, the owner selects the tools to keep. A permission whose input changed goes back to its default level. Chat goes back to its defaults (read Allow, write Ask). An app goes back to Off. Access stays for permissions that did not change. A tool that the owner cleared at review does not count as new later.
Remove MCP server removes the server, its accounts, its tokens and all
Access for its permissions. After that, an app call to its function gets
not_found. If the owner adds the server again, the app call gets
unauthorized until the owner gives access again.
Errors
| Case | Text or code |
|---|---|
Address is not https: (and not loopback) | "Use an https address." |
| Address is longer than 512 characters | "Use a shorter address." |
| No answer, TLS error, not an MCP server | "Redac could not connect to this server." and one reason line |
| Browser sign-in without registration | "This server does not let Redac register. Redac cannot sign in to it yet." |
| Sign-in details name another resource | "This server's sign-in details do not match its address." |
| Server refused the browser sign-in | "The server refused sign-in: …" with at most 300 characters of its text |
| Token refused when the owner adds it | "The server did not accept this token." |
| No usable tool on the server | Each row shows "Redac cannot use this tool." and its reason. Add connection is disabled. |
| Account protection is not available | "Account protection is unavailable. Sign-in is disabled." Add server is disabled. |
| More than 256 servers | "Redac can connect at most 256 MCP servers." |
| Tool blocked | unavailable: "This tool changed. Review it in Connections." |
| Server offline at call time | unavailable: "Linear did not answer." |
| Deadline | unavailable: "Linear did not answer in 60 seconds." Redac sends notifications/cancelled. |
| Result larger than 1 MiB | unavailable: "The result is larger than 1 MiB." |
| JSON-RPC error from the server | unavailable: "Linear refused the call: …" with at most 300 characters of its text |
Tool error (isError: true) | unavailable, with the tool's text |
| Token or sign-in refused at call time | unavailable: "Reconnect this account". The account shows Reconnect. |
| Arguments do not match the input schema | invalid_args |
| Permission at Off, or not declared | unauthorized |
| Server removed | not_found |
The reasons after "Redac could not connect to this server." are: "The address was not found.", "The address did not answer.", "The connection is not secure.", "The address is not on the public internet.", "The address sent Redac to another address.", "The answer was too large.", "The request was too large." and "The address did not answer as an MCP server." Redac never shows the text that the server sent with an HTTP error.
For Browser sign-in, a 401 makes Redac refresh the token one time and send
the call again. If the refresh fails, the account shows Reconnect. For a
token, a 401 puts the account in Reconnect at once: a token has no
refresh. Reconnect on a token account takes a new token for the same account,
which keeps its Access. A session that gets HTTP 404 opens again one time.
Limits
| Limit | Value |
|---|---|
Tools in one tools/list result | 512 (Redac ignores the tools after 512) |
| Input schema of one tool | 64 KiB (UTF-8 bytes of its JSON) |
| Depth of one input schema | 64 levels |
| Description of one tool | 2,048 characters; Redac cuts longer text at review |
| One result | 1 MiB |
| One request body | 64 KiB |
| Deadline of one call | 60 seconds, open and retries included |
| Session idle close | 5 minutes |
| Server address | 512 characters |
| Server name | 120 characters |
| MCP servers on one computer | 256 |
| Accounts, all providers together | 100 (Browser sign-in and token accounts) |
A tool that breaks a bound shows at review as "Redac cannot use this tool."
with its reason. The owner cannot select it. An input schema must be an object
schema (type: 'object'). An output schema, when the tool has one, must also
be an object schema. Each pattern and each patternProperties key must be a
regular expression that compiles, else the reason is "Its input description has
an invalid pattern."
Network
The server address must use https:. Only a localhost, 127.0.0.1 or
[::1] server can use http:. A loopback server can connect only to a
loopback address. Any other server can connect only to public addresses,
checked after DNS. Other private network addresses are not allowed.
Redac sends requests only to the approved origins: the MCP origin, and for
Browser sign-in the authorization server, token and registration origins. The
review card shows them. When the protected resource metadata (RFC 9728) has a
resource, it must match the server address (RFC 9728 §3.3), else Redac stops
before it contacts the authorization server. Redac sends that value as the
resource parameter. A redirect fails. Redac sends no cookies. Only the
request to the MCP address carries the token. Redac declares no MCP client
capabilities: no sampling, no elicitation and no roots. Logs keep the server,
tool, connection, duration and status. They never keep arguments, results,
tokens or headers.
Not in this version
- MCP functions on the phone and in Redac Web. The entries have no
remotebinding, and the phone's Access state does not list MCP servers. - Local (stdio) servers and the old HTTP+SSE transport.
- Resources, prompts, server notifications between calls and progress.
- A client id that the owner types.