Secret providers
Keep shared credentials in AWS Secrets Manager and let MintMCP resolve them at request time, instead of pasting token values into the MintMCP control plane. A secret provider is a reference to an external secret store (today, AWS Secrets Manager) that MintMCP reads each time it needs the current value, so the authoritative copy stays in the store your security team already runs.
Secret providers source values for shared bearer tokens and additional header values on remote MCPs, and for agent M2M credentials. Per-user OAuth doesn't need them (the user's own token is already scoped and rotated by the upstream identity provider), so secret providers are specifically for the shared-credential case: the service account token or API key that every user of a Virtual MCP (VMCP) authenticates with to the upstream service.
Secret providers are an Enterprise feature gated behind a feature flag. If the Secret providers tab is not visible on your Enterprise Settings page, your organization is not yet entitled to the feature.
Why use a secret provider
Shared bearer tokens are the highest-value credentials MintMCP handles: a single GitHub service-account token on an engineering VMCP is a key to every repository. Without secret providers, you either paste the token into MintMCP (encrypted at rest, but the authoritative copy now lives in the control plane and rotates there too) or skip shared auth entirely.
Secret providers give you a third option:
- Single source of truth. The authoritative value lives in AWS Secrets Manager, rotations happen there, and MintMCP never holds a persistent copy.
- Rotation without MintMCP changes. Update the secret in AWS and the next request through the VMCP picks it up: no redeploy, no reconfiguration.
- Your audit trail covers credential access. Every
GetSecretValuecall is logged in your CloudTrail under the assumed role, so your existing security tooling sees it. - Least privilege at the IAM layer. You control exactly which secret ARNs the MintMCP-assumed role can read, down to a single secret.
How it works
A secret provider is two things: an AWS IAM role that MintMCP assumes in your account, and a set of references (secret ARN plus optional JSON path) to individual secrets readable under that role.
Trust model
When a request needs to resolve a secret, MintMCP's cloud control plane calls sts:AssumeRole against the role ARN you configured, presenting an external ID that only you and MintMCP know. If the role's trust policy doesn't pin that external ID, the AssumeRole fails, so a leaked role ARN alone isn't enough to access your secrets.
MintMCP assumes the role from a single, stable MintMCP-owned AWS account; the provider setup dialog shows the exact account and a ready-to-paste trust policy. Trusting that account, combined with the external ID condition, means only MintMCP, presenting your external ID, can assume the role. The assumed-role session then calls secretsmanager:GetSecretValue against the referenced secret ARN.
External ID
The external ID pins the trust. When you create a provider, MintMCP generates a random external ID that you paste into the role's trust policy under sts:ExternalId. You can rotate the external ID at any time: generate a new one in MintMCP, update the trust policy in AWS, and the previous external ID stops working immediately.
JSON paths and version stages
If the Secrets Manager value is a JSON object (common: a single secret often holds multiple related fields), point MintMCP at a specific field rather than the whole blob. The Fetch keys button in the bearer-token configuration calls GetSecretValue once and lists the top-level keys so you can pick one without guessing. Leave the JSON path blank for plaintext secrets.
You can also pin a version stage (AWS's AWSCURRENT by default, AWSPREVIOUS, or any custom stage label), which is useful when you want MintMCP to consume a stable label while you stage rotations on another.
Security model
The trust boundary sits at your IAM role. MintMCP can read only the secret ARNs that role permits, only while your trust policy names MintMCP's account and your external ID, and every read lands in your CloudTrail. You can revoke access unilaterally at any time by editing the trust policy or the role's permissions.
Credential handling on the MintMCP side:
- No persistent copy. MintMCP stores the reference (provider ID, secret ARN, version stage, JSON path), never the secret value. At request time it resolves the reference, attaches the value to the upstream request (as
Authorization: Bearer <token>or as the configured header value), and discards it once the call completes. - Short caches only. Resolved secret values are cached encrypted in memory for a few minutes at most; beyond that window, MintMCP fetches a fresh value from AWS, which is how rotations propagate.
- No read-back in the UI. You cannot retrieve the external ID after saving (it's stored encrypted and only decrypted to sign AssumeRole calls), and you cannot retrieve resolved secret values through the admin UI. The one exception is the provider Test dialog, which returns a resolved value only for the one-time test ARN you typed in, so you can confirm what MintMCP will see. If you reopen a bearer-token form, MintMCP shows the ARN, version stage, and JSON path, but it cannot show the token, because it doesn't have one to show.
Create a secret provider
- Go to Enterprise Settings → Secret providers and click New provider.
- Give it a name (for example,
production-aws-us-east-1) that you'll recognize in the bearer-token picker later. - Paste the Role ARN of the IAM role in your AWS account that MintMCP will assume.
- Click Generate to get an external ID. The dialog's Generated configuration section shows the MintMCP AWS account ID and, once the external ID exists, a complete Trust policy (
sts:AssumeRolewith your external ID pinned understs:ExternalId) to copy into the role. - Click Create provider.
Before saving, the UI runs a live test: it takes a sample secret ARN you supply, assumes the role, calls GetSecretValue, and verifies the response. If anything fails (wrong trust policy, missing IAM permission, unreachable region, wrong external ID), the save is rejected with a specific error, so you can't save a broken provider.
You can re-run the test at any time from the provider row (the flask icon). A passing live test points a downstream credential failure at the specific secret reference rather than the provider.
Use a provider on a remote MCP
Once a provider exists, use it as the source of a shared bearer token or an additional header value on a remote MCP, or on an agent-identity credential.
For a bearer token:
- Open the connector's authentication configuration.
- Set the auth method to Bearer Token, connection type Shared, and change the Source dropdown from Enter token manually to AWS Secrets Manager.
- Pick a Secret Provider from the list.
- Paste the Secret ARN: the full
arn:aws:secretsmanager:<region>:<account>:secret:<name>of the secret to read. - Optionally set a Version Stage (defaults to
AWSCURRENT). - Optionally set a JSON Path if the secret is a JSON object: click Fetch keys to list available fields, or type a path like
$.accessToken. Leave blank for plaintext secrets. - Save.
For an additional header:
The same AWS Secrets Manager source option is available when configuring Additional Headers on a remote MCP. Select AWS Secrets Manager as the source, pick the provider, and supply the secret ARN with optional version stage and JSON path. At request time, MintMCP resolves the secret and injects it as the header value on the upstream request.
Rotate credentials
Rotate a secret value by updating it in AWS Secrets Manager. The MintMCP-side cache expires within about 5 minutes, after which new calls pick up the new value automatically: no deploy, no UI click, no notification to users.
If you use version stages, you can stage a rotation on AWSPENDING, validate it externally, then promote to AWSCURRENT. MintMCP follows whatever version stage the reference is configured with.
To rotate the trust rather than the value, rotate the external ID: edit the provider, click Generate for a new external ID, update the role's trust policy in AWS, and save. The previous external ID stops working as soon as the trust policy change propagates.
Permissions
Two org-level permissions govern the feature:
| Permission | Grants |
|---|---|
org:secret-providers:view | See the providers list and use existing providers as a bearer-token source. Cannot create, edit, or delete. |
org:secret-providers:manage | Full control: create, edit, test, rotate external ID, delete. |
The broader admin permission grants both. Anyone without at least view cannot see that the feature exists, because API reads of a provider return a not-found response rather than leaking which providers are configured. See Role-based access control for how permissions are assigned.
Audit
All secret provider lifecycle events flow into the organization's admin audit log:
- Create, update, and delete of a provider
- External ID rotation
- Test runs, including pass/fail and the test ARN used
- Every bearer-token configuration that references a provider, including the referenced ARN and JSON path
The provider's resource snapshot includes the name, kind (aws_secrets_manager), role ARN, and last test result. The encrypted external ID is redacted from snapshot diffs, so an audit-log reader doesn't see even the ciphertext. Secret values themselves are never in the audit log, and never in the gateway request log, which has always scrubbed bearer tokens.
On the AWS side, every AssumeRole and every GetSecretValue is a normal CloudTrail event under the role MintMCP assumed, with the external ID on the session name. That record lives in your account, on your CloudTrail retention.
Delete a provider
Deletion is only allowed if no connector references the provider. The delete call checks every bearer-token configuration that could point at it; if any does, the delete is rejected and the UI tells you which connectors still reference it. This prevents a stale reference from silently breaking auth on a production VMCP.
Limits and constraints
- Provider names are up to 100 characters.
- AWS Secrets Manager is the current provider kind.
- The AWS region is inferred from each secret ARN, not configured on the provider, so multiple providers can point at different regions.
- The test flow requires a test secret ARN, which is used only for the test call and not persisted on the provider.
- Secret providers cover shared bearer tokens, additional header values on remote MCPs, and agent M2M credentials. Per-user OAuth flows, hosted connector environment variables, and gateway middleware
ctx.secretsare separate mechanisms with their own configuration.
Related
- Add a remote MCP: where shared bearer tokens and additional headers are configured
- Authentication models: the shared-vs-per-user credential choice you're making when you pick a secret provider as a token source
- Role-based access control: assigning the view and manage permissions
- Gateway middleware: middleware-scoped
ctx.secrets, a separate injection mechanism - Add a hosted connector: environment-variable secrets live on the connector configuration, not in secret providers