Docs · Selan MCP
Selan MCP
One MCP server for your company's Selan data and its Reactor remote agents. It acts as the member who signed in, with that member's role.
What it is
Selan MCP is one MCP server at https://mcp.selan.ai/selan/mcp. Claude
Code connects to it from your terminal.
Through it a client reads your company's Selan data: who you are, the provider credentials you may see, your spend, the roster, the company settings, the connectors, the models and your recent requests. It also reads and manages Reactor remote agents: the workspaces they live in, the runners they run on, the agents and their earlier versions, their environment variables, their runs, their triggers, the company webhook that outside events arrive on, and their Google Cloud and connector access. And an agent's own run uses it to start the other agents of its workspace.
Every call acts as the member who signed in. That member's role decides what the call may see and do.
Connect
Claude Code through the Selan CLI needs nothing. The CLI already configures the server and signs its calls with your Selan session.
The server's URL, if you need it:
https://mcp.selan.ai/selan/mcp
Any other MCP client signs in through the browser, as you would to Selan itself, and gets an access token that lasts 30 days and a refresh token that lasts 90. A client that supports refresh tokens renews the connection itself: each refresh hands back a new pair, so a connection used at least every 90 days never asks you to sign in again. A refresh token works once; a reused one ends that sign-in and every token it issued. Removing a member, or switching them off, ends their connections at once.
An owner must have the Selan connector switched on. It is gated like any other connector. When an owner switches it off, the company loses it within the minute.
Roles
| Role | What it may do |
|---|---|
| read | Sees and uses the read tools only. Write tools do not appear in its tool list, and a call to one by name is refused before anything is sent. |
| edit | Everything read may do. Also creates, changes, starts, cancels, pauses and resumes. |
| owner | Everything edit may do. Also deletes, changes runners, and sets up the company webhook. |
Reactor checks the role itself on every call. Hiding tools is a courtesy to the client, not the lock, and nothing a client sends can widen a role. An edit member sees the owner tools, and Reactor refuses them.
A running remote agent cannot manage Reactor. Reactor refuses its
calls to the management tools. It calls with the read role: it reads with
selan_remote_agents_list, selan_remote_agent_runs_list,
selan_remote_agent_run_get and
selan_remote_agent_run_transcript, and starts other agents with the
tools under From inside a run.
selan_agent_start is the one write tool a read caller sees, because
Reactor decides who may start what.
A workspace supervisor's run is the exception. A workspace may have one supervisor, an agent whose prompt is its mission. Its run manages the other agents of its workspace with the agent, schedule, run and environment variable tools: it makes, changes, starts, messages and cancels, as the person who turned the supervisor on. It cannot set workspace rules, change itself or its own variables, or call the webhook and event trigger tools. Every other run stays read-only.
Over MCP only an owner may delete. In the Reactor web app an edit member still can. Runners and the company webhook are the exceptions: only an owner adds, changes or removes one, there too.
Reactor must be enabled
Reactor is switched on per company, by Selan. While it is off, every Reactor tool, reads included, answers:
Reactor is not enabled for this company
The switch stops management only. Scheduled triggers still fire, and runs already going finish.
Tools
Sixty-six tools. Role is the least role that may call the tool: read means any member. Destructive marks a tool that deletes.
Company and spend
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_whoami | Who this call acts for, their company and role | read | |
selan_tokens_list | The provider credentials this caller may see | read | |
selan_token_detail | One provider credential by id | read | |
selan_my_usage | The caller's own spend against their own limits | read | |
selan_company_usage | Company spend over a trailing window | owner | |
selan_members_list | The company roster | read | |
selan_settings_get | The company-wide switches | read | |
selan_connectors_list | The MCP connectors available to this developer | read | |
selan_models_list | The model ids this developer may pass to --model | read | |
selan_recent_requests | The newest 50 requests this caller may see | read |
selan_company_usage is a read tool, so every member sees it, but Selan
answers it for owners only.
Workspaces
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_workspaces_list | The company's workspaces, oldest first, each with how many agents it holds and its rules | read | |
selan_remote_workspace_create | Create an empty workspace | edit | |
selan_remote_workspace_rename | Rename a workspace | edit | |
selan_remote_workspace_set_rules | Set the rules every agent in a workspace reads before its own system prompt | edit | |
selan_remote_workspace_delete | Delete an empty workspace | owner | Yes |
Every agent is in exactly one workspace, and starts only agents in its
own. The first workspace is where your agents were put when workspaces
arrived, usually named Default. A workspace name is 1 to 40 characters,
and two workspaces of a company cannot share one, whatever the case.
A workspace is deleted only while it holds no agent, counting agents deleted in the last 7 days, and the last workspace cannot be deleted.
A workspace's rules are one text every agent in it reads before its own
system prompt. selan_remote_workspace_set_rules takes the
workspace's id and rules, 0 to 2,000 characters, and
replaces them whole; an empty text clears them. Every run started after the change
reads the new rules, and selan_remote_workspaces_list shows each
workspace's current rules.
Runners
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_runners_list | The company's runners, the machines agents can run on | read | |
selan_remote_runner_create | Add a runner, and get its token once and the lines that install it | owner | |
selan_remote_runner_update | Change a runner's name and how many runs it takes at once | owner |
A runner is a machine your company keeps on, such as a VPS, that runs an
agent's runs in seconds instead of on a vm made for each run. Each runner
comes with its id, name, slots,
busy, online, lastSeenAt and
version.
Every run sent to a runner is handed all of its agent's secrets, so only an owner adds or removes a runner. Self-hosted runners covers adding, installing and removing one.
selan_remote_runner_create adds a runner. It takes a
name of 1 to 40 characters that no other runner of your company holds,
and answers the runner, whose id is the
runnerId agents take, the token it polls with, and
install, one line per system that installs it with that token:
linux for Ubuntu 24.04,
mac for an Apple Silicon Mac, and
macPrivileged, the Mac line with --mac-host for
Xcode builds. The token is in this answer once
and never again. A new runner starts at 2 slots. No MCP tool removes a runner: an
owner does that in the Reactor web app.
selan_remote_runner_update sets a runner's name and
slots together. It takes the runner's id, a name of 1
to 40 characters and slots, the runs it takes at once, from 1 to 16. Both
are replaced, so send the current name to change only slots, as
selan_remote_runners_list shows it. A name another runner of your company
holds is refused. An owner sets the same two in the runner's dialog in the Reactor web
app, where slots is Runs at once.
Reactor owns slots: a new runner starts at 2, the machine takes a new value
from its next poll, and a RUNNER_SLOTS in the machine's env file is no
longer read.
A run sent to a runner that is offline or full ends at once as
unprovisioned, saying which. A run whose runner stops polling for 2
minutes ends lost.
Reactor agents
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_agents_list | The company's remote agents | read | |
selan_remote_agents_overview | The company's remote agents, each naming its workspace | read | |
selan_remote_agents_tagged | The agents carrying any of up to 8 tags | read | |
selan_remote_agents_canvas | One workspace's agents with their last run, triggers and expired connectors | read | |
selan_remote_agent_detail | One remote agent in full, system prompt included | read | |
selan_remote_agent_create | Create a remote agent in a workspace, on a runner or a vm made per run | edit | |
selan_remote_agent_update | Change an agent's name, system prompt, model, effort, tags, workspace or runner | edit | |
selan_remote_agent_delete | Delete an agent, its triggers and its service account | owner | Yes |
selan_remote_agent_history | Every version of an agent and of its schedules, newest first | read | |
selan_remote_agent_revert | Put back an earlier version of an agent or of one of its schedules | edit |
selan_remote_agents_canvas and selan_remote_agent_create
take a workspaceId from selan_remote_workspaces_list.
selan_remote_agent_update takes one too, to move the agent: it moves with
its triggers, runs and memory, and the lists of agents that may start it, or that it
may start, are cleared.
selan_remote_agent_create and selan_remote_agent_update
also take a runnerId: a runner's id from
selan_remote_runners_list, or null for a vm made per run.
It is required, so send null rather than leaving it out.
selan_remote_agent_update replaces all seven fields at once: send the
ones not changing as selan_remote_agent_detail shows them.
Effort is low, medium, high,
xhigh or max. An agent carries at most 8 tags, each 1 to 24
characters; selan_remote_agents_tagged compares them lower-cased and
trimmed, so Prod finds prod.
Every change to an agent or one of its schedules is kept as a version.
selan_remote_agent_history takes the agent's agentId and lists
each version with its kind (agent or trigger),
id, version, at, who made it (by:
their email, and the runId of the supervisor run that made
it, null for a person) and the whole config it left.
selan_remote_agent_revert takes an entry's kind,
id and version and writes that version again as a new one,
so nothing is lost and a revert can itself be reverted. Reverting an agent moves it
back to the workspace it was in then. An unknown version answers
no such version, and an agent trigger, whose id starts
agent:, keeps no versions.
Runs
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_agent_runs_list | The company's remote agent runs, newest first | read | |
selan_remote_agent_runs_all | Every run of the company, newest first | read | |
selan_remote_agent_runs_of_agent | One agent's newest runs | read | |
selan_remote_agent_run_get | One run: what it was asked, how it ended, its answer | read | |
selan_remote_agent_run_detail | One run in full, with its event log | read | |
selan_remote_agent_run_transcript | A run's transcript, 20,000 characters at a time | read | |
selan_remote_agent_run_blocks | A run's transcript as blocks | read | |
selan_remote_agent_run_start | Start a run of a remote agent | edit | |
selan_remote_agent_run_cancel | Cancel a run | edit | |
selan_remote_agent_run_send | Send a message to a run still going | edit |
Triggers
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_agent_triggers_list | The company's triggers | read | |
selan_remote_agent_trigger_history | When a trigger fired, and by whom | read | |
selan_remote_agent_trigger_create | Schedule a trigger for an agent | edit | |
selan_remote_agent_trigger_update | Change a trigger's target, schedule or prompt | edit | |
selan_remote_agent_trigger_set_enabled | Pause or resume a trigger | edit | |
selan_remote_agent_trigger_run | Fire a trigger now | edit | |
selan_remote_agent_trigger_delete | Delete a trigger and its fire history | owner | Yes |
selan_remote_agent_trigger_set_callers | Set which agents of the same workspace may start this one from inside their run | edit | |
selan_remote_agent_event_trigger_create | Start an agent when an outside event matches a sentence | edit | |
selan_remote_agent_event_trigger_update | Change an event trigger's sentence | edit |
selan_remote_agent_run_send takes 1 to 4,000 characters, which the agent
reads while it works. An ended run refuses it, and so does a run with 20 messages
already waiting.
selan_remote_agent_trigger_set_callers replaces the agent's list of
callers; an empty list means none.
Schedules work for every company from the day it joins: nothing is set up first.
selan_remote_agent_trigger_create and selan_remote_agent_trigger_update
save a schedule straight away, and selan_remote_agent_trigger_run fires one.
selan_remote_agent_trigger_history names how each fire began in
source: schedule, manual, agent,
wake, gitlab, custom or trello, a card landing in a watched Trello list.
An event trigger starts an agent when an outside event matches a
sentence. selan_remote_agent_event_trigger_create takes the
agent's agentId and a sentence of 1 to 4,000 characters in
plain words. A model reads each event the company webhook lets in against the
sentence, and a match starts a run of the agent as the member who made the trigger.
A GitLab comment event does not fire it while a run it started is still going.
selan_remote_agent_event_trigger_update takes the trigger's
id and a new sentence. Pause, resume, fire and delete an
event trigger with the same tools as a schedule.
Company webhook
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_webhook_get | The webhook's url and what it lets in | edit | |
selan_remote_webhook_create | Create the company's webhook and show its secret once | owner | |
selan_remote_webhook_rotate | Replace the secret, and optionally the url | owner | Yes |
selan_remote_webhook_allow | Let one GitLab group or one host in | owner | |
selan_remote_webhook_disallow | Stop letting one GitLab group or host in | owner | Yes |
A company has one webhook, where outside events arrive for its event
triggers. selan_remote_webhook_get answers webhook (null until an
owner creates it; otherwise its url and allowed, a list of
source and value, never the secret) and
canEdit, whether the caller is an owner.
selan_remote_webhook_create answers the url and the
secret once. Give GitLab both under Settings, Webhooks in each project,
the secret as the X-Gitlab-Token, with Issues events, Comments and
Merge request events ticked. A company that already has a webhook is refused: rotate
it. selan_remote_webhook_rotate requires newUrl, true or
false, and answers the new secret once, with the url. The
old secret stops at once, so each GitLab project needs the new one, and with
newUrl true the old url stops answering too.
Nothing is let in until an owner allows it.
selan_remote_webhook_allow takes a source and a
value. For gitlab, a group path such as
selan.ai lets in events from the projects under it that carry the
secret, and other groups are dropped. For custom, a hostname or IP may
post JSON of up to 16 KB to the url with no secret; a hostname is looked up again on
every post, an Idempotency-Key header makes a repeated post count once,
and any other host is refused. An invalid host answers 400. A company without a
webhook answers 404. selan_remote_webhook_disallow removes an entry: the
event triggers stay, and stop hearing that source.
Google Cloud and connectors
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_agent_connectors_list | An agent's connectors, each Google Cloud connector a row of its own | read | |
selan_remote_agent_cloud_set_up | Give an agent its Google Cloud service account | edit | |
selan_remote_agent_cloud_switch_product | Switch one Google Cloud connector, or one product of it, on or off for an agent | edit | |
selan_remote_agent_cloud_check | Check whether one Google Cloud connector of an agent can read a project | edit | |
selan_remote_agent_connector_connect | A link a person opens to sign an agent in to a connector, or grant one Google Cloud connector access | edit | |
selan_remote_agent_connector_forget | Drop an agent's sign-in to one connector | owner | Yes |
selan_remote_agent_cloud_forget | Remove an agent's Google Cloud access and its service account | owner | Yes |
An agent signs in to a connector from your terminal.
selan_remote_agent_connector_connect takes an agent id and a connector
slug and answers with a link. Open it in a browser and sign in to the provider.
Reactor then shows:
Connected. You can close this tab and go back to your terminal.
If the sign-in fails it shows Not connected. The link works for 10
minutes. A read member cannot call the tool.
Environment variables
| Tool | What it does | Role | Destructive |
|---|---|---|---|
selan_remote_agent_env_list | An agent's environment variables by name, who set each and when; never a value | read | |
selan_remote_agent_env_set | Set one of an agent's environment variables for its next run | edit | |
selan_remote_agent_env_remove | Remove one of an agent's environment variables | owner | Yes |
An agent's runs start Claude with its environment variables, and their values
are write-only. No tool or screen shows a value once it is set, and none is
repeated in an answer or an error. Each tool takes the agent's agentId.
selan_remote_agent_env_list answers vars, the agent's own,
each name with setBy and setAt;
inherited, the company-wide ones its runs get too, with
overridden where the agent sets the same name and its value wins; and
canEdit, whether you may change them.
selan_remote_agent_env_set takes a name and a
value, adds the variable or replaces its value, and answers
{ name }. A name is capitals, digits and _, not starting
with a digit, at most 64 characters. A value is 1 to 16,384 bytes of UTF-8 with no NUL
byte. An agent holds at most 50 variables; replacing one never counts toward that.
Names the runner owns are refused, with the rule in the message: any starting
SELAN_, ANTHROPIC_, CLAUDE_ or
GIT_, and system names such as PATH, HOME,
NODE_OPTIONS, LD_PRELOAD and HTTPS_PROXY.
selan_remote_agent_env_remove takes the name; after it, a
company-wide variable of that name reaches the agent's runs.
A change reaches the agent's next run, never one already going. These tools change one agent's variables only: the company-wide ones are set in the Reactor web app.
From inside a run
A remote agent's run reaches Selan MCP too, and starts other agents of its own
workspace. An agent may start another only when that one's list of callers
names it, set with selan_remote_agent_trigger_set_callers.
These three tools answer for a running agent only.
| Tool | What it does |
|---|---|
selan_agents_startable | The agents this run may start, each with its agentId and name |
selan_agent_start | Start a run of another agent with a message of 1 to 4,000 characters, and optionally wait for its answer |
selan_agent_run_wait | Wait up to 45 more seconds on a run this agent started |
With wait true, selan_agent_start waits up to 45 seconds.
finished true carries the run's state and
answer, its final message. finished false means the run is
still going: call selan_agent_run_wait with its runId
rather than starting it again, since a second start is a second run.
A start is refused when this agent is not on the other's list, and when this chain of runs has already reached that agent, which is how a loop would begin.
Not available over MCP
- Secrets. No tool returns a provider key. The secrets any tool shows are the company webhook's, once, to an owner, from
selan_remote_webhook_createandselan_remote_webhook_rotate, and a new runner's token, once, to an owner, fromselan_remote_runner_create. A credential is shown by its label, its vendor, whether it is serving and who added it, never by its value. An agent's environment variable is shown by its name, never by its value.