RudderVirt

#Building with AI agents

Rudder Virt exposes a Model Context Protocol (MCP) server so AI agents and other automation can create and maintain modules without using the web editor. An agent connected to the server can list and read modules, write module details, manifests, and rubrics, run and promote builds, and review grades. It can also read this documentation, so it can learn the aileron manifest format before writing one.

The MCP server is an alternative entry point to the same logic the web app uses. Everything an agent does is subject to the same authorization and audit rules as the UI.

#Getting an API key

The MCP server uses the same API key as the rest of the Rudder Virt API. Generate one in the web app:

  1. Open your organization's admin area and go to APIs.
  2. Select Generate New API Key and copy the key. It is shown only once.

Each user has one active key. Generating a new key invalidates the previous one, and Invalidate API key revokes it entirely. The key acts as you: every call is authorized against your roles at the time of the call. You must be an admin (teacher or admin role) of an organization to author or build its modules, and the organization must be permitted to create modules.

#Connecting a client

Authenticate with the API key as a bearer token. Replace YOUR_API_KEY with the key you generated.

Claude Code: add the server from your terminal.

claude mcp add --transport http ruddervirt https://your-ruddervirt-host/mcp --header "Authorization: Bearer YOUR_API_KEY"

Other MCP clients take a JSON configuration like this (consult your client's docs for where it lives):

{
	"mcpServers": {
		"ruddervirt": {
			"type": "http",
			"url": "https://your-ruddervirt-host/mcp",
			"headers": {
				"Authorization": "Bearer YOUR_API_KEY"
			}
		}
	}
}

To check connectivity without a full client, send a tools/list request with curl:

curl -sS https://your-ruddervirt-host/mcp \
	-H "Authorization: Bearer YOUR_API_KEY" \
	-H "Content-Type: application/json" \
	-H "Accept: application/json, text/event-stream" \
	-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

A missing or invalid key returns 401. Both request headers (Content-Type and Accept) are required by the transport.

#What the agent can do

Tools are grouped by task.

Discovery

  • list_organizations: list the organizations you can author in, with your role and whether each may create modules. You belong to several, so call this first to get the organizationId that every other module tool needs.

Authoring

  • list_modules, get_module: browse an organization's modules and read one in full (details, briefing, rubric, manifest, tags, access level, builds).
  • list_base_builds: list the builds the organization may reference as a source.build_ref base image (its own Base Image-tagged modules, maintainer-shared modules, and consumer-shared Base Image modules, promoted to its zone), with the buildName and vmNames you need to write the ref.
  • create_module: create a module, or patch it in place if a module with the same name already exists in the organization. organizationId and name identify the module and everything else is optional: only the fields you pass are written, so changing one setting leaves the rubric, manifest and briefings alone. Creating a new module does require description, briefing and aileronManifest. Tags are additive here; use set_module_tag with value=null to remove one.
  • update_module_details, update_manifest, update_rubric, set_module_tag: edit the parts of an existing module.

Build and preview lifecycle

  • launch_build: start a real build of the module's current manifest in the organization's deployment zone.
  • list_builds: list builds and the current stable pointer.
  • get_build: get one build's status and its provisioner logs — how the agent watches a build in progress and works out why a failed build failed. Logs are tailed to the most recent limit entries (200 by default).
  • create_preview: launch a preview clone so you can test and grade it before promoting. Pass buildId to preview a specific succeeded build — one active preview per module, so asking for a preview of a different build fails rather than returning the wrong image. Omit buildId to preview the module's stable build for the organization's zone, which re-points an existing preview instead of failing. Returns a consoleUrl you can open to watch the VM yourself, and a previewBuildId saying which build the preview actually runs. A preview is free — no virt, no VM Slot — but it lasts one hour (expiresAt says when it ends) and an organization may only have one live at a time, across every module.
  • get_preview: read the current preview clone, which build it points at, when it expires, and its consoleUrl. Null means there is no live preview — including one that has passed its hour and been reaped.
  • reprovision_preview: reset the preview to a clean unsolved state, optionally onto a newer build as you iterate. A targetBuildId must be in the same deployment zone as the preview. This is the right way to start over. It rotates to a fresh clone of the build image and sequences the old one's teardown, and it resets the one-hour deadline.
  • destroy_preview: tear the preview down, freeing the organization's one live preview so a different module can be previewed. Not needed for cleanup, since a preview expires on its own within the hour. Teardown is asynchronous, so the clone keeps running briefly after this returns and a consolePath captured earlier still points at it. If you only want a clean VM, reprovision instead of destroying and recreating.
  • promote_stable_build: promote a succeeded build to stable.

Grading review

  • grade_preview (owner/maintainer only): autograde the module's preview clone, so an agent can test a rubric it wrote without you clicking Grade in the browser. Asynchronous; one grade in flight per preview. Grading drives the VM's serial console, so this refuses while a VM is still booting and names the power state it is in. That is a wait-and-retry answer rather than a failure, and it records no grade. A preview finishes provisioning well before its VMs finish booting.
  • get_preview_grades (owner/maintainer only — the breakdown is effectively the answer key): the preview's grade history with the full per-rubric-component breakdown: the score each component produced, the commands the grader ran, and their output. This is what tells an agent why a component scored, so it can fix a rubric that measures the wrong thing. A row with failed: true is an infrastructure failure rather than a score. Read the error in its gradeResultData and retry instead of tuning the rubric against the zero.
  • get_module_grade_summary: read the module's maximum grade (from its rubric) and aggregate grade statistics.

Documentation

  • list_docs, read_doc: list and read these documentation pages as markdown. The same pages are also offered as MCP resources under ruddervirt-docs:///<slug>.

Classroom and student management are not exposed. Use the web app for those.

#Learning the manifest format

A module is one or more virtual machines described by an aileron manifest. An agent should read the format before authoring one. The server's instructions point agents at the key pages, and they are always reachable through the documentation tools:

  • read_doc("building/reference"): every manifest field. See also Reference.
  • read_doc("building/concepts"): the primitives (sources, provisioners, networking, files). See also Concepts.
  • read_doc("building/recipes/hello-world"): a minimal worked example. See also Recipes.
  • read_doc("grader/writing-rubrics"): the rubric format. See also Writing rubrics.

#A typical authoring flow

  1. list_organizations to pick the organization to work in (one that has canCreateModules), and read_doc("building/reference") plus read_doc("building/recipes/hello-world") to learn the manifest format.
  2. list_modules to see what already exists, or get_module to read one you are revising.
  3. create_module (or update_manifest) to write the manifest, then update_rubric to add grading.
  4. launch_build, then poll get_build until isTerminal is true. If it failed, the logs it returns say why.
  5. create_preview from that build and open the consoleUrl it returns to see the VM in your browser; reprovision_preview onto a newer build as you iterate on the manifest.
  6. grade_preview to try the rubric against the preview, then get_preview_grades to see what each component scored and why. Give the VM time to boot first: grade_preview says so if it is not ready. Fix the rubric (or the manifest) and repeat, using reprovision_preview whenever you need the VM back in its unsolved state.
  7. promote_stable_build once it is good, destroy_preview to clear the way for the next module's preview, and get_module_grade_summary to review results once students have run it.

#Trying a module you did not write

An organization that only consumes a module — one shared with it, or a public module — can still preview it, to judge whether it is worth assigning. That loop is shorter, because there is no build to pick and no rubric to tune:

  1. list_modules and check hasStableBuildInOrgZone. False means the module has not been promoted into this organization's deployment zone, so there is nothing to run yet.
  2. create_preview with no buildId. The preview runs the zone's stable build, which is exactly what students get on release; any other buildId is refused for a consumer.
  3. Open the consoleUrl and work through the module.
  4. destroy_preview when finished, so the organization can preview another module. It costs nothing to leave running either — it expires within the hour on its own.

grade_preview and get_preview_grades are not part of this loop — they are limited to the module's own organization and its maintainers. See Previewing a module for the browser equivalent.