Skip to main content
Glama
d-bui

users-demo

by d-bui

사용자 관리 API + MCP 레이어드 데모

Node.js(JS 전용)로 만드는 작은 데모. "동일한 API를 인간 사용자와 AI 에이전트 양쪽에, 별도의 인증·별도의 공개 범위로 제공하고, AI 쪽에는 **MCP 서버(API 설명 레이어)**를 씌운다" 라는 구성을 레이어별로 보여주기 위한 발표용 샘플입니다.

설계의 원형은 spx-learning-square의 실운영 MCP(spx-learning-square/mcp/, 65개 도구, .mcpb 배포). 이 데모는 그 개념을 최소 구성으로 축소한 것입니다.

전체 구조

 人間ユーザー ──ログイン──▶ セッショントークン ─┐
                                                  │ Authorization: Bearer
 AI (Claude) ──▶ MCP サーバー ──PAT──────────────┤
              (mcp/index.mjs                     ▼
                = API 説明層)          ┌─────────────────────────┐
                                        │ API サーバー (Express)  │
                                        │  認証層(2 系統)       │
                                        │  エージェント公開       │
                                        │  レジストリ             │
                                        │  controller             │
                                        │  service                │
                                        │  repository(メモリ)   │
                                        └─────────────────────────┘

Related MCP server: entra-scim-mcp

레이어 구성

계층

파일

역할

인증 계층(인간)

api/auth/userAuth.mjs

로그인 → 세션 토큰 발급. userOnly 가드

인증 계층(AI)

api/auth/agentAuth.mjs

PAT(사전 발급 키) 검증. 로그인 불필요

공개 레지스트리

api/agentRegistry.mjs

AI에 개방하는 API의 등록 목록. 미등록 API는 인증이 통과해도 403

컨트롤러 계층

api/usersController.mjs

HTTP ⇄ 서비스 변환 + 라우트별 가드 선언

서비스 계층

api/usersService.mjs

업무 규칙(검증·중복 체크). HTTP를 모름

리포지토리 계층

api/usersRepository.mjs

데이터 저장(데모는 메모리. 실무에서는 MySQL 등으로 교체)

MCP 계층(API 설명 계층)

mcp/index.mjs

AI에게 API 사용법을 일본어로 설명하면서 중개. 권한은 없음

권한 매트릭스(데모의 핵심)

API

인간 사용자

AI 에이전트

GET /api/users(목록)

✅

✅ 등록됨

GET /api/users/:id(조회)

✅

✅ 등록됨

POST /api/users(생성)

✅

✅ 등록됨

PUT /api/users/:id(수정)

✅

❌ user_only

DELETE /api/users/:id(삭제)

✅

❌ user_only

GET /api/agent/apis(공개 목록)

✅

✅ 등록됨

파괴적 작업(수정·삭제)은 레지스트리에 등록하지 않음으로써 인간 전용으로 만든다. "AI에게 무엇을 허용할지"가 agentRegistry.mjs 한 파일에서 조회 가능한 것이 포인트.

실행 방법

1. API 서버

npm install
npm run api          # http://localhost:3000

Docker로 실행하는 경우(컨테이너화하는 것은 API만):

npm run docker       # = docker compose up --build → http://localhost:3000

MCP 계층(mcp/index.mjs)은 컨테이너에 넣지 않는다. Claude Desktop / Claude Code가 이용자 머신에서 stdio로 기동하는 프로세스이므로, 배포는 Docker가 아니라 .mcpb로 수행한다. 여기도 발표 포인트: API는 서버 측(Docker/ECS), MCP는 클라이언트 측(.mcpb)으로 배포 단위가 나뉜다.

인간 사용자 흐름(로그인 → CRUD):

# ログイン(デモ: alice / demo)
TOKEN=$(curl -s -X POST localhost:3000/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"login_id":"alice","password":"demo"}' | node -p 'JSON.parse(require("fs").readFileSync(0)).data.token')

curl -s localhost:3000/api/users -H "Authorization: Bearer $TOKEN"          # 一覧
curl -s -X DELETE localhost:3000/api/users/3 -H "Authorization: Bearer $TOKEN"  # 削除も OK

AI 에이전트 흐름(PAT, 기본 키 agent-demo-key):

curl -s localhost:3000/api/users -H "Authorization: Bearer agent-demo-key"       # ✅ 200
curl -s localhost:3000/api/agent/apis -H "Authorization: Bearer agent-demo-key"  # ✅ 公開一覧
curl -s -X DELETE localhost:3000/api/users/2 \
  -H "Authorization: Bearer agent-demo-key"                                       # ❌ 403 user_only

에러 코드는 2종류가 있다: user_only = 인간 전용 가드가 붙은 API(수정·삭제), agent_not_allowed = 가드는 forAgent지만 레지스트리 미등록 API.

2. MCP 서버(API 설명 계층)

디버그 UI(MCP Inspector):

npm run inspect

Claude Code에 등록:

claude mcp add users-demo -- node /Users/d.bui/Documents/project/mcp-from-scratch/mcp/index.mjs

대화 예: "사용자 목록 보여줘" → list_users, "새 멤버 등록해줘" → create_user, "3번 삭제해줘" → 도구가 없으므로 관리 화면 안내(instructions로 지시됨).

3. E2E 테스트(MCP를 "Claude 대신"으로 호출)

npm test             # test/mcp-client.test.mjs

MCP SDK의 클라이언트로 mcp/index.mjs에 stdio 연결하고(Claude와 동일 경로), API 기동 → 전체 도구 + 리소스 + 이상 케이스(존재하지 않는 ID / email 중복 / 스키마 위반)를 자동 검증한다. 발표 시 라이브 데모에도 사용 가능.

4. Claude Desktop용 .mcpb로 배포

.mcpb = manifest.json + 코드를 zip한 Desktop Extension. 더블클릭으로 설치할 수 있고, 이용자는 Node 설치도 설정 파일 편집도 불필요. API URL과 액세스 키는 user_config(설치 시 폼)에서 env로 주입된다 (sensitive: true 키는 OS 키체인에 저장).

npx @anthropic-ai/mcpb validate manifest.json
npm run pack         # → dist/users-mcp-demo.mcpb(node_modules ごと同梱)

빌드 산출물은 dist/에 출력된다(git 관리 제외). .mcpbignore로 API 코드나 Docker 관련 파일은 확장 기능에 동봉되지 않는다 — 번들에 들어가는 것은 manifest.json + mcp/ + node_modules뿐.

발표 슬라이드

slides/index.html을 브라우저에서 열면 바로 발표 가능(← → 키로 이동, 14장, 오프라인 동작). 전체 구조 → 각 레이어의 코드 샷 → 권한 매트릭스 → 배포 → 데모 절차 → 실운영에서의 교훈, 구성.

발표 포인트(spx-learning-square 실운영에서)

  • MCP 계층은 권한이 없다. DB에 접촉하지 않고, PAT로 REST API를 호출할 뿐. 권한 판정· 검증은 모두 API 측 한 곳 — MCP가 고장나도 UI로는 불가능한 사고는 발생하지 않는다.

  • 인증은 2계통으로 분리. 인간 = 로그인 + 세션, AI = 사전 발급 PAT. 토큰의 출처가 다르면 폐기·감사·레이트 제한도 별도로 설계할 수 있다.

  • AI 공개는 "명시적 등록제". 경로의 프리픽스로 개방하면, 옆의 민감한 API까지 의도치 않게 열리는 사고가 발생한다(실제로 발생할 뻔한 교훈). 레지스트리는 그대로 "AI용 API 명세서"로도 기능한다.

  • 도구 설명문은 모델에 대한 지시서. "ID는 추측하지 말고 list_users로 해결" "삭제는 관리 화면으로 안내" 같은 운영 규칙을 description / instructions에 작성함으로써, AI의 행동을 코드가 아니라 문장으로 제어할 수 있다.

  • 에러는 throw하지 않고 isError + 기계 판독 가능 code로 반환. 모델이 code를 읽고 스스로 리커버리할 수 있다(email_taken → 다른 안 제안, 등).

  • stdout은 JSON-RPC 전용. stdio 서버에서 console.log하면 통신이 깨진다. 로그는 반드시 console.error.

참고

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to manage Microsoft Entra users and groups via the SCIM 2.0 Provisioning API, including provisioning, deprovisioning, group membership, custom security attributes, and lifecycle operations.
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables autonomous AI agents to securely access and execute external tools, such as GitHub REST API operations, with per-user authentication, authorization, audit logging, and observability.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables management of system users through a simple sample API, exposed as MCP tools for natural-language interaction.
    -