vault-mcp
Provides integration with HashiCorp Vault for centralized credential management, including secure storage, retrieval, and auditing of secrets for servers, websites, and APIs.
Click on "Install 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., "@vault-mcpshow me the SSH credentials for prod-web-01"
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.
vault-mcp
vault-mcp 는 단순한 HashiCorp Vault 관리 도구가 아니라, 사내 서버·웹사이트·API 접속
정보(Credential)를 중앙에서 인증·인가·감사하며 관리하는 Ops Broker 다.
LLM(Claude) 또는 CLI 가 사용자의 요청을 중앙 API 에 전달하면, 중앙 API 가 사용자 인증·인가 → 리소스 해석 → Vault Credential 조회 → 결과 마스킹 → 감사 기록을 통제한다. 실제 Secret 은 Vault 에만 있고, LLM·CLI·DB·API 응답 어디에도 새지 않는다.
현재 단계: STEP 8.7 — Resource 유형 확장(SERVER/WEBSITE/API) 완료. 다음은 STEP 9(인증 개선). SSH 실행(Runner)은 STEP 10 으로 아직 미구현이다. 단계별 상세는 docs/development-roadmap.md.
목차
Related MCP server: Better Auth MCP Server
핵심 원칙
원칙 | 내용 |
Secret 격리 | 실제 Secret 은 Vault 에만. DB·API 응답·로그·감사에는 |
1 Resource = 1 Credential | 하나의 등록 항목 = 하나의 접속 대상 = 하나의 Credential. |
소유자 전용 | 리소스는 소유자만 관리. 타인 리소스는 403 이 아니라 404(존재 은닉). |
클라이언트 입력 불신 | 요청 body 의 |
LLM 은 별칭만 | Claude 는 |
감사 강제 | 모든 Credential 접근(등록/교체/삭제/reveal)은 감사 로그에 기록(Secret 원문 제외). |
아키텍처
현재 구현된 데이터 흐름(등록 / 조회 / 삭제). SSH 실행(Runner)은 STEP 10 으로 아직 없다.
flowchart TD
subgraph client [클라이언트]
W[Web UI · Jinja2]
S[Claude Skill · REST]
end
W -->|Cookie 세션 + CSRF| API
S -->|API Key| API
API[vault-mcp FastAPI]
API -->|인증 4종 → users.id| AUTH{인증·인가}
AUTH -->|비민감 메타데이터| PG[(PostgreSQL<br/>vault_mcp schema)]
AUTH -->|credential_ref 로 Secret| VAULT[(HashiCorp Vault<br/>KV v2)]
API --> AUDIT[(audit_logs)]
PG -.->|credential_ref = 논리 경로| VAULT흐름 | 경로 |
등록 | 리소스 등록(PG) → Credential 등록 → Vault write → |
조회(reveal) | 소유권 확인(PG) → |
삭제 | Vault soft delete → PG 상태/ |
컴포넌트 책임:
컴포넌트 | 한다 | 하지 않는다 |
Claude Skill |
| Secret 원문 출력(사용자 요청해도 금지), Vault/경로 접근 |
Web UI | 로그인, 리소스 CRUD, Credential 등록/교체/삭제, API Key 발급 | Secret 재표시(Web 에 reveal 없음) |
FastAPI | 인증·인가·리소스 해석·Vault 연동·마스킹·감사 | Secret 을 응답/로그에 노출 |
Vault | 실제 Secret 저장 | — |
PostgreSQL | 비민감 메타데이터 + | 실제 Secret 저장 |
Resource 유형과 저장 책임
STEP 8.7 부터 등록 대상은 SERVER / WEBSITE / API 세 유형이다(OTHER 는 범위 밖). 유형은
등록 후 변경 불가(409). 정본: docs/resource-types.md.
✓ 사용 · — 항상 NULL(보내면 400) · 굵게 = 필수
필드 | 저장소 | SERVER | WEBSITE | API |
| PG | ✓ / ✓ / ✓ | ✓ / ✓ / ✓ | ✓ / ✓ / ✓ |
| PG | ✓ / ✓ | ✓ / — | ✓ / — |
| PG | ✓ / ✓ | — | — |
| PG | — | ✓ | — |
| PG | — | — | ✓ / ✓ |
| PG | — | — | ✓ |
| PG | —(¹) | ✓ | ✓(= |
| PG | — | ✓ | ✓ |
| Vault | ✓ / ✓ | — | — |
| Vault | ✓(²) | ✓ | — |
| Vault | ✓(²) | — | — |
| Vault | — | — | ✓(³) |
(¹) SERVER 의 SSH
username은 Vault 에만 있다(하위 호환). 그래서 목록 응답의login_id는 SERVER 에서 항상null.(²) SERVER 는
auth_type(SshAuthType) 에 따라password또는private_key(+선택passphrase).(³) API 는
auth_type(ApiAuthType) 이 어떤 Secret 이 필수인지 결정한다.client_id는 secret 이 아니므로 PG,client_secret은 Vault — reveal 이 한 쌍으로 반환.
인증 유형 enum 은 분리 유지한다: SERVER = SshAuthType(PASSWORD/PRIVATE_KEY, Vault),
API = ApiAuthType(API_KEY/ACCESS_TOKEN/BEARER_TOKEN/PERSONAL_ACCESS_TOKEN/CLIENT_CREDENTIALS/
OAUTH_TOKEN/WEBHOOK_SECRET/CUSTOM, PostgreSQL). WEBSITE 는 인증 유형 개념이 없다.
API 레퍼런스
Base prefix /api/v1. 스키마·Authorize·curl 예시: docs/swagger-guide.md
(/docs, /redoc, /openapi.json 은 local/dev 에서만 노출).
Secret 반환 은 reveal 하나뿐이다. 나머지 Credential API 는 상태 메타데이터만 준다.
Method | Path | 용도 | 인증 / scope | Secret |
GET |
| Liveness / Readiness(DB+Vault) | 없음 | — |
POST |
| LOCAL 가입 / 로그인(JWT 발급) | 없음 | — |
GET |
| 현재 사용자 프로필 | 인증 | — |
POST/GET/DELETE |
| API Key 발급(1회 노출)/목록/폐기 | Web 사용자만(API Key 로 불가) | 발급 시 1회 |
GET |
| operation 권한 있는 서버 목록/상세 |
| — |
POST/PUT/GET/DELETE |
| 전 유형 Credential 등록/교체/상태/삭제 | 인증 | — |
POST/PUT/GET/DELETE |
| SSH Credential (SERVER 전용 하위 호환) | 인증 | — |
GET |
| 내 소유 리소스 목록/검색(전 유형) |
| — |
POST |
| ⚠️ Credential 원문 조회 |
| 평문 |
/resources/{id}/credentials(전 유형, STEP 8.7 신규)와/servers/{id}/credentials/ssh(SERVER 전용 하위 호환)는 SERVER 에 대해 동작·저장 결과가 동일하다. 후자는 WEBSITE/API 대상이면 409.reveal 응답은
resource_typediscriminator 로 갈리는 oneOf(SERVER/WEBSITE/API). SERVER 응답은resource_type키만 additive 로 추가돼 기존 Skill 이 그대로 동작한다.scope 표기 불일치는 코드 그대로다:
servers.read(점) vsresources:read/credentials:reveal(콜론).
Web UI(/web/*, HTML+Cookie, OpenAPI 미노출): 로그인, 대시보드, 리소스 CRUD(유형 선택 →
유형별 폼), Credential 등록/삭제(reveal 없음), API Key 발급/폐기. 상세: docs/web-ui.md.
인증 방식
한 Authorization 헤더에서 4종을 라우팅하며 모두 내부 users.id 로 귀결된다. 클라이언트가
보낸 user_id/tenant_id/oid 는 신뢰하지 않는다.
방식 | 헤더 | 알고리즘 | 사용자 식별 | 용도 · 활성 조건 |
LOCAL JWT |
| HS256 |
| 개발 주 로그인 / Web UI. |
Microsoft Entra |
| RS256(only, JWKS) |
| 사내 SSO. Bearer JWT 기본 경로 |
API Key |
| HMAC-SHA256 해시 |
| Claude/CLI. 접두 |
DEV | 헤더 없음 | — |
| 로컬 편의. |
저장 안 되는 것: 평문 password(Argon2id 해시만), Access/Refresh Token, API Key 원문(발급 시 1회만 노출). 상세: docs/token-storage-policy.md.
LOCAL(HS256)과 Entra(RS256)는 알고리즘·issuer·audience 로 분리, 교차검증 금지.
API Key scope:
resources:read,credentials:reveal,servers.read등. Web 사용자는 scope 검사를 통과(스코프 개념은 API Key 전용).상세: docs/local-authentication.md, docs/entra-authentication.md, docs/api-key-authentication.md.
Vault 경로와 삭제 정책
논리 경로(DB credential_ref 에 저장). DB 값이 경로의 정본 — 읽기/교체/삭제 시 재생성하지
않고 저장값을 그대로 쓴다(그래서 기존 행이 호환 로직 없이 동작). 경로는 UUID 로만 구성(사용자
입력·alias 미사용 → path traversal 차단).
구분 | 형식 |
신규(전 유형) |
|
legacy(STEP 6~8 SERVER) |
|
KV v2 물리 경로 = {mount}/data/{credential_ref}. VaultClient 는 App Token Policy 가 실제로
허용하는 endpoint 만 쓴다:
동작 | HTTP endpoint | 필요 capability |
write / read |
|
|
metadata read |
|
|
soft delete |
|
|
undelete(보상) |
|
|
삭제는 soft delete 다(destroy 아님, 복구 가능). 정책이
data/*에 delete 를 주지 않으므로DELETE /data/가 아니라POST /delete/(버전 지정, metadata 로 current_version 선조회)를 쓴다 — 전자를 쓰면 403 으로 삭제가 전부 실패한다. Resource 삭제도 Vault Secret 을 함께 soft delete 하고, DB commit 실패 시 undelete 로 보상한다. 정본: docs/vault-client.md, docs/credential-storage-flow.md.
데이터 모델
전용 PostgreSQL schema vault_mcp 에 격리(공유 DB vault_mcp 의 public·타 schema 미사용).
enum 은 비네이티브 VARCHAR(32). 정본: docs/data-model.md.
테이블 | 역할 |
| 신원. LOCAL(login_id+password_hash) / MICROSOFT(tenant_id+entra_oid) 두 출처 |
| API Key 메타데이터. 원문 미저장(key_hash/key_prefix 만) |
| 등록 대상 Resource(SERVER/WEBSITE/API 전부). 이름은 하위 호환으로 유지 |
| 인가 단위: 사용자 × 리소스 × operation. Default Deny, DENY 우선 |
| Vault 접속 메타데이터. 중앙 Vault(시스템 소유)면 owner NULL |
| 감사 이력. Secret 컬럼 없음 |
주요 제약(server_resources):
uq_server_resources_owner_user_id_alias— UNIQUE(owner_user_id, alias) WHERE status ≠ 'DELETED'(partial). soft delete 는 행을 남기므로, 삭제한 별칭을 재사용할 수 있게 DELETED 를 제외한다(0006). → 같은 alias 의 DELETED 행이 여러 개일 수 있어 alias 조회는 DELETED 를 거른다.resource_type_allowed—resource_type IN ('SERVER','WEBSITE','API')auth_type_api_only—auth_type IS NULL OR resource_type = 'API'(SshAuthType/ApiAuthType 혼용 차단)
Migration 이력(revision id 는 alembic_version.version_num VARCHAR(32) 제약):
revision | 내용 |
| 초기 스키마 5테이블(vault_mcp schema, enum=VARCHAR(32)) |
| LOCAL 로그인 필드 + api_keys 테이블, Entra 필드 nullable 전환 |
|
|
|
|
|
|
| alias unique 를 DELETED 제외 partial index 로 교체 |
SQLite(테스트)는 ALTER COLUMN / ADD CONSTRAINT 미지원 → NOT NULL 완화·CHECK 추가는 PostgreSQL 에서만 수행하고, SQLite 는 모델
create_all이 동일한 최종 스키마를 만든다.
빠른 시작
요구: Python 3.12+, uv. DB/Vault 없이도 /api/v1/health 는 뜬다.
# [로컬 PC / WSL·zsh]
uv sync # 가상환경 + 의존성
cp .env.example .env # 값 채우기(아래 환경 변수 참고)
uv run uvicorn app.main:app --reload # 또는: bash scripts/run-local.shAPI 문서:
http://127.0.0.1:8000/docs(local/dev 에서만)Web UI:
http://127.0.0.1:8000/web/loginPoC 로그인 계정 생성:
docs/poc-user-seed.md의 seed 스크립트
LOCAL 로그인은
.env에서LOCAL_AUTH_ENABLED=true여야 활성화된다(기본 false). Credential 등록/조회는 Vault 연결이 필요하다 — 개발 Vault 터널·App Token 준비는 docs/vault-local-development.md.
환경 변수
.env 로 관리(Git 커밋 금지, .env.example 만 저장). Secret 값은 Vault 또는 K8S Secret 으로,
.env 에는 서버별 Credential 을 넣지 않는다.
접두 | 예시 키 | 비고 |
| APP_ENV, APP_HOST, APP_PORT |
|
| DB_HOST/PORT/NAME/USERNAME/PASSWORD/SCHEMA | 공유 DB |
| LOCAL_AUTH_ENABLED, LOCAL_JWT_SECRET, LOCAL_JWT_ISSUER | HS256 자체 JWT |
| API_KEY_HASH_SECRET, API_KEY_MAX_ACTIVE_PER_USER | 미설정 시 SHA-256 fallback |
| ENTRA_TENANT_ID, ENTRA_CLIENT_SECRET, ENTRA_AUDIENCE, ENTRA_ISSUER | Resource Server 검증 |
| VAULT_ADDR, VAULT_TOKEN / VAULT_TOKEN_FILE, VAULT_KV_MOUNT | Token 원문 또는 0600 파일 |
| DEV_AUTH_ENABLED, DEV_AUTH_USER_ID | local/dev 한정(prod fail-fast) |
기타 | LOG_LEVEL, DOCS_ENABLED, CORS_ALLOWED_ORIGINS |
굵게 = SecretStr(로그/응답 미노출): DB_PASSWORD, LOCAL_JWT_SECRET,
API_KEY_HASH_SECRET, ENTRA_CLIENT_SECRET, VAULT_TOKEN.
테스트·품질 게이트
uv run pytest # 493 passed, 7 skipped (skip = 실 Vault 통합 테스트)
uv run ruff check . # All checks passed
uv run ruff format --check .
uv run mypy app # strict, no issues (87 files)테스트 32개 파일. 보안 경계(타 사용자 접근, 권한 없는 operation, Secret 노출, alias 위조, Vault 실패 일관성 등)를 필수로 테스트.
실 Vault 통합 테스트는 기본 skip. 실행:
VAULT_MCP_INTEGRATION=1 VAULT_ADDR=... VAULT_TOKEN_FILE=... uv run pytest tests/vault/test_real_vault_integration.py.
디렉터리 구조
app/
main.py FastAPI 앱 조립 + OpenAPI 설정
core/ config, exceptions, openapi, api_docs, logging, middleware, security
api/
dependencies.py 인증/서비스 DI
v1/router.py, v1/endpoints/ health, auth, me, api_keys, servers,
credentials(SSH 하위호환), resource_credentials(전 유형),
my_resources(목록/검색/reveal)
internal/ dev 전용 라우터(local/dev 에서만 등록)
auth/ verifier(Entra), local_token/local_service, dependencies, context, jwks, password
api_keys/ generator, hasher, service, repository, schemas
credentials/ service, compensation, validation, schemas, errors
server_resources/ crud, service(alias 해석/인가), repository, validation, schemas
vault/ client(KV v2), factory, token_file, credential_ref, errors
db/ base(schema 격리), session, models/{user,api_key,server_resource,...}
domain/ enums, errors, resolved
audit/ service(감사 기록)
web/ router(Jinja2), csrf, dependencies
templates/ static/{css,js} Web UI
scripts/seed_poc_user.py PoC 사용자 seed
ssh/ operations/ SSH Runner·운영 API 자리(STEP 10~11, 미구현)
migrations/versions/ Alembic 0001~0006
tests/ api, api_keys, auth, services, vault, web, skills, db, models
skills/vault-mcp/ 전사 공통 Claude Skill(REST 호출, Secret 미출력)
deploy/ gitops-repo(Kustomize+ArgoCD), k8s/dev(수동 kubectl 대안)
docs/ 설계·운영 문서(아래 인덱스)
Dockerfile Jenkinsfile 멀티스테이지 이미지 / CI 파이프라인개발 단계
STEP | 내용 | 상태 |
1 | FastAPI 골격 | ✅ |
2 | DB 모델·권한·서버 해석(Alembic, schema 격리) | ✅ |
3 | Microsoft Entra 인증 | ✅ |
4 | LOCAL 로그인 + API Key + 사용자별 Vault 경로 모델 | ✅ |
5 | 개발 Vault 설치·단독 검증(NCP) | ✅ |
6 | FastAPI ↔ Vault 연동 + Credential 등록 | ✅ |
7 | Skill 기반 REST API PoC | ✅ |
8 | 사용자 Web UI(Jinja2) | ✅ |
8.5 / 8.6 | 개발 K8S 배포 / Jenkins+Harbor+ArgoCD GitOps | ✅ |
8.7 | Resource 유형 확장(SERVER/WEBSITE/API) | ✅ |
9 | 사용자 인증 개선(Device Flow/짧은 Access Token) | 예정 |
10 | SSH Runner 등 Credential 활용 | 미구현 |
11 / 12 / 13 | 읽기 전용 운영 API / CLI+Keyring / K8S 배포 정리 | 미구현 |
아직 미구현: SSH 실행(Runner), 운영 API(logs/status/disk), CLI/OS Keyring. Entra 실제 App Registration 통합 검증은 조직 환경에서 수행 필요.
배포
Jenkins(CI) → Harbor(registry) → ArgoCD(GitOps). 정본: docs/ci-gitops.md, deploy/gitops-repo/README.md.
flowchart LR
GIT[소스 push] -->|pollSCM| J[Jenkins]
J -->|build| IMG[이미지 sha-태그]
IMG -->|push| H[Harbor]
J -->|newTag 갱신 commit| D[vault-mcp-deploy repo]
D -->|watch| A[ArgoCD]
A -->|PreSync: migration Job| K[K8S vault-mcp ns]
A -->|sync: Deployment| K이미지:
Dockerfile멀티스테이지, non-root(uid 10001), uvicorn :8000. Secret 미포함(K8S Secret 주입).Jenkinsfile: Init(short SHA) → Build → Push Harbor → deploy repo 의
newTag를sha-<SHA>로 갱신. Deployment 와 migration Job 이 같은 SHA 로 반영(불일치 방지).GitOps:
deploy/gitops-repo/(Kustomize + ArgoCD Application). migration 은 PreSync Hook, seed 는 수동 1회.deploy/k8s/dev/는 GitOps 없이 수동 kubectl apply 로 검증하는 대안이다.
기술 스택
영역 | 스택 |
언어 | Python 3.12+ |
웹 | FastAPI ≥0.115, Uvicorn ≥0.34 |
검증 | Pydantic v2 ≥2.9, pydantic-settings ≥2.6 |
DB | SQLAlchemy 2.x async, asyncpg ≥0.30, Alembic ≥1.14, PostgreSQL |
인증 | PyJWT[crypto] ≥2.9, pwdlib[argon2] ≥0.2 |
Vault/HTTP | httpx ≥0.28 (KV v2 직접 호출) |
Web | Jinja2 ≥3.1, python-multipart |
개발 | pytest + pytest-asyncio, aiosqlite, ruff(line 100, py312), mypy(strict) |
패키지 | uv(비패키지 애플리케이션 모드) |
문서 인덱스
Git 정책: 기본 브랜치 main, 명시적 요청 없이 commit/push 하지 않는다. .env·Token·인증서·
Private Key 는 커밋 금지. 프로젝트 원칙과 작업 하네스는 CLAUDE.md.
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/gwanghun-choi/vault-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server