External MCP servers are declared in .mcp-workflows/servers.json. Each entry maps a friendly alias (e.g., linear) to either an stdio command or an HTTP endpoint.
Example (stdio + OAuth)
{
"servers": {
"linear": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.linear.app/mcp"],
"auth": "oauth",
"clientName": "oplink-linear-demo",
"oauthRedirectUrl": "http://127.0.0.1:22228/oauth/callback",
"tokenCacheDir": "./.tokens/linear",
"description": "Linear hosted MCP server"
}
}
}
Rules
.env files from your --config directory before expansion. Precedence: shell > .env.{NODE_ENV}.local > .env.{NODE_ENV} > .env.local > .env.${VAR} placeholders still fail startup (by design)..mcp-workflows/servers.json.{
"mcpServers": {
"oplink-atlassian": {
"command": "node",
"args": [
"/path/to/repo/packages/cli/bin/oplink.mjs",
"server",
"--config",
"/path/to/repo/examples/atlassian-demo/.mcp-workflows"
]
}
}
}
tokenCacheDir is resolved relative to the config dir.servers.json must contain at least one server.OAuth flow cheatsheet
--config pointing at your .mcp-workflows.describe_tools({ "workflow": "name" }) or call external_auth_setup() once..tokens/<alias>.Auto‑discovery vs scripted
See also