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 的客户端通过 stdio 连接 mcp/index.mjs(与 Claude 相同的路径), 自动验证 API 启动 → 全部工具 + 资源 + 异常情况(不存在的 ID / email 重复 / 违反 schema)。 也可用于发表时的现场演示。

4. 面向 Claude Desktop 通过 .mcpb 分发

.mcpb = manifest.json + 代码打包成 zip 的 Desktop Extension。双击即可 安装,用户无需安装 Node 或编辑配置文件。 API URL 和访问密钥通过 user_config(安装时的表单)注入到 env 中 (sensitive: true 的密钥会保存到操作系统的钥匙串中)。

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

构建产物输出到 dist/(不在 git 管理范围内)。通过 .mcpbignore, API 代码和 Docker 相关文件不会被打包进扩展 — bundle 中只包含 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.
    -