Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import sidebarDeveloper from './sidebar-menus/plugin-development'
import sidebarLearning from './sidebar-menus/learning'
import sidebarHistory from './sidebar-menus/history'
import sidebarAbout from './sidebar-menus/about'
import sidebarMcp from './sidebar-menus/mcp'

import apiMenu from './sidebar-menus/api'

Expand Down Expand Up @@ -330,6 +331,7 @@ export default defineUserConfig({
'/manual/': sidebarUserGuide,
'/learning/': sidebarLearning,
'/developer/': sidebarDeveloper,
'/mcp/': sidebarMcp,
'/history/': sidebarHistory,
'/api/': apiMenu,
'/': [
Expand Down
6 changes: 3 additions & 3 deletions docs/.vuepress/layouts/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ const isHomePage = computed(() => pageData.value.frontmatter.home === true);
<Layout>
<!-- Adding announcement before content (works on all pages) -->
<template #heroAfter>
<div v-if="isHomePage"class="homepage-announce">
<div v-if="isHomePage" class="homepage-announce">
<p>
<b>Rundeck / Runbook Automation 6.1.0</b> is now available! <a href='/history/6_x/version-6.1.0.html'>Check out the <b>Release Notes</b> for more information.</a>
<b>The Rundeck MCP Server is now available for download! <a href='/mcp/'>Check out the documentation</a> for more information.</b>
</p>
</div>
</template>
Expand All @@ -23,7 +23,7 @@ const isHomePage = computed(() => pageData.value.frontmatter.home === true);
<template #sidebarTop>
<div v-if="!isHomePage" class="sidebar-announce">
<p>
<a href='/history/6_x/version-6.1.0.html'><b>6.1.0</b> is now available! Check out the <b>Release Notes</b> for more information.</a>
<b><a href='/mcp/'>Check out the new Rundeck MCP Server documentation!</a></b>
</p>
</div>
</template>
Expand Down
4 changes: 4 additions & 0 deletions docs/.vuepress/navbar-menus/development.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ export default [{
text: 'API',
link: '/api/'
},
{
text: 'MCP Server',
link: '/mcp/'
},
{
text: 'Plugin Development',
link: '/developer/'
Expand Down
17 changes: 17 additions & 0 deletions docs/.vuepress/sidebar-menus/mcp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default [
{
text: 'MCP Server',
collapsible: true,
link: '/mcp/',
children: [
{ text: 'Overview', link: '/mcp/' },
{ text: 'Installation', link: '/mcp/installation.md' },
{ text: 'Other Setups', link: '/mcp/other-setups.md' },
{ text: 'Best Practices', link: '/mcp/best-practices.md' },
{ text: 'Configuration Reference', link: '/mcp/configuration.md' },
{ text: 'Multiple Instances', link: '/mcp/multiple-instances.md' },
{ text: 'Technical Capabilities', link: '/mcp/capabilities.md' },
{ text: 'FAQ & Troubleshooting', link: '/mcp/faq.md' },
]
}
]
27 changes: 27 additions & 0 deletions docs/mcp/best-practices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Best Practices

A short checklist for running the MCP server against a real Rundeck instance, not just a sandbox. None of this is enforced by the server itself; it's what to set up around it.

## Before you point it at a real instance

- **Use a dedicated Rundeck user for the API token, not your own account.** If you ever need to cut off the assistant's access, you disable one token instead of your own login. It also keeps a clean audit trail: actions the assistant takes show up under that user, not mixed in with your own manual changes.

Create the user in Rundeck, then generate its token from that user's own profile page (**User Profile → Generate API Token**).

- **Write an ACL policy scoped to that user, limiting it to what you're comfortable with an AI assistant doing.** Without one, that user (and therefore the assistant) has whatever access Rundeck's defaults grant. The ACL policy is the actual enforcement point, not the tools themselves (see the next item).

Start narrow (specific projects, read-only, no job execution) and widen it as you get comfortable. Validate any policy with `acl_validate` before submitting it with `acl_manage`. See [ACL policies](capabilities.md#acl-policies).

- **Review generated job definitions and ACL policies before they go anywhere.** `job_create`, `job_validate`, and `acl_validate` check structure only, not your organization's conventions or Rundeck's own server-side rules. See [Technical Capabilities](capabilities.md) for exactly what each one covers.

- **Point it at a non-production instance first**, especially the first time you chain `job_create` into `api_call`'s import endpoint. Confirm the round-trip does what you expect before doing it against production.

- **Treat the API token like a credential, because it is one.** Don't put it in shell history, commit it to version control, or paste it into a shared doc or ticket. If you're using `RUNDECK_INSTANCES` for more than one environment, keep the registry file `chmod 600` and out of any repo. See [Multiple Instances](multiple-instances.md).

- **Rotate the token periodically, and know how to revoke it.** This is easiest with a dedicated user (first item above): revoking that one token cuts the assistant off without touching anyone else's access.

## Related

- [Technical Capabilities](capabilities.md): what each tool actually checks vs. submits
- [Multiple Instances](multiple-instances.md): the `RUNDECK_INSTANCES` registry and file permissions
- [FAQ & Troubleshooting](faq.md)
60 changes: 60 additions & 0 deletions docs/mcp/capabilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Technical Capabilities

Everything the Rundeck MCP Server exposes to an AI assistant: **tools** (actions it can take), **resources** (documentation it can read), and **prompts** (guided workflows it can walk through). You don't need to know any of this to use the server — describe what you want, and the assistant picks the right one. This page exists for two narrower reasons: trusting what the assistant did after it acted, and building against the protocol directly (a custom client, prompt, or skill layered on top).

## Tools

Tools are how the assistant acts: calling the Rundeck API, generating and validating job definitions, managing ACL policies, provisioning runners. All inputs are validated with [Zod](https://zod.dev) schemas — for exact parameters, ask the assistant or inspect the server directly; the schemas live in the code, not here, so a written copy can't drift out of sync with it.

### Guidance mode

For most tools (`api_call`, `job_create`, `job_validate`, `runner_create`, `acl_validate`, `acl_manage`, `rundeck_connect`), calling one without its required arguments doesn't fail outright — it returns markdown **guidance** explaining what's needed, so the assistant can recover and ask a follow-up instead of dead-ending. Malformed input (wrong type, invalid enum value) still returns a normal validation error. `job_create`, `job_validate`, `runner_create`, and `acl_manage` each name a fallback `api_call` endpoint in their guidance response, for the rare case the specialized tool doesn't cover what you need.

### API access

`api_call` executes a request against your live instance — querying projects, jobs, executions, or nodes, or triggering a run. `api_list` discovers available endpoints by category first, if you're not sure what's there. Requires `RUNDECK_URL` and `RUNDECK_TOKEN`.

### Destructive-action confirmation

A `DELETE` request through `api_call` (including a runner's `regenerateCreds` endpoint) and `acl_manage` calls with `action: "delete"` or `"update"` all pause before reaching Rundeck: the assistant's MCP client is asked to confirm the action with you directly, and the call only proceeds once you approve. A decline is a hard stop — there's no retry path around it. If your client can't prompt you this way, the call is blocked outright rather than skipped silently. Server operators can disable the check entirely with `SKIP_ELICITATION` (see [Configuration Reference](configuration.md)).

### Job definitions

`job_create` generates a job definition (YAML or JSON) from a plain-language description — workflow steps, node filters, options, schedules — without calling your instance. `job_validate` checks an existing definition's structure before import.

**Scope note:** both check structure only — required fields, valid `loglevel` values, a well-formed workflow. Neither knows or enforces your organization's own conventions: required notification targets, where secrets must be stored, naming standards. If you want an assistant to apply house rules on top of what these generate, that's a custom prompt or client-side skill layered on top, not something these tools do themselves.

### Runners

`runner_create` provisions a Rundeck Runner at system or project scope, on Docker, Kubernetes, Linux, or Windows. It only *registers* the runner — fetching and starting it is always a separate, later step. The response includes a one-time token that can't be retrieved again, so the assistant should surface it to you immediately.

**ACL note:** Rundeck enforces access control at the Runner level. There's no separate ACL context for a Runner's individual Replicas — a Replica's visibility follows whatever the parent Runner's ACL grants. If a Replica isn't visible where you expect, check the Runner-level grant, not a Replica-specific one (there isn't one).

### ACL policies

Rundeck ACL policies are easy to get subtly wrong by hand — a missing `context`, `by`, or `allow`/`deny` clause silently turns into a denied access check with no error at edit time. `acl_validate` checks a policy's structure offline before it's ever submitted (not a substitute for Rundeck's own server-side validation). `acl_manage` lists, gets, creates, updates, or deletes a stored policy file at system or project scope; `update` and `delete` require confirmation (see [Destructive-action confirmation](#destructive-action-confirmation)). See [Best Practices](best-practices.md) for scoping a policy to the user whose token the assistant uses.

### Documentation search

`docs_search` searches local Rundeck documentation by keyword, with optional category filters, when you don't already know the exact resource to read. It returns ranked excerpts, not full pages — the assistant follows up by reading the matching resource directly.

### Multi-instance connection

`rundeck_connect` switches the active Rundeck instance by name. It only exists at all when `RUNDECK_INSTANCES` is configured — see [Multiple Instances](multiple-instances.md).

## Resources

Resources give an AI assistant read-only access to Rundeck documentation, addressed with `rundeck://` URIs. Two kinds:

- **Self-contained**, built into the server and always available: API reference, job schemas, workflow strategies, node filter syntax, terminology, and plugin overviews.
- **`rundeck://docs/*`**, which mirror the published documentation site (manual, administration, developer, rd-cli, integrations) and read from a local checkout at `RUNDECK_DOCS_PATH` (see [Configuration Reference](configuration.md)).

The assistant discovers and reads these on its own — there's nothing to configure or invoke directly.

## Prompts

Prompts are pre-configured, guided workflows for common tasks: creating a job, making an API call, configuring a project, setting up authentication, writing a node filter, integrating a plugin. Where a tool's guidance mode gives a nudge on one missing parameter, a prompt is the full walkthrough — documentation references, tool recommendations, and step-by-step instructions in one response.

Most of the time you won't invoke these directly; asking the assistant naturally gets you the same result. If your client has a prompt picker (in Claude Code, `/mcp` lists connected servers' prompts), it surfaces each prompt's optional arguments there — you don't need them memorized here.

> Plugin *scaffolding* (generating new plugin source code) isn't exposed as an MCP tool or prompt. Plugin-related prompts and resources cover configuring and using existing plugins, not authoring new ones.
41 changes: 41 additions & 0 deletions docs/mcp/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Configuration Reference

Every environment variable the MCP server reads, in one place. If you just want the two you need to get started, see [Installation](installation.md#required-configuration) instead — this page is for when you want the complete picture, or need something not covered there.

## Connection

| Variable | Applies to | Default | Purpose |
|---|---|---|---|
| `RUNDECK_URL` | Docker & npx | — | Base URL of your Rundeck instance, e.g. `https://rundeck.example.com`. Required for `api_call` and anything that calls through it (`runner_create`, `acl_manage`); `job_create`/`job_validate` need no live instance. |
| `RUNDECK_TOKEN` | Docker & npx | — | Rundeck API token. Same requirement as `RUNDECK_URL`. |
| `RUNDECK_INSTANCES` | Docker & npx | — | JSON registry of multiple named Rundeck instances, for switching between them (e.g. prod/staging) in the same session instead of setting `RUNDECK_URL`/`RUNDECK_TOKEN` directly. See [Multiple Instances](multiple-instances.md). |

## API behavior

| Variable | Applies to | Default | Purpose |
|---|---|---|---|
| `RUNDECK_API_VERSION` | Docker & npx | `59` | Rundeck API version appended to the base URL. Only needed if your instance runs a different supported version. |
| `RUNDECK_API_TIMEOUT_MS` | Docker & npx | `30000` | Timeout for `api_call`'s underlying HTTP request (also bounds `runner_create` and `acl_manage`). |
| `RUNDECK_SKIP_OPENAPI_VALIDATE` | Docker & npx | — | Set to `1` to disable pre-request validation of `api_call` parameters against the shipped OpenAPI spec. |

## Documentation source (npx only)

The Docker image resolves its own bundled documentation automatically at a fixed path, so none of these three apply to it.

| Variable | Applies to | Default | Purpose |
|---|---|---|---|
| `RUNDECK_DOCS_PATH` | npx only | Auto-detected (rarely resolves for an MCP client) | Path to a Rundeck documentation checkout on disk. Without it, `docs_search`, the documentation resources, and OpenAPI-based validation in `api_call` silently come up empty. |
| `RUNDECK_DOCS_BRANCH` | npx only | `4.0.x` | Branch of [rundeck/docs](https://github.com/rundeck/docs) to download when no documentation is already present. |
| `SKIP_RUNDECK_DOCS_DOWNLOAD` | npx only | — | Set to `1` to skip the automatic documentation download during `npm install`/`npm ci`. |

## Safety

| Variable | Applies to | Default | Purpose |
|---|---|---|---|
| `SKIP_ELICITATION` | Docker & npx | — | Set to `1` or `true` to bypass the confirmation prompt for destructive actions (`api_call` `DELETE`/credential regeneration, `acl_manage` `update`/`delete`) and let them proceed without asking. A server-operator setting, not something an agent can set via tool parameters. See [Destructive-action confirmation](capabilities.md#destructive-action-confirmation). |

## Diagnostics

| Variable | Applies to | Default | Purpose |
|---|---|---|---|
| `MCP_DEBUG` | Docker & npx | — | Set to `1` or `true` for verbose server-side logging. |
51 changes: 51 additions & 0 deletions docs/mcp/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# FAQ & Troubleshooting

## Setup

### `docs_search` and documentation resources return nothing

This almost always means `RUNDECK_DOCS_PATH` isn't resolving:

1. Confirm the environment variable is actually set in your MCP client's configuration (see [Other Setups](other-setups.md)). Auto-detection only works when the server is launched from inside its own repository checkout, which is never the case when an MCP client spawns it.
2. Confirm the path points at an actual documentation checkout on disk, and that it contains the expected markdown files.
3. If you're on the Docker image, this shouldn't come up; it resolves its own bundled docs path automatically. If it does, check that `RUNDECK_DOCS_PATH` wasn't set to a container-local path that doesn't exist.

### `api_call` (or anything that calls through it) fails

1. Verify `RUNDECK_URL` is correct and reachable from wherever the server process runs.
2. Verify `RUNDECK_TOKEN` is valid and has the permissions the call needs.
3. Verify `RUNDECK_API_VERSION` matches a version your instance actually supports.
4. If the error mentions a timeout, the instance may be unreachable or overloaded. `RUNDECK_API_TIMEOUT_MS` controls how long the server waits before giving up (default 30 seconds).
5. If the error is about an unrecognized endpoint or parameter, check your Rundeck version (see below).

### `api_call` rejects an endpoint or parameter that looks correct

Each MCP server release validates `api_call` requests against the OpenAPI spec current as of that release, and may expect endpoints or fields that don't exist on an older Rundeck/RBA instance. This is most likely to show up if your instance predates **Rundeck 6.1.0** — the release that introduced API v59, the server's default `RUNDECK_API_VERSION`. Upgrade the Rundeck instance, or, if that's not possible, set `RUNDECK_SKIP_OPENAPI_VALIDATE=1` to bypass the local check. This applies on both Docker and npx.

### The Docker container won't start

The Docker daemon needs to be *running*, not just installed (Docker Desktop, Rancher Desktop, etc.), since your MCP client starts a container on demand each time it connects: if the daemon isn't up, the connection fails before the server ever gets a chance to run.

## Behavior

### Does `job_create` enforce our organization's coding standards?

No. `job_create` and `job_validate` check structure only. See their entries in [Technical Capabilities](capabilities.md) for exactly what that covers. Neither knows about organization-specific conventions like "secrets must come from a particular key storage path" or "job failures must trigger a specific notification."

If you want an assistant to apply house rules on top of what these tools generate, that's a job for a custom prompt or client-side skill layered on top of the MCP server, not a configuration option on `job_create` itself. The tool is deliberately generic, useful across every Rundeck/RBA setup rather than tuned to one.

### I generated an ACL policy for a Runner, but its Replicas don't show up the way I expected

This is expected. Rundeck enforces ACLs at the Runner level: there's no separate ACL context for an individual Replica. A Replica's visibility follows whatever the parent Runner's ACL grants (typically `runner: [read]`); there's no additional grant to add for the Replicas themselves. If a Replica isn't visible where you expect, check the Runner-level grant rather than looking for a Replica-specific one.

### Why does the npm/`npx` setup need `RUNDECK_DOCS_PATH`, but Docker doesn't?

`npm install` downloads a documentation checkout as part of its postinstall step, but into the installed package's own directory, not the working directory your MCP client happens to launch the process from. The server's auto-detection logic only looks in a few `cwd`-relative locations, so it won't find that download unless your client's working directory happens to line up. Setting `RUNDECK_DOCS_PATH` explicitly sidesteps the guesswork. The Docker image doesn't have this problem because its documentation lands at a fixed, known path inside the container every time.

### Why did the assistant stop and ask me to confirm before deleting or updating something?

Destructive actions — an `api_call` `DELETE` (including regenerating a runner's credentials) or `acl_manage` with `update`/`delete` — always pause for your explicit confirmation before they reach Rundeck; the assistant can't answer on your behalf. See [Destructive-action confirmation](capabilities.md#destructive-action-confirmation). If you're a server operator and want to remove this check entirely, set `SKIP_ELICITATION` (see [Configuration Reference](configuration.md)) — there's no way to bypass it per-call from the assistant side.

### What happens if I call a tool without its required parameters?

For most tools, you get back **guidance** (a markdown explanation of what's needed and why) instead of a hard error, so an assistant can recover and ask a follow-up question rather than dead-ending. See [Guidance mode](capabilities.md#guidance-mode) for exactly which tools support this and what triggers it. Malformed input (wrong type, invalid enum value) still returns a normal validation error.
Loading
Loading