muster

Muster n. German: pattern, sample.┄Here: an aggregating MCP server.

One endpoint.
Every MCP server
your teams run.

muster connects the MCP servers an organisation runs — a factory's MES and maintenance system, a service desk and its directory, a CRM and an ERP, a platform's Kubernetes and Prometheus, your own — and serves their tools through a single authenticated endpoint. Agents connect once, find tools without flooding their context window, run procedures as deterministic workflows, and make every call as the person they work for.

agent session · /mcpmanufacturing
▸ filter_tools { "query": "line 3 stopped" }
  workflow_line-stop-triage  Explain a line stop: the downtime event, the alarms around it, the order it hit, the asset's history
  x_mes_list_downtime        List the downtime events of a line in a time window
  x_scada_read_alarms        Read the alarms of an asset in a time window
▸ call_tool { "name": "workflow_line-stop-triage", "arguments": { "line": "L3", "since": "06:30" } }
  status: completed · 5 steps, 1 skipped · as lena@example.com · trace 8b2e…f4
x_<server>_<tool> workflow_<name> core_*
Where it fits shop floor · service desk · back office · platform

The systems differ. The shape of the work does not.

A shift lead, a service-desk analyst, an account manager and an engineer on call ask their agents very different questions, and every answer lives in three or four systems that were never built to be read together. Each system speaks MCP through its own server; muster is where the servers meet. One example per area: the servers behind the endpoint, the procedure sewn into a workflow, and the identity every call carries.

Manufacturing workflow_line-stop-triage

“Line 3 stopped at 06:40. Why, and what did it hit?”

The MES has the downtime event, the SCADA historian the alarms around it, the ERP the production order that was running, the maintenance system the asset's history. The workflow reads the four in order and opens a work order only when the alarm matches a known failure mode.

  • mes
  • scada
  • erp
  • cmms
  1. stopx_mes_list_downtimethe event, reason code, duration
  2. alarmsx_scada_read_alarmsten minutes either side
  3. orderx_erp_get_production_orderwhat was running, due when
  4. historyx_cmms_list_work_ordersthe asset, last 90 days
  5. ticketx_cmms_create_work_ordercondition: known failure mode

As the shift lead. The maintenance system accepts the work order because they may open one for that line; muster adds no service account.

X-muster-Toolset: workflow:line-stop-triage
IT processes workflow_joiner-access

“A new engineer starts on Monday. Give them what their team has.”

The approved request is in the service desk, the team's shared groups in the directory, its repositories on GitHub. The workflow derives the access from what the team's members already hold instead of a form, grants it, and writes what it granted back to the request.

  • servicenow
  • okta
  • github
  1. requestx_servicenow_get_requestapproved by the manager
  2. peersx_okta_list_group_membersthe groups the team shares
  3. groupsx_okta_add_user_to_groupforEach shared group
  4. reposx_github_add_team_memberthe team's repositories
  5. closex_servicenow_update_requestwhat was granted, by whom

As the analyst who runs it. The agent sees one tool and cannot add anyone to a group on its own; the directory refuses groups the analyst may not assign, and every grant carries their name.

X-muster-Toolset: workflow:joiner-access
Enterprise processes workflow_renewal-brief

“Which contracts renew this quarter, and how healthy are those accounts?”

The contracts are in the CRM, the support history in the help desk, the unpaid invoices in the ERP, the last review deck in the document store. The workflow assembles one brief per account, and the CRM returns only the accounts the person may see: a rep gets their territory, a director the region.

  • salesforce
  • zendesk
  • erp
  • sharepoint
  1. contractsx_salesforce_queryrenewing within 90 days
  2. ticketsx_zendesk_list_ticketsforEach account · open, 90 days
  3. invoicesx_erp_list_open_invoicesforEach account · overdue
  4. reviewx_sharepoint_searchthe last review deck
  5. briefoutputone typed document per account

As the account manager. The CRM's sharing rules, not muster, decide which accounts the brief covers; the same workflow yields a different brief for each person.

X-muster-Toolset: preset:read-only, workflow:renewal-brief
Platform engineering workflow_pod-triage

“Checkout pods are not running in payments. What is going on?”

The cluster has the pods and their events, the containers their logs, Prometheus the restart rate and the firing alerts. The workflow gathers the evidence in one pass, tolerates a pod whose logs are already gone, and posts to the on-call channel when a step fails for real.

  • kubernetes
  • prometheus
  • slack
  1. podsx_kubernetes_listkind: Pod, by selector
  2. eventsx_kubernetes_listcondition: pods found
  3. logsx_kubernetes_logsforEach pod · allowFailure
  4. signalsx_prometheus_query · x_prometheus_alertsparallel
  5. notex_slack_postonFailure

Examples, not a catalogue: each is an ordinary Workflow resource of the shape shown next, and the servers are whatever speaks MCP in your organisation — a vendor's server, a community one, or one you wrote against your own system's API. How aggregation works · Register a server

Workflow engine kind: Workflow · muster.giantswarm.io/v1alpha1

Procedures become tools.

Work in any of these systems is a sequence: find the record, read what hangs off it, ask a second system, compare, decide. Left to an agent, the sequence is rediscovered on every run, differently each time, at full token cost. A workflow sews the sequence into one tool. It is a list of steps — tool calls, forEach loops and parallel groups — gated by conditions and joined by templates. muster exposes it as workflow_<name> with the arguments you declared; the steps run the same way every time, and every run leaves a durable execution record. Below, the platform example in full; a line stop or a renewal brief is written with the same constructs.

workflow.yamlkubectl apply -f · or core_workflow_create
apiVersion: muster.giantswarm.io/v1alpha1
kind: Workflow
metadata:
  name: pod-triage
  namespace: muster
spec:
  description: Find the pods of a workload that are not running and gather their evidence
  args:
    namespace: { type: string, required: true }
    selector:  { type: string, required: true }
  steps:
    - id: pods
      tool: x_kubernetes_list
      args: { kind: Pod, namespace: "{{ .input.namespace }}", labelSelector: "{{ .input.selector }}" }
    - id: events
      tool: x_kubernetes_list
      args: { kind: Event, namespace: "{{ .input.namespace }}" }
      condition:
        template: "{{ gt (len .results.pods.items) 0 }}"
    - id: logs
      forEach:
        items: "{{ .results.pods.items }}"
        as: pod
        steps:
          - id: tail
            tool: x_kubernetes_logs
            args: { name: "{{ .vars.pod.metadata.name }}", namespace: "{{ .input.namespace }}", tailLines: 50 }
            allowFailure: true
    - id: signals
      parallel:
        - id: restarts
          tool: x_prometheus_query
          args: { query: 'increase(kube_pod_container_status_restarts_total{namespace="{{ .input.namespace }}"}[1h])' }
        - id: alerts
          tool: x_prometheus_alerts
          args: { namespace: "{{ .input.namespace }}" }
  onFailure:
    - id: note
      tool: x_slack_post
      args: { channel: "#oncall", text: "pod-triage failed for {{ .input.namespace }}/{{ .input.selector }}" }
  output:
    pods:     "{{ .results.pods.items }}"
    restarts: "{{ .results.restarts.data.result }}"
    alerts:   "{{ len .results.alerts.alerts }}"
WorkflowExecution pod-triage-… idle
stepstatustook
waiting for a run…

Workflows compose: one workflow calls another's workflow_<name> tool, a toolset selects them with workflow:<name>, and an agent finds them by intent through filter_tools. Create workflows · Workflow reference

Kubernetes-native helm install muster giantswarm/muster

Servers and workflows are resources.

On a cluster, muster runs in Kubernetes mode: MCPServer, Workflow and WorkflowExecution are custom resources reconciled by muster itself. Status, conditions and events say which servers are reachable now and which workflows have every tool they need. A server is registered in a pull request, reviewed like any other manifest and rolled out by Flux; the people who use it configure nothing.

MCPServerkubectl get mcpservers
spec:
  type: streamable-http
  url: https://mcp-kubernetes.muster.svc/mcp
  toolPrefix: k8s
  auth:
    type: oauth
    forwardToken: true
    requiredAudiences: [dex-k8s-authenticator]
status:
  state: Running
  conditions: [Connected, ToolsDiscovered]

Connected, health-checked and reconnected with backoff. The tool list is followed as it changes; the status and the events tell the story.

Workflowkubectl get wf
spec:
  args: { … }
  steps: [ … ]
  onFailure: [ … ]
  output: { … }
status:
  available: true
  requiredTools:
    - x_kubernetes_list
    - x_kubernetes_logs
    - x_prometheus_query

Validated at admission by CEL rules on the CRD. The workflow's tool appears in a session as soon as every tool it references is available there.

WorkflowExecutionkubectl get wfe
spec:
  workflowName: pod-triage
  status: completed
  input: { namespace: payments, … }
  steps:
    - { id: pods,    status: completed, duration: 412ms }
    - { id: events,  status: completed, duration: 231ms }
    - { id: tail_1,  status: failed,    allowFailure: true }
    - …

One record per run, labelled by workflow and status, kept under a retention you set. Readable with kubectl, the CLI, or core_workflow_execution_get.

$ kubectl -n muster get mcpservers
NAME          TYPE              URL                                       AUTOSTART   STATUS    AGE
kubernetes    streamable-http   https://mcp-kubernetes.muster.svc/mcp     true        Running   14d
prometheus    streamable-http   https://mcp-prometheus.muster.svc/mcp     true        Running   14d
github        streamable-http   https://api.githubcopilot.com/mcp/        true        Running   3d
servicenow    streamable-http   https://mcp-servicenow.integration.svc/mcp   true     Running   3d
$ kubectl -n muster get wf,wfe
NAME                                       AGE
workflow.muster.giantswarm.io/pod-triage   9d

NAME                                                          WORKFLOW     STATUS
workflowexecution.muster.giantswarm.io/pod-triage-7f3k2       pod-triage   completed
workflowexecution.muster.giantswarm.io/pod-triage-b1q8x       pod-triage   failed

What the chart ships

  • The three CRDs, and a separate muster-crds chart when their lifecycle should be its own release
  • RBAC, with editor roles for MCPServer and Workflow so teams register their own servers
  • NetworkPolicy and a Cilium variant restricting ingress to the aggregator and metrics ports
  • ServiceMonitor, a PrometheusRule set and a Grafana dashboard
  • Ingress, or Gateway API HTTPRoute and BackendTrafficPolicy
  • HPA and PDB, and Valkey-backed sessions and grants for more than one replica
  • An extra CA bundle for MCP servers behind a private CA

In Kubernetes mode stdio servers are refused: a child process of the muster pod would run under its service account. Servers run as their own workloads and are registered by URL. Installation · Custom resources

Identity and single sign-on OAuth 2.1 · RFC 9728 · RFC 8693 · PKCE

Every call is made as the person.

A shared muster is an OAuth 2.1 resource server in front of Dex. A person logs in once and gets one session; muster carries that identity to every MCP server behind it and records who called what. Nothing muster adds widens access: a toolset bounds what the model can see, and the backends' own authorization stays the boundary.

$ muster auth status

muster: authenticated
  Endpoint: https://muster.example.com
  Identity: dana@example.com
  Expires:  in 29 minutes · session 30 days

MCP Servers:
  mcp-kubernetes    Connected  [SSO: Forwarded]
  mes               Connected  [SSO: Forwarded]
  erp               Connected  [SSO: Exchanged]
  salesforce        Not authenticated   Run: muster auth login --server salesforce

Protect the endpoint with Dex · Authenticate the CLI · Toolsets · Why token forwarding

Discovery 13 meta-tools · x_<server>_<tool>

A catalogue that fits a context window.

An MCP client loads every tool definition of every attached server before the first question is asked; an organisation's servers contribute hundreds. muster's clients see thirteen meta-tools instead. filter_tools ranks the catalogue against a query and returns a short, summarised page; describe_tool returns one schema; call_tool runs it. The catalogue can be hundreds of tools wide and still cost a few hundred tokens a turn. Servers that serve the same tools for different targets form a family and appear as one surface with an instance argument.

MCP tools reference · How the catalogue is built

  • list_tools
  • filter_tools
  • describe_tool
  • call_tool
  • list_resources
  • filter_resources
  • describe_resource
  • get_resource
  • list_prompts
  • filter_prompts
  • describe_prompt
  • get_prompt
  • list_core_tools
Get started brew · curl · helm · go

Ten minutes to an IDE calling tools through muster.

muster is a single static binary for Linux, macOS and Windows, a container image and a Helm chart. Binaries are signed in CI and verified by muster self-update.

brew trust giantswarm/muster
brew install giantswarm/muster/muster

Serve, register, call

$ muster serve                       # http://localhost:8090/mcp
$ muster create mcpserver files --type=stdio --command=npx \
    --args="-y,@modelcontextprotocol/server-filesystem,$HOME" --autoStart=true
$ muster list mcpserver              # files   Running   stdio
$ muster call x_files_list_allowed_directories

Connect an IDE

muster standalone runs the aggregator and a stdio bridge in one process. Against a running or remote muster, use muster agent --mcp-server; the bridge performs the browser login for the IDE.

{
  "mcpServers": {
    "muster": { "command": "muster", "args": ["standalone"] }
  }
}

The quick start continues from here: exploring the catalogue in the REPL, toolsets and the first workflow. On a cluster, the installation guide covers Dex, Valkey-backed sessions, network policies and metrics.

Documentation tutorials · how-to · reference · explanation