MCP
Security & configuration
MCP servers run third-party code, so Flowly wraps them with several layers of defense β all on where it should be, opt-in where it matters.
Built-in guards
- OSV malware gate β before an
npx/uvxserver spawns, Flowly queries the OSV database for known-malware advisories and blocks the spawn if any. Fail-open (network errors allow); per-server opt-out withosvCheck: false. - Filtered subprocess environment β stdio servers get only a safe baseline (
PATH,HOME, β¦) plus theenvyou list. Flowly's own provider keys never leak into them. - Credential redaction β tokens and keys in error output are replaced with
[REDACTED]before the model or logs see them. - Prompt-injection scan β tool descriptions are scanned for override patterns and logged (not blocked) so a hostile server is detectable.
- Circuit breaker β a server that fails repeatedly is short-circuited for a cooldown, so the model stops hammering it and recovers automatically.
- Sandbox β under
FLOWLY_SANDBOXthe whole agent, MCP subprocesses included, runs insidesandbox-exec(macOS) /bwrap(Linux).
Trust the servers you add
These guards reduce risk; they don't make an arbitrary MCP server safe. A server you connect runs real code and sees the arguments the agent sends it. Add servers from sources you trust.
Where to look when a server fails
Subprocess stderr is redirected to ~/.flowly/logs/mcp-stderr.log (so a chatty server can't corrupt the TUI). When a server won't connect:
bash
flowly mcp test <name> # connect + surface the error
cat ~/.flowly/logs/mcp-stderr.log # the server's own outputmcpServers config reference
Servers live under the top-level mcpServers key in ~/.flowly/config.json. Keys are camelCase on disk; server names and env/headers keys are preserved verbatim.
json
{
"mcpServers": {
"example": {
"enabled": true,
"command": "npx", // stdio: command + args + env
"args": ["-y", "@scope/pkg"],
"env": { "TOKEN": "${TOKEN}" },
"url": "", // http/sse: url + headers instead
"headers": {},
"transport": "auto", // auto | stdio | http | sse
"timeout": 120, // per-tool-call seconds
"connectTimeout": 60, // initial connect seconds
"tools": {
"include": [], // whitelist (empty = all)
"exclude": [], // blacklist (ignored if include set)
"resources": false, // expose resources/* utility tools
"prompts": false // expose prompts/* utility tools
},
"auth": "", // "" | "oauth"
"scope": "", // optional OAuth scope
"sslVerify": true, // true | false | CA-bundle path
"clientCert": "", // mTLS cert (path or [cert, key])
"clientKey": "",
"osvCheck": true, // OSV malware gate
"sampling": { // server-initiated LLM (off by default)
"enabled": false,
"model": "",
"maxRpm": 10,
"maxTokensCap": 4096,
"allowedModels": []
}
}
}
}