# Secrets

> Securely store and inject API keys, tokens, and credentials into MCP server calls at runtime.

Workspace secrets store sensitive credentials -- API keys, tokens, webhook URLs -- that MCP servers need to operate. Secrets are encrypted at rest using AES-GCM and decrypted only at the moment a tool call is made.

---

## How Secrets Work

```mermaid
flowchart LR
    U["You set GITHUB_TOKEN"] --> WS["Workspace\n(encrypted storage)"]
    WS -->|"tools/call"| GW["Gateway decrypts\nat call time"]
    GW -->|"X-Mcp-Secret-GITHUB-TOKEN"| S["GitHub MCP Server"]

    style U fill:#1e293b,stroke:#6b7280,color:#fff
    style WS fill:#3b82f6,stroke:#2563eb,color:#fff
    style GW fill:#1e293b,stroke:#6b7280,color:#fff
    style S fill:#1e293b,stroke:#6b7280,color:#fff
```

1. You **create a secret** with a key name and value (for example, `GITHUB_TOKEN` = `ghp_abc123...`)
2. Aerostack **encrypts** the value with AES-GCM and stores only the ciphertext
3. When you add a server to the workspace, you specify which secrets it needs via `inject_secrets`
4. At call time, the gateway **decrypts** the relevant secrets and injects them into the upstream request

---

## Injection Methods

Secrets are injected differently depending on the server's auth type:

| Server Auth Type | How Secrets Are Injected |
|-----------------|--------------------------|
| `secret-headers` (default) | As `X-Mcp-Secret-{KEY}` HTTP headers |
| `bearer` | As `Authorization: Bearer {value}` header |
| Skills (function-backed) | In the request body as `{ secrets: { KEY: value } }` |

  The `X-Mcp-Secret-` header key format converts underscores to hyphens. For example, `GITHUB_TOKEN` becomes `X-Mcp-Secret-GITHUB-TOKEN`.

---

## Create or Update a Secret

Secrets use upsert semantics -- if a secret with the same key name already exists, the value is overwritten.

### Dashboard

Open your workspace, go to the **Secrets** tab, and click **Add Secret**. Enter the key name and value. If a secret with that key already exists, the value is replaced.

### CLI

```bash
aerostack workspace secret set my-workspace GITHUB_TOKEN ghp_abc123def456...
```

### Key Name Normalization

Secret key names are automatically normalized:

- Converted to **uppercase**
- Non-alphanumeric characters (except underscore) replaced with `_`

Examples:
- `github-token` becomes `GITHUB_TOKEN`
- `my.api.key` becomes `MY_API_KEY`
- `SlackWebhook` becomes `SLACKWEBHOOK`

---

## List Secrets

View all secret key names in a workspace. **Secret values are never returned** -- only names and metadata.

### Dashboard

Open your workspace and click the **Secrets** tab. You will see a list of all secret key names with their creation dates.

### CLI

```bash
aerostack workspace secret list my-workspace
```

```
  KEY                  CREATED
  GITHUB_TOKEN         2026-03-15
  SLACK_BOT_TOKEN      2026-03-15
  LINEAR_API_KEY       2026-03-16
```

  Secret values are write-only. Once stored, the plaintext value cannot be retrieved through the API or dashboard. If you need to change a value, create a new secret with the same key name to overwrite it.

---

## Delete a Secret

### Dashboard

Open the workspace, go to **Secrets**, find the secret, and click **Delete**.

### CLI

```bash
aerostack workspace secret delete my-workspace GITHUB_TOKEN
```

  Deleting a secret does not automatically update server `inject_secrets` configurations. Servers that reference a deleted secret will simply not receive it -- they will not error, but the server may fail if it requires the credential.

---

## Connecting Secrets to Servers

When you [add a server](/workspaces/add-tools) to your workspace, you specify which secrets it should receive via the `inject_secrets` configuration.

### Dashboard

When adding or editing a server in the workspace, select the secrets to inject from a dropdown of available workspace secrets.

### CLI

```bash
# Add a server with secret injection
aerostack workspace server add my-workspace @aerostack/github --secrets GITHUB_TOKEN

# Update which secrets a server receives
aerostack workspace server update my-workspace github --secrets GITHUB_TOKEN,GITHUB_WEBHOOK_SECRET
```

Only the secrets listed in `inject_secrets` are sent to that server. A server never receives secrets not explicitly assigned to it.

---

## Per-Server Scoping

Each server in a workspace can receive a different set of secrets. This is the recommended pattern:

```
Workspace: dev-tools
  Secrets: GITHUB_TOKEN, LINEAR_API_KEY, SLACK_BOT_TOKEN

  Server: GitHub MCP     → inject_secrets: [GITHUB_TOKEN]
  Server: Linear MCP     → inject_secrets: [LINEAR_API_KEY]
  Server: Slack MCP      → inject_secrets: [SLACK_BOT_TOKEN]
```

The GitHub server only receives `GITHUB_TOKEN`. It never sees the Linear or Slack credentials. This follows the principle of least privilege.

---

## Security

- **Encrypted at rest** -- secrets are encrypted with AES-GCM before storage
- **Decrypted only at call time** -- the plaintext value exists in memory only during the upstream request
- **Never cached in plaintext** -- the gateway decrypts on every call
- **Scoped to a workspace** -- secrets are not shared across workspaces
- **Write-only** -- once stored, the value cannot be retrieved through any API

---

## Common Patterns

### Multi-Service Workspace

A workspace with multiple servers, each needing different credentials:

```bash
# Create secrets
aerostack workspace secret set dev-tools GITHUB_TOKEN ghp_abc...
aerostack workspace secret set dev-tools LINEAR_API_KEY lin_abc...
aerostack workspace secret set dev-tools SLACK_BOT_TOKEN xoxb-abc...

# Slack → SLACK_BOT_TOKEN
```

### Shared Secrets

Multiple servers can reference the same secret. For example, if two servers both need a database URL:

```bash
aerostack workspace secret set my-workspace DATABASE_URL postgres://...
# Both Server A and Server B inject DATABASE_URL
```

### Rotating Secrets

To rotate a secret, overwrite it with a new value. The change takes effect immediately for all servers that inject it:

```bash
aerostack workspace secret set my-workspace GITHUB_TOKEN ghp_new_value...
```

No restarts needed -- the gateway decrypts secrets fresh on every call.

---

## Plan Limits

| Plan | Secrets per Workspace |
|------|----------------------|
| Free | 10 |
| Starter | 50 |
| Pro | 200 |
| Business | 1,000 |
| Enterprise | Unlimited |
