Viktor MCP Server | Viktor Docs

Documentation

Learn how to set up and get the most out of Viktor.

The Viktor MCP server lets any MCP-compatible agent delegate work to Viktor. It exposes the same threads, runs, results, and files as the Viktor Public API, with two agent-friendly tools that can start a task and wait for its result in one call.

Connect

1. Create a scoped API key

Open Settings → API Keys and generate a personal or team key. For the simplest ask_viktor workflow, grant:

Add other scopes only when the MCP client needs the corresponding tools. The server advertises only tools allowed by the key's current scopes.

2. Add the remote server to your MCP client

Every client needs the same two pieces of information: the server URL and an authentication header. Either header style works:

Claude Code

claude mcp add --transport http viktor https://api.viktor.com/mcp \
  --header "Authorization: Bearer $VIKTOR_API_KEY"

Cursor

Add the server to ~/.cursor/mcp.json (or the project's .cursor/mcp.json):

{
  "mcpServers": {
    "viktor": {
      "url": "https://api.viktor.com/mcp",
      "headers": {
        "Authorization": "Bearer <VIKTOR_API_KEY>"
      }
    }
  }
}

Other clients

Most MCP clients accept the same mcpServers JSON shape as the Cursor example, or offer a settings screen where you enter the URL and header. If your client asks for a transport, choose Streamable HTTP, not the legacy SSE transport.

Use your client's secret or environment-variable support instead of saving a live key directly in a shared configuration file.

3. Verify the connection

Call whoami. It requires no scope and returns the key type, granted scopes, the workspace's rate-limit tier, and the active (tier-scaled) rate limits. If other tools are missing, update the key's scopes in the Viktor dashboard and refresh the client's tool list.

Recommended workflow

For a one-off task, call ask_viktor with a message:

{
  "message": "Analyze this month's revenue and summarize the biggest changes.",
  "speed": "smarter",
  "timeout_seconds": 120,
  "idempotency_key": "monthly-revenue-2026-07"
}

ask_viktor creates a thread, starts a run, waits up to timeout_seconds, and returns the result when it is ready. Results can contain Markdown, structured JSON, and file artifacts.

If the wait ends first, the response includes wait_timed_out: true and the run_id. Call wait_for_run with that ID. Do not call ask_viktor again, because that can start duplicate work unless the same idempotency key is reused.

For long-running or interactive workflows:

  1. Call create_thread to queue work without waiting.
  2. Call wait_for_run or get_run with the returned run ID.
  3. Call send_message on the same thread to continue the conversation with its history.
  4. Use get_file_download_url for any artifact IDs returned in the result.

Tool reference

Tool What it does Required scopes
ask_viktor Start a new thread and wait for its result threads:create, runs:create, runs:read
create_thread Start a new thread and queue a run without waiting threads:create, runs:create
send_message Continue an existing thread and queue a run messages:create, runs:create
wait_for_run Wait for a run to finish and return its result runs:read
get_run Read a run's current status runs:read
get_run_result Fetch a terminal run's result runs:read
cancel_run Request cancellation of an in-flight run runs:create
list_threads List the key's threads, newest first threads:read
get_thread Get a thread's status threads:read
list_messages List user-visible messages in a thread messages:read
list_runs List a thread's runs, newest first runs:read
run_script Run a Python script directly in the sandbox and wait for its result scripts:execute
wait_for_script_run Wait for a script run to finish and return its result scripts:execute
get_script_run Read a script run's status and result scripts:execute
cancel_script_run Cancel a queued script run scripts:execute
list_integrations List connected integrations and their SDK modules integrations:read
list_integration_tools List an integration's SDK tools with schemas and snippets integrations:read
get_file_download_url Exchange an artifact token for a short-lived URL files:read
whoami Identify the key, scopes, and rate limits None

Script runs without an agent

run_script executes one Python script directly in the workspace sandbox — no agent turn. The script runs as the key owner's identity and can call connected integrations through the workspace SDK. Discover what it can call with list_integrations and list_integration_tools; each tool comes with a runnable snippet that run_script accepts as-is. Output files written to the directory in the VIKTOR_OUTPUT_DIR environment variable come back as artifacts for get_file_download_url. If the wait ends before the script finishes, the response includes wait_timed_out: true — continue with wait_for_script_run, not another run_script. See script runs in the Public API guide for limits.

Structured output

ask_viktor, create_thread, and send_message accept the same response_format JSON Schema as the REST API. When supplied, the completed result includes a validated json value. See the Public API guide.

Timeouts, progress, and retries

ask_viktor and wait_for_run perform bounded server-side polling. Clients that send an MCP progress token receive best-effort progress notifications while waiting.

Every tool call is rate limited against the same policy as its REST equivalent, scaled to the workspace's plan tier (higher plans get proportionally higher limits — see the Public API guide). If a wait times out, call wait_for_run again with the same run ID. Use idempotency_key whenever a tool starts a run so reconnects and retries cannot duplicate work.

Errors

Authentication failures are plain HTTP 401 or 403 responses so MCP clients can recognize credential problems. Tool failures are machine-readable JSON strings with an error and message, and may include http_status, scope, or rate-limit details.

Common fixes: