
Steroid_Kit
Steroid MCP›Running Tools
Running Tools — run_tool
run_tool executes one tool chosen from a search_tools result. It collects any missing credentials through your IDE, runs the tool on Steroid's cloud runtime, and returns the tool's output. Like search_tools, it is registered only in Connected mode.
What Happens When You Call run_tool
- Steroid looks up the server's credential and configuration requirements in the catalog.
- If the call includes
additional_user_input, your IDE prompts for those values and they are merged intoarguments. - Missing secrets and configuration are requested through IDE prompts (see below). Stored values are reused without asking.
- The server's credentials are sent to Steroid's execution service for this workflow.
- The service checks the capability handle: it must exist, be unexpired, unused, and cover
tool_name. - The tool runs in a fresh session of the MCP gateway and its output is returned.
NOTE
Credentials are collected before the handle is checked. Call run_toolwithin five minutes of the search, or you may be asked for a credential and then receive INVALID_TOKEN.
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
workflow_run_id | string | Yes | From the search_tools response. |
capability_token | string | Yes | From the same response. Valid for 5 minutes and one call. |
server_name | string | Yes | The chosen candidate's server_name, exactly. |
tool_name | string | Yes | The chosen candidate's tool_details.name, exactly. |
arguments | object | No | The tool's inputs, keyed by the names in tool_details.arguments. Defaults to {}. |
additional_user_input | array | No | Tool inputs the agent needs the user to supply. Not for secrets or configuration. |
Steroid forwards arguments to the tool unchanged — it does not validate them against the schema, so the tool itself reports a missing or misnamed input.
additional_user_input — type is string (default), number, integer or boolean
[
{
"name": "channel_id",
"description": "Which Slack channel should the message go to?",
"required": true,
"type": "string"
}
]Credentials & Configuration
Of the 241 catalog entries, 157 declare secrets such as API keys or tokens. The other 84 declare none, but 27 of those still need configuration values. No current entry uses OAuth.
First use: IDE prompts
When a secret is not yet stored, Steroid asks for it through MCP elicitation, so the value goes from you to Steroid without passing through the chat. How the prompt looks depends on your IDE; the request Steroid sends reads:
Secret request (one field per missing secret)
Please provide the following secrets for the slack server:
slack.bot_token <description from the catalog>Configuration is a separate prompt: "Please provide the following configuration for the slack server:". Declining or cancelling returns {"error": "Information not provided"} or {"error": "Operation cancelled"} and nothing runs.
Where credentials go
| Where | What is kept | For how long |
|---|---|---|
| Your machine | Encrypted file ~/.steroid/cryptfile_pass.cfg (not the OS keychain), saved only after the execution service accepts the value | Until removed or uninstalled |
| Steroid execution service | All of that server's secrets, sent on every call, scoped to the workflow | Up to 30 minutes |
| MCP gateway session | Secrets and configuration set for the single call | That call |
WARNING
Never paste credentials into arguments or the chat — use the prompt. Manage stored values from the CLI; see How Secret Injection Works.
Reading the Result
run_tool — success
{
"workflow_run_id": "w1a2b3c4d",
"step": "execution",
"status": "completed",
"artifact_ref": "a9f8e7d6c",
"artifact_token": "3c2b1a0f",
"full_result": "[{\"type\":\"text\",\"text\":\"Message posted to #deploys\"}]"
}full_resultis JSON text — decode it. It holds the tool's structured output object when the tool provides one, otherwise an array of MCP content items such as{"type": "text", "text": "…"}.- There is no universal
ok/outputfield; the contents are tool-specific. artifact_refandartifact_tokenare internal references. Nothing retrieves them later, so treatfull_resultas the output.- A single tool call can run for up to 590 seconds before the gateway times out.
Errors and Recovery
Failures return an envelope with error, error_code, message, hint and recovery_instructions. A capability handle is single-use, so every retry starts with a new search_tools call.
| error_code | Meaning | What to do |
|---|---|---|
INVALID_TOKEN | The handle is unknown or expired, or tool_name was not in that search's results. | Search again; use a tool from the new results. |
INVALID_STEP_SEQUENCE | The handle was already used. | Search again. |
WORKFLOW_NOT_FOUND | Workflow state is gone (kept up to one hour; cleared by a service restart). | Search again. |
EXECUTION_FAILED | The tool itself failed — often wrong arguments or a rejected credential. | Read message, fix the input, then search again. |
Examples
MCP tools/call requests, each made after a matching search_tools call. Replace the IDs with the values that search returned.
Post a Slack message — needs slack.bot_token and slack.team_id
{
"name": "run_tool",
"arguments": {
"workflow_run_id": "<from search_tools>",
"capability_token": "<from search_tools>",
"server_name": "slack",
"tool_name": "slack_post_message",
"arguments": {
"channel_id": "C0123456789",
"text": "Deployment to production complete."
}
}
}Create a GitHub issue — needs github.personal_access_token
{
"name": "run_tool",
"arguments": {
"workflow_run_id": "<from search_tools>",
"capability_token": "<from search_tools>",
"server_name": "github-official",
"tool_name": "issue_write",
"arguments": {
"method": "create",
"owner": "acme-corp",
"repo": "backend-api",
"title": "Rate limiting not applied to /export endpoint",
"body": "The /export endpoint bypasses the global rate limiter.",
"labels": ["bug"]
}
}
}Run a read-only Postgres query
{
"name": "run_tool",
"arguments": {
"workflow_run_id": "<from search_tools>",
"capability_token": "<from search_tools>",
"server_name": "postgres",
"tool_name": "query",
"arguments": { "sql": "SELECT COUNT(*) FROM events" }
}
}