sops-mcp
Provides tools for creating and managing Authelia OIDC client secrets, including generating random secrets and deriving PBKDF2-SHA512 hashes for Authelia's configuration format.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sops-mcpCreate a new encrypted secrets file with a generated API key."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
sops-mcp
MCP server for creating and managing SOPS-encrypted secret files using age encryption.
Designed for Claude Code (or any MCP client) to produce encrypted secrets.enc.yaml files without the model ever seeing plaintext values. All file content is passed as text parameters and returned as text — the server has no filesystem access to the client.
Why
Two goals drive the design:
1. Keep secrets in your source tree without leaking them. For a small project, running a full secrets manager (Vault, AWS Secrets Manager, etc.) is overkill for a handful of credentials. Encrypting secrets at rest in git and decrypting them in your CI/CD pipeline at deploy time is much cheaper:
Create
secrets.enc.yamlvia this server — age-encrypted against your public key, safe to commit.Commit it alongside your code.
Your CI/CD pipeline holds the age private key, decrypts at deploy time, and injects plaintext as environment variables into your container orchestrator.
The age private key lives in exactly one place: your CI/CD secrets store. Everywhere else — your laptop, your git remote, your container images — sees only ciphertext. See the worked example below.
2. Let an AI coding agent generate secrets it can never read. Claude (or any MCP client) can create passwords, rotate them, derive hashes, rename and delete them — but plaintext values never cross the MCP boundary back to the model. The server holds the encryption key; the client only submits requests and receives metadata. There is deliberately no "decrypt this one secret" tool. If a prompt injection or a misbehaving agent tried to exfiltrate a secret via tool output, there is no tool output to exfiltrate.
This pattern assumes a single age recipient (the one CI private key). For multi-recipient / team key management, use the sops CLI directly for recipient rotations and this server for content management.
Related MCP server: Janee
Design
Three ideas shape the tool surface:
No plaintext crosses the MCP boundary. Generated secret values are never returned to the client. There is deliberately no "decrypt this one key" tool. If you need plaintext, run
sops decryptyourself with the age private key.Metadata in plaintext. A
_meta_unencryptedblock sits alongside the encrypted values (using SOPS'sunencrypted_suffixfeature) and records each secret's source, how it was generated, and when it was last rotated. This lets the server list and rotate secrets without decrypting.No in-place value update for generated or derived secrets. Those change only via rotation — the mutation model is deliberate, not accidental. External secrets (e.g. an upstream API key the user controls) can be updated with
sops_update_external.
Secret sources
Every secret is one of three sources, recorded in _meta_unencrypted:
generated— Cryptographically random values (Pythonsecrets/ OS CSPRNG). You specify length and charset; the server stores both so it can regenerate on rotation.external— User-provided values encrypted as-is (SMTP credentials, third-party API keys, etc.). Preserved across rotation. Updated viasops_update_external.derived— Computed from another key in the same file via a named transform. When the source is rotated (or an external source is updated), the derived value is automatically recomputed in topological order. Useful for things like Authelia's PBKDF2 hashes of OIDC client secrets.
Transforms (for derived secrets)
Transform | Purpose | Deterministic |
| PBKDF2-SHA512 hash in Authelia's | No — random salt per call |
| Hex-encoded SHA-256 digest | Yes |
Tools
Creation and listing
Tool | What it does |
| Create a new encrypted file with one or more secrets (any mix of sources). |
| List keys, sources, and descriptions from a file without decrypting. |
| Convenience: create an Authelia OIDC client secret as a |
Mutation (require SOPS_AGE_KEY)
Tool | What it does |
| Regenerate all |
| Add new secrets to an existing file. Supports all three sources. Rejects collisions with existing keys. |
| Replace the value of an |
| Rename a key, preserving its value and metadata. Updates |
| Remove one or more keys. Rejects deleting a secret that another derived secret still references (unless the dependent is deleted in the same call). |
| Retrofit |
Setup
Prerequisites
Python 3.11+
sops CLI binary
An age keypair (see below)
Generating an age keypair
If you don't already have one, install age and run:
age-keygen -o age-key.txtThe file looks like:
# created: 2026-04-22T12:34:56Z
# public key: age1abc...xyz
AGE-SECRET-KEY-1HH...Public key (
age1...) — pass to this server asSOPS_MCP_AGE_PUBLIC_KEY. Safe to share anywhere.Private key (
AGE-SECRET-KEY-...) — store as a CI/CD secret (commonly namedSOPS_AGE_KEY). Never commit to source control. Anyone with this key can decrypt everysecrets.enc.yamlencrypted to the matching public key.
Back up the private key somewhere safe (password manager, hardware token). Losing it means losing access to every secret you've encrypted.
Installation
git clone <repo-url>
cd sops-mcp
python3 -m venv .venv
.venv/bin/pip install -e .Claude Code configuration
Add to your project's .mcp.json:
{
"mcpServers": {
"sops-mcp": {
"command": "/path/to/sops-mcp/.venv/bin/python",
"args": ["-m", "sops_mcp"],
"env": {
"SOPS_MCP_SOPS_BINARY": "/path/to/sops",
"SOPS_MCP_AGE_PUBLIC_KEY": "<your-age-public-key>"
}
}
}
}Environment variables
Variable | Required | Purpose |
| Yes* | Age public key for encryption |
| Yes* | Alternative to |
| No | Path to sops binary (default: |
| No | Log level (default: |
| Sometimes | Age private key — required for any mutation tool (rotate, add, update, rename, delete) |
| No |
|
| No | Bind host/port for SSE transport (default: |
| No | Comma-separated allowlist for the SSE |
| Sometimes | Required when SSE transport binds to |
* One of SOPS_MCP_AGE_PUBLIC_KEY or SOPS_AGE_RECIPIENTS must be set.
Security
No filesystem access — The server never reads from or writes to the client filesystem. All content is passed as text parameters and returned as text.
No private key for normal use — Encryption uses only the public key. The private key is needed only for mutation tools.
No plaintext in responses — Generated secret values are never returned. Derived values are returned because they're meant to be pasted into config files (e.g. an Authelia PBKDF2 hash) — don't derive values you don't intend to publish.
Secure temp files — Used only for sops CLI invocation. Created with 0600 permissions, overwritten with zeros before deletion, cleanup guaranteed by
finallyblock.OS-level entropy — Secret generation uses Python's
secretsmodule (backed by/dev/urandom).stdio transport by default — No network exposure; runs as a client child process.
Input validation — Key names must match
^[A-Z][A-Z0-9_]*$.
Encrypted file format
DB_PASSWORD: ENC[AES256_GCM,data:...,tag:...,type:str]
SMTP_USER: ENC[AES256_GCM,data:...,tag:...,type:str]
DB_PASSWORD_HASH: ENC[AES256_GCM,data:...,tag:...,type:str]
_meta_unencrypted:
version: 1
secrets:
DB_PASSWORD:
source: generated
description: Database password
generation:
length: 32
charset: alphanumeric
last_rotated: "2026-04-21T15:30:00Z"
SMTP_USER:
source: external
description: SMTP username
DB_PASSWORD_HASH:
source: derived
derivation:
transform: sha256_hex
from: DB_PASSWORD
last_rotated: "2026-04-21T15:30:00Z"
sops:
age:
- recipient: age1...
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
...
unencrypted_suffix: _unencryptedSecret values are AES-256-GCM encrypted. The _meta_unencrypted block is stored in plaintext (using SOPS's unencrypted_suffix feature) so metadata is readable without decryption.
Why these tools and not others
Per-key read (decrypt-one-secret): intentionally absent. Returning plaintext over the MCP boundary would give the model access to secret material during tool calls — an accidental exfiltration vector. If you need a plaintext value, run sops decrypt yourself with the age private key.
Per-key in-place update for generated/derived secrets: intentionally absent. sops_rotate_generated is the one path that changes those values, so rotations leave an audit trail (last_rotated timestamp) and cascade cleanly to derived secrets.
Multi-recipient / team key management (.sops.yaml, updatekeys): planned for a future release. v1 assumes a single age recipient. For multi-recipient setups, use the sops CLI directly for recipient rotations and this server for content management.
Other source types (imported, templated): out of scope. Those are orchestration concerns — fetch values from Vault or compose URLs in your deployment templating layer, then pass the result here as an external secret.
Supply chain integrity
The Docker build is hardened with three layers of verification, enforced by a CI gate.
Base image digest pinning
The Dockerfile pins python:3.12-slim by SHA-256 digest (@sha256:...) so Docker always pulls the exact image that was audited, not whatever the slim tag currently points to. The digest and cosign signature status are tracked in base-images.lock.json.
Update the base image (when upstream publishes security patches):
pip install requests # one-time
python3 lib/pin_base_images.pyBinary checksum verification
The sops and age binaries downloaded in the Dockerfile are verified with sha256sum -c against checksums from the official release pages. A tampered binary fails the build.
Python dependency hash pinning
Runtime dependencies are installed from requirements.lock.txt with pip install --require-hashes, which rejects any package whose content doesn't match the recorded SHA-256 hashes. This prevents dependency hijacking and typosquatting.
Update dependencies after editing requirements.in:
pip install pip-tools # one-time
lib/compile_requirements.shCI verification
The supply-chain.yml workflow runs lib/verify_requirements.py and lib/verify_base_images.py on every push and PR. It checks that all lockfiles are well-formed and all Dockerfile FROM lines are digest-pinned.
Verifying a published release
Every container image published to GHCR is signed by this repo's publish workflow using keyless cosign via sigstore, and ships with SLSA v1.0 build provenance and an SPDX SBOM attached as OCI artifacts. Every commit on main and every release tag is SSH-signed. You can verify all of this without holding any long-lived key material — the signatures are anchored in sigstore's public transparency log.
Install cosign: https://docs.sigstore.dev/system_config/installation
Verify the image signature. A successful verification proves the image was built by this repository's publish.yml workflow, not just that its digest matches a reference someone sent you.
cosign verify \
--certificate-identity-regexp 'https://github.com/privacyplaybook/sops-mcp/\.github/workflows/publish\.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/privacyplaybook/sops-mcp:<tag>Inspect the attestations.
# List all artifacts attached to the image
cosign tree ghcr.io/privacyplaybook/sops-mcp:<tag>
# Download the SBOM (SPDX JSON)
cosign download sbom ghcr.io/privacyplaybook/sops-mcp:<tag>
# Verify the SLSA build provenance
cosign verify-attestation --type slsaprovenance1 \
--certificate-identity-regexp 'https://github.com/privacyplaybook/sops-mcp/\.github/workflows/publish\.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/privacyplaybook/sops-mcp:<tag>Verify git tags and commits. The simplest check is the green Verified badge on the github.com commits and tags pages.
Development
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
pytest tests/ -v # 29 tests including end-to-end sops round-trip
ruff check src/ tests/Example: integrating with a CI/CD deployment pipeline
A common pattern: use this server to produce secrets.enc.yaml files committed to your infrastructure repo, then decrypt them in CI and inject the plaintext values as environment variables to a container orchestrator (Portainer, Kubernetes, Nomad).
Generate an age keypair once. Give the private key to your CI as a secret (e.g.
SOPS_AGE_KEY), the public key to Claude Code asSOPS_MCP_AGE_PUBLIC_KEY.Ask the model to produce a
secrets.enc.yamlwithsops_create_secrets.Commit the encrypted file.
In your deploy workflow, run
sops decrypt secrets.enc.yaml > .env(or equivalent) and pass the result to your orchestrator.When secrets need rotating, ask the model to run
sops_rotate_generatedorsops_update_external; commit and redeploy.
The _meta_unencrypted block lets your tools filter out the metadata (keys starting with _) when pushing values to an orchestrator, so metadata never leaks into environment variables.
License
Apache-2.0. See LICENSE.
Available Tools
9 toolssops_add_metadataA
Add _meta_unencrypted metadata to an existing SOPS-encrypted file that lacks it. Decrypts the file, adds metadata, and re-encrypts preserving original plaintext values. Requires SOPS_AGE_KEY env var for decryption.
| Name | Required | Description | Default |
|---|---|---|---|
| secret_metadata | Yes | Mapping of key names to metadata. Each value has 'source' ('generated', 'external', or 'derived') and optional 'description'. For 'derived', also provide 'transform' and 'from'. | |
| encrypted_content | Yes | Contents of a secrets.enc.yaml file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description bears full burden. It explains decryption, addition, and re-encryption preserving plaintext, but lacks details on error handling or pre-existing metadata scenarios.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose, efficient second sentence with process and prerequisite. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Adequate for a modification tool with nested parameters; covers purpose, process, and prerequisite. Lacks output description, but likely trivial for such tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with clear parameter descriptions. The description adds overall context but no additional parameter-level details beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool adds metadata to SOPS-encrypted files lacking it. Differentiates from sibling tools like sops_add_secrets by focusing on metadata rather than secrets.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Describes when to use (file lacks metadata) and prerequisite (SOPS_AGE_KEY env var). Does not explicitly state when not to use or alternatives, but context with siblings provides clarity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_add_secretsA
Add new secrets to an existing SOPS-encrypted file. Decrypts the file, merges in new secrets, and re-encrypts — preserving all existing values and metadata. Rejects keys that already exist in the file. Supports generated, external, and derived sources. Requires SOPS_AGE_KEY env var.
| Name | Required | Description | Default |
|---|---|---|---|
| secrets | Yes | New secrets to add | |
| encrypted_content | Yes | Contents of an existing secrets.enc.yaml file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description discloses key behavioral traits: it decrypts, merges, re-encrypts, preserves existing values and metadata, rejects duplicate keys, and supports multiple source types. This is comprehensive, though it could mention atomicity or error handling for missing keys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three well-structured sentences; first sentence immediately states purpose, second explains the process and constraints, third lists support and requirements. No redundant or extraneous information. Front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers workflow, prerequisites, and constraints well. However, it does not describe the return value (likely the updated encrypted content) or specify what happens on failure. Given no output schema, a brief mention of the output would make it more complete. Sibling tools exist but are not referenced for differentiation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already thoroughly describes each parameter. The description adds workflow context (decrypt, merge, re-encrypt) but does not enhance parameter semantics beyond what the schema provides. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Explicitly states 'Add new secrets to an existing SOPS-encrypted file' with specific verb and resource. Distinguishes from sibling tools like sops_create_secrets (which likely creates a new file) and sops_delete_secrets. The merge-and-preserve behavior further clarifies its unique role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides prerequisite (SOPS_AGE_KEY env var) but offers no explicit guidance on when to use this tool versus alternatives like sops_create_secrets or sops_update_external. The description implies usage by stating it works on existing files, but a direct comparison or when-to-use/when-not-to-use would improve clarity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_create_oidc_secretA
Convenience tool: create an Authelia-compatible OIDC client secret. Generates KEY_NAME as a 64-char alphanumeric 'generated' secret AND KEY_NAME_HASH as a 'derived' PBKDF2-SHA512 hash of it, stored together in a new encrypted file. The hash is returned in the response for pasting into Authelia's configuration.yml. Equivalent to calling sops_create_secrets with one generated and one derived (pbkdf2_sha512_authelia) entry.
| Name | Required | Description | Default |
|---|---|---|---|
| key_name | Yes | Base name for the plaintext secret (e.g. GRAFANA_OIDC_CLIENT_SECRET). The hash will be stored as KEY_NAME_HASH. Must match ^[A-Z][A-Z0-9_]*$. | |
| description | No | Human-readable note (e.g. 'OIDC client secret for Grafana') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explains that the tool generates a 64-char alphanumeric secret and a PBKDF2-SHA512 hash, stores them in a new encrypted file, and returns the hash. However, it does not disclose file naming conventions, overwrite behavior, or authorization requirements, leaving minor gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences long, each serving a distinct purpose: stating the tool's purpose, describing the behavior, and relating it to a sibling tool. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has two parameters, no output schema, and no annotations, the description covers input, output (hash in response), and equivalence to a sibling. It could mention potential side effects like file naming, but overall it is adequate for the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes both parameters with 100% coverage. The description adds value by explaining the relationship between 'key_name' and the hash key (KEY_NAME_HASH) and the nature of the generated secret, which goes beyond the schema's type constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states it is a 'convenience tool' for creating an 'Authelia-compatible OIDC client secret'. It clearly distinguishes itself from the sibling tool 'sops_create_secrets' by specifying it is equivalent to calling it with specific entries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies when to use this tool (for OIDC client secrets) and contrasts it with the alternative 'sops_create_secrets' by stating it is a convenience wrapper. It gives clear guidance on when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_create_secretsA
Generate and encrypt secrets as SOPS YAML. Returns encrypted content for the client to write to disk. Supports three sources: 'generated' (cryptographic randomness), 'external' (user-provided values), and 'derived' (computed from another key in the same file via a transform such as pbkdf2_sha512_authelia). Derived secret plaintexts are returned in the response so they can be copied into config files.
| Name | Required | Description | Default |
|---|---|---|---|
| secrets | Yes | List of secrets to create |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses that the tool returns encrypted content and that derived secret plaintexts are returned. It also explains the behavior of different sources (generated uses randomness, external requires value, derived uses transform from another key). Lacks disclosure on authentication or rate limits but is sufficient for basic usage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the main purpose, and uses clear, direct language. Every sentence adds value: first sentence states output and action, second sentence explains derived plaintext behavior, third sentence lists sources. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description appropriately explains the return value (encrypted content for client to write to disk) and derived secret plaintexts. It covers the main aspects of the tool's workflow. Could mention file path handling or error conditions but is fairly complete for a creation tool with complex parameter requirements.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for all parameters. Description adds value beyond schema by explaining the behavioral implications of source types (e.g., derived secrets return plaintexts, generated uses cryptographic randomness). This contextual information helps agents select and correctly invoke the tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it generates and encrypts secrets as SOPS YAML, returns encrypted content for client to write to disk. It specifies three distinct sources (generated, external, derived) with examples, distinguishing it from sibling tools like sops_add_secrets or sops_delete_secrets.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use this tool (for creating and encrypting secrets) and provides context about derived secrets returning plaintexts. It implicitly distinguishes from siblings by focusing on creation, but lacks explicit when-not-to-use or alternative recommendations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_delete_secretsA
Delete one or more keys from an existing SOPS-encrypted file. Removes both the encrypted value and the _meta_unencrypted entry. Rejects deletion of keys that other derived secrets depend on unless those dependents are also in the delete list. Requires SOPS_AGE_KEY env var.
| Name | Required | Description | Default |
|---|---|---|---|
| key_names | Yes | Keys to delete | |
| encrypted_content | Yes | Contents of an existing secrets.enc.yaml file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description discloses key behavioral traits: removal of both encrypted value and metadata entry, rejection of dependent keys unless included in the delete list, and the required environment variable. It lacks explicit output details but covers important safety and dependency behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no fluff. It front-loads the main action, then provides specific removal details, and ends with a crucial constraint. Every sentence adds necessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 2 parameters and no output schema, the description covers the deletion process, dependency rule, and env var requirement. It does not describe the return value or error scenarios beyond dependency rejection, but given the context, it is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by explaining the effect on parameters: it clarifies that deleting a key removes its encrypted value and meta entry, and that key_names may be rejected if dependencies are not also deleted. This goes beyond the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool deletes keys from a SOPS-encrypted file, with specific details about what is removed (encrypted value and _meta_unencrypted entry). It distinguishes itself from sibling tools like sops_add_secrets or sops_list_secrets by specifying deletion behavior and dependency handling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use (deleting keys) and includes a prerequisite (requires SOPS_AGE_KEY env var). However, it does not explicitly contrast with alternatives or provide when-not-to-use scenarios, though the dependency rejection provides a constraint.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_list_secretsA
List key names and metadata from a SOPS-encrypted file. No decryption needed — reads key names from encrypted YAML and metadata from the _meta_unencrypted block.
| Name | Required | Description | Default |
|---|---|---|---|
| encrypted_content | Yes | Contents of a secrets.enc.yaml file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully bears the responsibility. It discloses that it reads key names from encrypted YAML and metadata from the _meta_unencrypted block, and states no decryption is needed. This provides good behavioral insight, though it could be more explicit about being read-only.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero wasted words. The first sentence states the purpose, the second adds the critical behavioral detail. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple input-only tool with no output schema, the description covers the essentials. It could benefit from mentioning what kind of metadata is returned or that the tool is purely read-only, but it is sufficiently complete given the low complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter is fully described in the schema ('Contents of a secrets.enc.yaml file'), and the description adds value by explaining how the content is used (reading key names and metadata). This goes beyond the schema's bare description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists 'key names and metadata from a SOPS-encrypted file.' The verb 'List' and the resource are precise. It distinguishes from sibling tools by highlighting that no decryption is needed, which is unique among the sops_ tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for read-only inspection without decryption, setting clear context. However, it does not explicitly state when to use it versus alternatives (e.g., sops_add_secrets for modifications). Given many siblings, explicit when/when-not would be ideal, but the context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_rename_secretA
Rename a key in an existing SOPS-encrypted file. Preserves the value, source type, and metadata. Updates 'from' references in any derived secrets that depend on the renamed key. Requires SOPS_AGE_KEY env var.
| Name | Required | Description | Default |
|---|---|---|---|
| new_name | Yes | New key name (must match ^[A-Z][A-Z0-9_]*$ and not collide with an existing key) | |
| old_name | Yes | Current key name | |
| encrypted_content | Yes | Contents of an existing secrets.enc.yaml file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses that values, source type, and metadata are preserved; that 'from' references in derived secrets are updated; and that the SOPS_AGE_KEY env var is required. It does not mention error handling or idempotency but covers key behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with three sentences that front-load the main action and cover essential details (preservation, reference updates, env var requirement). No redundant or vague language.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations or output schema, the description provides sufficient context for the rename operation. It explains side effects (updating derived secrets) and a prerequisite (env var). It could mention what happens on failure or if the key does not exist, but overall it is adequate for an AI agent to understand the tool's behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description does not add meaning beyond the schema: it mentions 'key' and 'rename' but the parameters (encrypted_content, old_name, new_name) are already described in the schema. No additional constraints or examples are provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('rename a key'), the resource ('existing SOPS-encrypted file'), and distinguishes from sibling tools (add, delete, list, etc.) by focusing on renaming. It also details what is preserved and updated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use (to rename a key) but provides no explicit guidance on when not to use or alternatives. No mention of prerequisites or comparison with siblings like sops_add_secrets or sops_delete_secrets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_rotate_generatedA
Re-generate 'generated' secrets with new random values while preserving 'external' secrets. Requires SOPS_AGE_KEY env var for decryption.
| Name | Required | Description | Default |
|---|---|---|---|
| encrypted_content | Yes | Contents of an existing secrets.enc.yaml file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses the need for the SOPS_AGE_KEY env var and that external secrets are preserved, but it does not detail side effects like overwriting generated secrets or error conditions when the env var is missing. Given no annotations, more transparency would be beneficial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that conveys essential information without any unnecessary words or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While the description covers the core functionality and an important prerequisite, it lacks details about return values, error handling, and potential side effects. This is adequate for a simple tool but could be more complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 100% coverage with a description for the only parameter. The description does not add additional meaning beyond what the schema already provides, meeting the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: re-generating 'generated' secrets with new random values while preserving 'external' secrets. It uses a specific verb and resource, and distinguishes from sibling tools like sops_add_secrets.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It mentions the requirement for the SOPS_AGE_KEY environment variable, providing some usage context. However, it does not explicitly state when not to use this tool or mention alternative tools for similar operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sops_update_externalA
Replace the value of an 'external' secret (e.g. after the user rotated an upstream API key). Rejects attempts to update 'generated' or 'derived' secrets — use sops_rotate_generated for those. Recomputes any derived secrets that reference this key. Requires SOPS_AGE_KEY env var.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | New plaintext value | |
| key_name | Yes | Key to update | |
| encrypted_content | Yes | Contents of an existing secrets.enc.yaml file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses that the tool recomputes derived secrets referencing the key and rejects non-external secret types. It also states the environment variable requirement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero waste. The first sentence states the action and use case, the second adds restrictions and side effects. Front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 3 required parameters, no output schema, and no nested objects, the description is complete. It covers purpose, usage, behavioral side effects, and requirements.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the descriptions in the schema are clear. The tool description does not add extra meaning beyond the schema for the parameters, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool replaces the value of an external secret, uses a specific verb and resource, and distinguishes itself from siblings by explicitly mentioning that it rejects generated or derived secrets and directs to sops_rotate_generated for those.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use (after rotating an upstream API key) and when not to (for generated/derived secrets, with a specific alternative named). It also mentions a prerequisite (SOPS_AGE_KEY env var).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.10.0- First observed
sops_add_metadata - First observed
sops_add_secrets - First observed
sops_create_oidc_secret - First observed
sops_create_secrets - First observed
sops_delete_secrets - First observed
sops_list_secrets - First observed
sops_rename_secret - First observed
sops_rotate_generated - First observed
sops_update_external
TDQS
Scored across 9 tools
Each tool has a clear, distinct purpose: adding, creating, deleting, listing, renaming, rotating, updating, or adding metadata. No two tools overlap in functionality, and descriptions clearly differentiate them.
All tools follow a consistent 'sops_verb_noun' pattern in snake_case. The verbs (add, create, delete, list, rename, rotate, update) are descriptive and uniform.
With 9 tools, the server covers the essential operations for managing SOPS-encrypted secrets without being bloated. Each tool serves a necessary and well-scoped function.
The tool set covers all major lifecycle operations: create, read (list), update (add, rename, update_external, rotate), and delete. Minor gaps exist (e.g., no explicit metadata removal tool), but the surface is largely complete for secrets management.
Maintenance
Related MCP Connectors
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Hosted MCP server for AI agent identity, permissions, verification, and reusable proof.
A secret store for AI agents: the agent never sees the plaintext.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server that lets AI agents call APIs without ever seeing the credentials, using a local encrypted vault and per-secret allowlist policies for HTTP requests and subprocess environment variables.1AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceSecrets management MCP server that injects credentials into API requests for AI agents, enforcing policies and logging all activity without exposing raw keys.54 npm30MIT
- AlicenseNot gradedqualityCmaintenanceMCP server enabling AI agents to use secrets (API keys, tokens) via encrypted vault, executing HTTP/shell/SSH actions server-side while never exposing secret values to the AI.MIT
- AlicenseNot gradedqualityBmaintenanceEncrypted secrets management MCP server for AI agents, enabling secure storage, retrieval, rotation, and auditing of API keys and credentials with AES-128 encryption.MIT