@argo-mcp/mcp-argo-workflows
v1.2.0
Published
MCP server for Argo Workflows
Readme
Argo Workflows MCP
An MCP server that exposes Argo Workflows operations as tools. It connects to an Argo Workflows API server and lets MCP clients list, inspect, submit, and manage workflows, archived workflows, artifacts, Argo Events EventSources, and Sensors.
Table of contents
- Overview
- Quick start
- Launching the server
- CLI flags
- Environment variables
- Registering with an MCP client
- Tool reference
- Troubleshooting
Overview
The server speaks the MCP protocol over a streamable HTTP transport by default, or over stdio when launched with
--stdio (for embedding directly in an MCP client). On start-up it builds a typed Argo Workflows client from the
supplied CLI flags / environment variables, registers the full tool set (~38 tools), and serves requests until it
receives SIGINT or SIGTERM.
Authentication mirrors the way the upstream argo CLI authenticates: a static or rotating bearer token, a projected
Kubernetes service-account token, or no credentials at all. SSO is an Argo UI concern and is not supported here;
if your MCP client needs SSO it must mint a bearer token externally and pass it via one of the bearer modes below.
Quick start
Run against a local Argo Workflows server with no auth (development only):
just run-workflows --argo-server-url http://localhost:2746 --argo-auth-mode noneThen register it with your MCP client (see Registering with an MCP client).
The rest of this README walks through the run modes (how the server is invoked) and the auth modes (how it authenticates to the Argo server). Pick one from each section and combine the flags.
Launching the server
You need three things to launch:
- Server URL —
--argo-server-urlorARGO_SERVER_URL. Point at the Argo Workflows API server (e.g.https://argo.example.com). For a port-forwarded local server usehttp://localhost:2746. - Run mode — how the process itself is started: dev recipe, built binary, or HTTP-with-TLS. See Run modes.
- Auth mode —
--argo-auth-modeorARGO_AUTH_MODE. One ofbearer,bearer-file,k8s-service-account, ornone. Defaults tok8s-service-accountwhenKUBERNETES_SERVICE_HOSTis set (in-cluster), otherwisenone. See Auth modes.
Every example below combines a run-mode invocation with one auth mode's flags. Swap the auth flags for any other mode from the Auth modes section.
Run modes
Dev (no build) via just
Runs the TypeScript entry point with Bun. Best for local development against a real Argo server.
ARGO_TOKEN="<token>" just run-workflows \
--argo-server-url https://argo.example.com \
--argo-auth-mode bearerAll flags after run-workflows are forwarded to the server. Override the listener with --host / --port:
just run-workflows \
--host 127.0.0.1 \
--port 9001 \
--argo-server-url https://argo.example.com \
--argo-auth-mode noneBuilt binary
After building, the package exposes a mcp-argo-workflows bin (declared in
apps/mcp-argo-workflows/package.json#bin). Inside this repo, invoke the built artifact directly with node:
just filter mcp-argo-workflows
node apps/mcp-argo-workflows/dist/index.mjs \
--argo-server-url https://argo.example.com \
--argo-auth-mode k8s-service-accountAfter installing the package globally (or in a container that puts the bin on PATH), the same invocation becomes:
mcp-argo-workflows \
--argo-server-url https://argo.example.com \
--argo-auth-mode k8s-service-accountThis is the form to use inside a container or Pod.
Published package
The server is published to two registries under different scopes — same code, pick whichever fits:
| Registry | Scope | Package | Stable (@latest) | Prerelease (@alpha) | Auth |
| --------------- | ------------ | ------------------------------- | :----------------: | :-------------------: | ------------------------------ |
| npm (npmjs.org) | @argo-mcp | @argo-mcp/mcp-argo-workflows | ✓ | — | none — public |
| GitHub Packages | @odinn1984 | @odinn1984/mcp-argo-workflows | ✓ | ✓ | GitHub token (read:packages) |
For stable releases, use whichever fits (npmjs is easier). Alpha builds are only on GitHub Packages.
Internal workspace dependencies are bundled — no repo checkout or build required either way.
From npmjs (recommended for stable)
No .npmrc config needed:
npx -y @argo-mcp/mcp-argo-workflows \
--argo-server-url https://argo.example.com \
--argo-auth-mode k8s-service-accountFrom GitHub Packages
GitHub Packages requires authentication even for reads. Point the @odinn1984 scope at the GitHub registry
and supply a token with read:packages in ~/.npmrc:
@odinn1984:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}Then run it with npx:
npx -y @odinn1984/mcp-argo-workflows \
--argo-server-url https://argo.example.com \
--argo-auth-mode k8s-service-accountDist-tags
@latest— stable releases cut from Conventional Commits onmain. Published to both registries.@alpha— preview builds, published on every feature-branch / PR push as<x.y.z>-git<short-sha>. Published to GitHub Packages only.
Pin a version (e.g. @argo-mcp/[email protected]) when embedding the server in an MCP client config so
upgrades stay explicit.
HTTP with TLS
The default transport is HTTP on port 8081. To serve over HTTPS, supply both --tls-cert and --tls-key
(passing only one is an error):
just run-workflows \
--tls-cert ./certs/server.crt \
--tls-key ./certs/server.key \
--argo-server-url https://argo.example.com \
--argo-auth-mode bearer-file \
--argo-token-file ~/.argo/tokenstdio
Pass --stdio to speak MCP over the process' stdin/stdout instead of HTTP — the transport an MCP client uses when it
launches the server as a child process. --host, --port, and --tls-* are ignored in this mode; the --argo-*
connection flags still apply. All diagnostics go to stderr so they never corrupt the protocol stream.
just run-workflows --stdio \
--argo-server-url https://argo.example.com \
--argo-auth-mode bearer-file \
--argo-token-file ~/.argo/tokenAuth modes
Pick one and slot its flags into any of the run-mode commands above.
| Mode | Credential source |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| bearer | Static bearer token from the ARGO_TOKEN environment variable. |
| bearer-file | Bearer token read from --argo-token-file (re-read on each request). |
| k8s-service-account | Kubernetes service-account token; default path /var/run/secrets/kubernetes.io/serviceaccount/token, override with --argo-token-file. |
| none | No authentication (anonymous access). |
bearer — static token from the environment
Use when you have a long-lived service-account token or a freshly minted token and want to pass it directly.
How to get the token
From the Argo CLI (mints a token for the current kubeconfig user):
argo auth tokenThe first line of stdout (after the
Bearerprefix) is the token. Strip theBearerprefix and the trailing space when settingARGO_TOKEN.From a Kubernetes service-account in the
argonamespace (Argo ≥ 3.4 with client-side token generation):kubectl -n argo create token argo-server --duration=24hFrom a long-lived service-account Secret (Kubernetes ≤ 1.23 style, or a manually-created
kubernetes.io/service-account-tokenSecret):kubectl -n argo get secret <sa-secret-name> -o jsonpath='{.data.token}' | base64 -d
Auth flags
--argo-auth-mode bearerThe token is read from the ARGO_TOKEN environment variable at boot:
export ARGO_TOKEN="<token>"Note:
ARGO_TOKENis an environment variable, not a CLI flag, so the token never appears in the host's process list. It is read once at boot and fixed until restart — for a rotating token usebearer-file.
bearer-file — token read from a file each request
Use when the token rotates on disk (sidecar refresher, kubectl create token cron, etc.). The file is re-read on every
outbound request, so rotation is picked up without restarting the server.
How to get the token file
Write any of the bearer-token sources above to a file:
kubectl -n argo create token argo-server --duration=24h > ~/.argo/token chmod 600 ~/.argo/tokenOr have your token refresher write to that path on a schedule. The file must contain just the raw token (no
Bearerprefix or surrounding whitespace; trailing whitespace is trimmed on read).
Auth flags
--argo-auth-mode bearer-file --argo-token-file ~/.argo/tokenk8s-service-account — in-cluster service-account token
Use when the MCP server runs inside the same Kubernetes cluster as Argo Workflows (e.g. as a Pod). The container's projected service-account token is read from disk and sent as a bearer token.
How to get the token
Nothing to do — the kubelet projects the token onto the Pod's filesystem. The default path is:
/var/run/secrets/kubernetes.io/serviceaccount/tokenFor this to work, the Pod's ServiceAccount needs RBAC permissions against the Argo API server (typically a
RoleBinding to a Role with workflows, workflowtemplates, etc. verbs).
Auth flags (default token path)
--argo-auth-mode k8s-service-accountAuth flags with a custom token path (e.g. a non-default projected volume, or a token mounted from a kubectl create
token cron):
--argo-auth-mode k8s-service-account --argo-token-file /var/run/argo/tokenWhen KUBERNETES_SERVICE_HOST is set you can omit --argo-auth-mode entirely — the server defaults to
k8s-service-account in-cluster.
none — no authentication
Use only against an Argo server that has authentication disabled (--auth-mode=server on the Argo server, or a local
dev cluster). No credential is sent.
Auth flags
--argo-auth-mode noneCLI flags
| Flag | Type | Default | Description |
| --------------------------------- | ------- | --------- | -------------------------------------------------------------------------------------------------------------------- |
| --stdio | boolean | false | Speak MCP over stdio instead of HTTP (for embedding in an MCP client); ignores --host/--port/--tls-*. |
| --host | string | 0.0.0.0 | Bind address (HTTP transport only). |
| --port | string | 8081 | TCP port (HTTP transport only). |
| --tls-cert | string | — | Path to a PEM-encoded TLS certificate (requires --tls-key). |
| --tls-key | string | — | Path to a PEM-encoded TLS private key (requires --tls-cert). |
| --argo-server-url | string | — | Argo Workflows server URL (e.g. https://argo.example.com). |
| --argo-auth-mode | string | see note | Auth mode: bearer, bearer-file, k8s-service-account, or none. Defaults to k8s-service-account in-cluster, otherwise none. |
| --argo-token-file | string | — | Path to a token file (required for bearer-file; overrides the default path for k8s-service-account). |
| --argo-default-namespace | string | argo | Default Kubernetes namespace used when a tool call omits one. |
| --argo-insecure-skip-tls-verify | boolean | false | Skip TLS verification for outbound Argo requests (debug only). Scoped to the Argo client — other connections still verify TLS. |
Environment variables
The --argo-* connection flags fall back to environment variables when the flag is absent. A flag always wins over its
environment variable.
| Variable | Equivalent flag |
| ------------------------------- | ---------------------------------------------------------------- |
| ARGO_SERVER_URL | --argo-server-url |
| ARGO_AUTH_MODE | --argo-auth-mode |
| ARGO_TOKEN | (environment only — bearer mode has no token flag) |
| ARGO_TOKEN_FILE | --argo-token-file |
| ARGO_DEFAULT_NAMESPACE | --argo-default-namespace |
| ARGO_INSECURE_SKIP_TLS_VERIFY | --argo-insecure-skip-tls-verify (set to 1, true, or yes) |
Registering with an MCP client
Point the URL at whatever host and port the server is bound to. Any MCP client that supports the streamable HTTP transport can connect the same way. With the Claude Code CLI:
claude mcp add --transport http argo-workflows http://localhost:8081To have the client launch the server itself, register the --stdio command instead:
claude mcp add argo-workflows -- \
mcp-argo-workflows --stdio --argo-server-url https://argo.example.com --argo-auth-mode noneTool reference
Each tool is annotated as read-only or destructive. Read-only tools have no side effects on the Argo server. Destructive tools mutate or delete cluster state and may be irreversible.
Info
| Tool | Description | Kind |
| ------------------ | ------------------------------------------------------------------------------------------------------ | --------- |
| get_argo_info | Return the Argo Workflows server-level info (executor image, default executor, links, navColor, etc.). | Read-only |
| get_argo_version | Return the Argo Workflows server version (semantic version, git commit, build date, Go version). | Read-only |
| get_user_info | Return the authenticated user identity as seen by the Argo server (issuer, subject, groups, email). | Read-only |
Workflow read
| Tool | Description | Kind |
| ------------------- | ----------------------------------------------------------------------------------------------- | --------- |
| list_workflows | List workflows in a namespace with optional label/field selectors and pagination. | Read-only |
| get_workflow | Fetch a single workflow by name (full Workflow resource: spec + status). | Read-only |
| get_workflow_logs | Stream-drain workflow logs across one or all pods into a single text payload (capped at ~64KB). | Read-only |
| get_pod_logs | Stream-drain logs for a single pod inside a workflow into one text payload (capped at ~64KB). | Read-only |
Workflow lifecycle
| Tool | Description | Kind |
| ------------------- | ------------------------------------------------------------------------------------------------------ | --------- |
| submit_workflow | Submit a workflow from a referenced template (WorkflowTemplate, ClusterWorkflowTemplate, CronWorkflow). | Mutating |
| lint_workflow | Lint a workflow manifest server-side without creating it. | Read-only |
| suspend_workflow | Suspend a running workflow at the next step boundary (reversible via resume_workflow). | Mutating |
| resume_workflow | Resume a previously suspended workflow. | Mutating |
| resubmit_workflow | Resubmit a workflow as a new run; the original workflow is left untouched. | Mutating |
| set_workflow | Set node-level fields on a workflow: phase, message, or output parameters. | Mutating |
Workflow destructive
| Tool | Description | Kind |
| -------------------- | ----------------------------------------------------------------------------------------------- | ----------- |
| retry_workflow | Retry a failed or errored workflow; failed pods are deleted and the run restarts. Irreversible. | Destructive |
| stop_workflow | Gracefully stop a running workflow via the exit handler, leaving it in a terminal state. | Destructive |
| terminate_workflow | Hard-kill a workflow; every pod is deleted immediately without running exit handlers. | Destructive |
| delete_workflow | Permanently delete a workflow resource from the cluster; history and outputs are lost. | Destructive |
Artifacts
| Tool | Description | Kind |
| ------------------------------ | ------------------------------------------------------------------------------------- | --------- |
| get_workflow_output_artifact | Stream a workflow output artifact to a local file; returns { path, bytes, sha256 }. | Read-only |
| get_workflow_input_artifact | Stream a workflow input artifact to a local file; returns { path, bytes, sha256 }. | Read-only |
The artifact tools are read-only against the Argo server; the local-disk write is caller-directed via destinationPath.
Archived workflow read
| Tool | Description | Kind |
| ------------------------------------- | ------------------------------------------------------------------------------------------------- | --------- |
| list_archived_workflows | List archived (persisted) workflows with namespace, selector, started-at, and pagination filters. | Read-only |
| get_archived_workflow | Fetch a single archived workflow by UID. | Read-only |
| list_archived_workflow_label_keys | List all label keys present on archived workflows. | Read-only |
| list_archived_workflow_label_values | List all values for a given label key across archived workflows. | Read-only |
Archived workflow mutating
| Tool | Description | Kind |
| ---------------------------- | -------------------------------------------------------------------------------------------- | ----------- |
| delete_archived_workflow | Delete an archived workflow record by UID; the original live workflow is not affected. | Destructive |
| retry_archived_workflow | Retry an archived workflow by UID; pods for failed/errored nodes are deleted and re-created. | Destructive |
| resubmit_archived_workflow | Resubmit an archived workflow by UID as a fresh workflow; the archive record is untouched. | Mutating |
Event sources
| Tool | Description | Kind |
| ----------------------- | -------------------------------------------------------------------------------------- | ----------- |
| list_event_sources | List Argo Events EventSources in a namespace. | Read-only |
| get_event_source | Get a single Argo Events EventSource by name. | Read-only |
| create_event_source | Create a new Argo Events EventSource in a namespace. | Mutating |
| update_event_source | Update an existing Argo Events EventSource; the request replaces the spec. | Mutating |
| delete_event_source | Delete an Argo Events EventSource by name; downstream consumers stop receiving events. | Destructive |
| get_event_source_logs | Drain Argo Events EventSource logs into a single text payload (bounded at ~64KB). | Read-only |
Sensors
| Tool | Description | Kind |
| ----------------- | -------------------------------------------------------------------------------------------------- | ----------- |
| list_sensors | List Argo Events Sensors in a namespace. | Read-only |
| get_sensor | Get a single Argo Events Sensor by name. | Read-only |
| create_sensor | Create an Argo Events Sensor. | Mutating |
| update_sensor | Update an existing Argo Events Sensor by name. | Mutating |
| delete_sensor | Delete an Argo Events Sensor by name; in-flight triggers tied to it are removed. | Destructive |
| get_sensor_logs | Drain Argo Events Sensor logs into a single text payload (bounded; truncation marker on overflow). | Read-only |
Troubleshooting
missing Argo Workflows server URL
Pass --argo-server-url or set ARGO_SERVER_URL.
auth mode "bearer" requires a token
Set the ARGO_TOKEN environment variable. See bearer for how to mint one.
auth mode "bearer-file" requires a token file
Pass --argo-token-file or set ARGO_TOKEN_FILE. See
bearer-file for how to populate the file.
401 Unauthorized from every tool
The bearer token expired or has no RBAC permissions. In bearer-file mode, refresh the token (re-run
argo auth token) and overwrite the token file — no server restart needed. In bearer mode, restart the server with
a fresh ARGO_TOKEN.
x509: certificate signed by unknown authority
The Argo server is using a private CA. For local development you can set --argo-insecure-skip-tls-verify (debug only —
disables TLS verification for the Argo client). In production, mount the CA bundle into the host's trust store instead.
