> For the complete documentation index, see [llms.txt](https://docs.duplocloud.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.duplocloud.com/docs/armor/mcp-servers/credential-masking-for-mcp-servers.md).

# Credential Masking For MCP Servers

Raw MCP server configs support credential placeholders — named variables that are resolved from the scope's bound credential immediately before the `.mcp.json` session file is written. This keeps secrets and per-environment values out of the server config entirely.

***

## Placeholder Syntax

Two forms are supported:

| Placeholder                    | Resolves from                  |
| ------------------------------ | ------------------------------ |
| `${credential.<key>}`          | `Credential.Data["<key>"]`     |
| `${credential.metadata.<key>}` | `Credential.MetaData["<key>"]` |

Lookups are **flat, case-sensitive, and exact-match**. Placeholders can appear anywhere inside a string value in the raw config tree — in `url`, `command`, items in `args`, values in `env`, `headers`, or any other string field. Multiple placeholders in a single string are supported.

***

## Example

**Raw config registered on the MCP server:**

```json
{
  "mcpServers": {
    "grafana": {
      "command": "uvx",
      "args": ["mcp-grafana"],
      "env": {
        "GRAFANA_URL": "${credential.url}",
        "GRAFANA_SERVICE_ACCOUNT_TOKEN": "${credential.token}"
      }
    }
  }
}
```

![](/files/bPv4AdvIBY96UimordZS)

**Bound credential on the scope:**

The credential fields must match the placeholder keys exactly. For the config above, the credential must have a field named `token` and a field named `url`:

![](/files/KWhE7bUIFojq9KEEo1i8)

**Resolved `.mcp.json` written for the session:**

```json
{
  "mcpServers": {
    "grafana": {
      "command": "uvx",
      "args": ["mcp-grafana"],
      "env": {
        "GRAFANA_URL": "https://system-svc-grafana-oc-default.ai-sandbox-apps.duplocloud.net",
        "GRAFANA_SERVICE_ACCOUNT_TOKEN": "<resolved token value>"
      }
    }
  }
}
```

The raw config stored on the server is never modified. Placeholder resolution happens in memory at session start and the resolved values exist only for the duration of that agent session.

***

## Naming Requirements

The key after `credential.` or `credential.metadata.` must **exactly match** the credential field name, including case. For example:

* `${credential.token}` requires a credential field named exactly `token`
* `${credential.url}` requires a credential field named exactly `url`
* `${credential.metadata.api-key}` requires a metadata key named exactly `api-key`

***

## Missing Keys Fail Loud

If any placeholder references a key that does not exist on the bound credential:

1. The **entire MCP server** is dropped from `.mcp.json` for that session
2. A `WARNING` is logged by the platform
3. The system prompt's **`## Connected MCP Servers`** section marks the server as `(FAILED TO LOAD)`, listing the missing key names and the credential name

This means the agent can see exactly what is missing and report it to the user — for example: *"The Grafana MCP server failed to load because the bound credential `default` is missing the key `token`."*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.duplocloud.com/docs/armor/mcp-servers/credential-masking-for-mcp-servers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
