Connect an MCP server
External MCP tools show up as bash: mcp call SERVER TOOL. Config lives in the repository database, not in git. Transport is HTTP streamable only — there is no stdio server.
This is not a published *.mcp.sh on your site. Those are tools you expose. This page is inbound: you call someone else’s server.
Done looks like
mcp list --server NAME prints lines like mcp call NAME some_tool. mcp call NAME some_tool --json '{…}' returns that tool’s result. The same ssec_… (or OAuth session) still works after you leave the chat.
Worked example A: OAuth server (Resend-style)
Job: the server wants a browser login. You are a repository owner.
mcp connect resend --url https://mcp.resend.com
Expected shape:
Open this URL to authorize MCP server `resend`:
https://…/sails/mcp/oauth/start/mcpsess_...
Session: mcpsess_...
Then run: mcp connect poll mcpsess_...
- Open the URL. Finish the provider login.
- Back in the shell:
mcp connect poll mcpsess_...
Expected shape:
Connected MCP server `resend`. Use `mcp list --server resend` or `mcp call resend TOOL`.
mcp list --server resend
mcp call resend TOOL --json '{}'
Replace TOOL with a name from mcp list. Do not pass --wait from bash_exec. Same buffering problem as secret open --wait / upload --wait: you never see the URL. Print, then mcp connect poll SESSION_ID.
--timeout SECS applies to mcp connect / poll. If authorization expires later, run mcp connect again. Tokens refresh while the connection is established.
Worked example B: API key header
Job: Exa (or any server that wants a static header). Store the key first — see Store a secret.
secret open exa-key
secret poll INTAKE_ID
# prints: ssec_...
mcp add exa --url https://mcp.exa.ai/mcp \
--header "x-api-key=ssec_..." \
--visibility owner
GitHub-style Bearer:
mcp add github --url https://mcp.example.com/mcp \
--header "Authorization=Bearer ssec_..." \
--visibility owner
Exact ssec_… is substituted when the platform makes the call. If you cannot use that token, the call fails closed.
mcp reload
mcp list --server exa
mcp call exa search --json '{"query":"sails static site"}'
mcp add needs write access. Default --visibility owner means only the creator can call it. Repository owners can mcp chmod / mcp remove any server but cannot call it unless they are in the visibility scope.
Who can use the server
mcp chmod exa --visibility members
mcp chmod exa --visibility group --group writers
mcp show exa
mcp remove exa
| Visibility | Who can mcp call |
|---|---|
owner (default) | Creator only |
group | Creator + --group NAME |
members | Any repository member |
Migrate a one-time .sails/mcp.json with mcp import ~/.sails/mcp.json (owner).
Commands
mcp help
| Command | What it does |
|---|---|
mcp connect NAME --url URL | Owner. Print OAuth URL; then mcp connect poll SESSION_ID |
mcp connect NAME --url URL --wait | Block until authorized — avoid inside bash_exec |
mcp add NAME --url URL [--header K=V]… | Register static headers / ssec_… |
mcp list [--server NAME] | Tools you can use (mcp call SERVER TOOL lines) |
mcp call SERVER TOOL [--json '{}'] | Invoke |
mcp call SERVER TOOL --json '{}' --background | Long job when the server supports MCP tasks |
mcp task wait SERVER TASK_ID [--timeout SECS] | Poll that background task |
mcp reload | Re-read config from the database (resets idle connections) |
mcp show NAME | Config (redacted if you cannot use it) |
mcp resource list / read / templates SERVER | Read-only resources |
mcp prompt list / get SERVER NAME | Prompts |
mcp resource list github
mcp resource read github "file://docs/README.md"
mcp prompt get github summarize --json '{"text":"..."}'
mcp call github heavy-job --json '{}' --background
mcp task wait github TASK_ID --timeout 600
Failure modes
| What you see | What it means | What to do |
|---|---|---|
mcp connect denied | Owner-only | An owner runs it, or elevate that goal |
| Poll times out | Nobody finished the browser step | mcp connect again; new session id |
mcp list omits the server | Visibility, or you never mcp reload | mcp show NAME; mcp chmod; mcp reload |
| Call fails closed / header empty | You cannot use that ssec_… | secret list; secret chmod if it should be shared |
| No such tool | Wrong server name, or list is stale | mcp list --server NAME |
| Private IP / URL blocked | Same outbound policy as curl | Public HTTPS URL only |
| You started a stdio process | Not supported | HTTP streamable URL only |
| You committed the API key | Wrong store | secret open / secret set, put ssec_… in --header |
Sampling and elicitation are declined (headless bash). Progress for long calls prints [mcp progress] … on stderr.
Site tools you publish yourself are *.mcp.sh — not this command. Secrets how-to: Store a secret.