selan.ai

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

RoleWhat 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

ToolWhat it doesRoleDestructive
selan_whoamiWho this call acts for, their company and roleread
selan_tokens_listThe provider credentials this caller may seeread
selan_token_detailOne provider credential by idread
selan_my_usageThe caller's own spend against their own limitsread
selan_company_usageCompany spend over a trailing windowowner
selan_members_listThe company rosterread
selan_settings_getThe company-wide switchesread
selan_connectors_listThe MCP connectors available to this developerread
selan_models_listThe model ids this developer may pass to --modelread
selan_recent_requestsThe newest 50 requests this caller may seeread

selan_company_usage is a read tool, so every member sees it, but Selan answers it for owners only.

Workspaces

ToolWhat it doesRoleDestructive
selan_remote_workspaces_listThe company's workspaces, oldest first, each with how many agents it holds and its rulesread
selan_remote_workspace_createCreate an empty workspaceedit
selan_remote_workspace_renameRename a workspaceedit
selan_remote_workspace_set_rulesSet the rules every agent in a workspace reads before its own system promptedit
selan_remote_workspace_deleteDelete an empty workspaceownerYes

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

ToolWhat it doesRoleDestructive
selan_remote_runners_listThe company's runners, the machines agents can run onread
selan_remote_runner_createAdd a runner, and get its token once and the lines that install itowner
selan_remote_runner_updateChange a runner's name and how many runs it takes at onceowner

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

ToolWhat it doesRoleDestructive
selan_remote_agents_listThe company's remote agentsread
selan_remote_agents_overviewThe company's remote agents, each naming its workspaceread
selan_remote_agents_taggedThe agents carrying any of up to 8 tagsread
selan_remote_agents_canvasOne workspace's agents with their last run, triggers and expired connectorsread
selan_remote_agent_detailOne remote agent in full, system prompt includedread
selan_remote_agent_createCreate a remote agent in a workspace, on a runner or a vm made per runedit
selan_remote_agent_updateChange an agent's name, system prompt, model, effort, tags, workspace or runneredit
selan_remote_agent_deleteDelete an agent, its triggers and its service accountownerYes
selan_remote_agent_historyEvery version of an agent and of its schedules, newest firstread
selan_remote_agent_revertPut back an earlier version of an agent or of one of its schedulesedit

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

ToolWhat it doesRoleDestructive
selan_remote_agent_runs_listThe company's remote agent runs, newest firstread
selan_remote_agent_runs_allEvery run of the company, newest firstread
selan_remote_agent_runs_of_agentOne agent's newest runsread
selan_remote_agent_run_getOne run: what it was asked, how it ended, its answerread
selan_remote_agent_run_detailOne run in full, with its event logread
selan_remote_agent_run_transcriptA run's transcript, 20,000 characters at a timeread
selan_remote_agent_run_blocksA run's transcript as blocksread
selan_remote_agent_run_startStart a run of a remote agentedit
selan_remote_agent_run_cancelCancel a runedit
selan_remote_agent_run_sendSend a message to a run still goingedit

Triggers

ToolWhat it doesRoleDestructive
selan_remote_agent_triggers_listThe company's triggersread
selan_remote_agent_trigger_historyWhen a trigger fired, and by whomread
selan_remote_agent_trigger_createSchedule a trigger for an agentedit
selan_remote_agent_trigger_updateChange a trigger's target, schedule or promptedit
selan_remote_agent_trigger_set_enabledPause or resume a triggeredit
selan_remote_agent_trigger_runFire a trigger nowedit
selan_remote_agent_trigger_deleteDelete a trigger and its fire historyownerYes
selan_remote_agent_trigger_set_callersSet which agents of the same workspace may start this one from inside their runedit
selan_remote_agent_event_trigger_createStart an agent when an outside event matches a sentenceedit
selan_remote_agent_event_trigger_updateChange an event trigger's sentenceedit

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

ToolWhat it doesRoleDestructive
selan_remote_webhook_getThe webhook's url and what it lets inedit
selan_remote_webhook_createCreate the company's webhook and show its secret onceowner
selan_remote_webhook_rotateReplace the secret, and optionally the urlownerYes
selan_remote_webhook_allowLet one GitLab group or one host inowner
selan_remote_webhook_disallowStop letting one GitLab group or host inownerYes

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

ToolWhat it doesRoleDestructive
selan_remote_agent_connectors_listAn agent's connectors, each Google Cloud connector a row of its ownread
selan_remote_agent_cloud_set_upGive an agent its Google Cloud service accountedit
selan_remote_agent_cloud_switch_productSwitch one Google Cloud connector, or one product of it, on or off for an agentedit
selan_remote_agent_cloud_checkCheck whether one Google Cloud connector of an agent can read a projectedit
selan_remote_agent_connector_connectA link a person opens to sign an agent in to a connector, or grant one Google Cloud connector accessedit
selan_remote_agent_connector_forgetDrop an agent's sign-in to one connectorownerYes
selan_remote_agent_cloud_forgetRemove an agent's Google Cloud access and its service accountownerYes

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

ToolWhat it doesRoleDestructive
selan_remote_agent_env_listAn agent's environment variables by name, who set each and when; never a valueread
selan_remote_agent_env_setSet one of an agent's environment variables for its next runedit
selan_remote_agent_env_removeRemove one of an agent's environment variablesownerYes

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.

ToolWhat it does
selan_agents_startableThe agents this run may start, each with its agentId and name
selan_agent_startStart a run of another agent with a message of 1 to 4,000 characters, and optionally wait for its answer
selan_agent_run_waitWait 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_create and selan_remote_webhook_rotate, and a new runner's token, once, to an owner, from selan_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.