#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:
- Open your organization's admin area and go to APIs.
- 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 theorganizationIdthat 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 asource.build_refbase image (its ownBase Image-tagged modules, maintainer-shared modules, and consumer-sharedBase Imagemodules, promoted to its zone), with thebuildNameandvmNamesyou 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.organizationIdandnameidentify 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 requiredescription,briefingandaileronManifest. Tags are additive here; useset_module_tagwithvalue=nullto 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 recentlimitentries (200 by default).create_preview: launch a preview clone so you can test and grade it before promoting. PassbuildIdto 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. OmitbuildIdto preview the module's stable build for the organization's zone, which re-points an existing preview instead of failing. Returns aconsoleUrlyou can open to watch the VM yourself, and apreviewBuildIdsaying which build the preview actually runs. A preview is free — no virt, no VM Slot — but it lasts one hour (expiresAtsays 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 itsconsoleUrl. 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. AtargetBuildIdmust 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 aconsolePathcaptured 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 withfailed: trueis an infrastructure failure rather than a score. Read theerrorin itsgradeResultDataand 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 underruddervirt-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
list_organizationsto pick the organization to work in (one that hascanCreateModules), andread_doc("building/reference")plusread_doc("building/recipes/hello-world")to learn the manifest format.list_modulesto see what already exists, orget_moduleto read one you are revising.create_module(orupdate_manifest) to write the manifest, thenupdate_rubricto add grading.launch_build, then pollget_builduntilisTerminalis true. If it failed, the logs it returns say why.create_previewfrom that build and open theconsoleUrlit returns to see the VM in your browser;reprovision_previewonto a newer build as you iterate on the manifest.grade_previewto try the rubric against the preview, thenget_preview_gradesto see what each component scored and why. Give the VM time to boot first:grade_previewsays so if it is not ready. Fix the rubric (or the manifest) and repeat, usingreprovision_previewwhenever you need the VM back in its unsolved state.promote_stable_buildonce it is good,destroy_previewto clear the way for the next module's preview, andget_module_grade_summaryto 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:
list_modulesand checkhasStableBuildInOrgZone. False means the module has not been promoted into this organization's deployment zone, so there is nothing to run yet.create_previewwith nobuildId. The preview runs the zone's stable build, which is exactly what students get on release; any otherbuildIdis refused for a consumer.- Open the
consoleUrland work through the module. destroy_previewwhen 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.