Local KMS MCP
Servidor MCP ligero y local para gestión de claves por agente.
Documentación
local-kms-mcp-server
Servidor MCP ligero y local-first para gestión de claves por agente.
Dale a cada agente su propia identidad de firma, sin depender de un KMS externo ni exponer claves privadas.
local-kms-mcp-server genera, almacena, rota y utiliza pares de claves de firma completamente en la máquina local. Las claves nunca
salen del proceso, nunca tocan la red y permanecen bajo control.
Está diseñado para clientes MCP y entornos de ejecución de agentes que necesitan identidades aisladas y componibles para tareas como flujos DID/SSI, handshakes de autenticación, firma de desafíos y cualquier flujo de trabajo donde los agentes deban demostrar algo criptográficamente.
Qué Hace
- Genera pares de claves de firma asociados a un keyId (una identidad por agente o tarea)
- Almacena claves localmente usando un keystore simple basado en archivos
- Firma payloads en base64 sin exponer nunca el material de la clave privada
- Rota claves de forma segura preservando la consistencia del algoritmo
- Elimina claves con borrado seguro opcional (sobrescritura con datos aleatorios)
- Lista algoritmos de firma y claves disponibles
- Opcionalmente cifra las claves en reposo usando AES-256-GCM
- Se ejecuta sobre MCP vía stdio (por defecto) o HTTP cuando sea necesario
Algoritmos Soportados
| Algoritmo | Valor de herramienta | Notas |
|---|---|---|
| Ed25519 | ed25519 | Buen default para firma general y casos de uso tipo DID |
| ECDSA secp256k1 | ecdsa-secp256k1 | Común para Ethereum, Bitcoin y otros flujos Web3 |
| ECDSA P-256 | ecdsa-prime256v1 | ES256, WebAuthn y compatibilidad con KMS en la nube común |
| ECDSA P-384 | ecdsa-secp384r1 | Entornos NIST P-384 de mayor seguridad |
Requisitos
- Node.js
>=24.0.0 - Un cliente MCP que soporte servidores MCP por stdio o HTTP
Inicio Rápido
Transporte stdio
Usa stdio cuando ejecutes desde Claude Desktop, Cursor u otro cliente MCP local.
{
"mcpServers": {
"local-kms": {
"command": "npx",
"args": ["-y", "local-kms-mcp-server"],
"env": {
"STORE_PATH": "/Users/yourname/.local-kms",
"ENCRYPT_STORE": "true",
"STORE_ENCRYPTION_KEY": "<base64-32-byte-key>"
}
}
}
}
Transporte HTTP
Usa HTTP solo cuando quieras explícitamente un endpoint de red local.
TRANSPORT=http PORT=8080 npx local-kms-mcp-server
Endpoint:
POST http://localhost:8080/mcp
Instalación
Ejecuta directamente con npx:
npx -y local-kms-mcp-server
O instala globalmente:
npm install -g local-kms-mcp-server
local-kms-mcp-server
Configuración
| Variable de entorno | Default | Descripción |
|---|---|---|
STORE_PATH | ./keys | Directorio usado para archivos de claves persistidos |
TRANSPORT | stdio | Transporte MCP: stdio o http |
PORT | 8080 | Puerto HTTP usado solo cuando TRANSPORT=http |
ENCRYPT_STORE | false | Establecer a true o 1 para cifrar archivos de claves en reposo |
STORE_ENCRYPTION_KEY | none | Clave de 32 bytes codificada en base64 requerida cuando el cifrado está habilitado |
Para desarrollo local hay un archivo de ejemplo en .env.example, pero para uso real con clientes MCP es mejor pasar
los valores a través de la configuración env del cliente para que el arranque sea determinista.
Genera una clave de cifrado:
node -e "console.log(require('node:crypto').randomBytes(32).toString('base64'))"
Referencia de Herramientas
Todas las entradas de herramientas se validan con Zod. Las claves públicas y firmas se devuelven como cadenas base64.
| Herramienta | Propósito | Entrada | Salida |
|---|---|---|---|
check_keypair | Verificar si una clave existe | { "keyId": "agent-1" } | { "exists": true } |
list_keys | Listar todos los IDs de claves almacenados | {} | { "keys": ["agent-1", "agent-2"] } |
list_algorithms | Listar todos los algoritmos de firma soportados | {} | { "algorithms": ["ed25519", ...] } |
generate_key | Crear y persistir un nuevo par de claves | { "keyId": "agent-1", "algo": "ed25519" } | { "publicKey": "..." } |
get_key_info | Devolver la clave pública almacenada para un ID | { "keyId": "agent-1" } | { "publicKey": "..." } |
rotate_key | Rotar un par de claves existente usando su algoritmo almacenado | { "keyId": "agent-1" } | { "newPublicKey": "..." } |
delete_key | Eliminar un par de claves con borrado seguro opcional | { "keyId": "agent-1", "secureWipe": true } | { "success": true } |
sign_message | Firmar un payload codificado en base64 | { "keyId": "agent-1", "message": "aGVsbG8=" } | { "signature": "..." } |
Notas:
generate_keyfalla si elkeyIdya existerotate_keyincrementa elversionalmacenadodelete_keyconsecureWipe: truesobrescribe el archivo de clave con datos aleatorios antes de la eliminaciónsign_messageespera quemessageya esté codificado en base64sign_messageacepta una anulación opcional dealgo, pero en uso normal el algoritmo almacenado suele ser lo que quieres
Flujo de Uso Típico
- Llama a
list_algorithmspara ver los algoritmos de firma disponibles - Llama a
generate_keypara un nuevokeyId - Llama a
get_key_infopara recuperar la clave pública para registro o distribución - Llama a
sign_messagecuando el agente necesite firmar un desafío o payload - Llama a
rotate_keycuando necesites nuevo material de clave para el mismokeyId - Llama a
delete_keypara eliminar de forma segura un par de claves cuando ya no sea necesario - Llama a
check_keypairolist_keyspara inventario y comprobaciones de existencia
Ejemplo de payload sign_message:
{
"keyId": "key-1",
"message": "eyJub25jZSI6IjEyMyJ9"
}
Modelo de Almacenamiento
Las claves sin cifrar se almacenan como un archivo por clave bajo ${STORE_PATH}:
${STORE_PATH}/${keyId}.json
Los registros almacenados contienen:
{
"keyId": "key-1",
"algo": "ed25519",
"publicKey": "...",
"privateKey": "...",
"version": 1,
"createdAt": "2026-04-18T12:34:56.000Z"
}
Cuando ENCRYPT_STORE=true, el contenido del archivo se cifra y se persiste como texto cifrado en base64 en lugar de JSON en texto plano.
Notas de Seguridad
- Las claves privadas nunca salen del servidor a través de respuestas MCP
- Los archivos de clave se escriben con permisos
0600 - El cifrado en reposo es opcional pero recomendado para cualquier cosa más allá de desarrollo local desechable
- El modo HTTP no añade autenticación ni TLS por sí mismo; mantenlo detrás de un límite local de confianza o tu propio proxy inverso
- Los valores de
keyIdse convierten en nombres de archivo, así que usa IDs estables y seguros para sistemas de archivos
Desarrollo
pnpm install
pnpm build
pnpm test
pnpm lint
pnpm format:check
Ejecuta localmente después de compilar:
pnpm start
Observa la salida compilada durante el desarrollo:
pnpm start:dev
Extensión con Nuevos Algoritmos
- Implementa un nuevo adaptador extendiendo
KeyAlgorithmAdapter - Regístralo en
src/keystore/index.ts - Expón el nombre del adaptador a través del esquema de herramienta relevante si los usuarios deberían poder seleccionarlo
import { KeyAlgorithmAdapter } from '../adapter.js';
import type { KeyPair } from '../types.js';
export class MyAdapter extends KeyAlgorithmAdapter {
readonly name = 'my-algo';
generate(): KeyPair {
/* ... */
}
sign(privateKey: string, data: Buffer): string {
/* ... */
}
verify(publicKey: string, data: Buffer, signature: string): boolean {
/* ... */
}
rotate(_currentKeyPair: KeyPair): KeyPair {
return this.generate();
}
}
Estructura del Proyecto
src/
config/ environment parsing and validation
keystore/ adapters, registry, and file-based storage
tools/ MCP tool registration and handlers
utils/ crypto helpers, errors, serializers
server.ts MCP server construction
main.ts stdio and HTTP entry point
test/ unit tests
Licencia
MIT