MCP (Model Context Protocol)
norsk-ctl ships a full MCP server so an LLM-driven host (Claude Code, Claude Desktop, Cursor, etc.) can drive the same operations as the CLI and web UI — launch and inspect instances, configure the daemon, and (via a proxied Studio MCP) author workflows inside each running Studio instance.
There are two MCP surfaces, one connection:
- Daemon-side tools — orchestration: launch/inspect/teardown instances, images, config.
- Per-instance Studio tools — proxied under
studio.<instanceId>.*for workflow authoring and dashboard design. They appear once the matching instance is running.
Prerequisites
Section titled “Prerequisites”- A running
norsk-ctldaemon (norsk-ctl serve, or it’ll auto-spawn). - An MCP host. Claude Code is the reference target; any host that accepts a stdio MCP entry works.
Connect from Claude Code
Section titled “Connect from Claude Code”The CLI carries the stdio bridge — norsk-ctl mcp proxies stdio to the daemon’s HTTP MCP endpoint at /mcp on the local loopback. Add this to your Claude Code MCP config:
{ "mcpServers": { "norsk-ctl": { "command": "norsk-ctl", "args": ["mcp"] } }}The bridge auto-spawns the daemon if it isn’t already running (same discovery logic as every other CLI command). The /mcp endpoint bypasses proxy auth on the loopback interface so the local bridge doesn’t need credentials.
What’s exposed
Section titled “What’s exposed”The live norsk://instructions resource is the canonical breakdown — fetch it from your MCP host (or read backend/src/mcp/instructions.md in the repo). High-level summary:
| Tool | Purpose |
|---|---|
status | Composite read: daemon readiness, instance summary, proxy state, host hardware. Call this first |
instance.list / instance.describe | Enumerate / inspect instances |
instance.launch / instance.restart / instance.relaunch / instance.delete | Lifecycle |
instance.switch_workflow | Swap the active workflow YAML and restart Studio |
instance.update_ingest_ports | Patch ingest port assignments on a running instance |
image.list / image.list_baked | Local Norsk image inventory, filtered by the norsk-ctl.baked-plugins label for baked variants |
working_directory.scaffold / working_directory.inspect | Scaffold the plugins / studio-save-files / dashboards skeleton; inspect enumerates the workflows and dashboards within |
config.show / config.set | Read / write ~/.norsk-ctl/config.yaml |
sdk.stage | Stage a Studio SDK release into a working directory |
studio.bootstrap | Recipe: idempotent zero-to-ready (writes config if absent, pulls images, reports readiness) |
workflow.create_and_apply | Recipe: write a known YAML workflow + instance.switch_workflow |
studio.<instanceId>.* | Proxied Studio MCP — appears once an instance is running |
Tool annotations follow the MCP spec: readOnlyHint on inspection tools, destructiveHint on relaunch/delete/restart/config.set, idempotentHint on restart and studio.bootstrap.
There are no daemon-side plugin tools — plugin scaffold/install/build lives on the Studio product’s HTTP API (/products/norsk-studio/api/plugins/*); see Manage plugins.
Resources
Section titled “Resources”URIs are norsk://. Read them via your host’s resource UI; bodies are sized for direct context inclusion.
norsk://index— entry-point mapnorsk://instructions— the live, canonical instructions documentnorsk://openapi/indexandnorsk://openapi/endpoint/{method}/{path}— every REST endpointnorsk://openapi/schema/{name}— every named schemanorsk://recipes/{topic}— curated recipes (launch,workflow,dashboard,working-directory,studio-mcp,sdk)norsk://state/instances,norsk://state/config,norsk://state/working-directory— live state mirrorsnorsk://studio/{instanceId}/{originalUri}— per-instance Studio resources, once an instance is up
Prompts
Section titled “Prompts”Surfaced as /mcp__norsk-ctl__<name> in Claude Code. Each is a markdown brief that tells the model how to use the tools — they don’t call the tools themselves.
launch-studio— get a running Studio with a workflow loadednew-workflow— author a workflow via the Studio MCP pathinspect-studio— guided read of an existing instanceextend-studio— end-to-end feature build (workflow + dashboard, with optional plugin steps that point at the Studio product’s/api/pluginsendpoints)
Search
Section titled “Search”docs.search is the discovery escape hatch — keyword search across recipes, OpenAPI summaries, named-schema descriptions, and the instructions doc. Returns { uri, snippet, score } so you can follow up with a targeted resources/read.
How the proxied Studio MCP works
Section titled “How the proxied Studio MCP works”Each running Studio container exposes its own MCP server over HTTP. The norsk-ctl MCP server opens a client to each one as it comes up and re-registers its tools, resources, and prompts under a per-instance namespace.
- Tools appear as
studio.<instanceId>.<originalToolName>(e.g.studio.live-9100.workflow.list). Each carries[instance: <id>]in its description so the model picks the right one in multi-instance environments. - Resources appear as
norsk://studio/<instanceId>/<originalUri>. - Prompts appear as
studio.<instanceId>.<originalPromptName>. notifications/tools/list_changedandnotifications/resources/list_changedfire on instance up/down so the host’s tool list grows and shrinks without a reconnect.
Use the proxied tools whenever you’re authoring workflows or dashboards — the daemon side cannot author those for you.
Gotchas
Section titled “Gotchas”- Plugin changes don’t apply to running instances. Rebuild the baked image via the Studio product’s
plugins/buildendpoint and relaunch from a product template that pins it. workflow.create_and_applyis not the authoring path. It applies a known YAML body. Author via the Studio MCP (studio.<id>.*tools) and use this only to apply backups, fixtures, or cross-instance copies.- Studio MCP shows up asynchronously. After
instance.launchreturns, the daemon retries the upstream MCP handshake with exponential backoff. If the tool list doesn’t includestudio.<id>.*immediately, give it a few seconds. - The
/mcpendpoint is loopback-bypass. It is unauthenticated on the loopback interface only. The proxy refuses to forward/mcptraffic from the outside — connect via the stdio bridge, not the public proxy URL.
See also
Section titled “See also”- Manage plugins — plugin tooling, on the Studio product’s HTTP API
- The live
norsk://instructionsresource is the source of truth — read it from your MCP host or openbackend/src/mcp/instructions.mdin the repo