Skip to content
Open
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: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions charts/openab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Each agent lives under `agents.<name>`.
| `workingDir` | Working directory and HOME inside the container. | `"/home/agent"` |
| `env` | Inline environment variables passed to the agent process. | `{}` |
| `envFrom` | Additional environment sources from existing Secrets or ConfigMaps. | `[]` |
| `mcpServers` | MCP servers forwarded to ACP `session/new` and `session/load`. | `{}` |
| `pool.maxSessions` | Maximum concurrent ACP sessions for the agent. | `10` |
| `pool.sessionTtlHours` | Idle session TTL in hours. | `24` |
| `reactions.enabled` | Enable status reactions. | `true` |
Expand Down Expand Up @@ -82,6 +83,25 @@ agents:

This is useful for credentials such as `GH_TOKEN` without storing them directly in Helm values.

### Forward MCP servers

```yaml
agents:
codex:
command: codex-acp
workingDir: /home/agent
mcpServers:
local-tools:
command: example-mcp-server
args:
- --data-dir
- /home/agent/.cache/example-mcp
env:
MCP_STORAGE: /home/agent/.cache/example-mcp
```

OpenAB renders this as `[agent.mcp_servers."local-tools"]` and forwards it to ACP agents that support client MCP servers.

### Provide `AGENTS.md` with `--set-file`

```bash
Expand Down
24 changes: 23 additions & 1 deletion charts/openab/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ data:
args = {{ if $cfg.args }}{{ $cfg.args | toJson }}{{ else }}[]{{ end }}
working_dir = {{ $cfg.workingDir | default "/home/agent" | toJson }}
{{- if $cfg.env }}
env = { {{ $first := true }}{{ range $k, $v := $cfg.env }}{{ if not $first }}, {{ end }}{{ $k }} = {{ $v | toJson }}{{ $first = false }}{{ end }} }
env = { {{ $first := true }}{{ range $k, $v := $cfg.env }}{{ if not $first }}, {{ end }}{{ $k | toJson }} = {{ $v | toJson }}{{ $first = false }}{{ end }} }
{{- end }}
{{- range $cfg.secretEnv }}
{{- if hasKey ($cfg.env | default dict) .name }}
Expand All @@ -154,6 +154,28 @@ data:
{{- if $mergedInheritEnv }}
inherit_env = {{ $mergedInheritEnv | toJson }}
{{- end }}
{{- range $serverName, $server := $cfg.mcpServers }}

[agent.mcp_servers.{{ $serverName | toJson }}]
{{- if $server.type }}
type = {{ $server.type | toJson }}
{{- end }}
{{- if $server.command }}
command = {{ $server.command | toJson }}
{{- end }}
{{- if $server.args }}
args = {{ $server.args | toJson }}
{{- end }}
{{- if $server.url }}
url = {{ $server.url | toJson }}
{{- end }}
{{- if $server.env }}
env = { {{ $first := true }}{{ range $k, $v := $server.env }}{{ if not $first }}, {{ end }}{{ $k | toJson }} = {{ $v | toJson }}{{ $first = false }}{{ end }} }
{{- end }}
{{- if $server.headers }}
headers = { {{ $first := true }}{{ range $k, $v := $server.headers }}{{ if not $first }}, {{ end }}{{ $k | toJson }} = {{ $v | toJson }}{{ $first = false }}{{ end }} }
{{- end }}
{{- end }}

[pool]
max_sessions = {{ ($cfg.pool).maxSessions | default 10 }}
Expand Down
70 changes: 70 additions & 0 deletions charts/openab/tests/configmap_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,73 @@ tests:
- notMatchRegex:
path: data["config.toml"]
pattern: 'inherit_env'

- it: renders MCP stdio servers
set:
agents.kiro.mcpServers:
local-tools:
command: example-mcp-server
args:
- "--data-dir"
- "/home/agent/.cache/example-mcp"
env:
MCP_STORAGE: /home/agent/.cache/example-mcp
asserts:
- matchRegex:
path: data["config.toml"]
pattern: '\[agent\.mcp_servers\."local-tools"\]'
- matchRegex:
path: data["config.toml"]
pattern: 'command = "example-mcp-server"'
- matchRegex:
path: data["config.toml"]
pattern: 'args = \["--data-dir","/home/agent/.cache/example-mcp"\]'
- matchRegex:
path: data["config.toml"]
pattern: 'env = \{ "MCP_STORAGE" = "/home/agent/.cache/example-mcp" \}'

- it: renders MCP HTTP servers
set:
agents.kiro.mcpServers:
remote-tools:
type: http
url: https://mcp.example.com/mcp
headers:
Authorization: "${REMOTE_MCP_AUTH_HEADER}"
asserts:
- matchRegex:
path: data["config.toml"]
pattern: '\[agent\.mcp_servers\."remote-tools"\]'
- matchRegex:
path: data["config.toml"]
pattern: 'type = "http"'
- matchRegex:
path: data["config.toml"]
pattern: 'url = "https://mcp.example.com/mcp"'
- matchRegex:
path: data["config.toml"]
pattern: 'headers = \{ "Authorization" = "\$\{REMOTE_MCP_AUTH_HEADER\}" \}'

- it: quotes MCP inline table keys
set:
agents.kiro.mcpServers:
remote-tools:
type: http
url: https://mcp.example.com/mcp
env:
MCP-STORAGE.PATH: /home/agent/.cache/example-mcp
headers:
X-API-Key: "${REMOTE_MCP_API_KEY}"
asserts:
- matchRegex:
path: data["config.toml"]
pattern: 'env = \{ "MCP-STORAGE\.PATH" = "/home/agent/.cache/example-mcp" \}'
- matchRegex:
path: data["config.toml"]
pattern: 'headers = \{ "X-API-Key" = "\$\{REMOTE_MCP_API_KEY\}" \}'

- it: does not render MCP servers when unset
asserts:
- notMatchRegex:
path: data["config.toml"]
pattern: 'mcp_servers'
16 changes: 16 additions & 0 deletions charts/openab/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ agents:
# # secretName: my-secrets
# # secretKey: GEMINI_API_KEY
# secretEnv: []
# # MCP servers forwarded to ACP session/new and session/load.
# # Example:
# # mcpServers:
# # local-tools:
# # command: example-mcp-server
# # args: ["--data-dir", "/home/agent/.cache/example-mcp"]
# # env: {}
# mcpServers: {}
# pool:
# maxSessions: 10
# sessionTtlHours: 24
Expand Down Expand Up @@ -272,6 +280,14 @@ agents:
# Load env vars from existing Secrets or ConfigMaps, e.g. GH_TOKEN.
envFrom: []
secretEnv: [] # list of {name, secretName, secretKey} — rendered as valueFrom.secretKeyRef; keys auto-added to inherit_env
# MCP servers forwarded to ACP session/new and session/load.
# Example:
# mcpServers:
# local-tools:
# command: example-mcp-server
# args: ["--data-dir", "/home/agent/.cache/example-mcp"]
# env: {}
mcpServers: {}
pool:
maxSessions: 10
sessionTtlHours: 24
Expand Down
11 changes: 11 additions & 0 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ working_dir = "/home/agent"
# To pass additional env vars from the OAB process (e.g. vars injected via K8s envFrom),
# list them in inherit_env. Keys in [agent].env take precedence over inherited ones.
# inherit_env = ["API_BASE_URL", "MODEL_NAME"]
#
# To forward MCP servers to agents that support ACP client MCP servers:
# [agent.mcp_servers.local_tools]
# command = "example-mcp-server"
# args = ["--data-dir", "/home/agent/.cache/example-mcp"]
# env = { MCP_STORAGE = "/home/agent/.cache/example-mcp" }
#
# [agent.mcp_servers.remote_tools]
# type = "http"
# url = "https://mcp.example.com/mcp"
# headers = { Authorization = "${REMOTE_MCP_AUTH_HEADER}" }

# [agent]
# command = "codex"
Expand Down
36 changes: 36 additions & 0 deletions docs/config-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,45 @@ The AI agent subprocess that OpenAB spawns to handle messages via ACP.
| `working_dir` | string | `"/tmp"` | Working directory for the agent process. |
| `env` | map | `{}` | Extra environment variables (e.g. `{ OPENAI_API_KEY = "${OPENAI_API_KEY}" }`). |
| `inherit_env` | string[] | `[]` | Env var names to inherit from the OAB process (e.g. vars injected via K8s `envFrom`). Keys in `env` take precedence. |
| `mcp_servers` | table | `{}` | MCP servers forwarded to the ACP agent in `session/new` and `session/load`. |

> **Default inherited vars:** After `env_clear()`, the agent always receives `HOME`, `PATH`, and `USER` (on Windows: `USERPROFILE`, `USERNAME`, `PATH`, `SystemRoot`, `SystemDrive`). Use `inherit_env` to pass additional vars beyond this baseline.

### Agent MCP servers

Configure MCP servers under `[agent.mcp_servers.<name>]`. OpenAB forwards these entries to ACP-compatible agents that support client MCP servers, including `codex-acp` and `claude-agent-acp`.

Stdio server example:

```toml
[agent.mcp_servers.local_tools]
command = "example-mcp-server"
args = ["--data-dir", "/home/agent/.cache/example-mcp"]
env = { MCP_STORAGE = "/home/agent/.cache/example-mcp" }
```

HTTP server example:

```toml
[agent.mcp_servers.remote_tools]
type = "http"
url = "https://mcp.example.com/mcp"
headers = { Authorization = "${REMOTE_MCP_AUTH_HEADER}" }
```

Supported fields:

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `type` | string | `"stdio"` | MCP transport: `"stdio"`, `"http"`, or `"sse"`. |
| `command` | string | *required for stdio* | Local command to launch a stdio MCP server. |
| `args` | string[] | `[]` | Arguments passed to the stdio MCP server command. |
| `env` | map | `{}` | Environment variables passed to the stdio MCP server. |
| `url` | string | *required for http/sse* | Remote MCP server URL. |
| `headers` | map | `{}` | Headers sent to a remote HTTP or SSE MCP server. |

> **Security note:** MCP servers run inside the agent trust boundary. OpenAB still clears the child process environment before spawning the agent, so platform credentials such as Discord and Slack tokens are not passed unless you explicitly put them in `[agent].env`, `inherit_env`, or an MCP server `env`/`headers` value.

### Agent examples

```toml
Expand Down
Loading
Loading