Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

keysecrets-mcp

MCP wrapper around the halfax-secrets vault client. Exposes the KeySecrets vault to the Halfax AI agent (or any MCP host) as nine typed tools so the agent can fetch credentials at task-time without having them plumbed through env vars, argv, or config files.

Tools

Tool Domain Gate
secret_list(search?, secret_type?) read always
secret_get(name_or_id, field?) read (returns plaintext) always
secret_info(name_or_id) read (metadata only, NO plaintext) always
secret_types() read (static) always
vault_status() read (diagnostic) always
secret_create(name, secret_type, ...) write mutations env + change-role token
secret_update(name_or_id, ...) write mutations env + change-role token
secret_rotate_password(name_or_id, new_password) write mutations env + change-role token
secret_delete(name_or_id, confirm) write mutations env + change-role token + confirm=true

secret_get is the only tool that ever returns a plaintext value. Every other tool returns metadata only — id, name, type, tags, notes, available field names, timestamps. This keeps the agent's context safe by default.

Safety posture

Mutations are double-gated:

  1. MCP-env gate — the server only accepts mutation tool calls when KEYSECRETS_MCP_ALLOW_MUTATIONS=1 is set in the MCP process env. Default posture is read-only even when the bearer happens to carry a change-role token.
  2. Server-side role gate — the KeySecrets server independently checks the bearer's role. A read-role token gets AuthError (HTTP 403) regardless of the MCP-env gate.

Either gate alone is sufficient to refuse the mutation. The env-var gate exists so an agent operating under a change-role bearer (e.g. on Betelgeuse where the canonical change-role token lives) cannot accidentally mutate without an explicit operator opt-in.

secret_delete additionally requires confirm=true — mirrors ks-get --delete --yes, no soft-undo exists.

Install

cd /home/halfax/Desktop/projects/keysecrets-mcp
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/pip install -e ../halfax-secrets   # local editable

For a host without the local checkout, replace the editable install with the GitLab-over-SSH form — via the gitlab: SSH alias (fleet convention, DECISIONS.md §1: the alias in ~/.ssh/config points at whichever box runs GitLab — Cygnus since 2026-05-29 — so URLs survive the next move):

.venv/bin/pip install git+ssh://gitlab/halfax/halfax-secrets.git

Configure

All configuration is via env (mirrors halfax-secrets discovery):

Var Purpose Default
KEYSECRETS_TOKEN or $KEYSECRETS_TOKEN_FILE bearer ~/.config/keysecrets/token
KEYSECRETS_URL server Netbird → LAN probe
KEYSECRETS_CA_CERT TLS bundle bundled cert
KEYSECRETS_CACHE_TTL read-cache TTL (s) 60
KEYSECRETS_MCP_ALLOW_MUTATIONS mutation gate 0 (refuse)
KEYSECRETS_MCP_LOG_LEVEL log level on stderr INFO

Wire into a host

Continue.dev (~/.continue/config.yaml)

mcpServers:
  - name: keysecrets
    command: /home/halfax/Desktop/projects/keysecrets-mcp/.venv/bin/python
    args:
      - /home/halfax/Desktop/projects/keysecrets-mcp/server.py
    env:
      KEYSECRETS_MCP_LOG_LEVEL: INFO
      # Uncomment to enable writes:
      # KEYSECRETS_MCP_ALLOW_MUTATIONS: "1"

Claude Code / generic stdio MCP client

{
  "mcpServers": {
    "keysecrets": {
      "command": "/home/halfax/Desktop/projects/keysecrets-mcp/.venv/bin/python",
      "args": ["/home/halfax/Desktop/projects/keysecrets-mcp/server.py"],
      "env": {
        "KEYSECRETS_MCP_LOG_LEVEL": "INFO"
      }
    }
  }
}

halfax-ai-vscode extension

Add to the default server list in halfax-ai-vscode/extension/src/tools/mcpManager.ts following the pattern of HAL_WEB_MCP_DEFAULT. Then repackage / reinstall the .vsix (versions track in extension/package.json).

Logging

All tool invocations log to stderr (the MCP stdio channel stays clean for protocol traffic). secret_get logs name, field, and value_len — never the value itself. Mutation calls log the operation type, target, and (for updates) the set of fields touched.

Why a wrapper exists

halfax-secrets is the Python lib (DECISIONS §16). Every project that needs credentials at runtime imports it. But the agent — running through MCP — couldn't reach the vault without this wrapper. Adding it closes the last "credential plumbing" gap: the agent can list, inspect, fetch, rotate, and create secrets through the same backend that every other project uses, without an admin manually copying values into an env file.

About

MCP wrapper for a self-hosted, post-quantum, end-to-end-encrypted secrets vault (X25519 + ML-KEM-768).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages