{
  "canonical_name": "okapi-ca/ms-365-admin-mcp-server",
  "compilation_id": "pack_04961d5062784a488b887691cd8be3b9",
  "created_at": "2026-05-18T04:32:58.627380+00:00",
  "created_by": "project-pack-compiler",
  "feedback": {
    "carrier_selection_notes": [
      "viable_asset_types=mcp_config, recipe, host_instruction, eval, preflight",
      "recommended_asset_types=mcp_config, recipe, host_instruction, eval, preflight"
    ],
    "evidence_delta": {
      "confirmed_claims": [
        "identity_anchor_present",
        "capability_and_host_targets_present",
        "install_path_declared_or_better"
      ],
      "missing_required_fields": [],
      "must_verify_forwarded": [
        "Run or inspect `npm install -g @okapi-ca/ms-365-admin-mcp-server` in an isolated environment.",
        "Confirm the project exposes the claimed capability to at least one target host."
      ],
      "quickstart_execution_scope": "allowlisted_sandbox_smoke",
      "sandbox_command": "npm install -g @okapi-ca/ms-365-admin-mcp-server",
      "sandbox_container_image": "node:22-slim",
      "sandbox_execution_backend": "docker",
      "sandbox_planner_decision": "llm_execute_isolated_install",
      "sandbox_validation_id": "sbx_7f35753a15c04c5c81ca6917c83c1372"
    },
    "feedback_event_type": "project_pack_compilation_feedback",
    "learning_candidate_reasons": [],
    "template_gaps": []
  },
  "identity": {
    "canonical_id": "project_987cc48ba124d36b5aeb01e0e431c265",
    "canonical_name": "okapi-ca/ms-365-admin-mcp-server",
    "homepage_url": null,
    "license": "unknown",
    "repo_url": "https://github.com/okapi-ca/ms-365-admin-mcp-server",
    "slug": "ms-365-admin-mcp-server",
    "source_packet_id": "phit_d10e8351c1494a41906e823d2a931f03",
    "source_validation_id": "dval_678c9500d6074d149e9cde5a9883812a"
  },
  "merchandising": {
    "best_for": "需要安全审查与权限治理能力，并使用 mcp_host的用户",
    "github_forks": 0,
    "github_stars": 3,
    "one_liner_en": "MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)",
    "one_liner_zh": "MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)",
    "primary_category": {
      "category_id": "security-permissions",
      "confidence": "high",
      "name_en": "Security & Permissions",
      "name_zh": "安全审查与权限治理",
      "reason": "strong category phrase match from project identity and outcome"
    },
    "target_user": "使用 mcp_host 等宿主 AI 的用户",
    "title_en": "ms-365-admin-mcp-server",
    "title_zh": "ms-365-admin-mcp-server 能力包",
    "visible_tags": [
      {
        "label_en": "Security & Permissions",
        "label_zh": "安全审查与权限治理",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "product_domain-security-permissions",
        "type": "product_domain"
      },
      {
        "label_en": "Web Task Automation",
        "label_zh": "网页任务自动化",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "user_job-web-task-automation",
        "type": "user_job"
      },
      {
        "label_en": "Browser Automation",
        "label_zh": "浏览器自动化",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "core_capability-browser-automation",
        "type": "core_capability"
      },
      {
        "label_en": "Node-based Workflow",
        "label_zh": "节点式流程编排",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "workflow_pattern-node-based-workflow",
        "type": "workflow_pattern"
      },
      {
        "label_en": "Local-first",
        "label_zh": "本地优先",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "selection_signal-local-first",
        "type": "selection_signal"
      }
    ]
  },
  "packet_id": "phit_d10e8351c1494a41906e823d2a931f03",
  "page_model": {
    "artifacts": {
      "artifact_slug": "ms-365-admin-mcp-server",
      "files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json",
        "REPO_INSPECTION.md",
        "CAPABILITY_CONTRACT.json",
        "EVIDENCE_INDEX.json",
        "CLAIM_GRAPH.json"
      ],
      "required_files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json"
      ]
    },
    "detail": {
      "capability_source": "Project Hit Packet + DownstreamValidationResult",
      "commands": [
        {
          "command": "npm install -g @okapi-ca/ms-365-admin-mcp-server",
          "label": "Node.js / npm · 官方安装入口",
          "source": "https://github.com/okapi-ca/ms-365-admin-mcp-server#readme",
          "verified": true
        }
      ],
      "display_tags": [
        "安全审查与权限治理",
        "网页任务自动化",
        "浏览器自动化",
        "节点式流程编排",
        "本地优先"
      ],
      "eyebrow": "安全审查与权限治理",
      "glance": [
        {
          "body": "判断自己是不是目标用户。",
          "label": "最适合谁",
          "value": "需要安全审查与权限治理能力，并使用 mcp_host的用户"
        },
        {
          "body": "先理解能力边界，再决定是否继续。",
          "label": "核心价值",
          "value": "MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)"
        },
        {
          "body": "未完成验证前保持审慎。",
          "label": "继续前",
          "value": "publish to Doramagic.ai project surfaces"
        }
      ],
      "guardrail_source": "Boundary & Risk Card",
      "guardrails": [
        {
          "body": "Prompt Preview 只展示流程，不证明项目已安装或运行。",
          "label": "Check 1",
          "value": "不要把试用当真实运行"
        },
        {
          "body": "mcp_host",
          "label": "Check 2",
          "value": "确认宿主兼容"
        },
        {
          "body": "publish to Doramagic.ai project surfaces",
          "label": "Check 3",
          "value": "先隔离验证"
        }
      ],
      "mode": "mcp_config, recipe, host_instruction, eval, preflight",
      "pitfall_log": {
        "items": [
          {
            "body": "README/documentation is current enough for a first validation pass.",
            "category": "能力坑",
            "evidence": [
              "capability.assumptions | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | README/documentation is current enough for a first validation pass."
            ],
            "severity": "medium",
            "suggested_check": "将假设转成下游验证清单。",
            "title": "能力判断依赖假设",
            "user_impact": "假设不成立时，用户拿不到承诺的能力。"
          },
          {
            "body": "未记录 last_activity_observed。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | last_activity_observed missing"
            ],
            "severity": "medium",
            "suggested_check": "补 GitHub 最近 commit、release、issue/PR 响应信号。",
            "title": "维护活跃度未知",
            "user_impact": "新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "downstream_validation.risk_items | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "进入安全/权限治理复核队列。",
            "title": "下游验证发现风险项",
            "user_impact": "下游已经要求复核，不能在页面中弱化。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "risks.scoring_risks | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "把风险写入边界卡，并确认是否需要人工复核。",
            "title": "存在评分风险",
            "user_impact": "风险会影响是否适合普通用户安装。"
          },
          {
            "body": "GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node",
            "category": "安全/权限坑",
            "evidence": [
              "community_evidence:github | cevd_103cf7f40efc40e99adfa2eb14d9717e | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/70 | 来源讨论提到 node 相关条件，需在安装/试用前复核。"
            ],
            "severity": "medium",
            "suggested_check": "来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。",
            "title": "来源证据：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node",
            "user_impact": "可能增加新用户试用和生产接入成本。"
          },
          {
            "body": "GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)",
            "category": "安全/权限坑",
            "evidence": [
              "community_evidence:github | cevd_6ede43fd3f7247e0981524934656dbeb | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71 | 来源类型 github_issue 暴露的待验证使用条件。"
            ],
            "severity": "medium",
            "suggested_check": "来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。",
            "title": "来源证据：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)",
            "user_impact": "可能影响授权、密钥配置或安全边界。"
          },
          {
            "body": "GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-005: Express body parser runs before authentication and rate limiting",
            "category": "安全/权限坑",
            "evidence": [
              "community_evidence:github | cevd_e53044f4bde148d7882ccf83273f1e22 | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/72 | 来源类型 github_issue 暴露的待验证使用条件。"
            ],
            "severity": "medium",
            "suggested_check": "来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。",
            "title": "来源证据：SEC-005: Express body parser runs before authentication and rate limiting",
            "user_impact": "可能影响授权、密钥配置或安全边界。"
          },
          {
            "body": "issue_or_pr_quality=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | issue_or_pr_quality=unknown"
            ],
            "severity": "low",
            "suggested_check": "抽样最近 issue/PR，判断是否长期无人处理。",
            "title": "issue/PR 响应质量未知",
            "user_impact": "用户无法判断遇到问题后是否有人维护。"
          },
          {
            "body": "release_recency=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | release_recency=unknown"
            ],
            "severity": "low",
            "suggested_check": "确认最近 release/tag 和 README 安装命令是否一致。",
            "title": "发布节奏不明确",
            "user_impact": "安装命令和文档可能落后于代码，用户踩坑概率升高。"
          }
        ],
        "source": "ProjectPitfallLog + ProjectHitPacket + validation + community signals",
        "summary": "发现 9 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。",
        "title": "踩坑日志"
      },
      "snapshot": {
        "contributors": 2,
        "forks": 0,
        "license": "unknown",
        "note": "站点快照，非实时质量证明；用于开工前背景判断。",
        "stars": 3
      },
      "source_url": "https://github.com/okapi-ca/ms-365-admin-mcp-server",
      "steps": [
        {
          "body": "不安装项目，先体验能力节奏。",
          "code": "preview",
          "title": "先试 Prompt"
        },
        {
          "body": "理解输入、输出、失败模式和边界。",
          "code": "manual",
          "title": "读说明书"
        },
        {
          "body": "把上下文交给宿主 AI 继续工作。",
          "code": "context",
          "title": "带给 AI"
        },
        {
          "body": "进入主力环境前先完成安装入口与风险边界验证。",
          "code": "verify",
          "title": "沙箱验证"
        }
      ],
      "subtitle": "MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)",
      "title": "ms-365-admin-mcp-server 能力包",
      "trial_prompt": "# ms-365-admin-mcp-server - Prompt Preview\n\n> Copy the prompt below into your AI host before installing anything.\n> Its purpose is to let you safely feel the project's workflow, not to claim the project has already run.\n\n## Copy this prompt\n\n```text\nYou are using an independent Doramagic capability pack for okapi-ca/ms-365-admin-mcp-server.\n\nProject:\n- Name: ms-365-admin-mcp-server\n- Repository: https://github.com/okapi-ca/ms-365-admin-mcp-server\n- Summary: MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)\n- Host target: mcp_host\n\nGoal:\nHelp me evaluate this project for the following task without installing it yet: MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)\n\nBefore taking action:\n1. Restate my task, success standard, and boundary.\n2. Identify whether the next step requires tools, browser access, network access, filesystem access, credentials, package installation, or host configuration.\n3. Use only the Doramagic Project Pack, the upstream repository, and the source-linked evidence listed below.\n4. If a real command, install step, API call, file write, or host integration is required, mark it as \"requires post-install verification\" and ask for approval first.\n5. If evidence is missing, say \"evidence is missing\" instead of filling the gap.\n\nPreviewable capabilities:\n- Capability 1: Use the source-backed project context to guide one small, checkable workflow step.\n\nCapabilities that require post-install verification:\n- Capability 1: Use the source-backed project context to guide one small, checkable workflow step.\n\nCore service flow:\n1. overview: Project Overview. Produce one small intermediate artifact and wait for confirmation.\n2. configuration: Configuration Reference. Produce one small intermediate artifact and wait for confirmation.\n3. system-architecture: System Architecture. Produce one small intermediate artifact and wait for confirmation.\n4. tool-categories: Tool Categories and Presets. Produce one small intermediate artifact and wait for confirmation.\n5. security-model: Security Model and Risk Classification. Produce one small intermediate artifact and wait for confirmation.\n\nSource-backed evidence to keep in mind:\n- https://github.com/okapi-ca/ms-365-admin-mcp-server\n- https://github.com/okapi-ca/ms-365-admin-mcp-server#readme\n- agent-skills/ms365-admin-mcp/SKILL.md\n- README.md\n- package.json\n- src/index.ts\n- src/cli.ts\n- src/cloud-config.ts\n- src/secrets.ts\n- docs/ARCHITECTURE.md\n\nFirst response rules:\n1. Start Step 1 only.\n2. Explain the one service action you will perform first.\n3. Ask exactly three questions about my target workflow, success standard, and sandbox boundary.\n4. Stop and wait for my answers.\n\nStep 1 follow-up protocol:\n- After I answer the first three questions, stay in Step 1.\n- Produce six parts only: clarified task, success standard, boundary conditions, two or three options, tradeoffs for each option, and one recommendation.\n- End by asking whether I confirm the recommendation.\n- Do not move to Step 2 until I explicitly confirm.\n\nConversation rules:\n- Advance one step at a time and wait for confirmation after each small artifact.\n- Write outputs as recommendations or planned checks, not as completed execution.\n- Do not claim tests passed, files changed, commands ran, APIs were called, or the project was installed.\n- If the user asks for execution, first provide the sandbox setup, expected output, rollback, and approval checkpoint.\n```\n",
      "voices": [
        {
          "body": "来源平台：github。github/github_issue: SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node（https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/70）；github/github_issue: SEC-005: Express body parser runs before authentication and rate limitin（https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/72）；github/github_issue: SEC-004: UPN persisted in logs without redaction option (PII / GDPR expo（https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71）。这些是项目级外部声音，不作为单独质量证明。",
          "items": [
            {
              "kind": "github_issue",
              "source": "github",
              "title": "SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node",
              "url": "https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/70"
            },
            {
              "kind": "github_issue",
              "source": "github",
              "title": "SEC-005: Express body parser runs before authentication and rate limitin",
              "url": "https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/72"
            },
            {
              "kind": "github_issue",
              "source": "github",
              "title": "SEC-004: UPN persisted in logs without redaction option (PII / GDPR expo",
              "url": "https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71"
            }
          ],
          "status": "已收录 3 条来源",
          "title": "社区讨论"
        }
      ]
    },
    "homepage_card": {
      "category": "安全审查与权限治理",
      "desc": "MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)",
      "effort": "安装已验证",
      "forks": 0,
      "icon": "shield",
      "name": "ms-365-admin-mcp-server 能力包",
      "risk": "可发布",
      "slug": "ms-365-admin-mcp-server",
      "stars": 3,
      "tags": [
        "安全审查与权限治理",
        "网页任务自动化",
        "浏览器自动化",
        "节点式流程编排",
        "本地优先"
      ],
      "thumb": "purple",
      "type": "MCP 配置"
    },
    "manual": {
      "markdown": "# https://github.com/okapi-ca/ms-365-admin-mcp-server 项目说明书\n\n生成时间：2026-05-15 11:16:11 UTC\n\n## 目录\n\n- [Project Overview](#overview)\n- [Installation Guide](#installation)\n- [Configuration Reference](#configuration)\n- [System Architecture](#system-architecture)\n- [Code Generation Pipeline](#code-generation)\n- [Tool Categories and Presets](#tool-categories)\n- [Security Model and Risk Classification](#security-model)\n- [Azure Deployment Security](#azure-deployment-security)\n- [HTTP Transport and Deployment](#http-deployment)\n- [Docker and Container Deployment](#docker-deployment)\n\n<a id='overview'></a>\n\n## Project Overview\n\n### 相关页面\n\n相关主题：[System Architecture](#system-architecture), [Installation Guide](#installation), [Configuration Reference](#configuration)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/README.md)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- [src/index.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/index.ts)\n- [src/auth.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth.ts)\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n</details>\n\n# Project Overview\n\n## Introduction\n\nThe **ms-365-admin-mcp-server** is a Model Context Protocol (MCP) server that exposes Microsoft 365 admin capabilities as MCP tools. Built with TypeScript and strict mode, it enables AI assistants like Claude to perform Microsoft 365 administrative operations through the Microsoft Graph API.\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Purpose and Scope\n\nThe server acts as a bridge between AI assistants and Microsoft 365 admin functionality:\n\n- **Tool Generation**: Auto-generates 444+ MCP tools from the Microsoft Graph OpenAPI specification 资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n- **Security-First Design**: Every write operation is classified with risk levels (low/medium/high/critical) 资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- **Least Privilege**: Tools declare minimum required Graph API permissions via `appPermissions` in `endpoints.json` 资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n    subgraph \"MCP Client (Claude Desktop/Code)\"\n        A[AI Assistant]\n    end\n    \n    subgraph \"ms-365-admin-mcp-server\"\n        B[index.ts - MCP Server]\n        C[auth.ts - MSAL Authentication]\n        D[cli.ts - CLI Parsing]\n        E[endpoints.json - Tool Definitions]\n        F[generated/ - Zod Client]\n        G[cloud-config.ts - Endpoint Routing]\n    end\n    \n    subgraph \"Microsoft Graph API\"\n        H[Global Cloud]\n        I[China 21Vianet]\n    end\n    \n    A <--> B\n    B <--> C\n    B <--> D\n    B <--> E\n    B <--> F\n    C <--> H\n    C <--> I\n    G --> H\n    G --> I\n```\n\n## Project Layout\n\n| Directory/File | Purpose |\n|----------------|---------|\n| `bin/` | Code-generation scripts (OpenAPI → Zod client) |\n| `src/auth.ts` | MSAL client credentials flow authentication |\n| `src/cli.ts` | Commander argv parsing for CLI arguments |\n| `src/cloud-config.ts` | Global vs China (21Vianet) endpoint routing |\n| `src/endpoints.json` | Source of truth for tool definitions |\n| `src/generated/` | Auto-generated Zod schemas from OpenAPI |\n| `src/index.ts` | Main MCP server entry point |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Tool Categories\n\nThe server organizes its 444+ tools into distinct categories for easier discovery and management:\n\n| Category | Pattern | Description |\n|----------|---------|-------------|\n| `identity` | `user\\|group\\|role\\|device\\|pim\\|guest\\|external` | Users, groups, roles, devices, PIM, guests, external identities |\n| `exchange` | `exchange\\|mailbox\\|message` | Message traces, mailboxes |\n| `intune` | `intune\\|managed-devic\\|compliance` | Devices, compliance, configurations, Autopilot, apps, RBAC |\n| `governance` | `role-resource-namespace` | Access reviews, entitlement, lifecycle workflows, PIM for Groups/Roles |\n| `response` | `disable\\|revoke\\|block\\|reset\\|wipe` | Incident response operations |\n| `ediscovery` | `ediscovery` | eDiscovery cases (Microsoft Purview) |\n| `cloudpc` | `cloud-pc\\|provisioning-polic` | Cloud PC / Windows 365 |\n| `callrecords` | `call-record\\|call-session\\|pstn` | Teams call records |\n| `print` | `print` | Universal Print |\n| `infoprotection` | `bitlocker\\|sensitivity-label` | BitLocker, threat assessment, sensitivity labels |\n| `sharepointadmin` | `sharepoint` | SharePoint tenant administration |\n| `retention` | `retention` | Records management |\n\n资料来源：[src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Risk Classification\n\nAll non-GET operations must be classified with a risk level before execution. The server enforces this through `src/risk-level.ts`:\n\n```mermaid\ngraph LR\n    A[Tool Request] --> B{Method?}\n    B -->|GET| C[Default: low]\n    B -->|POST/PATCH/DELETE| D[Default: critical]\n    E[Configured Risk] --> F[effectiveRiskLevel]\n    C --> F\n    D --> F\n    F --> G{Allowed?}\n    G -->|Yes| H[Execute]\n    G -->|No| I[Block + Error]\n```\n\n### Risk Level Rubric\n\n| Level | Criteria | Examples |\n|-------|----------|----------|\n| `low` | Read-only queries, reports, trivial annotations | `run-hunting-query`, `add-security-alert-comment`, Intune reports |\n| `medium` | Reversible mutation affecting single entity | `update-user`, `add-group-member`, `create-invitation` |\n| `high` | Broad scope, credential change, or destructive+ | `revoke-user-sessions`, `update-conditional-access-policy` |\n| `critical` | Irreversible or tenant-wide impact | `delete-user`, `wipe-managed-device`, `delete-conditional-access-policy` |\n\n资料来源：[src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n### Critical Tools (Require Out-of-Band Sign-off)\n\nThe following operations are blocked even with `--allow-writes` and require formal change requests:\n\n- `delete-user`, `delete-group`, `delete-application`\n- `delete-conditional-access-policy`\n- `delete-managed-device`, `wipe-managed-device`\n- `add-directory-role-member` (on privileged roles)\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n\n## Authentication Flow\n\nThe server supports two authentication methods:\n\n### 1. Client Credentials Flow (Service Principal)\n\nFor automated/headless scenarios:\n\n```typescript\n// src/auth.ts - MSAL client credentials flow\nconst credential = new ClientCredentialCredential({\n  clientId: process.env.MS365_ADMIN_MCP_CLIENT_ID,\n  clientSecret: process.env.MS365_ADMIN_MCP_CLIENT_SECRET,\n  tenantId: process.env.MS365_ADMIN_MCP_TENANT_ID,\n});\n```\n\n### 2. Device Code Bootstrap (RFC 8628)\n\nFor Claude Desktop/Code integration where browser-based auth isn't available:\n\n```bash\nnpx ms-365-admin-mcp-auth --server https://your-host.azurecontainerapps.io/mcp\n```\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n\n## Cloud Configuration\n\nThe server supports Microsoft Azure's global cloud and China (21Vianet) operated cloud:\n\n```typescript\n// src/cloud-config.ts\nexport const CLOUD_CONFIG = {\n  global: {\n    authority: 'https://login.microsoftonline.com',\n    graph: 'https://graph.microsoft.com',\n  },\n  china: {\n    authority: 'https://login.partner.microsoftonline.cn',\n    graph: 'https://microsoftgraph.chinacloudapi.cn',\n  },\n};\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Development Setup\n\n```bash\n# Clone and install\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\nnpm install\n\n# Generate client from Graph OpenAPI spec\nnpm run generate\n\n# Build\nnpm run build\n\n# Test\nnpm test\n\n# Run MCP Inspector\nnpm run inspector\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Tool Definition Schema\n\nEach tool in `endpoints.json` follows this structure:\n\n```json\n{\n  \"toolName\": \"list-users\",\n  \"method\": \"GET\",\n  \"path\": \"/v1.0/users\",\n  \"appPermissions\": [\"User.Read.All\"],\n  \"llmTip\": \"Returns a list of users in the organization\",\n  \"riskLevel\": \"low\"\n}\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `toolName` | Yes | Unique identifier used by MCP clients |\n| `method` | Yes | HTTP method (GET, POST, PATCH, DELETE) |\n| `path` | Yes | Graph API endpoint path |\n| `appPermissions` | Yes | Minimum required Graph API permissions |\n| `llmTip` | No | Hint shown to the LLM in tool description |\n| `riskLevel` | No* | Risk classification (only required for non-GET) |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Tool Execution Flow\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant Server as ms-365-admin-mcp-server\n    participant Graph as Microsoft Graph API\n    \n    Client->>Server: list-users(...)\n    Server->>Server: Check risk level\n    Server->>Server: Validate auth token\n    Server->>Graph: GET /v1.0/users\n    Graph-->>Server: User list response\n    Server-->>Client: Tool result\n```\n\n## Package Information\n\nThe project is published to both npm and GitHub Container Registry:\n\n| Registry | Package/Image |\n|----------|---------------|\n| npm | `@okapi-ca/ms-365-admin-mcp-server` |\n| GHCR | `ghcr.io/okapi-ca/ms-365-admin-mcp-server` |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Coding Standards\n\n- **TypeScript Strict Mode**: No `any` without justification 资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- **No New Runtime Dependencies**: Prefer standard library additions\n- **Prettier + ESLint**: Must pass (`npm run format:check` and `npm run lint`)\n- **Comments Explain Why**: Name things well instead of over-commenting\n\n## Version History\n\n| Version | Tools | Key Changes |\n|---------|-------|-------------|\n| Latest | 444 | Security fixes, `set-application-verified-publisher` risk bump |\n| v369 | 369 | Cloud PC, Teams call records, Universal Print, Info Protection |\n| v306 | 306 | eDiscovery, Cloud PC, Intune, Identity Governance |\n| v199 | 199 | Elevated `dismiss-risky-users` to high risk |\n| v175 | 175 | Full security review, PIM, risk detections |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n---\n\n<a id='installation'></a>\n\n## Installation Guide\n\n### 相关页面\n\n相关主题：[Configuration Reference](#configuration), [Docker and Container Deployment](#docker-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [Dockerfile](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/Dockerfile)\n- [docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md)\n- [docs/SETUP_MACOS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_MACOS_EN.md)\n- [docs/SETUP_WINDOWS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_WINDOWS_EN.md)\n</details>\n\n# Installation Guide\n\nThis guide covers all supported methods for installing and configuring the `ms-365-admin-mcp-server`. The server exposes Microsoft 365 admin APIs as MCP tools, enabling AI assistants to perform administrative operations across Azure AD, Intune, Exchange, SharePoint, Teams, and other Microsoft 365 workloads.\n\n## Prerequisites\n\n### System Requirements\n\n| Requirement | Minimum | Recommended |\n|-------------|---------|-------------|\n| Node.js | v20.x | v22.x LTS |\n| npm | v10.x | v10.x |\n| Memory | 512 MB | 1 GB |\n| Disk Space | 200 MB | 500 MB |\n| OS | Windows 10+, macOS 11+, Linux | Windows 11, macOS 14+, Ubuntu 22.04+ |\n\n### Azure AD Requirements\n\nBefore installation, you must have:\n\n- An Azure AD tenant (single-tenant required for client credentials flow)\n- An registered application with appropriate Graph API permissions\n- A valid client secret or certificate credential\n\n资料来源：[docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md)\n\n## Installation Methods\n\nThe server supports three installation methods:\n\n```mermaid\ngraph TD\n    A[Installation Methods] --> B[Docker Container]\n    A --> C[Node.js Direct]\n    A --> D[Claude Desktop Integration]\n    \n    B --> B1[GHCR Registry]\n    B --> B2[Dockerfile Build]\n    \n    C --> C1[npm Global]\n    C --> C2[Local Clone]\n    \n    D --> D1[Inspector Testing]\n    D --> D2[Production Config]\n```\n\n## Method 1: Docker Installation\n\n### Pull from GHCR Registry\n\nThe pre-built container image is published to GitHub Container Registry:\n\n```bash\ndocker pull ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### Run the Container\n\n```bash\ndocker run -d \\\n  --name mcp-server \\\n  -p 8080:8080 \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=\"your-client-id\" \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=\"your-client-secret\" \\\n  -e MS365_ADMIN_MCP_TENANT_ID=\"your-tenant-id\" \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### Docker Security Configuration\n\nThe Dockerfile implements several security controls:\n\n| Feature | Implementation |\n|---------|----------------|\n| Non-root user | Container runs as `node` user (UID 1000) |\n| Security headers | X-Content-Type-Options, X-Frame-Options: DENY, CSP |\n| Cache permissions | Token files stored with mode 0600 |\n| Network isolation | Single-tenant enforcement |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Docker Bind Mounts for Persistent Cache\n\nFor production deployments requiring persistent authentication cache:\n\n```bash\ndocker run -d \\\n  --name mcp-server \\\n  -p 8080:8080 \\\n  -v /path/to/cache:/home/node/.mcp-auth \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=\"your-client-id\" \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=\"your-client-secret\" \\\n  -e MS365_ADMIN_MCP_TENANT_ID=\"your-tenant-id\" \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\nThe server honors the `MCP_REMOTE_CONFIG_DIR` environment variable, allowing Docker bind mounts and multi-user setups without patches.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Build from Dockerfile\n\nFor customization or air-gapped deployments:\n\n```bash\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\ndocker build -t ms-365-admin-mcp-server:local .\n```\n\n## Method 2: Node.js Installation\n\n### Option A: Install from npm Registry\n\n```bash\nnpm install -g @okapi-ca/ms-365-admin-mcp-server\n```\n\n### Option B: Local Development Setup\n\n```bash\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\nnpm install\n```\n\n#### Build Steps\n\n```bash\nnpm run generate    # Download Graph OpenAPI spec and generate client\nnpm run build\n```\n\n#### Verify Installation\n\n```bash\nnpm test\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Azure AD Application Registration\n\n### Required Permissions\n\nThe application requires Microsoft Graph API permissions. The following table summarizes permission scopes by category:\n\n| Category | Permission Type | Required Scopes |\n|----------|----------------|-----------------|\n| User Management | Application | User.ReadWrite.All |\n| Group Management | Application | Group.ReadWrite.All |\n| Device Management | Application | DeviceManagementManagedDevices.ReadWrite.All |\n| Exchange Admin | Application | Exchange.Admin |\n| SharePoint | Application | SharePoint.Admin |\n| Teams | Application | Team.ReadWrite.All |\n| Security | Application | SecurityEvents.ReadWrite.All |\n\n### Registration Steps\n\n1. Navigate to Azure Portal → Azure Active Directory → App registrations\n2. Select **New registration**\n3. Configure the application:\n   - **Name**: `ms-365-admin-mcp-server`\n   - **Supported account types**: Accounts in this organizational directory only\n   - **Redirect URI**: Leave blank (not required for daemon apps)\n4. Navigate to **Certificates & secrets** → **New client secret**\n5. Copy and securely store the secret value (it cannot be retrieved later)\n6. Navigate to **API permissions** → **Add a permission** → **Microsoft Graph**\n7. Select **Application permissions** and add required scopes\n8. Click **Grant admin consent**\n\n资料来源：[docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md)\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Yes | Azure AD application (client) ID |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Yes | Client secret value |\n| `MS365_ADMIN_MCP_TENANT_ID` | Yes | Azure AD tenant ID |\n| `MCP_REMOTE_CONFIG_DIR` | No | Override cache directory path |\n| `CI` | No | Set to `true` to disable clipboard operations |\n| `PORT` | No | HTTP server port (default: 8080) |\n\n### Local .env File\n\nCreate a `.env` file in the project root for local development:\n\n```bash\nMS365_ADMIN_MCP_CLIENT_ID=your-client-id\nMS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret\nMS365_ADMIN_MCP_TENANT_ID=your-tenant-id\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Command-Line Options\n\n```bash\nnode dist/index.js --help\n```\n\n| Option | Description |\n|--------|-------------|\n| `--client-id <id>` | Override MS365_ADMIN_MCP_CLIENT_ID |\n| `--client-secret <secret>` | Override MS365_ADMIN_MCP_CLIENT_SECRET |\n| `--tenant-id <id>` | Override MS365_ADMIN_MCP_TENANT_ID |\n| `--cache-dir <path>` | Override token cache directory |\n| `--allow-writes` | Enable write operations (default: read-only) |\n| `--list-tools` | List available tools and exit |\n| `--preset <name>` | Enable preset category filters |\n\n## Claude Desktop Integration\n\n### macOS Configuration\n\n1. Locate the Claude Desktop configuration file:\n   ```bash\n   ~/Library/Application Support/Claude/claude_desktop_config.json\n   ```\n\n2. Add the MCP server configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"--rm\",\n        \"-i\",\n        \"--env-file\",\n        \"/absolute/path/to/.env\",\n        \"-v\",\n        \"/path/to/cache:/home/node/.mcp-auth\",\n        \"ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\"\n      ]\n    }\n  }\n}\n```\n\n资料来源：[docs/SETUP_MACOS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_MACOS_EN.md)\n\n### Windows Configuration\n\n1. Locate the Claude Desktop configuration file:\n   ```powershell\n   %APPDATA%\\Claude\\claude_desktop_config.json\n   ```\n\n2. Add the MCP server configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"--rm\",\n        \"-i\",\n        \"--env-file\",\n        \"C:\\\\path\\\\to\\\\.env\",\n        \"-v\",\n        \"mcp-cache:C:\\\\Users\\\\ContainerAdministrator\\\\.mcp-auth\",\n        \"ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\"\n      ]\n    }\n  }\n}\n```\n\n资料来源：[docs/SETUP_WINDOWS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_WINDOWS_EN.md)\n\n### Interactive Testing with MCP Inspector\n\nFor testing the server configuration:\n\n```bash\nnpm run inspector\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Device Code Authentication (Optional)\n\nFor environments where browser-based authentication is unavailable, the server supports RFC 8628 device code flow:\n\n```bash\nnpx ms-365-admin-mcp-auth \\\n  --server https://your-host.azurecontainerapps.io/mcp\n```\n\nThe auth bootstrap tool:\n- Polls `/token` endpoint for authentication completion\n- Writes cache files (`<hash>_client_info.json` and `<hash>_tokens.json`) to `~/.mcp-auth/mcp-remote-<version>/`\n- Uses mode 0600 for cache files (secure permissions)\n- Cache key = `md5(serverUrl)`, matching `mcp-remote`'s `getServerUrlHash` exactly\n- Supports best-effort clipboard copy (auto-disabled under `CI=true` or non-TTY)\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n\n## Verifying Installation\n\n### List Available Tools\n\n```bash\nnode dist/index.js --list-tools\n```\n\nThis outputs all available MCP tools organized by category.\n\n### Test Authentication\n\n```bash\ncurl http://localhost:8080/health\n```\n\nExpected response:\n```json\n{\"status\": \"ok\", \"authenticated\": true}\n```\n\n## Exit Codes\n\nThe server documents exit codes for Docker/CI wrappers:\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success |\n| 1 | Usage error / invalid configuration |\n| 2 | Network error / Azure AD unreachable |\n| 3 | Access denied (insufficient permissions) |\n| 4 | Request timeout |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Troubleshooting\n\n### Common Issues\n\n| Issue | Solution |\n|-------|----------|\n| `Tenant 'common' rejected` | Ensure single-tenant registration; set `MS365_ADMIN_MCP_TENANT_ID` explicitly |\n| Token cache not persisting | Use `-v` flag to bind mount cache directory in Docker |\n| Permission denied errors | Verify app registration has admin consent granted |\n| Container exits immediately | Check logs with `docker logs mcp-server`; verify environment variables |\n\n### Documentation References\n\n- [Troubleshooting Guide](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/TROUBLESHOOTING.md) — covers Server disconnected, Platform SSO symptoms, device_code flow walkthrough\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md) — security architecture and best practices\n\n## Next Steps\n\nAfter successful installation:\n\n1. Review the [Tool Catalog](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md) to understand available operations\n2. Configure appropriate [risk levels](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md) for write operations\n3. Review use case patterns for [Identity Management](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/usecase-identity.md), [Intune](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/usecase-intune.md), and other workloads\n\n---\n\n<a id='configuration'></a>\n\n## Configuration Reference\n\n### 相关页面\n\n相关主题：[Project Overview](#overview), [Installation Guide](#installation), [HTTP Transport and Deployment](#http-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/cli.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/cli.ts)\n- [src/cloud-config.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/cloud-config.ts)\n- [src/secrets.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/secrets.ts)\n- [src/auth.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n</details>\n\n# Configuration Reference\n\n## Overview\n\nThe ms-365-admin-mcp-server provides a comprehensive configuration system that controls authentication, cloud endpoint selection, risk-based access control, and tool filtering. Configuration is driven through a combination of environment variables, CLI arguments, and JSON-based endpoint definitions.\n\nThe server implements a least-privilege security model where tools are classified by risk level, and the server operator can enforce a maximum permissible risk threshold to prevent accidental execution of destructive operations.\n\n## Configuration Architecture\n\n```mermaid\ngraph TD\n    A[Environment Variables] --> B[Secrets Module]\n    A --> C[Cloud Config Module]\n    D[CLI Arguments] --> E[CLI Parser]\n    E --> F[Runtime Config]\n    B --> F\n    C --> F\n    G[endpoints.json] --> H[Tool Registry]\n    H --> I[Risk Level Classifier]\n    I --> J[Access Control Filter]\n    F --> J\n    J --> K[MCP Tools]\n    \n    L[Auth Module] --> M[MSAL Token Cache]\n    B --> L\n    F --> L\n```\n\n## Environment Variables\n\nThe server requires Azure AD application registration credentials. All environment variables use the `MS365_ADMIN_MCP_` prefix.\n\n### Required Variables\n\n| Variable | Description | Required |\n|----------|-------------|----------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Azure AD application (client) ID | Yes |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Client secret for the application | Yes |\n| `MS365_ADMIN_MCP_TENANT_ID` | Azure AD tenant ID | Yes |\n\n### Optional Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `MS365_ADMIN_MCP_MAX_RISK_LEVEL` | Maximum risk level permitted | `medium` |\n| `MS365_ADMIN_MCP_CLOUD` | Target cloud: `global` or `china` | `global` |\n| `MS365_ADMIN_MCP_PRESET` | Comma-separated list of tool presets | `all` |\n| `MS365_ADMIN_MCP_PORT` | HTTP server port | `3000` |\n| `MCP_REMOTE_CONFIG_DIR` | Custom cache directory for OAuth tokens | Platform default |\n\n### Risk Level Configuration\n\nRisk levels control which tools are exposed or executable. The server enforces a maximum risk level that acts as an access control gate.\n\n| Risk Level | Rank | Description |\n|------------|------|-------------|\n| `low` | 1 | Safe read-only operations |\n| `medium` | 2 | Operations with moderate impact |\n| `high` | 3 | Significant impact operations |\n| `critical` | 4 | Irreversible or tenant-wide operations |\n\nThe effective risk level for a tool is determined as follows (资料来源：[src/risk-level.ts:1-20]())：\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\nKey rules:\n\n- If `configuredRiskLevel` is explicitly set, it is used directly\n- GET endpoints without explicit configuration default to `low`\n- Write endpoints without explicit configuration default to `critical` (fail-safe)\n- A tool is allowed if `rank(effectiveRiskLevel) <= rank(maxRiskLevel)`\n\n## Cloud Configuration\n\nThe server supports Microsoft 365 deployments in different sovereign clouds.\n\n```mermaid\ngraph LR\n    A[Config: cloud=global] --> B[login.microsoftonline.com]\n    C[Config: cloud=china] --> D[login.partner.microsoftonline.cn]\n    B --> E[Microsoft Graph Global]\n    D --> F[Microsoft Graph China 21Vianet]\n```\n\n### Supported Clouds\n\n| Cloud Identifier | Azure Environment | Graph Endpoint |\n|-----------------|-------------------|----------------|\n| `global` | Microsoft Azure | `https://graph.microsoft.com` |\n| `china` | Azure China 21Vianet | `https://microsoftgraph.chinacloudapi.cn` |\n\nThe cloud configuration is loaded from environment variable `MS365_ADMIN_MCP_CLOUD` (资料来源：[src/cloud-config.ts]()) and determines which Microsoft Graph endpoint the server authenticates against.\n\n## CLI Arguments\n\nThe server accepts command-line arguments parsed by Commander.js (资料来源：[src/cli.ts]())。\n\n| Argument | Short | Description | Default |\n|----------|-------|-------------|---------|\n| `--max-risk-level` | `-r` | Maximum risk level (low/medium/high/critical) | `medium` |\n| `--preset` | `-p` | Tool preset filter (security, identity, etc.) | `all` |\n| `--port` | | HTTP server port | `3000` |\n| `--list-tools` | | List available tools and exit | `false` |\n| `--inspector` | | Run with MCP Inspector | `false` |\n\n### Listing Tools with Presets\n\nTo validate preset patterns, run:\n\n```bash\nnode dist/index.js --preset mypreset --list-tools\n```\n\nThis validates that the preset regex matches tool names defined in `endpoints.json`.\n\n## Tool Presets\n\nTool presets filter the available tools based on regex patterns defined in `src/tool-categories.ts` (资料来源：[src/tool-categories.ts]())。\n\n### Available Presets\n\n| Preset Name | Pattern Matches | Description |\n|-------------|-----------------|-------------|\n| `security` | security, alert, incident, attack-simulation, threat-intel | Microsoft 365 Defender tools |\n| `audit` | audit, sign-in, provisioning, directory, deleted | Audit logs and sign-in activity |\n| `health` | service, health, issue, message | Service health and Message Center |\n| `reports` | report, activity, usage | Usage reports (Teams, Email, SharePoint) |\n| `identity` | user, group, role, conditional, directory, device, pim | Entra ID management |\n| `exchange` | exchange, mailbox, message, mail | Exchange Online administration |\n| `intune` | intune, managed, compliance, autopilot, mdm, mam | Intune device management |\n| `governance` | access-review, entitlement, lifecycle, terms-of-use | Identity Governance |\n| `compliance` | compliance, license, secure-score, risk-detection | Compliance center tools |\n| `response` | disable-user, revoke, block, reset, dismiss, wipe | Incident response operations |\n| `ediscovery` | ediscovery | Microsoft Purview eDiscovery |\n| `cloudpc` | cloud-pc, provisioning-policy | Windows 365 Cloud PC |\n| `callrecords` | call-record, call-session, pstn-call | Teams call records |\n| `print` | print | Universal Print |\n| `infoprotection` | bitlocker, sensitivity, threat-assessment | Information Protection |\n| `sharepointadmin` | sharepoint, site-admin | SharePoint admin center |\n| `retention` | retention, records | Records management |\n| `teamsadmin` | team, teams-app, teams-policy | Teams administration |\n| `all` | .* | All available tools |\n\n### Combining Presets\n\nMultiple presets can be combined using the `getCombinedPresetPattern` function (资料来源：[src/tool-categories.ts:60-75]())：\n\n```typescript\nexport function getCombinedPresetPattern(presets: string[]): string {\n  const patterns = presets.map((preset) => {\n    const category = TOOL_CATEGORIES[preset];\n    if (!category) {\n      throw new Error(\n        `Unknown preset: ${preset}. Available presets: ${Object.keys(TOOL_CATEGORIES).join(', ')}`\n      );\n    }\n    return category.pattern.source;\n  });\n  return patterns.join('|');\n}\n```\n\n## Authentication Configuration\n\nAuthentication uses the MSAL (Microsoft Authentication Library) client credentials flow (资料来源：[src/auth.ts]())。\n\n### Authentication Flow\n\n```mermaid\nsequenceDiagram\n    participant Server\n    participant MSAL\n    participant Azure AD\n    \n    Server->>Azure AD: Request token with client credentials\n    Azure AD-->>MSAL: Access token + refresh token\n    MSAL-->>Server: Token cached\n    Server->>Azure AD: Graph API calls with bearer token\n    Azure AD-->>Server: Response\n```\n\n### Token Cache Location\n\nTokens are cached in:\n- **macOS/Linux**: `~/.mcp-auth/mcp-remote-<version>/`\n- **Windows**: `%USERPROFILE%\\.mcp-auth\\mcp-remote-<version>\\`\n\nCache files are named `<hash>_client_info.json` and `<hash>_tokens.json` with mode 0600 permissions.\n\n### Remote Server Authentication\n\nFor remote HTTP server mode, device code authentication is supported (资料来源：[CONTRIBUTING.md]())：\n\n- Cache key = `md5(serverUrl)` to match `mcp-remote`'s `getServerUrlHash`\n- Best-effort clipboard copy for device codes (auto-disabled under `CI=true`)\n- Configurable cache directory via `--cache-dir` or `MCP_REMOTE_CONFIG_DIR`\n\n## Endpoint Configuration\n\nThe `src/endpoints.json` file is the source of truth for all tool definitions (资料来源：[src/endpoints.json]())。\n\n### Endpoint Schema\n\nEach endpoint definition includes:\n\n| Field | Description |\n|-------|-------------|\n| `toolName` | Unique identifier for the tool |\n| `method` | HTTP method (GET, POST, PATCH, DELETE) |\n| `path` | Microsoft Graph API path |\n| `description` | Human-readable description |\n| `appPermissions` | Required Graph API permissions |\n| `riskLevel` | Configured risk level (low/medium/high/critical) |\n| `category` | Tool category for filtering |\n\n### Risk Classification Examples\n\nCritical-risk tools (资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md]())：\n\n- `delete-user`\n- `delete-group`\n- `delete-conditional-access-policy`\n- `wipe-managed-device`\n- `delete-managed-device`\n\nHigh-risk tools:\n- `revoke-user-sessions`\n- `confirm-compromised-users`\n- `create-conditional-access-policy`\n- `update-conditional-access-policy`\n\n## Configuration Precedence\n\nConfiguration values are resolved in the following order (highest to lowest priority):\n\n1. CLI arguments (command-line overrides)\n2. Environment variables\n3. Default values\n\n```mermaid\ngraph TD\n    A[Config Sources] --> B[CLI Arguments]\n    A --> C[Environment Variables]\n    A --> D[Default Values]\n    B --> E[Runtime Merged Config]\n    C --> E\n    D --> E\n    E --> F[Server Initialization]\n```\n\n## Example Configuration Files\n\n### Development .env File\n\nCreate a local `.env` file in the project root (资料来源：[CONTRIBUTING.md]())：\n\n```bash\nMS365_ADMIN_MCP_CLIENT_ID=your-app-client-id\nMS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret\nMS365_ADMIN_MCP_TENANT_ID=your-tenant-id\n```\n\n### Docker Configuration\n\nFor Docker deployments, use environment variables or bind-mounted configuration:\n\n```bash\ndocker run \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=... \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=... \\\n  -e MS365_ADMIN_MCP_TENANT_ID=... \\\n  -e MS365_ADMIN_MCP_MAX_RISK_LEVEL=medium \\\n  -e MCP_REMOTE_CONFIG_DIR=/data/mcp-config \\\n  -v /path/to/config:/data/mcp-config \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server\n```\n\n## Exit Codes\n\nThe server uses specific exit codes for Docker and CI integration (资料来源：[CONTRIBUTING.md]())：\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success |\n| 1 | Usage error / invalid configuration |\n| 2 | Network error |\n| 3 | Authentication denied |\n| 4 | Request timeout |\n\n## Verification\n\nRun the verification script to ensure configuration is valid:\n\n```bash\nnpm run verify\n```\n\nThis runs:\n- TypeScript compilation (`npm run build`)\n- Linting (`npm run lint`)\n- Formatting checks (`npm run format:check`)\n- Test suite (`npm test`)\n\n---\n\n<a id='system-architecture'></a>\n\n## System Architecture\n\n### 相关页面\n\n相关主题：[Project Overview](#overview), [Code Generation Pipeline](#code-generation), [Tool Categories and Presets](#tool-categories)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [docs/ARCHITECTURE.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/ARCHITECTURE.md)\n- [src/server.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/server.ts)\n- [src/http-server.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/http-server.ts)\n- [src/graph-client.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/graph-client.ts)\n- [src/auth.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth.ts)\n</details>\n\n# System Architecture\n\nThe ms-365-admin-mcp-server is a Model Context Protocol (MCP) server that exposes Microsoft 365 administrative operations as AI-consumable tools. It acts as a bridge between Large Language Models (LLMs) and the Microsoft Graph API, providing over 444 administrative endpoints organized into security-aware tool categories.\n\n## Overview\n\nThe server follows a layered architecture pattern with clear separation of concerns:\n\n1. **Authentication Layer** — MSAL-based OAuth2 client credentials flow\n2. **Tool Registry** — Declarative tool definitions from OpenAPI specs\n3. **Risk Control Layer** — Tool filtering based on configurable risk thresholds\n4. **MCP Transport Layer** — STDIO server or HTTP/SSE endpoint\n5. **Graph API Client** — Auto-generated TypeScript client from OpenAPI\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Core Components\n\n### Authentication Module (`src/auth.ts`)\n\nThe server uses MSAL (Microsoft Authentication Library) with the client credentials flow for service-to-service authentication. This flow is suitable for daemon applications that operate without user interaction.\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                    Authentication Flow                          │\n├─────────────────────────────────────────────────────────────────┤\n│  1. Server starts → Initialize MSAL ConfidentialClientApplication │\n│  2. Acquire token via client credentials (client_id + secret)     │\n│  3. Token cached with expiration handling                         │\n│  4. Graph API calls include Bearer token                          │\n│  5. On 401 → Automatic token refresh                              │\n└─────────────────────────────────────────────────────────────────┘\n```\n\nConfiguration requires three environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Azure AD application (client) ID |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Client secret from certificate or app registration |\n| `MS365_ADMIN_MCP_TENANT_ID` | Azure AD tenant ID |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Cloud Configuration (`src/cloud-config.ts`)\n\nThe server supports Microsoft Azure's global cloud as well as the China (21Vianet) operated cloud. Endpoint selection is configurable to support sovereign cloud deployments.\n\n| Cloud Environment | Endpoint Pattern |\n|-------------------|------------------|\n| Global | `graph.microsoft.com` |\n| China (21Vianet) | `graph.microsoft.cn` |\n\n### Tool Registry (`src/endpoints.json`)\n\nThe `endpoints.json` file is the source of truth for all tool definitions. Each tool entry specifies:\n\n```json\n{\n  \"toolName\": {\n    \"method\": \"GET|POST|PATCH|PUT|DELETE\",\n    \"path\": \"/v1.0/{resource}\",\n    \"appPermissions\": [\"Permission.Read.All\"],\n    \"llmTip\": \"Human-readable hint for the LLM\",\n    \"riskLevel\": \"low|medium|high|critical\"\n  }\n}\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Risk Level System (`src/risk-level.ts`)\n\nThe server implements a risk-based access control system. Each non-GET operation must declare a risk level, and operators can configure a maximum allowed risk level.\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\nRisk levels are enforced at runtime:\n\n| Level | Criteria | Examples |\n|-------|----------|----------|\n| `low` | Read-only in effect | `list-users`, reports |\n| `medium` | Reversible mutation | `update-user`, `add-group-member` |\n| `high` | Broad scope or credential changes | `revoke-user-sessions`, `update-conditional-access-policy` |\n| `critical` | Irreversible or tenant-wide | `delete-user`, `wipe-managed-device` |\n\n资料来源：[src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts), [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Tool Categories (`src/tool-categories.ts`)\n\nTools are organized into preset categories that map to regex patterns. Users can select specific categories to reduce the tool surface or enable focused administration.\n\n```typescript\nexport const TOOL_CATEGORIES: Record<string, ToolCategory> = {\n  identity: {\n    name: 'identity',\n    pattern: /user|group|device|directory|role/i,\n    description: 'Users, groups, roles, devices, PIM, guests, external identities',\n  },\n  compliance: {\n    name: 'compliance',\n    pattern: /license|secure-score|conditional-access|auth-methods/i,\n    description: 'Licenses, Secure Score, Identity Protection, risk detections, CA policies',\n  },\n  // ... additional categories\n};\n```\n\nAvailable presets include: `identity`, `exchange`, `intune`, `governance`, `compliance`, `response`, `ediscovery`, `cloudpc`, `callrecords`, `print`, `infoprotection`, `sharepointadmin`, `retention`, `teamsadmin`, `reports`, `audit`, and `all`.\n\n资料来源：[src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Server Architecture\n\n### STDIO Mode (MCP Standard)\n\nIn standard MCP mode, the server communicates over STDIO using JSON-RPC messages. This is the default mode for Claude Desktop and other MCP-compatible clients.\n\n```\n┌──────────────┐     STDIO (JSON-RPC)      ┌──────────────────────┐\n│  MCP Client  │ ◄──────────────────────► │  ms-365-admin-mcp    │\n│  (Claude)    │                           │  server              │\n└──────────────┘                           └──────────────────────┘\n```\n\n### HTTP Server Mode\n\nThe server can also run as an HTTP endpoint with Server-Sent Events (SSE) for streaming responses. This mode is suitable for remote deployments in containerized environments.\n\n```\n┌──────────────┐     HTTPS + SSE           ┌──────────────────────┐\n│  HTTP Client │ ◄──────────────────────► │  ms-365-admin-mcp    │\n│  (Remote)    │                           │  http-server         │\n└──────────────┘                           └──────────────────────┘\n```\n\nThe HTTP server supports two authentication mechanisms:\n\n1. **OAuth2 Client Credentials** — Direct token authentication\n2. **Device Code Flow** — Interactive authentication for CLI tools\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Device Code Bootstrap (`src/auth-bootstrap.ts`)\n\nFor HTTP server deployments, the `ms-365-admin-mcp-auth` CLI tool implements RFC 8628 device code flow to pre-seed the mcp-remote token cache:\n\n```bash\nms-365-admin-mcp-auth --server https://your-host.azurecontainerapps.io/mcp\n```\n\nThis allows Claude Desktop/Code to skip the browser-based authentication flow when connecting to remote servers.\n\nKey features:\n- Cache key = `md5(serverUrl)` for compatibility with mcp-remote\n- Token files stored in `~/.mcp-auth/mcp-remote-<version>/` with mode 0600\n- Best-effort clipboard copy (auto-disabled under `CI=true`)\n- Exit codes: 0 (ok), 1 (usage), 2 (network), 3 (denied), 4 (timeout)\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts), [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Code Generation Pipeline\n\nThe server uses a code generation pipeline to transform the Microsoft Graph OpenAPI specification into type-safe TypeScript/Zod client code:\n\n```\n┌─────────────────┐     npm run generate      ┌─────────────────────┐\n│  Graph OpenAPI  │ ───────────────────────► │  src/generated/      │\n│  Specification  │                          │  (zod schemas +     │\n│                 │                          │   typed clients)    │\n└─────────────────┘                          └─────────────────────┘\n```\n\nThe `bin/` directory contains scripts that:\n1. Download the latest Graph API OpenAPI spec\n2. Parse and transform the specification\n3. Generate Zod validation schemas\n4. Create typed Graph API client methods\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## CLI Interface (`src/cli.ts`)\n\nThe server uses Commander.js for CLI argument parsing. Key commands:\n\n| Command | Description |\n|---------|-------------|\n| `npm run inspector` | Start MCP Inspector for interactive testing |\n| `--list-tools` | Display all available tools matching current preset |\n| `--list-permissions` | Show required Graph API permissions |\n| `--preset <name>` | Select tool category preset |\n| `--max-risk <level>` | Set maximum allowed risk level |\n| `--allow-writes` | Enable write operations (disabled by default) |\n\nExample usage:\n```bash\n# List tools in the identity preset\nnode dist/index.js --preset identity --list-tools\n\n# Start with compliance tools and allow medium-risk operations\nnode dist/index.js --preset compliance --max-risk medium --allow-writes\n```\n\n## Security Model\n\nThe server implements defense-in-depth through multiple layers:\n\n### 1. Permission Layer\nEvery tool declares minimum required Graph API permissions (`appPermissions`). The server never requests overly broad permissions like `.ReadWrite.All` when `.Read.All` suffices.\n\n### 2. Risk Classification\nWrite operations are classified into four risk levels. The `--max-risk` flag limits which operations can execute.\n\n### 3. Explicit Write Confirmation\nBy default, write operations are disabled. The `--allow-writes` flag enables them, but high-risk operations still require explicit confirmation.\n\n### 4. Audit Trail\nAll operations are logged with timestamps, tool names, and risk levels for security auditing.\n\nCritical-risk tools require out-of-band sign-off and should not be executed through the chat interface without formal change request documentation:\n\n| Tool | Risk Level |\n|------|------------|\n| `delete-user` | critical |\n| `delete-group` | critical |\n| `delete-conditional-access-policy` | critical |\n| `delete-managed-device` | critical |\n| `wipe-managed-device` | critical |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n\n## Development Workflow\n\n### Local Development Setup\n\n```bash\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\nnpm install\nnpm run generate    # Download Graph OpenAPI spec and generate client\nnpm run build\nnpm test\n```\n\n### Adding a New Tool\n\n1. Edit `src/endpoints.json` with the new endpoint definition\n2. Run `npm run generate` to regenerate the client\n3. Verify tool registration with `--list-tools`\n4. Add tests for non-trivial parameter handling\n5. Update `README.md` tool tables\n\n### Verification Commands\n\n```bash\nnpm run format:check  # Prettier validation\nnpm run lint          # ESLint validation\nnpm test              # Run test suite\nnpm run verify        # All checks (format + lint + test)\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Project Layout\n\n```\nms-365-admin-mcp-server/\n├── bin/                    # Code-generation scripts (OpenAPI → zod client)\n├── src/\n│   ├── auth.ts             # MSAL client credentials flow\n│   ├── auth-bootstrap.ts   # Device code bootstrap CLI\n│   ├── cli.ts              # Commander argv parsing\n│   ├── cloud-config.ts     # Global vs China (21Vianet) endpoints\n│   ├── endpoints.json      # Source of truth for tool definitions\n│   ├── generated/          # Auto-generated zod schemas and clients\n│   ├── graph-client.ts     # Graph API client wrapper\n│   ├── http-server.ts      # HTTP/SSE server implementation\n│   ├── risk-level.ts       # Risk classification logic\n│   ├── server.ts           # MCP STDIO server implementation\n│   └── tool-categories.ts  # Tool category presets\n├── docs/                   # Documentation\n├── agent-skills/           # Claude Code skill definitions\n└── README.md\n```\n\n## Deployment Options\n\n### Docker Container\n\nThe server is published to GitHub Container Registry:\n\n```bash\ndocker run -p 8080:8080 \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=... \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=... \\\n  -e MS365_ADMIN_MCP_TENANT_ID=... \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### Claude Desktop Integration\n\nFor local development, add to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@okapi-ca/ms-365-admin-mcp-server\"],\n      \"env\": {\n        \"MS365_ADMIN_MCP_CLIENT_ID\": \"...\",\n        \"MS365_ADMIN_MCP_CLIENT_SECRET\": \"...\",\n        \"MS365_ADMIN_MCP_TENANT_ID\": \"...\"\n      }\n    }\n  }\n}\n```\n\n### Claude Code Skill Installation\n\n```bash\ncp -r agent-skills/ms365-admin-mcp ~/.claude/skills/\n```\n\nThe skill auto-loads when the conversation matches its description field.\n\n---\n\n<a id='code-generation'></a>\n\n## Code Generation Pipeline\n\n### 相关页面\n\n相关主题：[System Architecture](#system-architecture), [Tool Categories and Presets](#tool-categories)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [bin/generate-graph-client.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/generate-graph-client.mjs)\n- [bin/modules/generate-mcp-tools.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/generate-mcp-tools.mjs)\n- [bin/modules/simplified-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/simplified-openapi.mjs)\n- [bin/modules/extract-descriptions.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/extract-descriptions.mjs)\n- [bin/modules/download-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/download-openapi.mjs)\n- [src/generated/endpoint-types.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/generated/endpoint-types.ts)\n- [src/graph-tools.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/graph-tools.ts)\n- [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n</details>\n\n# Code Generation Pipeline\n\n## Overview\n\nThe **Code Generation Pipeline** is an automated build process that transforms the Microsoft Graph OpenAPI specification into a fully-typed MCP (Model Context Protocol) server implementation. This pipeline generates TypeScript/Zod schemas, endpoint types, and tool definitions, enabling type-safe interactions with over 500 Microsoft Graph API endpoints.\n\n**资料来源:** [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n    A[Microsoft Graph OpenAPI Spec] --> B[download-openapi.mjs]\n    B --> C[simplified-openapi.mjs]\n    C --> D[extract-descriptions.mjs]\n    D --> E[generate-mcp-tools.mjs]\n    E --> F[generate-graph-client.mjs]\n    F --> G[src/generated/]\n    G --> H[endpoint-types.ts]\n    G --> I[schemas.ts]\n    G --> J[descriptions.ts]\n    G --> K[endpoints.json]\n    K --> L[graph-tools.ts]\n    L --> M[MCP Server]\n```\n\n## Pipeline Components\n\n### 1. OpenAPI Download Module\n\n**File:** `bin/modules/download-openapi.mjs`\n\nDownloads the Microsoft Graph OpenAPI specification from the official Microsoft Graph metadata repository.\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `outputPath` | `string` | Local path to save the downloaded OpenAPI spec |\n| `version` | `string` | API version to download (default: `v1.0`) |\n\n**Key behaviors:**\n- Fetches OpenAPI spec from `https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml`\n- Handles network errors with retry logic\n- Validates downloaded file structure\n\n**资料来源:** [bin/modules/download-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/download-openapi.mjs)\n\n### 2. Simplified OpenAPI Processor\n\n**File:** `bin/modules/simplified-openapi.mjs`\n\nTransforms the raw OpenAPI specification into a simplified intermediate format optimized for code generation.\n\n**Transformation rules:**\n- Flattens nested schema references\n- Resolves `$ref` pointers\n- Extracts path parameters, query parameters, and request body schemas\n- Normalizes response schemas\n\n**Output structure:**\n\n```typescript\ninterface SimplifiedEndpoint {\n  path: string;\n  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n  operationId: string;\n  summary?: string;\n  parameters: Parameter[];\n  requestBody?: RequestBody;\n  responses: Record<string, Response>;\n  security?: SecurityRequirement[];\n}\n```\n\n**资料来源:** [bin/modules/simplified-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/simplified-openapi.mjs)\n\n### 3. Description Extractor\n\n**File:** `bin/modules/extract-descriptions.mjs`\n\nExtracts human-readable descriptions from OpenAPI operations for use in tool documentation and LLM prompts.\n\n**Extraction sources (priority order):**\n1. `operation.description` - Primary description\n2. `operation.summary` - Fallback summary\n3. Parameter descriptions from schema\n\n**Generated output:**\n\n```typescript\ninterface ToolDescription {\n  operationId: string;\n  description: string;\n  parameterDescriptions: Record<string, string>;\n  deprecationNotice?: string;\n}\n```\n\n**资料来源:** [bin/modules/extract-descriptions.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/extract-descriptions.mjs)\n\n### 4. MCP Tools Generator\n\n**File:** `bin/modules/generate-mcp-tools.mjs`\n\nGenerates MCP tool definitions from the processed OpenAPI specification.\n\n**Generation process:**\n\n```mermaid\ngraph LR\n    A[OpenAPI Operations] --> B[Parse endpoint config]\n    B --> C[Generate tool name]\n    C --> D[Create Zod schema]\n    D --> E[Extract risk level]\n    E --> F[Write to endpoints.json]\n```\n\n**Tool naming convention:**\n- Operation IDs are converted to kebab-case\n- Prefixes are preserved for categorization (e.g., `list-`, `get-`, `create-`, `update-`, `delete-`)\n\n**Generated metadata per tool:**\n\n| Field | Source | Description |\n|-------|--------|-------------|\n| `toolName` | operationId → kebab-case | Unique tool identifier |\n| `pathPattern` | OpenAPI path | API endpoint path |\n| `method` | HTTP method | GET, POST, PUT, PATCH, DELETE |\n| `appPermissions` | securitySchemes | Required Graph API permissions |\n| `llmTip` | description | Optional hint for LLM context |\n| `riskLevel` | Manual annotation | low/medium/high/critical |\n\n**资料来源:** [bin/modules/generate-mcp-tools.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/generate-mcp-tools.mjs), [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n\n### 5. Graph Client Generator\n\n**File:** `bin/generate-graph-client.mjs`\n\nOrchestrates the entire pipeline and generates TypeScript source files.\n\n**Generated artifacts:**\n\n| File | Purpose |\n|------|---------|\n| `src/generated/endpoint-types.ts` | TypeScript interfaces for all endpoints |\n| `src/generated/schemas.ts` | Zod validation schemas |\n| `src/generated/descriptions.ts` | Tool descriptions and documentation |\n\n**资料来源:** [bin/generate-graph-client.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/generate-graph-client.mjs)\n\n## Generated Output Files\n\n### endpoint-types.ts\n\nAuto-generated TypeScript types derived from OpenAPI schemas.\n\n```typescript\n// Auto-generated - DO NOT EDIT\nexport interface ListUsersResponse {\n  '@odata.context'?: string;\n  value: User[];\n}\n```\n\n**资料来源:** [src/generated/endpoint-types.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/generated/endpoint-types.ts)\n\n### endpoints.json\n\nThe source of truth for all tool definitions, serving as the configuration manifest for tool registration.\n\n```jsonc\n{\n  \"toolName\": \"list-users\",\n  \"pathPattern\": \"/users\",\n  \"method\": \"GET\",\n  \"appPermissions\": [\"User.Read.All\"],\n  \"llmTip\": \"List all users in the organization\",\n  \"riskLevel\": \"low\"\n}\n```\n\n**资料来源:** [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n\n## Tool Registration Flow\n\nAfter code generation, the pipeline integrates with the MCP server through `graph-tools.ts`:\n\n```mermaid\ngraph TD\n    A[endpoints.json] --> B[loadEndpoints]\n    B --> C[For each endpoint]\n    C --> D[Create Zod param schema]\n    D --> E[Generate tool description]\n    E --> F[Calculate risk level]\n    F --> G[server.tool registration]\n    G --> H[MCP Server runtime]\n```\n\n**Risk level calculation logic:**\n\n```typescript\nfunction effectiveRiskLevel(configuredRiskLevel, method) {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\n**资料来源:** [src/graph-tools.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/graph-tools.ts), [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Execution Workflow\n\n### Standard Generation\n\n```bash\nnpm run generate\n```\n\nThis command:\n1. Downloads the latest Graph OpenAPI spec\n2. Simplifies and normalizes the spec\n3. Extracts descriptions\n4. Generates MCP tool definitions\n5. Outputs TypeScript types and schemas\n\n### Full Build Pipeline\n\n```bash\nnpm run generate    # Download and generate code\nnpm run build       # Compile TypeScript\nnpm test            # Run verification tests\nnpm run verify      # lint + format + test\n```\n\n**资料来源:** [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Configuration\n\n### Risk Level Annotations\n\nTools requiring special risk classification must be annotated in `endpoints.json`:\n\n```jsonc\n{\n  \"toolName\": \"delete-user\",\n  \"riskLevel\": \"critical\"\n}\n```\n\n**Risk classification rubric:**\n\n| Level | Criteria | Example Tools |\n|-------|----------|---------------|\n| `low` | Read-only queries, reports | `list-users`, `get-user` |\n| `medium` | Reversible single-entity mutation | `update-user`, `add-group-member` |\n| `high` | Significant impact, credential changes | `revoke-user-sessions`, `update-ca-policy` |\n| `critical` | Irreversible or tenant-wide | `delete-user`, `wipe-managed-device` |\n\n**资料来源:** [CONTRIBUTING.md:50-62](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Permission Mapping\n\nApplication permissions are declared per tool in `endpoints.json`:\n\n```jsonc\n{\n  \"toolName\": \"list-sign-ins\",\n  \"appPermissions\": [\"AuditLog.Read.All\"]\n}\n```\n\n**资料来源:** [agent-skills/ms365-admin-mcp/references/graph-permissions.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/graph-permissions.md)\n\n## Adding New Tools\n\n### Workflow\n\n```mermaid\ngraph TD\n    A[Find Graph API endpoint] --> B[Add to endpoints.json]\n    B --> C[Run npm run generate]\n    C --> D[Verify tool registration]\n    D --> E[Add tests if needed]\n    E --> F[Update documentation]\n```\n\n### Step 1: Identify the Endpoint\n\nLocate the desired operation in the [Microsoft Graph OpenAPI spec](https://github.com/microsoftgraph/msgraph-metadata).\n\n### Step 2: Register in endpoints.json\n\n```jsonc\n{\n  \"toolName\": \"list-something\",\n  \"pathPattern\": \"/something\",\n  \"method\": \"GET\",\n  \"appPermissions\": [\"Something.Read.All\"],\n  \"llmTip\": \"Optional hint shown to the LLM\",\n  \"riskLevel\": \"low\"\n}\n```\n\n### Step 3: Regenerate Code\n\n```bash\nnpm run generate\n```\n\n### Step 4: Verify Registration\n\n```bash\nnode dist/index.js --list-tools | grep list-something\nnode dist/index.js --list-permissions | grep Something\n```\n\n**资料来源:** [CONTRIBUTING.md:30-45](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Verification and Testing\n\n### List Tools\n\nDisplay all registered tools:\n\n```bash\nnode dist/index.js --list-tools\n```\n\n### List Permissions\n\nDisplay required Graph API permissions:\n\n```bash\nnode dist/index.js --list-permissions\n```\n\n### Preset Filtering\n\nList tools by preset category:\n\n```bash\nnode dist/index.js --preset security --list-tools\nnode dist/index.js --preset identity --list-tools\n```\n\n**Available presets:** `security`, `audit`, `health`, `reports`, `identity`, `exchange`, `intune`, `governance`, `compliance`, `response`, `ediscovery`, `cloudpc`, `callrecords`, `print`, `infoprotection`, `sharepointadmin`, `retention`, `teamsadmin`, `all`\n\n**资料来源:** [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Summary\n\nThe Code Generation Pipeline is the backbone of the ms-365-admin-mcp-server, enabling:\n\n| Capability | Description |\n|------------|-------------|\n| **Automation** | Eliminates manual TypeScript/Zod schema writing |\n| **Consistency** | Uniform tool naming and structure |\n| **Type Safety** | End-to-end TypeScript typing from OpenAPI to server |\n| **Extensibility** | Easy addition of new Graph API endpoints |\n| **Documentation** | Auto-generated descriptions and permission lists |\n\nBy maintaining `endpoints.json` as the single source of truth and running `npm run generate`, developers can keep the MCP server synchronized with the evolving Microsoft Graph API surface.\n\n---\n\n<a id='tool-categories'></a>\n\n## Tool Categories and Presets\n\n### 相关页面\n\n相关主题：[System Architecture](#system-architecture), [Security Model and Risk Classification](#security-model)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n</details>\n\n# Tool Categories and Presets\n\n## Overview\n\nTool Categories and Presets provide a logical grouping mechanism for the 515 tools exposed by the ms-365-admin-mcp-server. Categories use regex patterns to match tool names against predefined groups, enabling bulk operations, risk assessment, and organized documentation across different Microsoft 365 admin domains.\n\nThe system serves two primary purposes:\n- **Organization**: Grouping related tools by functional domain (security, identity, compliance, etc.)\n- **Risk governance**: Applying consistent risk levels and access controls across tool groupings\n\n资料来源：[src/tool-categories.ts:1-1]()\n\n## Architecture\n\n```mermaid\ngraph TD\n    A[endpoints.json] --> B[Tool Definitions]\n    B --> C{regex pattern matching}\n    D[tool-categories.ts] --> C\n    C --> E[ToolCategory Assignment]\n    E --> F[Risk Level Resolution]\n    G[risk-level.ts] --> F\n    F --> H[MCP Server Response]\n    \n    I[riskLevel from config] --> F\n    J[HTTP Method GET/POST/PUT/DELETE] --> G\n```\n\n### Core Components\n\n| Component | File | Responsibility |\n|-----------|------|----------------|\n| ToolCategory interface | `src/tool-categories.ts` | Defines the category schema |\n| TOOL_CATEGORIES registry | `src/tool-categories.ts` | Maps category names to regex patterns |\n| effectiveRiskLevel() | `src/risk-level.ts` | Resolves risk level per tool |\n| isToolAllowed() | `src/risk-level.ts` | Checks if tool passes max risk threshold |\n\n资料来源：[src/tool-categories.ts:1-15]()\n\n## ToolCategory Interface\n\n```typescript\nexport interface ToolCategory {\n  name: string;\n  pattern: RegExp;\n  description: string;\n}\n```\n\n| Field | Type | Purpose |\n|-------|------|---------|\n| `name` | `string` | Unique identifier for the category |\n| `pattern` | `RegExp` | Regex pattern tested against tool names |\n| `description` | `string` | Human-readable description for documentation |\n\n资料来源：[src/tool-categories.ts:1-5]()\n\n## Category Registry\n\nThe `TOOL_CATEGORIES` record contains all predefined categories. Each category uses a case-insensitive regex pattern to match tool names defined in `endpoints.json`.\n\n资料来源：[src/tool-categories.ts:7-40]()\n\n### Available Categories\n\n| Preset | Pattern Scope | Description |\n|--------|---------------|-------------|\n| `security` | `security\\|alert\\|incident\\|attack-simulation\\|threat-intel` | Security alerts, incidents, attack simulations, and threat intelligence (Microsoft 365 Defender) |\n| `audit` | `audit\\|sign-in\\|provisioning\\|directory\\|deleted-user\\|deleted-group` | Audit logs, deleted items (directory audits, sign-ins, provisioning) |\n| `health` | `service\\|health\\|issue\\|message` | Service health and Message Center announcements |\n| `reports` | `report\\|activity\\|usage` | Usage reports (Teams, Email, Active Users, SharePoint, OneDrive, Mailbox, M365 Apps) |\n| `identity` | Complex pattern (users, groups, roles, conditional access, PIM, devices, etc.) | Identity and access management (Entra ID users, groups, roles, devices, PIM, guest users, external identities) |\n\n资料来源：[src/tool-categories.ts:7-40]()\n\n## Risk Level System\n\n### Effective Risk Level Resolution\n\nThe `effectiveRiskLevel()` function determines the actual risk level for any tool:\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\n| Scenario | Result |\n|----------|--------|\n| `configuredRiskLevel` is set | Returns configured value |\n| Method is GET (case-insensitive) | Returns `low` |\n| Method is POST/PUT/DELETE, no config | Returns `critical` (fail-safe default) |\n\n资料来源：[src/risk-level.ts:10-18]()\n\n### Risk Level Hierarchy\n\n| Level | Criteria | Example Tools |\n|-------|----------|---------------|\n| `low` | Read-only operations | `list-users`, `get-security-alert` |\n| `medium` | Reversible mutations on single entities | `update-user`, `add-group-member` |\n| `high` | Significant impact, credential changes, or destructive operations | `revoke-user-sessions`, `update-conditional-access-policy` |\n| `critical` | Irreversible or tenant-wide impact | `delete-user`, `wipe-managed-device`, `delete-conditional-access-policy` |\n\n资料来源：[CONTRIBUTING.md:1-20]()\n\n### Tool Permission Check\n\nThe `isToolAllowed()` function compares the tool's effective risk against the server's configured maximum:\n\n```typescript\nexport function isToolAllowed(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string,\n  maxRiskLevel: RiskLevel\n): boolean {\n  return rank(effectiveRiskLevel(configuredRiskLevel, method)) <= rank(maxRiskLevel);\n}\n```\n\nThe `rank()` function (implied internal) orders risk levels: `low < medium < high < critical`.\n\n资料来源：[src/risk-level.ts:20-25]()\n\n## Category Matching Flow\n\n```mermaid\ngraph LR\n    A[Tool Name] --> B{Iterate TOOL_CATEGORIES}\n    B -->|match found| C[Assign Category]\n    B -->|no match| D[Uncategorized]\n    \n    E[Tool Method] --> F[effectiveRiskLevel]\n    F --> G{Method == GET?}\n    G -->|Yes| H[risk = low]\n    G -->|No| I{configuredRiskLevel?}\n    I -->|Yes| J[risk = configured]\n    I -->|No| K[risk = critical]\n```\n\n## Adding a New Preset\n\n### Step 1: Edit tool-categories.ts\n\nAdd a new entry to the `TOOL_CATEGORIES` object:\n\n```typescript\nexport const TOOL_CATEGORIES: Record<string, ToolCategory> = {\n  mypreset: {\n    name: 'mypreset',\n    pattern: /pattern-matching-tool-names/i,\n    description: 'Short human-readable description',\n  },\n  // ...existing categories\n};\n```\n\n资料来源：[CONTRIBUTING.md:25-35]()\n\n### Step 2: Validate the Pattern\n\n```bash\nnode dist/index.js --preset mypreset --list-tools\n```\n\nThis command tests the regex against all tools in `endpoints.json` and lists matches.\n\n资料来源：[CONTRIBUTING.md:37-38]()\n\n## Tool Definition Schema\n\nTools are defined in `endpoints.json` with the following structure:\n\n```json\n{\n  \"toolName\": {\n    \"method\": \"GET|POST|PUT|DELETE\",\n    \"appPermissions\": [\"Permission.Read.All\"],\n    \"llmTip\": \"Optional hint for LLM\",\n    \"riskLevel\": \"low|medium|high|critical\"  // only for non-GET\n  }\n}\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `method` | Yes | HTTP method for the Graph API call |\n| `appPermissions` | Yes | Minimum Graph API permissions |\n| `llmTip` | No | Hint displayed to LLM in tool description |\n| `riskLevel` | For non-GET | Risk classification per the rubric |\n\n资料来源：[CONTRIBUTING.md:55-65]()\n\n## Preset Index\n\n| Preset | Use Case File | Primary Tools |\n|--------|---------------|---------------|\n| `security` | `usecase-security.md` | Alerts, incidents, attack simulations, threat intel |\n| `audit` | `usecase-audit.md` | Directory audits, sign-ins, provisioning logs |\n| `health` | `usecase-health.md` | Service health, Message Center |\n| `reports` | `usecase-reports.md` | Teams, Email, SharePoint, OneDrive usage |\n| `identity` | `usecase-identity.md` | Users, groups, roles, devices, PIM |\n| `exchange` | `usecase-exchange.md` | Message traces, mailboxes |\n| `intune` | `usecase-intune.md` | Device management, compliance, configurations |\n| `governance` | `usecase-governance.md` | Access reviews, entitlement, lifecycle |\n| `compliance` | `usecase-compliance.md` | Licenses, Secure Score, Identity Protection |\n| `response` | `usecase-response.md` | Incident response operations |\n| `ediscovery` | `usecase-ediscovery.md` | eDiscovery cases (Purview) |\n| `cloudpc` | `usecase-cloudpc.md` | Cloud PC / Windows 365 |\n| `callrecords` | `usecase-callrecords.md` | Teams call records |\n| `print` | `usecase-print.md` | Universal Print |\n| `infoprotection` | `usecase-infoprotection.md` | BitLocker, sensitivity labels |\n| `sharepointadmin` | `usecase-sharepointadmin.md` | SharePoint tenant administration |\n| `retention` | `usecase-retention.md` | Records management |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md:1-50]()\n\n## Verification Commands\n\nAfter adding a new preset, verify registration:\n\n```bash\n# List tools matching the preset\nnode dist/index.js --list-tools | grep <pattern>\n\n# Check required permissions\nnode dist/index.js --list-permissions | grep <Permission>\n```\n\n资料来源：[CONTRIBUTING.md:66-72]()\n\n## Integration with MCP Server\n\nThe tool categories system integrates with the MCP server's execution pipeline:\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant MCPServer\n    participant RiskChecker\n    participant GraphAPI\n    \n    Client->>MCPServer: call_tool(toolName, params)\n    MCPServer->>MCPServer: Match toolName against TOOL_CATEGORIES\n    MCPServer->>RiskChecker: effectiveRiskLevel(configured, method)\n    RiskChecker-->>MCPServer: resolvedRiskLevel\n    MCPServer->>RiskChecker: isToolAllowed(resolvedRiskLevel, maxRiskLevel)\n    RiskChecker-->>MCPServer: allowed: boolean\n    \n    alt allowed == false\n        MCPServer-->>Client: Error: Tool exceeds max risk level\n    else allowed == true\n        MCPServer->>GraphAPI: Execute request\n        GraphAPI-->>MCPServer: Response\n        MCPServer-->>Client: Tool result\n    end\n\n---\n\n<a id='security-model'></a>\n\n## Security Model and Risk Classification\n\n### 相关页面\n\n相关主题：[Tool Categories and Presets](#tool-categories), [Azure Deployment Security](#azure-deployment-security)\n\n<details>\n<summary>Relevant Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\n- [docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n- [docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n- [docs/SECURITY_REVIEW_2026-04-25.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-25.md)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- [agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n</details>\n\n# Security Model and Risk Classification\n\n## Overview\n\nThe ms-365-admin-mcp-server implements a defense-in-depth security model centered on risk classification for all Graph API operations. Every tool exposed by the server is classified according to its potential impact, and the server enforces configurable risk caps to prevent accidental execution of destructive or high-impact operations.\n\nThe security model serves two primary purposes:\n\n1. **Operational Safety** — Prevent unintended destructive operations (deletes, wipes, credential changes) from executing without explicit confirmation\n2. **Prompt Injection Defense** — Protect against malicious data injected through Microsoft Graph responses into the LLM context window\n\n资料来源：[docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n\n## Risk Level Taxonomy\n\nThe server defines four risk levels in ascending order of severity. Each level corresponds to a specific operational threshold and requires explicit user action to execute.\n\n| Level | Criteria | Example Operations |\n|-------|----------|-------------------|\n| `low` | Read-only operations, reports, POST-only queries, or trivial annotations | `run-hunting-query`, `add-security-alert-comment`, listing operations |\n| `medium` | Reversible mutations affecting a single entity | `update-user`, `add-group-member`, `create-invitation` |\n| `high` | Significant impact: broad scope, credential change, or destructive | `revoke-user-sessions`, `update-conditional-access-policy`, `confirm-compromised-users` |\n| `critical` | Irreversible or tenant-wide impact | `delete-user`, `wipe-managed-device`, `delete-conditional-access-policy` |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Risk Level Rank\n\nRisk levels are ranked numerically for comparison purposes. Higher numbers indicate greater severity.\n\n```typescript\nconst RISK_RANK: Record<RiskLevel, number> = {\n  low: 0,\n  medium: 1,\n  high: 2,\n  critical: 3,\n};\n```\n\n资料来源：[src/risk-level.ts:1-5](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Risk Classification Algorithm\n\nThe effective risk level for any tool is determined by a deterministic algorithm that combines explicit configuration with method-based defaults.\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\n**Decision Logic:**\n\n1. If `configuredRiskLevel` is explicitly set in `endpoints.json`, use it\n2. For GET requests without explicit configuration, default to `low` (safe reads)\n3. For non-GET requests (write operations) without explicit configuration, default to `critical` — this is a **fail-safe** design that prevents silently exposing unannotated write endpoints\n\n资料来源：[src/risk-level.ts:17-25](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Access Control Function\n\nThe `isToolAllowed` function determines whether a tool at a given risk level is permitted given a maximum risk cap.\n\n```typescript\nexport function isToolAllowed(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string,\n  maxRiskLevel: RiskLevel\n): boolean {\n  return rank(effectiveRiskLevel(configuredRiskLevel, method)) <= rank(maxRiskLevel);\n}\n```\n\nA tool is allowed when its effective risk level rank is **less than or equal to** the configured maximum risk level.\n\n资料来源：[src/risk-level.ts:27-32](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Server Configuration Flags\n\n### `--allow-writes`\n\nBy default, the server operates in **read-only mode**. The `--allow-writes` flag must be explicitly passed to enable any write operations, regardless of their risk level.\n\nThis flag is a prerequisite for risk-based filtering — even if `--max-risk-level medium` is set, no writes execute without `--allow-writes`.\n\n资料来源：[docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n\n### `--max-risk-level <level>`\n\nCaps the maximum risk level of tools registered at startup. Implies `--allow-writes`.\n\n| Cap Value | Effect |\n|-----------|--------|\n| `--max-risk-level low` | Only read operations (`low`) are exposed |\n| `--max-risk-level medium` | Adds medium-risk mutations; hides high/critical tools |\n| `--max-risk-level high` | Adds high-risk operations; critical tools hidden |\n| `--max-risk-level critical` | All tools exposed (default with `--allow-writes`) |\n\nWhen `--max-risk-level medium` is used:\n- BitLocker recovery keys (`high` read) are hidden\n- LAPS passwords (`high` read) are hidden\n- 15 additional medium-risk reads are filtered\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n## Security Controls (SEC-G Series)\n\n### SEC-G01 — Risk Level Cap\n\nThe `--max-risk-level` CLI flag caps the risk level of registered tools. Implies `--allow-writes`. Unannotated writes default to `critical` (fail-safe).\n\nThis control ensures that sensitive endpoints cannot be invoked even if an attacker somehow manipulates the tool invocation, because the server never registers them.\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n### SEC-G02 — Nonce-Enveloped Responses\n\nEvery successful Microsoft Graph tool response is wrapped in a nonce-delimited envelope with an untrusted-data preamble before reaching the LLM:\n\n```\n<graph_response_NN>\n[UNTRUSTED DATA - VERIFY BEFORE USE]\n<nonce>base64_encoded_random_bytes</nonce>\n<content>actual_response</content>\n</graph_response_NN>\n```\n\n- Per-call `crypto.randomBytes(8)` nonce prevents envelope escape\n- Defends against **prompt injection** through user-controlled Graph fields:\n  - `displayName`\n  - `mail` subject\n  - Chat body\n  - Site title\n  - OAuth app name\n  - Any other user-facing field\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n### SEC-G03 — Sensitive Read Annotations\n\n22 sensitive-read GET operations are annotated with explicit risk levels:\n\n| Category | Count | Risk Levels |\n|----------|-------|-------------|\n| BitLocker recovery keys | 1 | `high` |\n| LAPS passwords | 1 | `high` |\n| eDiscovery cases/custodians/searches | 4 | `high` |\n| Subject rights requests | 1 | `high` |\n| Auth methods | 3 | `medium` |\n| Sign-ins | 2 | `medium` |\n| Risk detections | 2 | `medium` |\n| Message traces | 2 | `medium` |\n| Federated credentials | 2 | `medium` |\n\nThese annotations feed SEC-G01: `--max-risk-level medium` automatically hides the `high`-level sensitive reads.\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n## Critical Operations by Category\n\nCritical-level operations require out-of-band sign-off and should never be executed based solely on chat confirmation.\n\n### Identity\n\n| Tool | Impact |\n|------|--------|\n| `delete-user` | Permanently removes user from tenant |\n| `delete-group` | Removes group and all memberships |\n| `add-directory-role-member` | Grants permanent privileged role |\n| `disable-user-account` | On privileged/break-glass accounts |\n\n### Compliance & Security\n\n| Tool | Impact |\n|------|--------|\n| `delete-conditional-access-policy` | Removes tenant-wide access controls |\n| `delete-ediscovery-case` | Permanently removes legal hold case |\n| `wipe-managed-device` | Remote wipe of enrolled device |\n| `clean-windows-device` | Removes device from Intune |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n\n## High-Risk Operations\n\nHigh-risk operations require explicit confirmation and dry-run before execution.\n\n### Confirmation Required\n\n| Tool | Risk | Requirement |\n|------|------|-------------|\n| `revoke-user-sessions` | high | Confirm before executing |\n| `confirm-compromised-users` | high | Confirm per case |\n| `confirm-safe-users` | high | Confirm per case |\n| `dismiss-risky-users` | high | Confirm per case |\n| `change-user-password` | high | Confirm with operator |\n| `update-device` | high | Confirm with operator |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/usecase-compliance.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/usecase-compliance.md)\n\n## Security Architecture Flow\n\n```mermaid\ngraph TD\n    A[Tool Invocation Request] --> B{--allow-writes enabled?}\n    B -->|No| C[Reject All Writes]\n    B -->|Yes| D[Check effectiveRiskLevel]\n    D --> E{Lookup configuredRiskLevel<br/>in endpoints.json}\n    E -->|Found| F[Use Configured Level]\n    E -->|Not Found| G{Method = GET?}\n    G -->|Yes| H[Default: low]\n    G -->|No| I[Default: critical<br/>FAIL-SAFE]\n    F --> J[Calculate rank<br/>effectiveRiskLevel]\n    H --> J\n    I --> J\n    J --> K{rank ≤ maxRiskLevel?}\n    K -->|Yes| L[Execute Tool]\n    K -->|No| M[Block Tool<br/>Not Registered]\n    L --> N[Graph API Call]\n    N --> O[Wrap in Nonce Envelope<br/>SEC-G02]\n    O --> P[Return to LLM]\n```\n\n## Risk Level Inheritance\n\nThe risk classification follows a hierarchical inheritance model:\n\n```mermaid\ngraph LR\n    A[endpoints.json] --> B[Tool Registration]\n    B --> C{--max-risk-level}\n    C --> D[Tool Availability]\n    \n    E[GET Methods] --> F[Default: low<br/>unless overridden]\n    G[Write Methods] --> H[Default: critical<br/>fail-safe]\n```\n\n## Tool Categories and Risk Patterns\n\nThe server organizes tools into presets based on name patterns, each with distinct risk profiles.\n\n```typescript\n// From src/tool-categories.ts\nconst PATTERNS = {\n  security: /alert|incident|attack/i,\n  audit: /audit|sign-in|provisioning|deleted/i,\n  health: /serviceHealth|messageCenter/i,\n  response: /disable-user|revoke|block|reset|confirm|dismiss/i,\n  // ... more categories\n};\n```\n\n资料来源：[src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Verification Commands\n\nVerify tool registration and permissions:\n\n```bash\n# List all registered tools\nnode dist/index.js --list-tools\n\n# List required Graph permissions\nnode dist/index.js --list-permissions\n\n# Verify a specific preset\nnode dist/index.js --preset security --list-tools\n\n# Verify specific risk level tools\nnode dist/index.js --max-risk-level medium --list-tools\n```\n\n资料来源：[docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n\n## Security Review Process\n\nAll security-relevant changes undergo review per documented processes:\n\n| Review Date | Scope |\n|-------------|-------|\n| 2026-04-20 | Initial security review — SEC-G01, SEC-G02, SEC-G03 implementation |\n| 2026-04-25 | Follow-up review — permission scope reductions, `dismiss-risky-users` elevation |\n\nThe review identified and addressed:\n- Over-privileged permission scopes reduced to least-privilege\n- `dismiss-risky-users` elevated from `medium` to `high`\n- Query string sanitization to prevent secret leakage\n- Dead dependency removal\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)  \n资料来源：[docs/SECURITY_REVIEW_2026-04-25.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-25.md)\n\n## Best Practices for Operators\n\n1. **Start with `--max-risk-level medium`** — Only escalate when high-risk tools are required\n2. **Dry-run before high/critical operations** — Always read the target object first\n3. **Out-of-band confirmation for critical** — Use ticketing systems for delete/wipe operations\n4. **Review permissions quarterly** — Run `--list-permissions` to audit required scopes\n5. **Never run without understanding** — Each `references/usecase-*.md` file documents tool risk levels before use\n\n## Module Dependencies\n\nThe security model is implemented in pure, testable modules:\n\n| Module | Purpose |\n|--------|---------|\n| `src/risk-level.ts` | Risk level computation and comparison |\n| `src/user-token-authorization.ts` | User token validation |\n| `src/jwks-stale-cache.ts` | JWKS caching for token validation |\n| `src/upstream-error.ts` | Graph API error handling |\n| `src/untrusted-envelope.ts` | Nonce envelope wrapping |\n\nAll modules have unit test coverage (51 tests covering all security-critical paths).\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n---\n\n<a id='azure-deployment-security'></a>\n\n## Azure Deployment Security\n\n### 相关页面\n\n相关主题：[Security Model and Risk Classification](#security-model), [HTTP Transport and Deployment](#http-deployment), [Docker and Container Deployment](#docker-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [docs/AZURE_DEPLOYMENT_SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/AZURE_DEPLOYMENT_SECURITY.md)\n- [infra/main.bicep](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/infra/main.bicep)\n- [infra/parameters.example.jsonc](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/infra/parameters.example.jsonc)\n- [docs/CYSEC-1420/graph-permissions-baseline.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/graph-permissions-baseline.md)\n- [docs/CYSEC-1420/network-design-gate.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/network-design-gate.md)\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n- [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n</details>\n\n# Azure Deployment Security\n\n## Overview\n\nThe ms-365-admin-mcp-server provides a comprehensive Azure deployment security model designed to protect Microsoft 365 administrative operations. This documentation covers the security controls, network architecture, secret management, and compliance considerations for deploying the server in Azure Container Apps.\n\n## Core Security Principles\n\n### Defense in Depth\n\nThe security architecture implements multiple layers of protection:\n\n1. **Network Isolation** — Private networking with VNet integration and egress restrictions\n2. **Secret Management** — Azure Key Vault for all sensitive credentials\n3. **Authentication** — Microsoft Identity (MSAL) with client credentials flow\n4. **Authorization** — Role-based access with MCP permission scopes\n5. **Audit** — Comprehensive logging with PII redaction capabilities\n6. **Certificate Authentication** — Preference for certificates over client secrets\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n## Network Architecture\n\n### Private Endpoint Configuration\n\nThe deployment uses private networking to restrict communication paths. All egress traffic is routed through Azure Firewall or Network Security Groups (NSGs) to enforce granular control.\n\n```mermaid\ngraph TD\n    subgraph \"Azure Cloud\"\n        subgraph \"Virtual Network\"\n            CA[\"Container Apps<br/>Environment\"]\n            VNET[\"VNet Integration\"]\n        end\n        subgraph \" egress\"\n            FW[\"Azure Firewall\"]\n            PE[\"Private Endpoint<br/>Key Vault\"]\n        end\n    end\n    \n    subgraph \"Microsoft Services\"\n        AAD[\"Microsoft Identity<br/>login.microsoftonline.com\"]\n        GRAPH[\"Microsoft Graph<br/>graph.microsoft.com\"]\n    end\n    \n    CA --> VNET\n    VNET --> FW\n    FW --> AAD\n    FW --> GRAPH\n    CA --> PE\n    PE --> KV[\"Key Vault\"]\n    \n    style CA fill:#e1eff6\n    style FW fill:#fff3cd\n    style KV fill:#d4edda\n```\n\n### Required Egress Endpoints\n\nThe server requires outbound access to the following Microsoft endpoints:\n\n| Endpoint | Purpose | Sovereign Equivalent |\n|----------|---------|----------------------|\n| `login.microsoftonline.com` | Microsoft Entra authentication | `login.partner.microsoftonline.cn` |\n| `graph.microsoft.com` | Microsoft Graph API | `microsoftgraph.chinacloudapi.cn` |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md) | [docs/CYSEC-1420/network-design-gate.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/network-design-gate.md)\n\n### HTTP Mode Security\n\nWhen exposing the server via HTTP transport, strict controls apply:\n\n- **Never** expose on `0.0.0.0` without a reverse proxy enforcing TLS\n- **Always** pass `--allowed-clients` with the minimum set of Entra app IDs\n- Use `--allow-any-tenant-user` only when explicitly intended (defaults to deny)\n\n```bash\n# Example secure HTTP startup\nnode dist/index.js \\\n  --transport streamable-http \\\n  --allowed-clients \"app-id-1,app-id-2\" \\\n  --public-url https://mcp.example.com \\\n  --log-redact-upn\n```\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n## Secret Management\n\n### Azure Key Vault Integration\n\nAll sensitive credentials **must** be stored in Azure Key Vault rather than environment files or source control.\n\n| Secret Name | Description | Required |\n|-------------|-------------|----------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Entra application client ID | Yes |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Client secret (if not using cert) | Conditional |\n| `MS365_ADMIN_MCP_KEYVAULT_URL` | Key Vault base URL | Yes |\n| `AZURE_STORAGE_ACCOUNT_NAME` | Table storage for OAuth state | OAuth mode only |\n| `AZURE_STORAGE_TABLE_NAME` | Table name for PKCE state | OAuth mode only |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Certificate Authentication\n\nThe deployment **prefers** certificate-based authentication over client secrets:\n\n```mermaid\ngraph LR\n    A[\"Key Vault<br/>Certificate\"] --> B[\"Managed Identity\"]\n    B --> C[\"Container Apps<br/>Environment\"]\n    C --> D[\"Microsoft Graph<br/>API\"]\n```\n\nBenefits of certificate authentication:\n- No secret rotation required (certificate validity managed separately)\n- Federated credentials eliminate client secret storage entirely\n- Workload identity federation supported for GitHub Actions deployments\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Secret Rotation Policy\n\n| Credential Type | Rotation Interval |\n|----------------|-------------------|\n| Client Secrets | 90 days |\n| Certificates | Per certificate validity period |\n| Federated Credentials | No rotation required |\n\n## Identity and Access Management\n\n### Authentication Modes\n\nThe server supports two authentication modes:\n\n1. **Application Credentials (Default)** — Client ID + Secret/Certificate\n2. **OAuth Mode** — Full OAuth 2.0 authorization code flow with PKCE\n\n```mermaid\ngraph TD\n    subgraph \"OAuth Mode Flow\"\n        U[\"User/Browser\"] --> |\"1. GET /authorize\"| MCP[\"MCP Server\"]\n        MCP --> |\"2. Redirect to Entra\"| AAD[\"Microsoft Entra\"]\n        U --> |\"3. User Authentication\"| AAD\n        AAD --> |\"4. Auth Code + PKCE\"| MCP\n        MCP --> |\"5. Token Request\"| AAD\n        AAD --> |\"6. Access Token\"| MCP\n    end\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### OAuth Storage\n\nOAuth mode requires Azure Table Storage for PKCE state management:\n\n| Component | Configuration |\n|-----------|--------------|\n| Storage Account | Standard_LRS, TLS 1.2, OAuth-only authentication |\n| Table Name | `oauthstate` (configurable) |\n| Access | Managed Identity with Storage Table Data Contributor role |\n| PKCE Lifetime | 10 minutes |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Graph API Permissions\n\n### Least Privilege Model\n\nThe deployment follows a least-privilege approach with application permissions scoped to required operations only.\n\n资料来源：[docs/CYSEC-1420/graph-permissions-baseline.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/graph-permissions-baseline.md)\n\n### Application Permission Categories\n\n| Category | Permission Type | Example Operations |\n|----------|----------------|-------------------|\n| Directory | Read.All | list-users, list-groups |\n| Device Management | ReadWrite.All | update-device, wipe-managed |\n| Policy | ReadWrite.All | create-conditional-access-policy |\n| Security | Read.All / ReadWrite.All | list-risky-users, confirm-compromised |\n\n### Required Read Permissions (Default)\n\n```\nDirectory.Read.All\nGroup.Read.All\nUser.Read.All\nDevice.Read.All\nDeviceManagementRBAC.Read.All\nPolicy.Read.All\nAuditLog.Read.All\n```\n\n资料来源：[agent-skills/ms365-admin-mcp/references/graph-permissions.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/graph-permissions.md)\n\n## Logging and Monitoring\n\n### PII-Aware Logging\n\nThe server provides built-in PII redaction for logs forwarded to SIEM systems:\n\n```bash\nnode dist/index.js --log-redact-upn\n```\n\nThis flag replaces UPN values in log lines with deterministic SHA-256 prefixes:\n\n```\nOriginal: \"Authenticated user alice@example.com\"\nRedacted: \"Authenticated user sha256:1a2b3c4d5e6f...\"\n```\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Audit Trail\n\nEnable verbose logging for complete audit trails:\n\n```bash\nnode dist/index.js -v  # Enable verbose logging\n```\n\nThe following audit operations are available via the MCP tools:\n\n| Tool | Purpose |\n|------|---------|\n| `list-directory-audits` | Directory sign-in and activity logs |\n| `list-intune-audit-events` | Intune device management events |\n| `list-sign-ins` | Conditional Access and sign-in logs |\n\n### Log Storage Configuration\n\nThe Winston logger uses a configurable log directory:\n\n```bash\nexport MS365_ADMIN_MCP_LOG_DIR=/var/log/ms365-admin-mcp\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Bicep Infrastructure Deployment\n\n### Deployment Architecture\n\n```mermaid\ngraph TD\n    subgraph \"Resource Group\"\n        subgraph \"Networking\"\n            VNET[\"Virtual Network\"]\n            SUBNET[\"Subnet\"]\n            FW[\"Azure Firewall\"]\n        end\n        subgraph \"Compute\"\n            ACA[\"Container Apps<br/>Environment\"]\n            APP[\"MCP Server<br/>Container\"]\n        end\n        subgraph \"Data\"\n            KV[\"Key Vault\"]\n            SA[\"Storage Account\"]\n            TBL[\"Table Storage\"]\n        end\n        subgraph \"Identity\"\n            UAMI[\"User-Assigned<br/>Managed Identity\"]\n        end\n    end\n    \n    APP --> SUBNET\n    APP --> KV\n    APP --> SA\n    APP --> UAMI\n    UAMI --> KV\n    UAMI --> SA\n    FW --> VNET\n    \n    style APP fill:#e1eff6\n    style KV fill:#d4edda\n    style FW fill:#fff3cd\n```\n\n### Required Bicep Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `allowedClients` | array | Yes | List of Entra app IDs permitted to connect |\n| `tags` | object | Yes | Tags propagated to all resources |\n| `acrLoginServer` | string | Yes | Azure Container Registry login server |\n| `location` | string | Yes | Azure region |\n| `environmentName` | string | Yes | Deployment environment |\n| `maxReplicas` | int | No | Maximum container replicas (default: 1) |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Storage Account Configuration\n\nThe Bicep template provisions a secure storage account for OAuth PKCE state:\n\n```json\n{\n  \"sku\": {\n    \"name\": \"Standard_LRS\"\n  },\n  \"properties\": {\n    \"minimumTlsVersion\": \"TLS1_2\",\n    \"allowSharedKeyAccess\": false,\n    \"defaultToOAuthAuthentication\": true\n  }\n}\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Private Container Registry\n\nThe deployment supports pulling images from private Azure Container Registry:\n\n```bicep\nregistries: {\n  loginServer: acrLoginServer\n  identity: uamiResourceId\n  passwordSecretRef: ''\n}\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Deployment Checklist\n\n### Pre-Deployment Security Review\n\n- [ ] Store all secrets in Azure Key Vault\n- [ ] Configure allowed clients (minimum Entra app IDs)\n- [ ] Enable PII redaction for log forwarding\n- [ ] Configure network segmentation with allowed egress endpoints\n- [ ] Apply Conditional Access to service principal (geofencing, sign-in risk)\n- [ ] Review and minimize Graph API permissions\n\n### Deployment Validation\n\n- [ ] Verify HTTP mode not exposed on `0.0.0.0`\n- [ ] Confirm managed identity access to Key Vault\n- [ ] Test OAuth PKCE flow with Table Storage\n- [ ] Validate verbose logging output\n- [ ] Verify allowed clients can connect\n\n### Post-Deployment Monitoring\n\n- [ ] Monitor `list-sign-ins` for anomalies on service principal\n- [ ] Enable directory audit log forwarding to SIEM\n- [ ] Set up alerts for critical tool invocations\n- [ ] Review access reviews for application owners\n\n## Migration Guide\n\n### From Version 0.1.0 to 0.2.x\n\n1. **Required**: Add `--allowed-clients` parameter (HTTP mode refuses startup without it)\n2. **Required for OAuth mode**: Add `--public-url` if behind reverse proxy\n3. **Review**: Check `--allow-any-tenant-user` if relying on implicit behavior\n4. **Optional**: Update Bicep to add Storage Account for OAuth PKCE bridge\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Scaling Considerations\n\n- Single replica is the default\n- For multi-replica deployments, externalize PKCE storage first\n- Run `az deployment group create` with updated Bicep for Storage Account provisioning\n\n## Related Documentation\n\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md) — Core security practices\n- [docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md) — Application registration guide\n- [docs/CYSEC-1420/](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/) — Security compliance documentation\n\n---\n\n<a id='http-deployment'></a>\n\n## HTTP Transport and Deployment\n\n### 相关页面\n\n相关主题：[Docker and Container Deployment](#docker-deployment), [Azure Deployment Security](#azure-deployment-security), [Configuration Reference](#configuration)\n\n<details>\n<summary>Relevant Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\n- [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- [src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n</details>\n\n# HTTP Transport and Deployment\n\nThe ms-365-admin-mcp-server supports multiple transport mechanisms for exposing Microsoft 365 administration capabilities to MCP clients. The HTTP transport layer forms the foundation for remote deployments, OAuth-based authentication flows, and secure communication between clients and the server.\n\n## Overview\n\nThe server implements a flexible HTTP transport architecture that supports both local stdio connections and remote HTTP-based deployments. This dual-mode design enables the server to operate as a local desktop companion (via Claude Desktop) or as a scalable cloud-hosted service accessible to multiple users simultaneously.\n\n### Transport Modes\n\n| Transport Mode | Use Case | Authentication |\n|---------------|----------|----------------|\n| stdio | Local Claude Desktop integration | Direct client credentials |\n| StreamableHTTP | Claude.ai Web, Claude Desktop remote | OAuth 2.0 + PKCE proxy |\n| Remote HTTP | Containerized deployments (Azure Container Apps) | Device code bootstrap |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## HTTP Server Architecture\n\n### Core Components\n\nThe HTTP transport is implemented across several interconnected modules:\n\n| Module | Responsibility |\n|--------|----------------|\n| `http-server.ts` | Main HTTP server, routing, middleware, security headers |\n| `oauth-proxy.ts` | OAuth 2.0 discovery, PKCE proxy, Entra ID integration |\n| `token-validator.ts` | JWT validation, tenant verification, scope enforcement |\n| `auth-bootstrap.ts` | RFC 8628 device_code flow for remote authentication |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Request Flow\n\n```mermaid\ngraph TD\n    A[MCP Client] --> B[HTTP Server<br/>src/http-server.ts]\n    B --> C{Auth Mode}\n    C -->|OAuth| D[OAuth Proxy<br/>src/oauth-proxy.ts]\n    C -->|Device Code| E[Auth Bootstrap<br/>src/auth-bootstrap.ts]\n    C -->|Client Creds| F[Direct Auth]\n    D --> G[Token Validator<br/>src/token-validator.ts]\n    E --> G\n    F --> G\n    G --> H{Valid Token?}\n    H -->|Yes| I[Tool Executor]\n    H -->|No| J[401/403 Response]\n    I --> K[Microsoft Graph API]\n```\n\n## OAuth 2.0 Proxy Mode\n\nThe `--oauth-mode` flag enables Entra-backed OAuth 2.0 + PKCE proxy endpoints, allowing Claude Desktop, Claude Code, and Claude.ai Web to authenticate users through Microsoft Entra ID without client-side configuration beyond the server URL.\n\n### Discovery Endpoints\n\n| Endpoint | Purpose |\n|----------|---------|\n| `GET /.well-known/oauth-authorization-server` | OAuth 2.0 authorization server metadata |\n| `GET /.well-known/oauth-protected-resource` | Protected resource metadata for client discovery |\n| `GET /.well-known/microsoft-hosted-userpolicy` | Microsoft-hosted user policy information |\n\n资料来源：[CHANGELOG.md:73-75](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Authentication Headers\n\nThe server implements proper WWW-Authenticate header responses:\n\n| Scenario | Header Response |\n|----------|-----------------|\n| Missing token | `WWW-Authenticate: Bearer resource_metadata=\"...\"` |\n| Invalid token | `WWW-Authenticate: Bearer resource_metadata=\"...\", error=\"invalid_token\"` |\n\nWithout these headers, Claude clients could not discover the protected-resource metadata and would surface `Authorization with the MCP server failed` before ever reaching `/authorize`.\n\n资料来源：[CHANGELOG.md:81-85](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Required Configuration\n\nWhen running in OAuth mode, deployments must specify:\n\n```bash\n--oauth-mode\n--public-url https://<fqdn>  # Required when behind a reverse proxy\n--required-user-scopes <scopes>  # If callers request a specific scope\n```\n\nDeployments relying on the implicit \"any authenticated user\" behavior must add `--allow-any-tenant-user` to their startup command.\n\n资料来源：[CHANGELOG.md:34-37](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Remote HTTP Server with Device Code Authentication\n\nThe `ms-365-admin-mcp-auth` bootstrap tool implements RFC 8628 device_code flow to pre-seed the mcp-remote token cache, allowing Claude Desktop/Code to skip the browser flow for remote MCP servers.\n\n### Authentication Flow\n\n```mermaid\nsequenceDiagram\n    participant Client as Claude Desktop/Code\n    participant Auth as ms-365-admin-mcp-auth\n    participant Server as MCP Server (Remote)\n    participant Entra as Microsoft Entra ID\n\n    Client->>Auth: ms-365-admin-mcp-auth --server <url>\n    Auth->>Entra: POST /devicecode\n    Entra-->>Auth: device_code, verification_uri\n    Auth->>Client: Display verification URL\n    loop Poll until authenticated\n        Auth->>Entra: POST /token (device_code)\n        Entra-->>Auth: pending | success\n    end\n    Auth->>Server: Cached tokens stored locally\n    Client->>Server: MCP requests (uses cached tokens)\n```\n\n### Command Line Interface\n\n```bash\nms-365-admin-mcp-auth [options]\n\nRequired Options:\n  -s, --server <url>    MCP server URL (with or without /mcp suffix)\n\nOptions:\n  --scope <scope>       Override OAuth scope (defaults to server metadata)\n  --cache-dir <path>    Override cache directory\n  --timeout <minutes>   Authentication timeout (default: 8 minutes)\n```\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n\n### Token Cache Location\n\nTokens are cached at:\n```\n~/.mcp-auth/mcp-remote-<version>/\n├── <hash>_client_info.json\n└── <hash>_tokens.json\n```\n\nThe cache key is computed as `md5(serverUrl)`, matching mcp-remote's `getServerUrlHash` function exactly. File permissions are set to mode `0600` for security.\n\n资料来源：[CHANGELOG.md:56-58](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Exit Codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success |\n| 1 | Usage error |\n| 2 | Network failure |\n| 3 | Access denied |\n| 4 | Timeout |\n\nThese exit codes facilitate Docker and CI wrapper scripting.\n\n资料来源：[CHANGELOG.md:63-65](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Security Configuration\n\n### Security Headers\n\nAll HTTP responses include the following security headers:\n\n| Header | Value | Purpose |\n|--------|-------|---------|\n| `X-Content-Type-Options` | `nosniff` | Prevent MIME type sniffing |\n| `X-Frame-Options` | `DENY` | Prevent clickjacking |\n| `Cache-Control` | `no-store` | Prevent sensitive data caching |\n| Content-Security-Policy | `default-src 'none'` | Restrict resource loading |\n\n### Rate Limiting\n\nThe Express server is configured with `trust proxy` set to `1` to properly handle `X-Forwarded-For` headers from Azure Container Apps or reverse proxies. This prevents the `express-rate-limit` validator from incorrectly blocking requests due to unexpected forwarded headers.\n\n资料来源：[CHANGELOG.md:88-91](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Request Validation\n\n| Validation Type | Implementation |\n|-----------------|----------------|\n| Body size limit | 100 KB maximum |\n| Path traversal | Parameters checked for `../`, `/`, `\\`, `?`, `#`, `&` |\n| ReDoS protection | `--enabled-tools` regex capped at 500 characters |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Token Validation\n\nThe token validator enforces:\n\n1. **Tenant isolation**: Tenant `common` is rejected; single-tenant mode required for client credentials\n2. **Scope verification**: Tokens must include required user scopes\n3. **Audience validation**: Token audience must match server configuration\n4. **Error logging**: Failed validations log `aud`, `tid`, and `upn` for debugging\n\n### Risk Classification for Write Operations\n\nThe HTTP transport integrates with the risk-level system to enforce write operation restrictions:\n\n| Risk Level | Description | Enforcement |\n|------------|-------------|-------------|\n| `low` | Read-only operations, reports | Allowed by default |\n| `medium` | Reversible mutations, single entity | Requires `--allow-writes` |\n| `high` | Significant impact, credential changes | Requires explicit cap |\n| `critical` | Irreversible or tenant-wide | Requires `--allow-critical` |\n\n资料来源：[src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Deployment Patterns\n\n### Local Deployment (Stdio)\n\nFor local use with Claude Desktop, the server operates in stdio mode:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@okapi-ca/ms-365-admin-mcp-server\"]\n    }\n  }\n}\n```\n\n### Remote HTTP Deployment (Container Apps)\n\n```bash\ndocker run -d \\\n  --name mcp-server \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=<client-id> \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=<secret> \\\n  -e MS365_ADMIN_MCP_TENANT_ID=<tenant-id> \\\n  -p 3000:3000 \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### OAuth-Enabled Deployment\n\n```bash\nnpm start -- \\\n  --oauth-mode \\\n  --public-url https://mcp.contoso.com/mcp \\\n  --allow-any-tenant-user \\\n  --max-risk-level medium\n```\n\n## Command Line Options\n\n### Transport Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `--oauth-mode` | Enable OAuth 2.0 proxy | Disabled |\n| `--public-url` | Public URL for OAuth callbacks | Required in OAuth mode |\n| `--required-user-scopes` | Scopes required in user tokens | Empty (any scope) |\n| `--allow-any-tenant-user` | Allow users from any tenant | Disabled |\n| `--cache-dir` | Override token cache directory | `~/.mcp-auth/mcp-remote-<ver>` |\n\n### Security Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `--allow-writes` | Allow write operations up to medium risk | Disabled |\n| `--allow-critical` | Allow critical write operations | Disabled |\n| `--max-risk-level` | Maximum allowed risk level | `medium` |\n\n### Other Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `--enabled-tools` | Regex pattern to limit available tools | All tools |\n| `--preset` | Enable a tool category preset | None |\n| `--list-tools` | List available tools and exit | - |\n| `--list-permissions` | List required permissions and exit | - |\n\n## Troubleshooting\n\n### Common Issues\n\n| Symptom | Cause | Solution |\n|---------|-------|----------|\n| `Server disconnected` | Network connectivity or proxy issue | Check `docs/TROUBLESHOOTING.md` |\n| Platform SSO errors | Conditional Access policy blocking | Review device_code flow documentation |\n| `ERR_ERL_UNEXPECTED_X_FORWARDED_FOR` | Rate limiter not trusting proxy | Ensure `--public-url` is set behind reverse proxy |\n\n### Debugging Steps\n\n1. Verify `--public-url` is set correctly when behind a reverse proxy\n2. Check that Entra app registration exposes the `access_as_user` scope\n3. Confirm `--required-user-scopes` matches the scopes your callers request\n4. Review logs for token validation failures (includes `aud`, `tid`, `upn`)\n\n## See Also\n\n- [Authentication and Authorization](src/auth.ts)\n- [Token Validation](src/token-validator.ts)\n- [Risk Model](docs/RISK_MODEL.md)\n- [Troubleshooting Guide](docs/TROUBLESHOOTING.md)\n\n---\n\n<a id='docker-deployment'></a>\n\n## Docker and Container Deployment\n\n### 相关页面\n\n相关主题：[HTTP Transport and Deployment](#http-deployment), [Azure Deployment Security](#azure-deployment-security), [Installation Guide](#installation)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [Dockerfile](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/Dockerfile)\n- [.dockerignore](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/.dockerignore)\n- [src/storage/index.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/index.ts)\n- [src/storage/oauth-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/oauth-storage.ts)\n- [src/storage/memory-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/memory-storage.ts)\n- [src/storage/table-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/table-storage.ts)\n</details>\n\n# Docker and Container Deployment\n\nThis page documents the Docker and container deployment architecture for the Microsoft 365 Admin MCP Server. The server is published to both npm as `@okapi-ca/ms-365-admin-mcp-server` and to GitHub Container Registry (GHCR) as `ghcr.io/okapi-ca/ms-365-admin-mcp-server`, enabling flexible deployment options for enterprise environments.\n\n## Overview\n\nThe MCP server supports containerized deployment through Docker, which is essential for production environments requiring isolation, scalability, and consistent runtime behavior. Container deployment enables integration with enterprise systems including Azure Container Instances, Azure Kubernetes Service, and on-premises Docker infrastructure.\n\n### Deployment Modes\n\nThe server operates in two primary modes:\n\n| Mode | Transport | Use Case |\n|------|-----------|----------|\n| **stdio** | Standard I/O | Local development, MCP Inspector, direct client integration |\n| **HTTP** | HTTP/SSE | Production deployments, remote client access, enterprise integration |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Docker Configuration\n\n### Base Image and Runtime\n\nThe Dockerfile configures a Node.js runtime environment optimized for the MCP server's requirements. The image uses a multi-stage build approach to minimize the final image size while ensuring all dependencies are properly installed.\n\n```dockerfile\n# Reference: Dockerfile structure from repository conventions\nFROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --only=production\nCOPY dist/ ./dist/\nCMD [\"node\", \"dist/index.js\"]\n```\n\n资料来源：[Dockerfile](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/Dockerfile)\n\n### Security Configuration\n\nThe container runs as a non-root user to comply with security best practices and enterprise compliance requirements. This prevents privilege escalation attacks and limits the blast radius of potential container compromises.\n\n> Non-root Docker user\n> - Security headers: `X-Content-Type-Options`, `X-Frame-Options: DENY`, `Cache-Control: no-store`, CSP `default-src 'none'`\n> - Body size limit: 100 KB\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Build Arguments and Environment Variables\n\n| Variable | Purpose | Required |\n|----------|---------|----------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Azure AD application client ID | Yes |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Application secret | Yes |\n| `MS365_ADMIN_MCP_TENANT_ID` | Azure AD tenant identifier | Yes |\n| `NODE_ENV` | Runtime environment (`production`) | Recommended |\n| `MS365_ADMIN_MCP_LOG_DIR` | Log output directory | Optional |\n\n## Persistent Storage Architecture\n\nThe server requires persistent storage for OAuth tokens and authentication state. The storage implementation supports multiple backends to accommodate different deployment scenarios.\n\n```mermaid\ngraph TD\n    A[MCP Server] --> B[Storage Abstraction Layer]\n    B --> C[Memory Storage]\n    B --> D[File-based Storage]\n    B --> E[Azure Table Storage]\n    \n    D --> F[~/.mcp-auth/]\n    E --> G[Azure Table]\n    \n    C -->|Ephemeral| H[Pod/Container Restart]\n    D -->|Persistent| I[Volume Mount]\n    E -->|Distributed| J[Multi-instance]\n```\n\n资料来源：[src/storage/index.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/index.ts)\n\n### Storage Backend Selection\n\n| Backend | Use Case | Persistence | Multi-instance |\n|---------|----------|-------------|----------------|\n| **Memory** | Local dev, single-use | ❌ Lost on restart | ❌ Not supported |\n| **File-based** | Single instance, Docker with volumes | ✅ Survives restart | ❌ Not recommended |\n| **Azure Table** | Production multi-instance | ✅ Distributed | ✅ Recommended |\n\n资料来源：[src/storage/oauth-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/oauth-storage.ts)\n\n### File-based Storage Details\n\nWhen using file-based storage, the server creates a directory structure under `~/.mcp-auth/mcp-remote-<version>/` with the following files:\n\n| File | Purpose | Permissions |\n|------|---------|-------------|\n| `<hash>_client_info.json` | Client registration metadata | 0600 |\n| `<hash>_tokens.json` | OAuth tokens (access, refresh) | 0600 |\n\nThe cache key uses `md5(serverUrl)` matching `mcp-remote`'s `getServerUrlHash` implementation exactly, ensuring compatibility with existing tooling.\n\n> Cache key = `md5(serverUrl)`, matching `mcp-remote`'s `getServerUrlHash` exactly; a regression test locks the hash against the known production URL.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Azure Table Storage Backend\n\nFor production deployments requiring high availability and horizontal scaling, the server supports Azure Table Storage as a distributed state backend:\n\n```typescript\n// Storage interface contract\nexport interface OAuthStorage {\n  getClientInfo(serverUrl: string): Promise<ClientInfo | null>;\n  saveClientInfo(serverUrl: string, info: ClientInfo): Promise<void>;\n  getTokens(serverUrl: string): Promise<Tokens | null>;\n  saveTokens(serverUrl: string, tokens: Tokens): Promise<void>;\n  deleteTokens(serverUrl: string): Promise<void>;\n}\n```\n\n资料来源：[src/storage/table-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/table-storage.ts)\n\n## Volume Mounts and Configuration\n\n### Host Path Bindings\n\nFor Docker deployments, the server honors the `--cache-dir` CLI flag and `MCP_REMOTE_CONFIG_DIR` environment variable to enable custom storage locations. This is essential for:\n\n- **Docker bind mounts**: Map host directories to container paths\n- **Multi-user setups**: Shared configuration directories\n- **Persistent logs**: Surviving container recreation\n\n> `--cache-dir` + `MCP_REMOTE_CONFIG_DIR` env var honoured, so Docker bind mounts and multi-user setups work without patches.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Recommended Volume Structure\n\n```yaml\nversion: '3.8'\nservices:\n  mcp-server:\n    image: ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n    volumes:\n      - ./config:/config:ro        # Application configuration\n      - mcp-auth:/root/.mcp-auth  # Persistent OAuth state\n      - mcp-logs:/root/.ms365-admin-mcp/logs  # Application logs\n    environment:\n      - MS365_ADMIN_MCP_CLIENT_ID=${CLIENT_ID}\n      - MS365_ADMIN_MCP_CLIENT_SECRET=${CLIENT_SECRET}\n      - MS365_ADMIN_MCP_TENANT_ID=${TENANT_ID}\n      - MCP_REMOTE_CONFIG_DIR=/config\n\nvolumes:\n  mcp-auth:\n  mcp-logs:\n```\n\n## Logging Configuration\n\nThe Winston logger default behavior was updated to support containerized environments where the standard home directory may not be accessible:\n\n> Winston logger now uses `MS365_ADMIN_MCP_LOG_DIR=/tmp/...` by default in the Bicep template, avoiding `EACCES` against `/nonexistent/.ms365-admin-mcp/logs` when the image runs as a rootless user without a home directory\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Log Directory Configuration\n\n| Environment | Default Path | Notes |\n|-------------|--------------|-------|\n| Bicep/Azure | `/tmp/ms365-admin-mcp/logs` | Avoids home directory issues |\n| Standard | `~/.ms365-admin-mcp/logs` | User's home directory |\n| Custom | Set via `MS365_ADMIN_MCP_LOG_DIR` | Override default |\n\n## Azure Deployment (Bicep)\n\nFor Azure-native deployments, the project includes Bicep templates supporting:\n\n### Required Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `allowedClients` | array | Required; HTTP mode refuses to start without it |\n| `tags` | object | Propagated to every resource; required by org-level policies |\n| `acrLoginServer` | string | Azure Container Registry login server |\n| `location` | string | Azure region |\n\n> `allowedClients` Bicep parameter (required; HTTP mode refuses to start without it)\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Container Registry Integration\n\nThe Bicep template configures Azure Container Registry pull access using a User-Assigned Managed Identity (UAMI):\n\n```bicep\nresource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = {\n  name: acrLoginServer\n}\n\nresource uami 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {\n  name: 'mcp-server-uami'\n}\n\nresource acrPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {\n  name: guid(acr.id, uami.id, 'acrpull')\n  scope: acr\n  properties: {\n    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')\n    principalId: uami.properties.principalId\n  }\n}\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Exit Codes\n\nThe server defines specific exit codes for container orchestration and CI/CD integration:\n\n| Code | Meaning | Use Case |\n|------|---------|----------|\n| 0 | Success | Normal operation, clean shutdown |\n| 1 | Usage error | Invalid arguments, missing required parameters |\n| 2 | Network error | Azure AD connectivity failure |\n| 3 | Access denied | Authentication/authorization failure |\n| 4 | Timeout | Request timeout during Graph API calls |\n\n> Documented exit codes (0 ok, 1 usage, 2 network, 3 denied, 4 timeout) for Docker / CI wrappers.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## HTTP Server Configuration\n\nWhen deployed in HTTP mode, the server exposes an HTTP endpoint with specific security configurations:\n\n### Security Headers\n\n| Header | Value | Purpose |\n|--------|-------|---------|\n| `X-Content-Type-Options` | `nosniff` | Prevent MIME type sniffing |\n| `X-Frame-Options` | `DENY` | Prevent clickjacking |\n| `Cache-Control` | `no-store` | Prevent sensitive data caching |\n| CSP | `default-src 'none'` | Content Security Policy |\n\n### Request Validation\n\n- **Body size limit**: 100 KB maximum\n- **Path parameter validation**: Rejects traversal patterns (`../`, `/`, `\\`, `?`, `#`, `&`) for `skipEncoding` parameters\n- **ReDoS protection**: `--enabled-tools` regex capped at 500 characters\n\n> Path parameter validation against traversal (`../`, `/`, `\\`, `?`, `#`, `&`) for `skipEncoding` params\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n## CI/CD Integration\n\n### Best-Effort Clipboard\n\nThe server includes clipboard functionality for copying authentication codes during device code flow. This behavior is automatically disabled in CI environments:\n\n```typescript\nconst clipboard = process.env.CI !== 'true' && process.stdout.isTTY\n  ? platformClipboard()\n  : null;\n```\n\n> Best-effort clipboard copy (`pbcopy` / `clip` / `wl-copy` / `xclip`), auto-disabled under `CI=true` or non-TTY.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Environment Detection\n\n| Variable | Detection | Behavior |\n|----------|-----------|----------|\n| `CI=true` | CI pipeline | Disable clipboard |\n| `non-TTY` | Background process | Disable clipboard |\n| `CI=undefined` + TTY | Interactive shell | Enable clipboard |\n\n## Troubleshooting\n\n### Common Deployment Issues\n\n| Issue | Cause | Resolution |\n|-------|-------|------------|\n| `EACCES` on logs | Home directory inaccessible | Set `MS365_ADMIN_MCP_LOG_DIR=/tmp/...` |\n| Authentication failures | Missing `allowedClients` | Configure Bicep parameter |\n| Token loss on restart | Memory storage selected | Use file or table storage backend |\n| Slow cold starts | Large image size | Use multi-stage build, `--only=production` |\n\n### Docker Bind Mount Patterns\n\nFor Persistent storage, use named volumes or host bind mounts:\n\n```bash\n# Named volumes (recommended)\ndocker run -v mcp-auth:/root/.mcp-auth ghcr.io/okapi-ca/ms-365-admin-mcp-server\n\n# Host bind mount\ndocker run -v /data/mcp-config:/root/.mcp-auth ghcr.io/okapi-ca/ms-365-admin-mcp-server\n```\n\n> `docs/TROUBLESHOOTING.md` — full section covering Docker bind-mount patterns, Conditional Access caveat\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Development with Docker\n\n### Building Locally\n\n```bash\n# Clone repository\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\n\n# Install dependencies\nnpm install\n\n# Generate client from OpenAPI spec\nnpm run generate\n\n# Build TypeScript\nnpm run build\n\n# Build Docker image\ndocker build -t ms-365-admin-mcp-server:latest .\n```\n\n### Running with Docker Compose\n\n```bash\n# Create .env file\ncat > .env << EOF\nMS365_ADMIN_MCP_CLIENT_ID=your-client-id\nMS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret\nMS365_ADMIN_MCP_TENANT_ID=your-tenant-id\nEOF\n\n# Start server\ndocker-compose up -d\n\n# View logs\ndocker-compose logs -f\n```\n\n## See Also\n\n- [Architecture Documentation](./ARCHITECTURE.md)\n- [Security Model](./SECURITY.md)\n- [HTTP Deployment](./HTTP_DEPLOYMENT.md)\n- [Troubleshooting Guide](./TROUBLESHOOTING.md)\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：okapi-ca/ms-365-admin-mcp-server\n\n摘要：发现 9 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n\n## 5. 安全/权限坑 · 来源证据：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n- 对用户的影响：可能增加新用户试用和生产接入成本。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_103cf7f40efc40e99adfa2eb14d9717e | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/70 | 来源讨论提到 node 相关条件，需在安装/试用前复核。\n\n## 6. 安全/权限坑 · 来源证据：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n- 对用户的影响：可能影响授权、密钥配置或安全边界。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_6ede43fd3f7247e0981524934656dbeb | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71 | 来源类型 github_issue 暴露的待验证使用条件。\n\n## 7. 安全/权限坑 · 来源证据：SEC-005: Express body parser runs before authentication and rate limiting\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-005: Express body parser runs before authentication and rate limiting\n- 对用户的影响：可能影响授权、密钥配置或安全边界。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_e53044f4bde148d7882ccf83273f1e22 | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/72 | 来源类型 github_issue 暴露的待验证使用条件。\n\n## 8. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | issue_or_pr_quality=unknown\n\n## 9. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | release_recency=unknown\n\n<!-- canonical_name: okapi-ca/ms-365-admin-mcp-server; human_manual_source: deepwiki_human_wiki -->\n",
      "markdown_key": "ms-365-admin-mcp-server",
      "pages": "draft",
      "source_refs": [
        {
          "evidence_id": "github_repo:1210842314",
          "kind": "repo",
          "supports_claim_ids": [
            "claim_identity",
            "claim_distribution",
            "claim_capability"
          ],
          "url": "https://github.com/okapi-ca/ms-365-admin-mcp-server"
        },
        {
          "evidence_id": "art_c4bcfedbb261436f9832f43b69287515",
          "kind": "docs",
          "supports_claim_ids": [
            "claim_identity",
            "claim_distribution",
            "claim_capability"
          ],
          "url": "https://github.com/okapi-ca/ms-365-admin-mcp-server#readme"
        }
      ],
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "ms-365-admin-mcp-server 说明书",
      "toc": [
        "https://github.com/okapi-ca/ms-365-admin-mcp-server 项目说明书",
        "目录",
        "Project Overview",
        "Introduction",
        "Purpose and Scope",
        "Architecture Overview",
        "Project Layout",
        "Tool Categories",
        "Doramagic 踩坑日志"
      ]
    }
  },
  "quality_gate": {
    "blocking_gaps": [],
    "category_confidence": "medium",
    "compile_status": "ready_for_review",
    "five_assets_present": true,
    "install_sandbox_verified": true,
    "missing_evidence": [],
    "next_action": "publish to Doramagic.ai project surfaces",
    "prompt_preview_boundary_ok": true,
    "publish_status": "publishable",
    "quick_start_verified": true,
    "repo_clone_verified": true,
    "repo_commit": "732693be975dece5f6309b70b1f3bb6b342cb3ce",
    "repo_inspection_error": null,
    "repo_inspection_files": [
      "Dockerfile",
      "package.json",
      "README.md",
      "docs/SETUP_MACOS_FR.md",
      "docs/HTTP_DEPLOYMENT.md",
      "docs/SECURITY_REVIEW_2026-04-25.md",
      "docs/SETUP_MACOS_EN.md",
      "docs/TROUBLESHOOTING.md",
      "docs/USE_CASES.md",
      "docs/SECURITY_REVIEW_2026-04-20.md",
      "docs/ARCHITECTURE.md",
      "docs/SETUP_WINDOWS_FR.md",
      "docs/SETUP_WINDOWS_EN.md",
      "docs/APP_ROLES.md",
      "docs/AZURE_DEPLOYMENT_SECURITY.md",
      "docs/RISK_MODEL.md",
      "docs/APP_REGISTRATION.md",
      "docs/playbooks/phishing-tenant-wide.md",
      "docs/playbooks/oauth-illicit-consent.md",
      "docs/playbooks/sharepoint-exfiltration.md",
      "docs/playbooks/README.md",
      "docs/playbooks/compromised-account.md",
      "docs/CYSEC-1420/network-design-gate.md",
      "docs/CYSEC-1420/pre-migration-inventory.md",
      "docs/CYSEC-1420/graph-permissions-baseline.md",
      "src/logger.ts",
      "src/token-validator.ts",
      "src/tool-categories.ts",
      "src/user-token-validator.ts",
      "src/version.ts",
      "src/risk-level.ts",
      "src/index.ts",
      "src/cloud-config.ts",
      "src/server.ts",
      "src/endpoints.json",
      "src/untrusted-envelope.ts",
      "src/secrets.ts",
      "src/oauth-rate-limiters.ts",
      "src/user-token-authorization.ts",
      "src/upstream-error.ts"
    ],
    "repo_inspection_verified": true,
    "review_reasons": [],
    "tag_count_ok": true,
    "unsupported_claims": []
  },
  "schema_version": "0.1",
  "user_assets": {
    "ai_context_pack": {
      "asset_id": "ai_context_pack",
      "filename": "AI_CONTEXT_PACK.md",
      "markdown": "# @okapi-ca/ms-365-admin-mcp-server - Doramagic AI Context Pack\n\n> 定位：安装前体验与判断资产。它帮助宿主 AI 有一个好的开始，但不代表已经安装、执行或验证目标项目。\n\n## 充分原则\n\n- **充分原则，不是压缩原则**：AI Context Pack 应该充分到让宿主 AI 在开工前理解项目价值、能力边界、使用入口、风险和证据来源；它可以分层组织，但不以最短摘要为目标。\n- **压缩策略**：只压缩噪声和重复内容，不压缩会影响判断和开工质量的上下文。\n\n## 给宿主 AI 的使用方式\n\n你正在读取 Doramagic 为 @okapi-ca/ms-365-admin-mcp-server 编译的 AI Context Pack。请把它当作开工前上下文：帮助用户理解适合谁、能做什么、如何开始、哪些必须安装后验证、风险在哪里。不要声称你已经安装、运行或执行了目标项目。\n\n## Claim 消费规则\n\n- **事实来源**：Repo Evidence + Claim/Evidence Graph；Human Wiki 只提供显著性、术语和叙事结构。\n- **事实最低状态**：`supported`\n- `supported`：可以作为项目事实使用，但回答中必须引用 claim_id 和证据路径。\n- `weak`：只能作为低置信度线索，必须要求用户继续核实。\n- `inferred`：只能用于风险提示或待确认问题，不能包装成项目事实。\n- `unverified`：不得作为事实使用，应明确说证据不足。\n- `contradicted`：必须展示冲突来源，不得替用户强行选择一个版本。\n\n## 它最适合谁\n\n- **正在使用 Claude/Codex/Cursor/Gemini 等宿主 AI 的开发者**：README 或插件配置提到多个宿主 AI。 证据：`README.md` Claim：`clm_0003` supported 0.86\n- **希望把专业流程带进宿主 AI 的用户**：仓库包含 Skill 文档。 证据：`agent-skills/ms365-admin-mcp/SKILL.md` Claim：`clm_0004` supported 0.86\n\n## 它能做什么\n\n- **AI Skill / Agent 指令资产库**（可做安装前预览）：项目包含可被宿主 AI 读取的 Skill 或 Agent 指令文件，可用于把专业流程带入 Claude、Codex、Cursor 等宿主。 证据：`agent-skills/ms365-admin-mcp/SKILL.md` Claim：`clm_0001` supported 0.86\n- **命令行启动或安装流程**（需要安装后验证）：项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 证据：`README.md` Claim：`clm_0002` supported 0.86\n\n## 怎么开始\n\n- `npm install -g @okapi-ca/ms-365-admin-mcp-server` 证据：`README.md` Claim：`clm_0005` supported 0.86\n- `git clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git` 证据：`README.md` Claim：`clm_0006` supported 0.86\n- `npx @okapi-ca/ms-365-admin-mcp-server@latest auth \\` 证据：`README.md` Claim：`clm_0007` supported 0.86\n\n## 继续前判断卡\n\n- **当前建议**：需要管理员/安全审批\n- **为什么**：继续前可能涉及密钥、账号、外部服务或敏感上下文，建议先经过管理员或安全审批。\n\n### 30 秒判断\n\n- **现在怎么做**：需要管理员/安全审批\n- **最小安全下一步**：先跑 Prompt Preview；若涉及凭证或企业环境，先审批再试装\n- **先别相信**：工具权限边界不能在安装前相信。\n- **继续会触碰**：命令执行、宿主 AI 配置、本地环境或项目文件\n\n### 现在可以相信\n\n- **适合人群线索：正在使用 Claude/Codex/Cursor/Gemini 等宿主 AI 的开发者**（supported）：有 supported claim 或项目证据支撑，但仍不等于真实安装效果。 证据：`README.md` Claim：`clm_0003` supported 0.86\n- **适合人群线索：希望把专业流程带进宿主 AI 的用户**（supported）：有 supported claim 或项目证据支撑，但仍不等于真实安装效果。 证据：`agent-skills/ms365-admin-mcp/SKILL.md` Claim：`clm_0004` supported 0.86\n- **能力存在：AI Skill / Agent 指令资产库**（supported）：可以相信项目包含这类能力线索；是否适合你的具体任务仍要试用或安装后验证。 证据：`agent-skills/ms365-admin-mcp/SKILL.md` Claim：`clm_0001` supported 0.86\n- **能力存在：命令行启动或安装流程**（supported）：可以相信项目包含这类能力线索；是否适合你的具体任务仍要试用或安装后验证。 证据：`README.md` Claim：`clm_0002` supported 0.86\n- **存在 Quick Start / 安装命令线索**（supported）：可以相信项目文档出现过启动或安装入口；不要因此直接在主力环境运行。 证据：`README.md` Claim：`clm_0005` supported 0.86\n\n### 现在还不能相信\n\n- **工具权限边界不能在安装前相信。**（unverified）：MCP/tool 类项目通常会触碰文件、网络、浏览器或外部 API，必须真实检查权限和日志。\n- **真实输出质量不能在安装前相信。**（unverified）：Prompt Preview 只能展示引导方式，不能证明真实项目中的结果质量。\n- **宿主 AI 版本兼容性不能在安装前相信。**（unverified）：Claude、Cursor、Codex、Gemini 等宿主加载规则和版本差异必须在真实环境验证。\n- **不会污染现有宿主 AI 行为，不能直接相信。**（inferred）：Skill、plugin、AGENTS/CLAUDE/GEMINI 指令可能改变宿主 AI 的默认行为。 证据：`agent-skills/ms365-admin-mcp/SKILL.md`\n- **可安全回滚不能默认相信。**（unverified）：除非项目明确提供卸载和恢复说明，否则必须先在隔离环境验证。\n- **真实安装后是否与用户当前宿主 AI 版本兼容？**（unverified）：兼容性只能通过实际宿主环境验证。\n- **项目输出质量是否满足用户具体任务？**（unverified）：安装前预览只能展示流程和边界，不能替代真实评测。\n- **安装命令是否需要网络、权限或全局写入？**（unverified）：这影响企业环境和个人环境的安装风险。 证据：`README.md`\n\n### 继续会触碰什么\n\n- **命令执行**：包管理器、网络下载、本地插件目录、项目配置或用户主目录。 原因：运行第一条命令就可能产生环境改动；必须先判断是否值得跑。 证据：`README.md`\n- **宿主 AI 配置**：Claude/Codex/Cursor/Gemini/OpenCode 等宿主的 plugin、Skill 或规则加载配置。 原因：宿主配置会改变 AI 后续工作方式，可能和用户已有规则冲突。 证据：`agent-skills/ms365-admin-mcp/SKILL.md`\n- **本地环境或项目文件**：安装结果、插件缓存、项目配置或本地依赖目录。 原因：安装前无法证明写入范围和回滚方式，需要隔离验证。 证据：`README.md`\n- **环境变量 / API Key**：项目入口文档明确出现 API key、token、secret 或账号凭证配置。 原因：如果真实安装需要凭证，应先使用测试凭证并经过权限/合规判断。 证据：`CONTRIBUTING.md`, `README.md`, `SECURITY.md`, `docs/APP_REGISTRATION.md` 等\n- **宿主 AI 上下文**：AI Context Pack、Prompt Preview、Skill 路由、风险规则和项目事实。 原因：导入上下文会影响宿主 AI 后续判断，必须避免把未验证项包装成事实。\n\n### 最小安全下一步\n\n- **先跑 Prompt Preview**：用安装前交互式试用判断工作方式是否匹配，不需要授权或改环境。（适用：任何项目都适用，尤其是输出质量未知时。）\n- **只在隔离目录或测试账号试装**：避免安装命令污染主力宿主 AI、真实项目或用户主目录。（适用：存在命令执行、插件配置或本地写入线索时。）\n- **先备份宿主 AI 配置**：Skill、plugin、规则文件可能改变 Claude/Cursor/Codex 的默认行为。（适用：存在插件 manifest、Skill 或宿主规则入口时。）\n- **不要使用真实生产凭证**：环境变量/API key 一旦进入宿主或工具链，可能产生账号和合规风险。（适用：出现 API、TOKEN、KEY、SECRET 等环境线索时。）\n- **安装后只验证一个最小任务**：先验证加载、兼容、输出质量和回滚，再决定是否深用。（适用：准备从试用进入真实工作流时。）\n\n### 退出方式\n\n- **保留安装前状态**：记录原始宿主配置和项目状态，后续才能判断是否可恢复。\n- **准备移除宿主 plugin / Skill / 规则入口**：如果试装后行为异常，可以把宿主 AI 恢复到试装前状态。\n- **记录安装命令和写入路径**：没有明确卸载说明时，至少要知道哪些目录或配置需要手动清理。\n- **准备撤销测试 API key 或 token**：测试凭证泄露或误用时，可以快速止损。\n- **如果没有回滚路径，不进入主力环境**：不可回滚是继续前阻断项，不应靠信任或运气继续。\n\n## 哪些只能预览\n\n- 解释项目适合谁和能做什么\n- 基于项目文档演示典型对话流程\n- 帮助用户判断是否值得安装或继续研究\n\n## 哪些必须安装后验证\n\n- 真实安装 Skill、插件或 CLI\n- 执行脚本、修改本地文件或访问外部服务\n- 验证真实输出质量、性能和兼容性\n\n## 边界与风险判断卡\n\n- **把安装前预览误认为真实运行**：用户可能高估项目已经完成的配置、权限和兼容性验证。 处理方式：明确区分 prompt_preview_can_do 与 runtime_required。 Claim：`clm_0008` inferred 0.45\n- **命令执行会修改本地环境**：安装命令可能写入用户主目录、宿主插件目录或项目配置。 处理方式：先在隔离环境或测试账号中运行。 证据：`README.md` Claim：`clm_0009` supported 0.86\n- **待确认**：真实安装后是否与用户当前宿主 AI 版本兼容？。原因：兼容性只能通过实际宿主环境验证。\n- **待确认**：项目输出质量是否满足用户具体任务？。原因：安装前预览只能展示流程和边界，不能替代真实评测。\n- **待确认**：安装命令是否需要网络、权限或全局写入？。原因：这影响企业环境和个人环境的安装风险。\n\n## 开工前工作上下文\n\n### 加载顺序\n\n- 先读取 how_to_use.host_ai_instruction，建立安装前判断资产的边界。\n- 读取 claim_graph_summary，确认事实来自 Claim/Evidence Graph，而不是 Human Wiki 叙事。\n- 再读取 intended_users、capabilities 和 quick_start_candidates，判断用户是否匹配。\n- 需要执行具体任务时，优先查 role_skill_index，再查 evidence_index。\n- 遇到真实安装、文件修改、网络访问、性能或兼容性问题时，转入 risk_card 和 boundaries.runtime_required。\n\n### 任务路由\n\n- **AI Skill / Agent 指令资产库**：先基于 role_skill_index / evidence_index 帮用户挑选可用角色、Skill 或工作流。 边界：可做安装前 Prompt 体验。 证据：`agent-skills/ms365-admin-mcp/SKILL.md` Claim：`clm_0001` supported 0.86\n- **命令行启动或安装流程**：先说明这是安装后验证能力，再给出安装前检查清单。 边界：必须真实安装或运行后验证。 证据：`README.md` Claim：`clm_0002` supported 0.86\n\n### 上下文规模\n\n- 文件总数：120\n- 重要文件覆盖：40/120\n- 证据索引条目：80\n- 角色 / Skill 条目：1\n\n### 证据不足时的处理\n\n- **missing_evidence**：说明证据不足，要求用户提供目标文件、README 段落或安装后验证记录；不要补全事实。\n- **out_of_scope_request**：说明该任务超出当前 AI Context Pack 证据范围，并建议用户先查看 Human Manual 或真实安装后验证。\n- **runtime_request**：给出安装前检查清单和命令来源，但不要替用户执行命令或声称已执行。\n- **source_conflict**：同时展示冲突来源，标记为待核实，不要强行选择一个版本。\n\n## Prompt Recipes\n\n### 适配判断\n\n- 目标：判断这个项目是否适合用户当前任务。\n- 预期输出：适配结论、关键理由、证据引用、安装前可预览内容、必须安装后验证内容、下一步建议。\n\n```text\n请基于 @okapi-ca/ms-365-admin-mcp-server 的 AI Context Pack，先问我 3 个必要问题，然后判断它是否适合我的任务。回答必须包含：适合谁、能做什么、不能做什么、是否值得安装、证据来自哪里。所有项目事实必须引用 evidence_refs、source_paths 或 claim_id。\n```\n\n### 安装前体验\n\n- 目标：让用户在安装前感受核心工作流，同时避免把预览包装成真实能力或营销承诺。\n- 预期输出：一段带边界标签的体验剧本、安装后验证清单和谨慎建议；不含真实运行承诺或强营销表述。\n\n```text\n请把 @okapi-ca/ms-365-admin-mcp-server 当作安装前体验资产，而不是已安装工具或真实运行环境。\n\n请严格输出四段：\n1. 先问我 3 个必要问题。\n2. 给出一段“体验剧本”：用 [安装前可预览]、[必须安装后验证]、[证据不足] 三种标签展示它可能如何引导工作流。\n3. 给出安装后验证清单：列出哪些能力只有真实安装、真实宿主加载、真实项目运行后才能确认。\n4. 给出谨慎建议：只能说“值得继续研究/试装”“先补充信息后再判断”或“不建议继续”，不得替项目背书。\n\n硬性边界：\n- 不要声称已经安装、运行、执行测试、修改文件或产生真实结果。\n- 不要写“自动适配”“确保通过”“完美适配”“强烈建议安装”等承诺性表达。\n- 如果描述安装后的工作方式，必须使用“如果安装成功且宿主正确加载 Skill，它可能会……”这种条件句。\n- 体验剧本只能写成“示例台词/假设流程”：使用“可能会询问/可能会建议/可能会展示”，不要写“已写入、已生成、已通过、正在运行、正在生成”。\n- Prompt Preview 不负责给安装命令；如用户准备试装，只能提示先阅读 Quick Start 和 Risk Card，并在隔离环境验证。\n- 所有项目事实必须来自 supported claim、evidence_refs 或 source_paths；inferred/unverified 只能作风险或待确认项。\n\n```\n\n### 角色 / Skill 选择\n\n- 目标：从项目里的角色或 Skill 中挑选最匹配的资产。\n- 预期输出：候选角色或 Skill 列表，每项包含适用场景、证据路径、风险边界和是否需要安装后验证。\n\n```text\n请读取 role_skill_index，根据我的目标任务推荐 3-5 个最相关的角色或 Skill。每个推荐都要说明适用场景、可能输出、风险边界和 evidence_refs。\n```\n\n### 风险预检\n\n- 目标：安装或引入前识别环境、权限、规则冲突和质量风险。\n- 预期输出：环境、权限、依赖、许可、宿主冲突、质量风险和未知项的检查清单。\n\n```text\n请基于 risk_card、boundaries 和 quick_start_candidates，给我一份安装前风险预检清单。不要替我执行命令，只说明我应该检查什么、为什么检查、失败会有什么影响。\n```\n\n### 宿主 AI 开工指令\n\n- 目标：把项目上下文转成一次对话开始前的宿主 AI 指令。\n- 预期输出：一段边界明确、证据引用明确、适合复制给宿主 AI 的开工前指令。\n\n```text\n请基于 @okapi-ca/ms-365-admin-mcp-server 的 AI Context Pack，生成一段我可以粘贴给宿主 AI 的开工前指令。这段指令必须遵守 not_runtime=true，不能声称项目已经安装、运行或产生真实结果。\n```\n\n\n## 角色 / Skill 索引\n\n- 共索引 1 个角色 / Skill / 项目文档条目。\n\n- **ms365-admin-mcp**（skill）：Reference skill for operating ms-365-admin-mcp-server through an LLM client. Load when a request involves a Microsoft 365 administrative operation requiring tenant-level permissions — Defender alert triage, sign-in investigation, PIM audit, Intune actions, eDiscovery, KQL hunting, Conditional Access management, or any tenant-scoped directory operation through application client credentials permissions. 激活提示：当用户任务与“ms365-admin-mcp”描述的流程高度相关时，先用它做安装前体验，再决定是否安装。 证据：`agent-skills/ms365-admin-mcp/SKILL.md`\n\n## 证据索引\n\n- 共索引 80 条证据。\n\n- **Security Incident Response Playbooks**（documentation）：Security Incident Response Playbooks 证据：`docs/playbooks/README.md`\n- **ms-365-admin-mcp-server**（documentation）：! CI https://github.com/okapi-ca/ms-365-admin-mcp-server/actions/workflows/ci.yml/badge.svg?branch=main https://github.com/okapi-ca/ms-365-admin-mcp-server/actions/workflows/ci.yml ! npm version https://img.shields.io/npm/v/@okapi-ca/ms-365-admin-mcp-server.svg https://www.npmjs.com/package/@okapi-ca/ms-365-admin-mcp-server ! License: MIT https://img.shields.io/badge/License-MIT-yellow.svg LICENSE 证据：`README.md`\n- **Agent skills**（documentation）：Drop-in skills for LLM agents that operate ms-365-admin-mcp-server . Skills wrap the server's 515 tools with a structured safety pattern dry-run → confirm → audit and route requests by use case to keep the model focused on the right subset. 证据：`agent-skills/README.md`\n- **Package**（package_manifest）：{ \"name\": \"@okapi-ca/ms-365-admin-mcp-server\", \"version\": \"0.6.2\", \"description\": \"A Model Context Protocol MCP server for Microsoft 365 admin operations via Graph API application permissions\", \"type\": \"module\", \"main\": \"dist/index.js\", \"bin\": { \"ms-365-admin-mcp-server\": \"dist/index.js\", \"ms-365-admin-mcp-auth\": \"dist/auth-bootstrap.js\" }, \"files\": \"dist\", \"README.md\", \"LICENSE\", \"CHANGELOG.md\" , \"publishConfig\": { \"access\": \"public\" }, \"repository\": { \"type\": \"git\", \"url\": \"git+https://github.com/okapi-ca/ms-365-admin-mcp-server.git\" }, \"bugs\": { \"url\": \"https://github.com/okapi-ca/ms-365-admin-mcp-server/issues\" }, \"homepage\": \"https://github.com/okapi-ca/ms-365-admin-mcp-server readme\",… 证据：`package.json`\n- **Contributing**（documentation）：Thanks for your interest in contributing to ms-365-admin-mcp-server . 证据：`CONTRIBUTING.md`\n- **ms365-admin-mcp**（skill_instruction）：A reusable Claude Code skill that wraps ms-365-admin-mcp-server with a structured safety pattern: discover the right tool by use case, dry-run first, confirm explicitly, audit after. The skill is a router — its reference files index the server's 515 tools by domain and point back to the authoritative documentation in docs/USE CASES.md ../../docs/USE CASES.md and docs/playbooks/ ../../docs/playbooks/README.md . 证据：`agent-skills/ms365-admin-mcp/SKILL.md`\n- **License**（source_file）：Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files the \"Software\" , to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 证据：`LICENSE`\n- **Azure AD App Registration Guide**（documentation）：This guide walks through creating an Entra ID Azure AD app registration with the application permissions required by ms-365-admin-mcp-server . 证据：`docs/APP_REGISTRATION.md`\n- **App Roles — Per-caller write gating**（documentation）：App Roles — Per-caller write gating 证据：`docs/APP_ROLES.md`\n- **Architecture**（documentation）：This document describes the internal design of ms-365-admin-mcp-server . 证据：`docs/ARCHITECTURE.md`\n- **Azure Container Apps — Deployment Security Architecture**（documentation）：Azure Container Apps — Deployment Security Architecture 证据：`docs/AZURE_DEPLOYMENT_SECURITY.md`\n- **HTTP Transport and Remote Deployment**（documentation）：HTTP Transport and Remote Deployment 证据：`docs/HTTP_DEPLOYMENT.md`\n- **Risk Model**（documentation）：Every write tool in ms-365-admin-mcp-server is labeled with a risk level. This document explains the classification, how it's surfaced, and how to use it. 证据：`docs/RISK_MODEL.md`\n- **Security Review — 2026-04-20**（documentation）：Internal security review covering the highest-value portions of the codebase. Finding IDs are stable SEC-Fxx for Priority 1 / OAuth, SEC-Gxx for Priority 2 / tool invocation gating so remediation PRs and future reviews can reference them cleanly. 证据：`docs/SECURITY_REVIEW_2026-04-20.md`\n- **Security Review — 2026-04-25**（documentation）：Comprehensive security review of ms-365-admin-mcp-server v0.6.1 covering the entire codebase. Finding IDs in this review use the SEC-NNN scheme independent from the P1/P2 series SEC-Fxx / SEC-Gxx in SECURITY REVIEW 2026-04-20.md ./SECURITY REVIEW 2026-04-20.md so remediation PRs and future reviews can reference them cleanly. 证据：`docs/SECURITY_REVIEW_2026-04-25.md`\n- **MS 365 Admin MCP — macOS setup guide**（documentation）：MS 365 Admin MCP — macOS setup guide 证据：`docs/SETUP_MACOS_EN.md`\n- **MS 365 Admin MCP — Guide d'installation macOS**（documentation）：MS 365 Admin MCP — Guide d'installation macOS 证据：`docs/SETUP_MACOS_FR.md`\n- **MS 365 Admin MCP — Windows setup guide device code flow**（documentation）：MS 365 Admin MCP — Windows setup guide device code flow 证据：`docs/SETUP_WINDOWS_EN.md`\n- **MS 365 Admin MCP — Guide d'installation Windows flux device code**（documentation）：MS 365 Admin MCP — Guide d'installation Windows flux device code 证据：`docs/SETUP_WINDOWS_FR.md`\n- **Troubleshooting**（documentation）：Common errors and how to diagnose them. 证据：`docs/TROUBLESHOOTING.md`\n- **Use Cases**（documentation）：Typical scenarios for using ms-365-admin-mcp-server through an LLM client Claude Desktop, Claude Code, custom agent, etc. . 证据：`docs/USE_CASES.md`\n- **CYSEC-1422 — Baseline des permissions Microsoft Graph**（documentation）：CYSEC-1422 — Baseline des permissions Microsoft Graph 证据：`docs/CYSEC-1420/graph-permissions-baseline.md`\n- **CYSEC-1420 — Network Design — Infrastructure Gate**（documentation）：CYSEC-1420 — Network Design — Infrastructure Gate 证据：`docs/CYSEC-1420/network-design-gate.md`\n- **CYSEC-1420 — Pre-Migration Inventory**（documentation）：CYSEC-1420 — Pre-Migration Inventory 证据：`docs/CYSEC-1420/pre-migration-inventory.md`\n- **Playbook — Compromised Account**（documentation）：End-to-end incident response scenario driven through ms-365-admin-mcp-server . From the first risk signal to the post-incident audit report, every step maps to a concrete MCP tool. 证据：`docs/playbooks/compromised-account.md`\n- **Playbook — OAuth Illicit Consent Consent Phishing**（documentation）：Playbook — OAuth Illicit Consent Consent Phishing 证据：`docs/playbooks/oauth-illicit-consent.md`\n- **Playbook — Phishing Campaign Tenant-Wide**（documentation）：Playbook — Phishing Campaign Tenant-Wide 证据：`docs/playbooks/phishing-tenant-wide.md`\n- **Playbook — SharePoint / OneDrive Exfiltration**（documentation）：Playbook — SharePoint / OneDrive Exfiltration 证据：`docs/playbooks/sharepoint-exfiltration.md`\n- **Summary**（documentation）：- feat — new tool, preset, or feature - fix — bug fix - sec — security fix - docs — documentation only - chore — tooling, deps, non-functional - refactor — no behavior change - test — tests only 证据：`.github/PULL_REQUEST_TEMPLATE.md`\n- **Changelog**（documentation）：All notable changes to ms-365-admin-mcp-server are documented here. 证据：`CHANGELOG.md`\n- **Security Policy**（documentation）：Only the latest release of ms-365-admin-mcp-server receives security updates. Older versions may contain vulnerabilities that have been fixed upstream. 证据：`SECURITY.md`\n- **Description**（documentation）：- Version / commit SHA: - Node version: node --version - OS: - Transport: stdio / HTTP - Cloud: global / china - Presets enabled: - --allow-writes : yes / no 证据：`.github/ISSUE_TEMPLATE/bug_report.md`\n- **Use case**（documentation）：- Graph API endpoint: /path/to/endpoint - HTTP method: GET / POST / PATCH / DELETE - Graph API permissions required: - Suggested toolName: - Suggested riskLevel if non-GET, see RISK MODEL.md ../../docs/RISK MODEL.md : - Matching preset: security / identity / ... / new preset 证据：`.github/ISSUE_TEMPLATE/feature_request.md`\n- **Graph API permissions**（documentation）：Reference list of Microsoft Graph application permissions client credentials consumed by ms-365-admin-mcp-server . Match these to the app registration backing your deployment. 证据：`agent-skills/ms365-admin-mcp/references/graph-permissions.md`\n- **Tools catalogue**（documentation）：Index of the 515 tools exposed by ms-365-admin-mcp-server , organized by preset and by risk level. Do not preload this file — prefer the per-domain usecase- .md files. This is a reference for cross-cutting questions \"what's critical across the server?\", \"which preset contains tool X?\" . 证据：`agent-skills/ms365-admin-mcp/references/tools-catalog.md`\n- **usecase-audit — Sign-ins, directory audits, deleted items**（documentation）：usecase-audit — Sign-ins, directory audits, deleted items 证据：`agent-skills/ms365-admin-mcp/references/usecase-audit.md`\n- **usecase-callrecords — Teams call records and PSTN**（documentation）：usecase-callrecords — Teams call records and PSTN 证据：`agent-skills/ms365-admin-mcp/references/usecase-callrecords.md`\n- **usecase-cloudpc — Cloud PC / Windows 365**（documentation）：usecase-cloudpc — Cloud PC / Windows 365 证据：`agent-skills/ms365-admin-mcp/references/usecase-cloudpc.md`\n- **usecase-compliance — Licenses, Secure Score, Identity Protection, Conditional Access**（documentation）：usecase-compliance — Licenses, Secure Score, Identity Protection, Conditional Access 证据：`agent-skills/ms365-admin-mcp/references/usecase-compliance.md`\n- **usecase-ediscovery — Microsoft Purview eDiscovery**（documentation）：usecase-ediscovery — Microsoft Purview eDiscovery 证据：`agent-skills/ms365-admin-mcp/references/usecase-ediscovery.md`\n- **usecase-exchange — Message traces and mailboxes**（documentation）：usecase-exchange — Message traces and mailboxes 证据：`agent-skills/ms365-admin-mcp/references/usecase-exchange.md`\n- **usecase-governance — Access reviews, entitlement, lifecycle workflows**（documentation）：usecase-governance — Access reviews, entitlement, lifecycle workflows 证据：`agent-skills/ms365-admin-mcp/references/usecase-governance.md`\n- **usecase-health — Service health and Message Center**（documentation）：usecase-health — Service health and Message Center 证据：`agent-skills/ms365-admin-mcp/references/usecase-health.md`\n- **usecase-identity — Users, groups, PIM, applications, guests**（documentation）：usecase-identity — Users, groups, PIM, applications, guests 证据：`agent-skills/ms365-admin-mcp/references/usecase-identity.md`\n- **usecase-infoprotection — BitLocker, sensitivity labels, threat assessment**（documentation）：usecase-infoprotection — BitLocker, sensitivity labels, threat assessment 证据：`agent-skills/ms365-admin-mcp/references/usecase-infoprotection.md`\n- **usecase-intune — Devices, compliance, Autopilot, MAM, remote actions**（documentation）：usecase-intune — Devices, compliance, Autopilot, MAM, remote actions 证据：`agent-skills/ms365-admin-mcp/references/usecase-intune.md`\n- **usecase-print — Universal Print**（documentation）：When to load: Universal Print inventory, usage, shares audit. 证据：`agent-skills/ms365-admin-mcp/references/usecase-print.md`\n- **usecase-reports — M365 usage reports**（documentation）：usecase-reports — M365 usage reports 证据：`agent-skills/ms365-admin-mcp/references/usecase-reports.md`\n- **usecase-response — Incident response and containment**（documentation）：usecase-response — Incident response and containment 证据：`agent-skills/ms365-admin-mcp/references/usecase-response.md`\n- **usecase-retention — Records management**（documentation）：usecase-retention — Records management 证据：`agent-skills/ms365-admin-mcp/references/usecase-retention.md`\n- **usecase-security — Alert and incident triage**（documentation）：usecase-security — Alert and incident triage 证据：`agent-skills/ms365-admin-mcp/references/usecase-security.md`\n- **usecase-sharepointadmin — SharePoint tenant administration**（documentation）：usecase-sharepointadmin — SharePoint tenant administration 证据：`agent-skills/ms365-admin-mcp/references/usecase-sharepointadmin.md`\n- **usecase-teamsadmin — Teams tenant-level administration**（documentation）：usecase-teamsadmin — Teams tenant-level administration 证据：`agent-skills/ms365-admin-mcp/references/usecase-teamsadmin.md`\n- **usecase-threatintel — Threat intelligence and KQL hunting**（documentation）：usecase-threatintel — Threat intelligence and KQL hunting 证据：`agent-skills/ms365-admin-mcp/references/usecase-threatintel.md`\n- **Endpoints**（structured_config）：{ \"pathPattern\": \"/security/alerts v2\", \"method\": \"get\", \"toolName\": \"list-security-alerts\", \"appPermissions\": \"SecurityAlert.Read.All\" , \"llmTip\": \"Lists security alerts from Microsoft 365 Defender. Use $filter=status eq 'new' or status eq 'inProgress' to filter by status. Use $filter=severity eq 'high' to filter by severity informational, low, medium, high . Use $orderby=createdDateTime desc to sort by newest. Use $top to limit results. Each alert has title, description, severity, status, category, serviceSource, detectionSource, and evidence.\" }, { \"pathPattern\": \"/security/alerts v2/{alert-id}\", \"method\": \"get\", \"toolName\": \"get-security-alert\", \"appPermissions\": \"SecurityAlert.Read.All… 证据：`src/endpoints.json`\n- **Tsconfig**（structured_config）：{ \"compilerOptions\": { \"target\": \"ES2020\", \"module\": \"NodeNext\", \"outDir\": \"dist\", \"rootDir\": \"src\", \"strict\": true, \"resolveJsonModule\": true }, \"include\": \"src/ / \" , \"exclude\": \"test/ / \" } 证据：`tsconfig.json`\n- **.dockerignore**（source_file）：.env .env. .git .gitignore .claude node modules openapi infra coverage .lcov .nyc output .DS Store .idea .vscode-test .token-cache.json .mcp.json CLAUDE.md README.md Dockerfile .dockerignore 证据：`.dockerignore`\n- **Dependabot**（source_file）：version: 2 updates: - package-ecosystem: npm directory: / schedule: interval: weekly day: monday open-pull-requests-limit: 10 reviewers: - okapi-ca labels: - dependencies groups: dev-dependencies: dependency-type: development update-types: - minor - patch mcp-sdk: patterns: - \"@modelcontextprotocol/ \" azure: patterns: - \"@azure/ \" 证据：`.github/dependabot.yml`\n- **Environment**（source_file）：node modules/ dist coverage .lcov .nyc output .tsbuildinfo .npm .eslintcache 证据：`.gitignore`\n- **.prettierignore**（source_file）：node modules dist coverage src/generated .venv .claude openapi 证据：`.prettierignore`\n- 其余 20 条证据见 `AI_CONTEXT_PACK.json` 或 `EVIDENCE_INDEX.json`。\n\n## 宿主 AI 必须遵守的规则\n\n- **把本资产当作开工前上下文，而不是运行环境。**：AI Context Pack 只包含证据化项目理解，不包含目标项目的可执行状态。 证据：`docs/playbooks/README.md`, `README.md`, `agent-skills/README.md`\n- **回答用户时区分可预览内容与必须安装后才能验证的内容。**：安装前体验的消费者价值来自降低误装和误判，而不是伪装成真实运行。 证据：`docs/playbooks/README.md`, `README.md`, `agent-skills/README.md`\n\n## 用户开工前应该回答的问题\n\n- 你准备在哪个宿主 AI 或本地环境中使用它？\n- 你只是想先体验工作流，还是准备真实安装？\n- 你最在意的是安装成本、输出质量、还是和现有规则的冲突？\n\n## 验收标准\n\n- 所有能力声明都能回指到 evidence_refs 中的文件路径。\n- AI_CONTEXT_PACK.md 没有把预览包装成真实运行。\n- 用户能在 3 分钟内看懂适合谁、能做什么、如何开始和风险边界。\n\n---\n\n## Doramagic Context Augmentation\n\n下面内容用于强化 Repomix/AI Context Pack 主体。Human Manual 只提供阅读骨架；踩坑日志会被转成宿主 AI 必须遵守的工作约束。\n\n## Human Manual 骨架\n\n使用规则：这里只是项目阅读路线和显著性信号，不是事实权威。具体事实仍必须回到 repo evidence / Claim Graph。\n\n宿主 AI 硬性规则：\n- 不得把页标题、章节顺序、摘要或 importance 当作项目事实证据。\n- 解释 Human Manual 骨架时，必须明确说它只是阅读路线/显著性信号。\n- 能力、安装、兼容性、运行状态和风险判断必须引用 repo evidence、source path 或 Claim Graph。\n\n- **Project Overview**：importance `high`\n  - source_paths: README.md, package.json, src/index.ts\n- **Installation Guide**：importance `high`\n  - source_paths: Dockerfile, docs/APP_REGISTRATION.md, docs/SETUP_MACOS_EN.md, docs/SETUP_WINDOWS_EN.md\n- **Configuration Reference**：importance `high`\n  - source_paths: src/cli.ts, src/cloud-config.ts, src/secrets.ts\n- **System Architecture**：importance `high`\n  - source_paths: docs/ARCHITECTURE.md, src/server.ts, src/http-server.ts, src/graph-client.ts, src/auth.ts\n- **Code Generation Pipeline**：importance `medium`\n  - source_paths: bin/generate-graph-client.mjs, bin/modules/generate-mcp-tools.mjs, bin/modules/simplified-openapi.mjs, bin/modules/extract-descriptions.mjs, bin/modules/download-openapi.mjs\n- **Tool Categories and Presets**：importance `high`\n  - source_paths: src/tool-categories.ts, src/risk-level.ts, src/endpoints.json\n- **Security Model and Risk Classification**：importance `high`\n  - source_paths: docs/RISK_MODEL.md, src/risk-level.ts, SECURITY.md, docs/SECURITY_REVIEW_2026-04-20.md, docs/SECURITY_REVIEW_2026-04-25.md\n- **Azure Deployment Security**：importance `medium`\n  - source_paths: docs/AZURE_DEPLOYMENT_SECURITY.md, infra/main.bicep, infra/parameters.example.jsonc, docs/CYSEC-1420/graph-permissions-baseline.md, docs/CYSEC-1420/network-design-gate.md\n\n## Repo Inspection Evidence / 源码检查证据\n\n- repo_clone_verified: true\n- repo_inspection_verified: true\n- repo_commit: `732693be975dece5f6309b70b1f3bb6b342cb3ce`\n- inspected_files: `Dockerfile`, `package.json`, `README.md`, `docs/SETUP_MACOS_FR.md`, `docs/HTTP_DEPLOYMENT.md`, `docs/SECURITY_REVIEW_2026-04-25.md`, `docs/SETUP_MACOS_EN.md`, `docs/TROUBLESHOOTING.md`, `docs/USE_CASES.md`, `docs/SECURITY_REVIEW_2026-04-20.md`, `docs/ARCHITECTURE.md`, `docs/SETUP_WINDOWS_FR.md`, `docs/SETUP_WINDOWS_EN.md`, `docs/APP_ROLES.md`, `docs/AZURE_DEPLOYMENT_SECURITY.md`, `docs/RISK_MODEL.md`, `docs/APP_REGISTRATION.md`, `docs/playbooks/phishing-tenant-wide.md`, `docs/playbooks/oauth-illicit-consent.md`, `docs/playbooks/sharepoint-exfiltration.md`\n\n宿主 AI 硬性规则：\n- 没有 repo_clone_verified=true 时，不得声称已经读过源码。\n- 没有 repo_inspection_verified=true 时，不得把 README/docs/package 文件判断写成事实。\n- 没有 quick_start_verified=true 时，不得声称 Quick Start 已跑通。\n\n## Doramagic Pitfall Constraints / 踩坑约束\n\n这些规则来自 Doramagic 发现、验证或编译过程中的项目专属坑点。宿主 AI 必须把它们当作工作约束，而不是普通说明文字。\n\n### Constraint 1: 能力判断依赖假设\n\n- Trigger: README/documentation is current enough for a first validation pass.\n- Host AI rule: 将假设转成下游验证清单。\n- Why it matters: 假设不成立时，用户拿不到承诺的能力。\n- Evidence: capability.assumptions | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | README/documentation is current enough for a first validation pass.\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 2: 维护活跃度未知\n\n- Trigger: 未记录 last_activity_observed。\n- Host AI rule: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- Why it matters: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- Evidence: evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | last_activity_observed missing\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 3: 下游验证发现风险项\n\n- Trigger: no_demo\n- Host AI rule: 进入安全/权限治理复核队列。\n- Why it matters: 下游已经要求复核，不能在页面中弱化。\n- Evidence: downstream_validation.risk_items | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 4: 存在评分风险\n\n- Trigger: no_demo\n- Host AI rule: 把风险写入边界卡，并确认是否需要人工复核。\n- Why it matters: 风险会影响是否适合普通用户安装。\n- Evidence: risks.scoring_risks | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 5: 来源证据：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n\n- Trigger: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n- Host AI rule: 来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- Why it matters: 可能增加新用户试用和生产接入成本。\n- Evidence: community_evidence:github | cevd_103cf7f40efc40e99adfa2eb14d9717e | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/70 | 来源讨论提到 node 相关条件，需在安装/试用前复核。\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 6: 来源证据：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n\n- Trigger: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n- Host AI rule: 来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- Why it matters: 可能影响授权、密钥配置或安全边界。\n- Evidence: community_evidence:github | cevd_6ede43fd3f7247e0981524934656dbeb | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71 | 来源类型 github_issue 暴露的待验证使用条件。\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 7: 来源证据：SEC-005: Express body parser runs before authentication and rate limiting\n\n- Trigger: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-005: Express body parser runs before authentication and rate limiting\n- Host AI rule: 来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- Why it matters: 可能影响授权、密钥配置或安全边界。\n- Evidence: community_evidence:github | cevd_e53044f4bde148d7882ccf83273f1e22 | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/72 | 来源类型 github_issue 暴露的待验证使用条件。\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 8: issue/PR 响应质量未知\n\n- Trigger: issue_or_pr_quality=unknown。\n- Host AI rule: 抽样最近 issue/PR，判断是否长期无人处理。\n- Why it matters: 用户无法判断遇到问题后是否有人维护。\n- Evidence: evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | issue_or_pr_quality=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 9: 发布节奏不明确\n\n- Trigger: release_recency=unknown。\n- Host AI rule: 确认最近 release/tag 和 README 安装命令是否一致。\n- Why it matters: 安装命令和文档可能落后于代码，用户踩坑概率升高。\n- Evidence: evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | release_recency=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n",
      "summary": "给宿主 AI 的上下文和工作边界。",
      "title": "AI Context Pack / 带给我的 AI"
    },
    "boundary_risk_card": {
      "asset_id": "boundary_risk_card",
      "filename": "BOUNDARY_RISK_CARD.md",
      "markdown": "# Boundary & Risk Card / 安装前决策卡\n\n项目：okapi-ca/ms-365-admin-mcp-server\n\n## Doramagic 试用结论\n\n当前结论：可以进入发布前推荐检查；首次使用仍应从最小权限、临时目录和可回滚配置开始。\n\n## 用户现在可以做\n\n- 可以先阅读 Human Manual，理解项目目的和主要工作流。\n- 可以复制 Prompt Preview 做安装前体验；这只验证交互感，不代表真实运行。\n- 可以把官方 Quick Start 命令放到隔离环境中验证，不要直接进主力环境。\n\n## 现在不要做\n\n- 不要把 Prompt Preview 当成项目实际运行结果。\n- 不要把 metadata-only validation 当成沙箱安装验证。\n- 不要把未验证能力写成“已支持、已跑通、可放心安装”。\n- 不要在首次试用时交出生产数据、私人文件、真实密钥或主力配置目录。\n\n## 安装前检查\n\n- 宿主 AI 是否匹配：mcp_host\n- 官方安装入口状态：已发现官方入口\n- 是否在临时目录、临时宿主或容器中验证：必须是\n- 是否能回滚配置改动：必须能\n- 是否需要 API Key、网络访问、读写文件或修改宿主配置：未确认前按高风险处理\n- 是否记录了安装命令、实际输出和失败日志：必须记录\n\n## 当前阻塞项\n\n- 无阻塞项。\n\n## 项目专属踩坑\n\n- 能力判断依赖假设（medium）：假设不成立时，用户拿不到承诺的能力。 建议检查：将假设转成下游验证清单。\n- 维护活跃度未知（medium）：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 下游验证发现风险项（medium）：下游已经要求复核，不能在页面中弱化。 建议检查：进入安全/权限治理复核队列。\n- 存在评分风险（medium）：风险会影响是否适合普通用户安装。 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 来源证据：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node（medium）：可能增加新用户试用和生产接入成本。 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n\n## 风险与权限提示\n\n- no_demo: medium\n\n## 证据缺口\n\n- 暂未发现结构化证据缺口。\n",
      "summary": "安装、权限、验证和推荐前风险。",
      "title": "Boundary & Risk Card / 边界与风险卡"
    },
    "human_manual": {
      "asset_id": "human_manual",
      "filename": "HUMAN_MANUAL.md",
      "markdown": "# https://github.com/okapi-ca/ms-365-admin-mcp-server 项目说明书\n\n生成时间：2026-05-15 11:16:11 UTC\n\n## 目录\n\n- [Project Overview](#overview)\n- [Installation Guide](#installation)\n- [Configuration Reference](#configuration)\n- [System Architecture](#system-architecture)\n- [Code Generation Pipeline](#code-generation)\n- [Tool Categories and Presets](#tool-categories)\n- [Security Model and Risk Classification](#security-model)\n- [Azure Deployment Security](#azure-deployment-security)\n- [HTTP Transport and Deployment](#http-deployment)\n- [Docker and Container Deployment](#docker-deployment)\n\n<a id='overview'></a>\n\n## Project Overview\n\n### 相关页面\n\n相关主题：[System Architecture](#system-architecture), [Installation Guide](#installation), [Configuration Reference](#configuration)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/README.md)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- [src/index.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/index.ts)\n- [src/auth.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth.ts)\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n</details>\n\n# Project Overview\n\n## Introduction\n\nThe **ms-365-admin-mcp-server** is a Model Context Protocol (MCP) server that exposes Microsoft 365 admin capabilities as MCP tools. Built with TypeScript and strict mode, it enables AI assistants like Claude to perform Microsoft 365 administrative operations through the Microsoft Graph API.\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Purpose and Scope\n\nThe server acts as a bridge between AI assistants and Microsoft 365 admin functionality:\n\n- **Tool Generation**: Auto-generates 444+ MCP tools from the Microsoft Graph OpenAPI specification 资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n- **Security-First Design**: Every write operation is classified with risk levels (low/medium/high/critical) 资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- **Least Privilege**: Tools declare minimum required Graph API permissions via `appPermissions` in `endpoints.json` 资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n    subgraph \"MCP Client (Claude Desktop/Code)\"\n        A[AI Assistant]\n    end\n    \n    subgraph \"ms-365-admin-mcp-server\"\n        B[index.ts - MCP Server]\n        C[auth.ts - MSAL Authentication]\n        D[cli.ts - CLI Parsing]\n        E[endpoints.json - Tool Definitions]\n        F[generated/ - Zod Client]\n        G[cloud-config.ts - Endpoint Routing]\n    end\n    \n    subgraph \"Microsoft Graph API\"\n        H[Global Cloud]\n        I[China 21Vianet]\n    end\n    \n    A <--> B\n    B <--> C\n    B <--> D\n    B <--> E\n    B <--> F\n    C <--> H\n    C <--> I\n    G --> H\n    G --> I\n```\n\n## Project Layout\n\n| Directory/File | Purpose |\n|----------------|---------|\n| `bin/` | Code-generation scripts (OpenAPI → Zod client) |\n| `src/auth.ts` | MSAL client credentials flow authentication |\n| `src/cli.ts` | Commander argv parsing for CLI arguments |\n| `src/cloud-config.ts` | Global vs China (21Vianet) endpoint routing |\n| `src/endpoints.json` | Source of truth for tool definitions |\n| `src/generated/` | Auto-generated Zod schemas from OpenAPI |\n| `src/index.ts` | Main MCP server entry point |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Tool Categories\n\nThe server organizes its 444+ tools into distinct categories for easier discovery and management:\n\n| Category | Pattern | Description |\n|----------|---------|-------------|\n| `identity` | `user\\|group\\|role\\|device\\|pim\\|guest\\|external` | Users, groups, roles, devices, PIM, guests, external identities |\n| `exchange` | `exchange\\|mailbox\\|message` | Message traces, mailboxes |\n| `intune` | `intune\\|managed-devic\\|compliance` | Devices, compliance, configurations, Autopilot, apps, RBAC |\n| `governance` | `role-resource-namespace` | Access reviews, entitlement, lifecycle workflows, PIM for Groups/Roles |\n| `response` | `disable\\|revoke\\|block\\|reset\\|wipe` | Incident response operations |\n| `ediscovery` | `ediscovery` | eDiscovery cases (Microsoft Purview) |\n| `cloudpc` | `cloud-pc\\|provisioning-polic` | Cloud PC / Windows 365 |\n| `callrecords` | `call-record\\|call-session\\|pstn` | Teams call records |\n| `print` | `print` | Universal Print |\n| `infoprotection` | `bitlocker\\|sensitivity-label` | BitLocker, threat assessment, sensitivity labels |\n| `sharepointadmin` | `sharepoint` | SharePoint tenant administration |\n| `retention` | `retention` | Records management |\n\n资料来源：[src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Risk Classification\n\nAll non-GET operations must be classified with a risk level before execution. The server enforces this through `src/risk-level.ts`:\n\n```mermaid\ngraph LR\n    A[Tool Request] --> B{Method?}\n    B -->|GET| C[Default: low]\n    B -->|POST/PATCH/DELETE| D[Default: critical]\n    E[Configured Risk] --> F[effectiveRiskLevel]\n    C --> F\n    D --> F\n    F --> G{Allowed?}\n    G -->|Yes| H[Execute]\n    G -->|No| I[Block + Error]\n```\n\n### Risk Level Rubric\n\n| Level | Criteria | Examples |\n|-------|----------|----------|\n| `low` | Read-only queries, reports, trivial annotations | `run-hunting-query`, `add-security-alert-comment`, Intune reports |\n| `medium` | Reversible mutation affecting single entity | `update-user`, `add-group-member`, `create-invitation` |\n| `high` | Broad scope, credential change, or destructive+ | `revoke-user-sessions`, `update-conditional-access-policy` |\n| `critical` | Irreversible or tenant-wide impact | `delete-user`, `wipe-managed-device`, `delete-conditional-access-policy` |\n\n资料来源：[src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n### Critical Tools (Require Out-of-Band Sign-off)\n\nThe following operations are blocked even with `--allow-writes` and require formal change requests:\n\n- `delete-user`, `delete-group`, `delete-application`\n- `delete-conditional-access-policy`\n- `delete-managed-device`, `wipe-managed-device`\n- `add-directory-role-member` (on privileged roles)\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n\n## Authentication Flow\n\nThe server supports two authentication methods:\n\n### 1. Client Credentials Flow (Service Principal)\n\nFor automated/headless scenarios:\n\n```typescript\n// src/auth.ts - MSAL client credentials flow\nconst credential = new ClientCredentialCredential({\n  clientId: process.env.MS365_ADMIN_MCP_CLIENT_ID,\n  clientSecret: process.env.MS365_ADMIN_MCP_CLIENT_SECRET,\n  tenantId: process.env.MS365_ADMIN_MCP_TENANT_ID,\n});\n```\n\n### 2. Device Code Bootstrap (RFC 8628)\n\nFor Claude Desktop/Code integration where browser-based auth isn't available:\n\n```bash\nnpx ms-365-admin-mcp-auth --server https://your-host.azurecontainerapps.io/mcp\n```\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n\n## Cloud Configuration\n\nThe server supports Microsoft Azure's global cloud and China (21Vianet) operated cloud:\n\n```typescript\n// src/cloud-config.ts\nexport const CLOUD_CONFIG = {\n  global: {\n    authority: 'https://login.microsoftonline.com',\n    graph: 'https://graph.microsoft.com',\n  },\n  china: {\n    authority: 'https://login.partner.microsoftonline.cn',\n    graph: 'https://microsoftgraph.chinacloudapi.cn',\n  },\n};\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Development Setup\n\n```bash\n# Clone and install\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\nnpm install\n\n# Generate client from Graph OpenAPI spec\nnpm run generate\n\n# Build\nnpm run build\n\n# Test\nnpm test\n\n# Run MCP Inspector\nnpm run inspector\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Tool Definition Schema\n\nEach tool in `endpoints.json` follows this structure:\n\n```json\n{\n  \"toolName\": \"list-users\",\n  \"method\": \"GET\",\n  \"path\": \"/v1.0/users\",\n  \"appPermissions\": [\"User.Read.All\"],\n  \"llmTip\": \"Returns a list of users in the organization\",\n  \"riskLevel\": \"low\"\n}\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `toolName` | Yes | Unique identifier used by MCP clients |\n| `method` | Yes | HTTP method (GET, POST, PATCH, DELETE) |\n| `path` | Yes | Graph API endpoint path |\n| `appPermissions` | Yes | Minimum required Graph API permissions |\n| `llmTip` | No | Hint shown to the LLM in tool description |\n| `riskLevel` | No* | Risk classification (only required for non-GET) |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Tool Execution Flow\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant Server as ms-365-admin-mcp-server\n    participant Graph as Microsoft Graph API\n    \n    Client->>Server: list-users(...)\n    Server->>Server: Check risk level\n    Server->>Server: Validate auth token\n    Server->>Graph: GET /v1.0/users\n    Graph-->>Server: User list response\n    Server-->>Client: Tool result\n```\n\n## Package Information\n\nThe project is published to both npm and GitHub Container Registry:\n\n| Registry | Package/Image |\n|----------|---------------|\n| npm | `@okapi-ca/ms-365-admin-mcp-server` |\n| GHCR | `ghcr.io/okapi-ca/ms-365-admin-mcp-server` |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Coding Standards\n\n- **TypeScript Strict Mode**: No `any` without justification 资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- **No New Runtime Dependencies**: Prefer standard library additions\n- **Prettier + ESLint**: Must pass (`npm run format:check` and `npm run lint`)\n- **Comments Explain Why**: Name things well instead of over-commenting\n\n## Version History\n\n| Version | Tools | Key Changes |\n|---------|-------|-------------|\n| Latest | 444 | Security fixes, `set-application-verified-publisher` risk bump |\n| v369 | 369 | Cloud PC, Teams call records, Universal Print, Info Protection |\n| v306 | 306 | eDiscovery, Cloud PC, Intune, Identity Governance |\n| v199 | 199 | Elevated `dismiss-risky-users` to high risk |\n| v175 | 175 | Full security review, PIM, risk detections |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n---\n\n<a id='installation'></a>\n\n## Installation Guide\n\n### 相关页面\n\n相关主题：[Configuration Reference](#configuration), [Docker and Container Deployment](#docker-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [Dockerfile](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/Dockerfile)\n- [docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md)\n- [docs/SETUP_MACOS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_MACOS_EN.md)\n- [docs/SETUP_WINDOWS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_WINDOWS_EN.md)\n</details>\n\n# Installation Guide\n\nThis guide covers all supported methods for installing and configuring the `ms-365-admin-mcp-server`. The server exposes Microsoft 365 admin APIs as MCP tools, enabling AI assistants to perform administrative operations across Azure AD, Intune, Exchange, SharePoint, Teams, and other Microsoft 365 workloads.\n\n## Prerequisites\n\n### System Requirements\n\n| Requirement | Minimum | Recommended |\n|-------------|---------|-------------|\n| Node.js | v20.x | v22.x LTS |\n| npm | v10.x | v10.x |\n| Memory | 512 MB | 1 GB |\n| Disk Space | 200 MB | 500 MB |\n| OS | Windows 10+, macOS 11+, Linux | Windows 11, macOS 14+, Ubuntu 22.04+ |\n\n### Azure AD Requirements\n\nBefore installation, you must have:\n\n- An Azure AD tenant (single-tenant required for client credentials flow)\n- An registered application with appropriate Graph API permissions\n- A valid client secret or certificate credential\n\n资料来源：[docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md)\n\n## Installation Methods\n\nThe server supports three installation methods:\n\n```mermaid\ngraph TD\n    A[Installation Methods] --> B[Docker Container]\n    A --> C[Node.js Direct]\n    A --> D[Claude Desktop Integration]\n    \n    B --> B1[GHCR Registry]\n    B --> B2[Dockerfile Build]\n    \n    C --> C1[npm Global]\n    C --> C2[Local Clone]\n    \n    D --> D1[Inspector Testing]\n    D --> D2[Production Config]\n```\n\n## Method 1: Docker Installation\n\n### Pull from GHCR Registry\n\nThe pre-built container image is published to GitHub Container Registry:\n\n```bash\ndocker pull ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### Run the Container\n\n```bash\ndocker run -d \\\n  --name mcp-server \\\n  -p 8080:8080 \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=\"your-client-id\" \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=\"your-client-secret\" \\\n  -e MS365_ADMIN_MCP_TENANT_ID=\"your-tenant-id\" \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### Docker Security Configuration\n\nThe Dockerfile implements several security controls:\n\n| Feature | Implementation |\n|---------|----------------|\n| Non-root user | Container runs as `node` user (UID 1000) |\n| Security headers | X-Content-Type-Options, X-Frame-Options: DENY, CSP |\n| Cache permissions | Token files stored with mode 0600 |\n| Network isolation | Single-tenant enforcement |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Docker Bind Mounts for Persistent Cache\n\nFor production deployments requiring persistent authentication cache:\n\n```bash\ndocker run -d \\\n  --name mcp-server \\\n  -p 8080:8080 \\\n  -v /path/to/cache:/home/node/.mcp-auth \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=\"your-client-id\" \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=\"your-client-secret\" \\\n  -e MS365_ADMIN_MCP_TENANT_ID=\"your-tenant-id\" \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\nThe server honors the `MCP_REMOTE_CONFIG_DIR` environment variable, allowing Docker bind mounts and multi-user setups without patches.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Build from Dockerfile\n\nFor customization or air-gapped deployments:\n\n```bash\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\ndocker build -t ms-365-admin-mcp-server:local .\n```\n\n## Method 2: Node.js Installation\n\n### Option A: Install from npm Registry\n\n```bash\nnpm install -g @okapi-ca/ms-365-admin-mcp-server\n```\n\n### Option B: Local Development Setup\n\n```bash\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\nnpm install\n```\n\n#### Build Steps\n\n```bash\nnpm run generate    # Download Graph OpenAPI spec and generate client\nnpm run build\n```\n\n#### Verify Installation\n\n```bash\nnpm test\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Azure AD Application Registration\n\n### Required Permissions\n\nThe application requires Microsoft Graph API permissions. The following table summarizes permission scopes by category:\n\n| Category | Permission Type | Required Scopes |\n|----------|----------------|-----------------|\n| User Management | Application | User.ReadWrite.All |\n| Group Management | Application | Group.ReadWrite.All |\n| Device Management | Application | DeviceManagementManagedDevices.ReadWrite.All |\n| Exchange Admin | Application | Exchange.Admin |\n| SharePoint | Application | SharePoint.Admin |\n| Teams | Application | Team.ReadWrite.All |\n| Security | Application | SecurityEvents.ReadWrite.All |\n\n### Registration Steps\n\n1. Navigate to Azure Portal → Azure Active Directory → App registrations\n2. Select **New registration**\n3. Configure the application:\n   - **Name**: `ms-365-admin-mcp-server`\n   - **Supported account types**: Accounts in this organizational directory only\n   - **Redirect URI**: Leave blank (not required for daemon apps)\n4. Navigate to **Certificates & secrets** → **New client secret**\n5. Copy and securely store the secret value (it cannot be retrieved later)\n6. Navigate to **API permissions** → **Add a permission** → **Microsoft Graph**\n7. Select **Application permissions** and add required scopes\n8. Click **Grant admin consent**\n\n资料来源：[docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md)\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Yes | Azure AD application (client) ID |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Yes | Client secret value |\n| `MS365_ADMIN_MCP_TENANT_ID` | Yes | Azure AD tenant ID |\n| `MCP_REMOTE_CONFIG_DIR` | No | Override cache directory path |\n| `CI` | No | Set to `true` to disable clipboard operations |\n| `PORT` | No | HTTP server port (default: 8080) |\n\n### Local .env File\n\nCreate a `.env` file in the project root for local development:\n\n```bash\nMS365_ADMIN_MCP_CLIENT_ID=your-client-id\nMS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret\nMS365_ADMIN_MCP_TENANT_ID=your-tenant-id\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Command-Line Options\n\n```bash\nnode dist/index.js --help\n```\n\n| Option | Description |\n|--------|-------------|\n| `--client-id <id>` | Override MS365_ADMIN_MCP_CLIENT_ID |\n| `--client-secret <secret>` | Override MS365_ADMIN_MCP_CLIENT_SECRET |\n| `--tenant-id <id>` | Override MS365_ADMIN_MCP_TENANT_ID |\n| `--cache-dir <path>` | Override token cache directory |\n| `--allow-writes` | Enable write operations (default: read-only) |\n| `--list-tools` | List available tools and exit |\n| `--preset <name>` | Enable preset category filters |\n\n## Claude Desktop Integration\n\n### macOS Configuration\n\n1. Locate the Claude Desktop configuration file:\n   ```bash\n   ~/Library/Application Support/Claude/claude_desktop_config.json\n   ```\n\n2. Add the MCP server configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"--rm\",\n        \"-i\",\n        \"--env-file\",\n        \"/absolute/path/to/.env\",\n        \"-v\",\n        \"/path/to/cache:/home/node/.mcp-auth\",\n        \"ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\"\n      ]\n    }\n  }\n}\n```\n\n资料来源：[docs/SETUP_MACOS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_MACOS_EN.md)\n\n### Windows Configuration\n\n1. Locate the Claude Desktop configuration file:\n   ```powershell\n   %APPDATA%\\Claude\\claude_desktop_config.json\n   ```\n\n2. Add the MCP server configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"--rm\",\n        \"-i\",\n        \"--env-file\",\n        \"C:\\\\path\\\\to\\\\.env\",\n        \"-v\",\n        \"mcp-cache:C:\\\\Users\\\\ContainerAdministrator\\\\.mcp-auth\",\n        \"ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\"\n      ]\n    }\n  }\n}\n```\n\n资料来源：[docs/SETUP_WINDOWS_EN.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SETUP_WINDOWS_EN.md)\n\n### Interactive Testing with MCP Inspector\n\nFor testing the server configuration:\n\n```bash\nnpm run inspector\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Device Code Authentication (Optional)\n\nFor environments where browser-based authentication is unavailable, the server supports RFC 8628 device code flow:\n\n```bash\nnpx ms-365-admin-mcp-auth \\\n  --server https://your-host.azurecontainerapps.io/mcp\n```\n\nThe auth bootstrap tool:\n- Polls `/token` endpoint for authentication completion\n- Writes cache files (`<hash>_client_info.json` and `<hash>_tokens.json`) to `~/.mcp-auth/mcp-remote-<version>/`\n- Uses mode 0600 for cache files (secure permissions)\n- Cache key = `md5(serverUrl)`, matching `mcp-remote`'s `getServerUrlHash` exactly\n- Supports best-effort clipboard copy (auto-disabled under `CI=true` or non-TTY)\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n\n## Verifying Installation\n\n### List Available Tools\n\n```bash\nnode dist/index.js --list-tools\n```\n\nThis outputs all available MCP tools organized by category.\n\n### Test Authentication\n\n```bash\ncurl http://localhost:8080/health\n```\n\nExpected response:\n```json\n{\"status\": \"ok\", \"authenticated\": true}\n```\n\n## Exit Codes\n\nThe server documents exit codes for Docker/CI wrappers:\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success |\n| 1 | Usage error / invalid configuration |\n| 2 | Network error / Azure AD unreachable |\n| 3 | Access denied (insufficient permissions) |\n| 4 | Request timeout |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Troubleshooting\n\n### Common Issues\n\n| Issue | Solution |\n|-------|----------|\n| `Tenant 'common' rejected` | Ensure single-tenant registration; set `MS365_ADMIN_MCP_TENANT_ID` explicitly |\n| Token cache not persisting | Use `-v` flag to bind mount cache directory in Docker |\n| Permission denied errors | Verify app registration has admin consent granted |\n| Container exits immediately | Check logs with `docker logs mcp-server`; verify environment variables |\n\n### Documentation References\n\n- [Troubleshooting Guide](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/TROUBLESHOOTING.md) — covers Server disconnected, Platform SSO symptoms, device_code flow walkthrough\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md) — security architecture and best practices\n\n## Next Steps\n\nAfter successful installation:\n\n1. Review the [Tool Catalog](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md) to understand available operations\n2. Configure appropriate [risk levels](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md) for write operations\n3. Review use case patterns for [Identity Management](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/usecase-identity.md), [Intune](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/usecase-intune.md), and other workloads\n\n---\n\n<a id='configuration'></a>\n\n## Configuration Reference\n\n### 相关页面\n\n相关主题：[Project Overview](#overview), [Installation Guide](#installation), [HTTP Transport and Deployment](#http-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/cli.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/cli.ts)\n- [src/cloud-config.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/cloud-config.ts)\n- [src/secrets.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/secrets.ts)\n- [src/auth.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n</details>\n\n# Configuration Reference\n\n## Overview\n\nThe ms-365-admin-mcp-server provides a comprehensive configuration system that controls authentication, cloud endpoint selection, risk-based access control, and tool filtering. Configuration is driven through a combination of environment variables, CLI arguments, and JSON-based endpoint definitions.\n\nThe server implements a least-privilege security model where tools are classified by risk level, and the server operator can enforce a maximum permissible risk threshold to prevent accidental execution of destructive operations.\n\n## Configuration Architecture\n\n```mermaid\ngraph TD\n    A[Environment Variables] --> B[Secrets Module]\n    A --> C[Cloud Config Module]\n    D[CLI Arguments] --> E[CLI Parser]\n    E --> F[Runtime Config]\n    B --> F\n    C --> F\n    G[endpoints.json] --> H[Tool Registry]\n    H --> I[Risk Level Classifier]\n    I --> J[Access Control Filter]\n    F --> J\n    J --> K[MCP Tools]\n    \n    L[Auth Module] --> M[MSAL Token Cache]\n    B --> L\n    F --> L\n```\n\n## Environment Variables\n\nThe server requires Azure AD application registration credentials. All environment variables use the `MS365_ADMIN_MCP_` prefix.\n\n### Required Variables\n\n| Variable | Description | Required |\n|----------|-------------|----------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Azure AD application (client) ID | Yes |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Client secret for the application | Yes |\n| `MS365_ADMIN_MCP_TENANT_ID` | Azure AD tenant ID | Yes |\n\n### Optional Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `MS365_ADMIN_MCP_MAX_RISK_LEVEL` | Maximum risk level permitted | `medium` |\n| `MS365_ADMIN_MCP_CLOUD` | Target cloud: `global` or `china` | `global` |\n| `MS365_ADMIN_MCP_PRESET` | Comma-separated list of tool presets | `all` |\n| `MS365_ADMIN_MCP_PORT` | HTTP server port | `3000` |\n| `MCP_REMOTE_CONFIG_DIR` | Custom cache directory for OAuth tokens | Platform default |\n\n### Risk Level Configuration\n\nRisk levels control which tools are exposed or executable. The server enforces a maximum risk level that acts as an access control gate.\n\n| Risk Level | Rank | Description |\n|------------|------|-------------|\n| `low` | 1 | Safe read-only operations |\n| `medium` | 2 | Operations with moderate impact |\n| `high` | 3 | Significant impact operations |\n| `critical` | 4 | Irreversible or tenant-wide operations |\n\nThe effective risk level for a tool is determined as follows (资料来源：[src/risk-level.ts:1-20]())：\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\nKey rules:\n\n- If `configuredRiskLevel` is explicitly set, it is used directly\n- GET endpoints without explicit configuration default to `low`\n- Write endpoints without explicit configuration default to `critical` (fail-safe)\n- A tool is allowed if `rank(effectiveRiskLevel) <= rank(maxRiskLevel)`\n\n## Cloud Configuration\n\nThe server supports Microsoft 365 deployments in different sovereign clouds.\n\n```mermaid\ngraph LR\n    A[Config: cloud=global] --> B[login.microsoftonline.com]\n    C[Config: cloud=china] --> D[login.partner.microsoftonline.cn]\n    B --> E[Microsoft Graph Global]\n    D --> F[Microsoft Graph China 21Vianet]\n```\n\n### Supported Clouds\n\n| Cloud Identifier | Azure Environment | Graph Endpoint |\n|-----------------|-------------------|----------------|\n| `global` | Microsoft Azure | `https://graph.microsoft.com` |\n| `china` | Azure China 21Vianet | `https://microsoftgraph.chinacloudapi.cn` |\n\nThe cloud configuration is loaded from environment variable `MS365_ADMIN_MCP_CLOUD` (资料来源：[src/cloud-config.ts]()) and determines which Microsoft Graph endpoint the server authenticates against.\n\n## CLI Arguments\n\nThe server accepts command-line arguments parsed by Commander.js (资料来源：[src/cli.ts]())。\n\n| Argument | Short | Description | Default |\n|----------|-------|-------------|---------|\n| `--max-risk-level` | `-r` | Maximum risk level (low/medium/high/critical) | `medium` |\n| `--preset` | `-p` | Tool preset filter (security, identity, etc.) | `all` |\n| `--port` | | HTTP server port | `3000` |\n| `--list-tools` | | List available tools and exit | `false` |\n| `--inspector` | | Run with MCP Inspector | `false` |\n\n### Listing Tools with Presets\n\nTo validate preset patterns, run:\n\n```bash\nnode dist/index.js --preset mypreset --list-tools\n```\n\nThis validates that the preset regex matches tool names defined in `endpoints.json`.\n\n## Tool Presets\n\nTool presets filter the available tools based on regex patterns defined in `src/tool-categories.ts` (资料来源：[src/tool-categories.ts]())。\n\n### Available Presets\n\n| Preset Name | Pattern Matches | Description |\n|-------------|-----------------|-------------|\n| `security` | security, alert, incident, attack-simulation, threat-intel | Microsoft 365 Defender tools |\n| `audit` | audit, sign-in, provisioning, directory, deleted | Audit logs and sign-in activity |\n| `health` | service, health, issue, message | Service health and Message Center |\n| `reports` | report, activity, usage | Usage reports (Teams, Email, SharePoint) |\n| `identity` | user, group, role, conditional, directory, device, pim | Entra ID management |\n| `exchange` | exchange, mailbox, message, mail | Exchange Online administration |\n| `intune` | intune, managed, compliance, autopilot, mdm, mam | Intune device management |\n| `governance` | access-review, entitlement, lifecycle, terms-of-use | Identity Governance |\n| `compliance` | compliance, license, secure-score, risk-detection | Compliance center tools |\n| `response` | disable-user, revoke, block, reset, dismiss, wipe | Incident response operations |\n| `ediscovery` | ediscovery | Microsoft Purview eDiscovery |\n| `cloudpc` | cloud-pc, provisioning-policy | Windows 365 Cloud PC |\n| `callrecords` | call-record, call-session, pstn-call | Teams call records |\n| `print` | print | Universal Print |\n| `infoprotection` | bitlocker, sensitivity, threat-assessment | Information Protection |\n| `sharepointadmin` | sharepoint, site-admin | SharePoint admin center |\n| `retention` | retention, records | Records management |\n| `teamsadmin` | team, teams-app, teams-policy | Teams administration |\n| `all` | .* | All available tools |\n\n### Combining Presets\n\nMultiple presets can be combined using the `getCombinedPresetPattern` function (资料来源：[src/tool-categories.ts:60-75]())：\n\n```typescript\nexport function getCombinedPresetPattern(presets: string[]): string {\n  const patterns = presets.map((preset) => {\n    const category = TOOL_CATEGORIES[preset];\n    if (!category) {\n      throw new Error(\n        `Unknown preset: ${preset}. Available presets: ${Object.keys(TOOL_CATEGORIES).join(', ')}`\n      );\n    }\n    return category.pattern.source;\n  });\n  return patterns.join('|');\n}\n```\n\n## Authentication Configuration\n\nAuthentication uses the MSAL (Microsoft Authentication Library) client credentials flow (资料来源：[src/auth.ts]())。\n\n### Authentication Flow\n\n```mermaid\nsequenceDiagram\n    participant Server\n    participant MSAL\n    participant Azure AD\n    \n    Server->>Azure AD: Request token with client credentials\n    Azure AD-->>MSAL: Access token + refresh token\n    MSAL-->>Server: Token cached\n    Server->>Azure AD: Graph API calls with bearer token\n    Azure AD-->>Server: Response\n```\n\n### Token Cache Location\n\nTokens are cached in:\n- **macOS/Linux**: `~/.mcp-auth/mcp-remote-<version>/`\n- **Windows**: `%USERPROFILE%\\.mcp-auth\\mcp-remote-<version>\\`\n\nCache files are named `<hash>_client_info.json` and `<hash>_tokens.json` with mode 0600 permissions.\n\n### Remote Server Authentication\n\nFor remote HTTP server mode, device code authentication is supported (资料来源：[CONTRIBUTING.md]())：\n\n- Cache key = `md5(serverUrl)` to match `mcp-remote`'s `getServerUrlHash`\n- Best-effort clipboard copy for device codes (auto-disabled under `CI=true`)\n- Configurable cache directory via `--cache-dir` or `MCP_REMOTE_CONFIG_DIR`\n\n## Endpoint Configuration\n\nThe `src/endpoints.json` file is the source of truth for all tool definitions (资料来源：[src/endpoints.json]())。\n\n### Endpoint Schema\n\nEach endpoint definition includes:\n\n| Field | Description |\n|-------|-------------|\n| `toolName` | Unique identifier for the tool |\n| `method` | HTTP method (GET, POST, PATCH, DELETE) |\n| `path` | Microsoft Graph API path |\n| `description` | Human-readable description |\n| `appPermissions` | Required Graph API permissions |\n| `riskLevel` | Configured risk level (low/medium/high/critical) |\n| `category` | Tool category for filtering |\n\n### Risk Classification Examples\n\nCritical-risk tools (资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md]())：\n\n- `delete-user`\n- `delete-group`\n- `delete-conditional-access-policy`\n- `wipe-managed-device`\n- `delete-managed-device`\n\nHigh-risk tools:\n- `revoke-user-sessions`\n- `confirm-compromised-users`\n- `create-conditional-access-policy`\n- `update-conditional-access-policy`\n\n## Configuration Precedence\n\nConfiguration values are resolved in the following order (highest to lowest priority):\n\n1. CLI arguments (command-line overrides)\n2. Environment variables\n3. Default values\n\n```mermaid\ngraph TD\n    A[Config Sources] --> B[CLI Arguments]\n    A --> C[Environment Variables]\n    A --> D[Default Values]\n    B --> E[Runtime Merged Config]\n    C --> E\n    D --> E\n    E --> F[Server Initialization]\n```\n\n## Example Configuration Files\n\n### Development .env File\n\nCreate a local `.env` file in the project root (资料来源：[CONTRIBUTING.md]())：\n\n```bash\nMS365_ADMIN_MCP_CLIENT_ID=your-app-client-id\nMS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret\nMS365_ADMIN_MCP_TENANT_ID=your-tenant-id\n```\n\n### Docker Configuration\n\nFor Docker deployments, use environment variables or bind-mounted configuration:\n\n```bash\ndocker run \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=... \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=... \\\n  -e MS365_ADMIN_MCP_TENANT_ID=... \\\n  -e MS365_ADMIN_MCP_MAX_RISK_LEVEL=medium \\\n  -e MCP_REMOTE_CONFIG_DIR=/data/mcp-config \\\n  -v /path/to/config:/data/mcp-config \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server\n```\n\n## Exit Codes\n\nThe server uses specific exit codes for Docker and CI integration (资料来源：[CONTRIBUTING.md]())：\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success |\n| 1 | Usage error / invalid configuration |\n| 2 | Network error |\n| 3 | Authentication denied |\n| 4 | Request timeout |\n\n## Verification\n\nRun the verification script to ensure configuration is valid:\n\n```bash\nnpm run verify\n```\n\nThis runs:\n- TypeScript compilation (`npm run build`)\n- Linting (`npm run lint`)\n- Formatting checks (`npm run format:check`)\n- Test suite (`npm test`)\n\n---\n\n<a id='system-architecture'></a>\n\n## System Architecture\n\n### 相关页面\n\n相关主题：[Project Overview](#overview), [Code Generation Pipeline](#code-generation), [Tool Categories and Presets](#tool-categories)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [docs/ARCHITECTURE.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/ARCHITECTURE.md)\n- [src/server.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/server.ts)\n- [src/http-server.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/http-server.ts)\n- [src/graph-client.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/graph-client.ts)\n- [src/auth.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth.ts)\n</details>\n\n# System Architecture\n\nThe ms-365-admin-mcp-server is a Model Context Protocol (MCP) server that exposes Microsoft 365 administrative operations as AI-consumable tools. It acts as a bridge between Large Language Models (LLMs) and the Microsoft Graph API, providing over 444 administrative endpoints organized into security-aware tool categories.\n\n## Overview\n\nThe server follows a layered architecture pattern with clear separation of concerns:\n\n1. **Authentication Layer** — MSAL-based OAuth2 client credentials flow\n2. **Tool Registry** — Declarative tool definitions from OpenAPI specs\n3. **Risk Control Layer** — Tool filtering based on configurable risk thresholds\n4. **MCP Transport Layer** — STDIO server or HTTP/SSE endpoint\n5. **Graph API Client** — Auto-generated TypeScript client from OpenAPI\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Core Components\n\n### Authentication Module (`src/auth.ts`)\n\nThe server uses MSAL (Microsoft Authentication Library) with the client credentials flow for service-to-service authentication. This flow is suitable for daemon applications that operate without user interaction.\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                    Authentication Flow                          │\n├─────────────────────────────────────────────────────────────────┤\n│  1. Server starts → Initialize MSAL ConfidentialClientApplication │\n│  2. Acquire token via client credentials (client_id + secret)     │\n│  3. Token cached with expiration handling                         │\n│  4. Graph API calls include Bearer token                          │\n│  5. On 401 → Automatic token refresh                              │\n└─────────────────────────────────────────────────────────────────┘\n```\n\nConfiguration requires three environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Azure AD application (client) ID |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Client secret from certificate or app registration |\n| `MS365_ADMIN_MCP_TENANT_ID` | Azure AD tenant ID |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Cloud Configuration (`src/cloud-config.ts`)\n\nThe server supports Microsoft Azure's global cloud as well as the China (21Vianet) operated cloud. Endpoint selection is configurable to support sovereign cloud deployments.\n\n| Cloud Environment | Endpoint Pattern |\n|-------------------|------------------|\n| Global | `graph.microsoft.com` |\n| China (21Vianet) | `graph.microsoft.cn` |\n\n### Tool Registry (`src/endpoints.json`)\n\nThe `endpoints.json` file is the source of truth for all tool definitions. Each tool entry specifies:\n\n```json\n{\n  \"toolName\": {\n    \"method\": \"GET|POST|PATCH|PUT|DELETE\",\n    \"path\": \"/v1.0/{resource}\",\n    \"appPermissions\": [\"Permission.Read.All\"],\n    \"llmTip\": \"Human-readable hint for the LLM\",\n    \"riskLevel\": \"low|medium|high|critical\"\n  }\n}\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Risk Level System (`src/risk-level.ts`)\n\nThe server implements a risk-based access control system. Each non-GET operation must declare a risk level, and operators can configure a maximum allowed risk level.\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\nRisk levels are enforced at runtime:\n\n| Level | Criteria | Examples |\n|-------|----------|----------|\n| `low` | Read-only in effect | `list-users`, reports |\n| `medium` | Reversible mutation | `update-user`, `add-group-member` |\n| `high` | Broad scope or credential changes | `revoke-user-sessions`, `update-conditional-access-policy` |\n| `critical` | Irreversible or tenant-wide | `delete-user`, `wipe-managed-device` |\n\n资料来源：[src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts), [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Tool Categories (`src/tool-categories.ts`)\n\nTools are organized into preset categories that map to regex patterns. Users can select specific categories to reduce the tool surface or enable focused administration.\n\n```typescript\nexport const TOOL_CATEGORIES: Record<string, ToolCategory> = {\n  identity: {\n    name: 'identity',\n    pattern: /user|group|device|directory|role/i,\n    description: 'Users, groups, roles, devices, PIM, guests, external identities',\n  },\n  compliance: {\n    name: 'compliance',\n    pattern: /license|secure-score|conditional-access|auth-methods/i,\n    description: 'Licenses, Secure Score, Identity Protection, risk detections, CA policies',\n  },\n  // ... additional categories\n};\n```\n\nAvailable presets include: `identity`, `exchange`, `intune`, `governance`, `compliance`, `response`, `ediscovery`, `cloudpc`, `callrecords`, `print`, `infoprotection`, `sharepointadmin`, `retention`, `teamsadmin`, `reports`, `audit`, and `all`.\n\n资料来源：[src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Server Architecture\n\n### STDIO Mode (MCP Standard)\n\nIn standard MCP mode, the server communicates over STDIO using JSON-RPC messages. This is the default mode for Claude Desktop and other MCP-compatible clients.\n\n```\n┌──────────────┐     STDIO (JSON-RPC)      ┌──────────────────────┐\n│  MCP Client  │ ◄──────────────────────► │  ms-365-admin-mcp    │\n│  (Claude)    │                           │  server              │\n└──────────────┘                           └──────────────────────┘\n```\n\n### HTTP Server Mode\n\nThe server can also run as an HTTP endpoint with Server-Sent Events (SSE) for streaming responses. This mode is suitable for remote deployments in containerized environments.\n\n```\n┌──────────────┐     HTTPS + SSE           ┌──────────────────────┐\n│  HTTP Client │ ◄──────────────────────► │  ms-365-admin-mcp    │\n│  (Remote)    │                           │  http-server         │\n└──────────────┘                           └──────────────────────┘\n```\n\nThe HTTP server supports two authentication mechanisms:\n\n1. **OAuth2 Client Credentials** — Direct token authentication\n2. **Device Code Flow** — Interactive authentication for CLI tools\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Device Code Bootstrap (`src/auth-bootstrap.ts`)\n\nFor HTTP server deployments, the `ms-365-admin-mcp-auth` CLI tool implements RFC 8628 device code flow to pre-seed the mcp-remote token cache:\n\n```bash\nms-365-admin-mcp-auth --server https://your-host.azurecontainerapps.io/mcp\n```\n\nThis allows Claude Desktop/Code to skip the browser-based authentication flow when connecting to remote servers.\n\nKey features:\n- Cache key = `md5(serverUrl)` for compatibility with mcp-remote\n- Token files stored in `~/.mcp-auth/mcp-remote-<version>/` with mode 0600\n- Best-effort clipboard copy (auto-disabled under `CI=true`)\n- Exit codes: 0 (ok), 1 (usage), 2 (network), 3 (denied), 4 (timeout)\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts), [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Code Generation Pipeline\n\nThe server uses a code generation pipeline to transform the Microsoft Graph OpenAPI specification into type-safe TypeScript/Zod client code:\n\n```\n┌─────────────────┐     npm run generate      ┌─────────────────────┐\n│  Graph OpenAPI  │ ───────────────────────► │  src/generated/      │\n│  Specification  │                          │  (zod schemas +     │\n│                 │                          │   typed clients)    │\n└─────────────────┘                          └─────────────────────┘\n```\n\nThe `bin/` directory contains scripts that:\n1. Download the latest Graph API OpenAPI spec\n2. Parse and transform the specification\n3. Generate Zod validation schemas\n4. Create typed Graph API client methods\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## CLI Interface (`src/cli.ts`)\n\nThe server uses Commander.js for CLI argument parsing. Key commands:\n\n| Command | Description |\n|---------|-------------|\n| `npm run inspector` | Start MCP Inspector for interactive testing |\n| `--list-tools` | Display all available tools matching current preset |\n| `--list-permissions` | Show required Graph API permissions |\n| `--preset <name>` | Select tool category preset |\n| `--max-risk <level>` | Set maximum allowed risk level |\n| `--allow-writes` | Enable write operations (disabled by default) |\n\nExample usage:\n```bash\n# List tools in the identity preset\nnode dist/index.js --preset identity --list-tools\n\n# Start with compliance tools and allow medium-risk operations\nnode dist/index.js --preset compliance --max-risk medium --allow-writes\n```\n\n## Security Model\n\nThe server implements defense-in-depth through multiple layers:\n\n### 1. Permission Layer\nEvery tool declares minimum required Graph API permissions (`appPermissions`). The server never requests overly broad permissions like `.ReadWrite.All` when `.Read.All` suffices.\n\n### 2. Risk Classification\nWrite operations are classified into four risk levels. The `--max-risk` flag limits which operations can execute.\n\n### 3. Explicit Write Confirmation\nBy default, write operations are disabled. The `--allow-writes` flag enables them, but high-risk operations still require explicit confirmation.\n\n### 4. Audit Trail\nAll operations are logged with timestamps, tool names, and risk levels for security auditing.\n\nCritical-risk tools require out-of-band sign-off and should not be executed through the chat interface without formal change request documentation:\n\n| Tool | Risk Level |\n|------|------------|\n| `delete-user` | critical |\n| `delete-group` | critical |\n| `delete-conditional-access-policy` | critical |\n| `delete-managed-device` | critical |\n| `wipe-managed-device` | critical |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n\n## Development Workflow\n\n### Local Development Setup\n\n```bash\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\nnpm install\nnpm run generate    # Download Graph OpenAPI spec and generate client\nnpm run build\nnpm test\n```\n\n### Adding a New Tool\n\n1. Edit `src/endpoints.json` with the new endpoint definition\n2. Run `npm run generate` to regenerate the client\n3. Verify tool registration with `--list-tools`\n4. Add tests for non-trivial parameter handling\n5. Update `README.md` tool tables\n\n### Verification Commands\n\n```bash\nnpm run format:check  # Prettier validation\nnpm run lint          # ESLint validation\nnpm test              # Run test suite\nnpm run verify        # All checks (format + lint + test)\n```\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Project Layout\n\n```\nms-365-admin-mcp-server/\n├── bin/                    # Code-generation scripts (OpenAPI → zod client)\n├── src/\n│   ├── auth.ts             # MSAL client credentials flow\n│   ├── auth-bootstrap.ts   # Device code bootstrap CLI\n│   ├── cli.ts              # Commander argv parsing\n│   ├── cloud-config.ts     # Global vs China (21Vianet) endpoints\n│   ├── endpoints.json      # Source of truth for tool definitions\n│   ├── generated/          # Auto-generated zod schemas and clients\n│   ├── graph-client.ts     # Graph API client wrapper\n│   ├── http-server.ts      # HTTP/SSE server implementation\n│   ├── risk-level.ts       # Risk classification logic\n│   ├── server.ts           # MCP STDIO server implementation\n│   └── tool-categories.ts  # Tool category presets\n├── docs/                   # Documentation\n├── agent-skills/           # Claude Code skill definitions\n└── README.md\n```\n\n## Deployment Options\n\n### Docker Container\n\nThe server is published to GitHub Container Registry:\n\n```bash\ndocker run -p 8080:8080 \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=... \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=... \\\n  -e MS365_ADMIN_MCP_TENANT_ID=... \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### Claude Desktop Integration\n\nFor local development, add to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@okapi-ca/ms-365-admin-mcp-server\"],\n      \"env\": {\n        \"MS365_ADMIN_MCP_CLIENT_ID\": \"...\",\n        \"MS365_ADMIN_MCP_CLIENT_SECRET\": \"...\",\n        \"MS365_ADMIN_MCP_TENANT_ID\": \"...\"\n      }\n    }\n  }\n}\n```\n\n### Claude Code Skill Installation\n\n```bash\ncp -r agent-skills/ms365-admin-mcp ~/.claude/skills/\n```\n\nThe skill auto-loads when the conversation matches its description field.\n\n---\n\n<a id='code-generation'></a>\n\n## Code Generation Pipeline\n\n### 相关页面\n\n相关主题：[System Architecture](#system-architecture), [Tool Categories and Presets](#tool-categories)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [bin/generate-graph-client.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/generate-graph-client.mjs)\n- [bin/modules/generate-mcp-tools.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/generate-mcp-tools.mjs)\n- [bin/modules/simplified-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/simplified-openapi.mjs)\n- [bin/modules/extract-descriptions.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/extract-descriptions.mjs)\n- [bin/modules/download-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/download-openapi.mjs)\n- [src/generated/endpoint-types.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/generated/endpoint-types.ts)\n- [src/graph-tools.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/graph-tools.ts)\n- [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n</details>\n\n# Code Generation Pipeline\n\n## Overview\n\nThe **Code Generation Pipeline** is an automated build process that transforms the Microsoft Graph OpenAPI specification into a fully-typed MCP (Model Context Protocol) server implementation. This pipeline generates TypeScript/Zod schemas, endpoint types, and tool definitions, enabling type-safe interactions with over 500 Microsoft Graph API endpoints.\n\n**资料来源:** [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n    A[Microsoft Graph OpenAPI Spec] --> B[download-openapi.mjs]\n    B --> C[simplified-openapi.mjs]\n    C --> D[extract-descriptions.mjs]\n    D --> E[generate-mcp-tools.mjs]\n    E --> F[generate-graph-client.mjs]\n    F --> G[src/generated/]\n    G --> H[endpoint-types.ts]\n    G --> I[schemas.ts]\n    G --> J[descriptions.ts]\n    G --> K[endpoints.json]\n    K --> L[graph-tools.ts]\n    L --> M[MCP Server]\n```\n\n## Pipeline Components\n\n### 1. OpenAPI Download Module\n\n**File:** `bin/modules/download-openapi.mjs`\n\nDownloads the Microsoft Graph OpenAPI specification from the official Microsoft Graph metadata repository.\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `outputPath` | `string` | Local path to save the downloaded OpenAPI spec |\n| `version` | `string` | API version to download (default: `v1.0`) |\n\n**Key behaviors:**\n- Fetches OpenAPI spec from `https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml`\n- Handles network errors with retry logic\n- Validates downloaded file structure\n\n**资料来源:** [bin/modules/download-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/download-openapi.mjs)\n\n### 2. Simplified OpenAPI Processor\n\n**File:** `bin/modules/simplified-openapi.mjs`\n\nTransforms the raw OpenAPI specification into a simplified intermediate format optimized for code generation.\n\n**Transformation rules:**\n- Flattens nested schema references\n- Resolves `$ref` pointers\n- Extracts path parameters, query parameters, and request body schemas\n- Normalizes response schemas\n\n**Output structure:**\n\n```typescript\ninterface SimplifiedEndpoint {\n  path: string;\n  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n  operationId: string;\n  summary?: string;\n  parameters: Parameter[];\n  requestBody?: RequestBody;\n  responses: Record<string, Response>;\n  security?: SecurityRequirement[];\n}\n```\n\n**资料来源:** [bin/modules/simplified-openapi.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/simplified-openapi.mjs)\n\n### 3. Description Extractor\n\n**File:** `bin/modules/extract-descriptions.mjs`\n\nExtracts human-readable descriptions from OpenAPI operations for use in tool documentation and LLM prompts.\n\n**Extraction sources (priority order):**\n1. `operation.description` - Primary description\n2. `operation.summary` - Fallback summary\n3. Parameter descriptions from schema\n\n**Generated output:**\n\n```typescript\ninterface ToolDescription {\n  operationId: string;\n  description: string;\n  parameterDescriptions: Record<string, string>;\n  deprecationNotice?: string;\n}\n```\n\n**资料来源:** [bin/modules/extract-descriptions.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/extract-descriptions.mjs)\n\n### 4. MCP Tools Generator\n\n**File:** `bin/modules/generate-mcp-tools.mjs`\n\nGenerates MCP tool definitions from the processed OpenAPI specification.\n\n**Generation process:**\n\n```mermaid\ngraph LR\n    A[OpenAPI Operations] --> B[Parse endpoint config]\n    B --> C[Generate tool name]\n    C --> D[Create Zod schema]\n    D --> E[Extract risk level]\n    E --> F[Write to endpoints.json]\n```\n\n**Tool naming convention:**\n- Operation IDs are converted to kebab-case\n- Prefixes are preserved for categorization (e.g., `list-`, `get-`, `create-`, `update-`, `delete-`)\n\n**Generated metadata per tool:**\n\n| Field | Source | Description |\n|-------|--------|-------------|\n| `toolName` | operationId → kebab-case | Unique tool identifier |\n| `pathPattern` | OpenAPI path | API endpoint path |\n| `method` | HTTP method | GET, POST, PUT, PATCH, DELETE |\n| `appPermissions` | securitySchemes | Required Graph API permissions |\n| `llmTip` | description | Optional hint for LLM context |\n| `riskLevel` | Manual annotation | low/medium/high/critical |\n\n**资料来源:** [bin/modules/generate-mcp-tools.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/modules/generate-mcp-tools.mjs), [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n\n### 5. Graph Client Generator\n\n**File:** `bin/generate-graph-client.mjs`\n\nOrchestrates the entire pipeline and generates TypeScript source files.\n\n**Generated artifacts:**\n\n| File | Purpose |\n|------|---------|\n| `src/generated/endpoint-types.ts` | TypeScript interfaces for all endpoints |\n| `src/generated/schemas.ts` | Zod validation schemas |\n| `src/generated/descriptions.ts` | Tool descriptions and documentation |\n\n**资料来源:** [bin/generate-graph-client.mjs](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/bin/generate-graph-client.mjs)\n\n## Generated Output Files\n\n### endpoint-types.ts\n\nAuto-generated TypeScript types derived from OpenAPI schemas.\n\n```typescript\n// Auto-generated - DO NOT EDIT\nexport interface ListUsersResponse {\n  '@odata.context'?: string;\n  value: User[];\n}\n```\n\n**资料来源:** [src/generated/endpoint-types.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/generated/endpoint-types.ts)\n\n### endpoints.json\n\nThe source of truth for all tool definitions, serving as the configuration manifest for tool registration.\n\n```jsonc\n{\n  \"toolName\": \"list-users\",\n  \"pathPattern\": \"/users\",\n  \"method\": \"GET\",\n  \"appPermissions\": [\"User.Read.All\"],\n  \"llmTip\": \"List all users in the organization\",\n  \"riskLevel\": \"low\"\n}\n```\n\n**资料来源:** [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n\n## Tool Registration Flow\n\nAfter code generation, the pipeline integrates with the MCP server through `graph-tools.ts`:\n\n```mermaid\ngraph TD\n    A[endpoints.json] --> B[loadEndpoints]\n    B --> C[For each endpoint]\n    C --> D[Create Zod param schema]\n    D --> E[Generate tool description]\n    E --> F[Calculate risk level]\n    F --> G[server.tool registration]\n    G --> H[MCP Server runtime]\n```\n\n**Risk level calculation logic:**\n\n```typescript\nfunction effectiveRiskLevel(configuredRiskLevel, method) {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\n**资料来源:** [src/graph-tools.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/graph-tools.ts), [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Execution Workflow\n\n### Standard Generation\n\n```bash\nnpm run generate\n```\n\nThis command:\n1. Downloads the latest Graph OpenAPI spec\n2. Simplifies and normalizes the spec\n3. Extracts descriptions\n4. Generates MCP tool definitions\n5. Outputs TypeScript types and schemas\n\n### Full Build Pipeline\n\n```bash\nnpm run generate    # Download and generate code\nnpm run build       # Compile TypeScript\nnpm test            # Run verification tests\nnpm run verify      # lint + format + test\n```\n\n**资料来源:** [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Configuration\n\n### Risk Level Annotations\n\nTools requiring special risk classification must be annotated in `endpoints.json`:\n\n```jsonc\n{\n  \"toolName\": \"delete-user\",\n  \"riskLevel\": \"critical\"\n}\n```\n\n**Risk classification rubric:**\n\n| Level | Criteria | Example Tools |\n|-------|----------|---------------|\n| `low` | Read-only queries, reports | `list-users`, `get-user` |\n| `medium` | Reversible single-entity mutation | `update-user`, `add-group-member` |\n| `high` | Significant impact, credential changes | `revoke-user-sessions`, `update-ca-policy` |\n| `critical` | Irreversible or tenant-wide | `delete-user`, `wipe-managed-device` |\n\n**资料来源:** [CONTRIBUTING.md:50-62](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Permission Mapping\n\nApplication permissions are declared per tool in `endpoints.json`:\n\n```jsonc\n{\n  \"toolName\": \"list-sign-ins\",\n  \"appPermissions\": [\"AuditLog.Read.All\"]\n}\n```\n\n**资料来源:** [agent-skills/ms365-admin-mcp/references/graph-permissions.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/graph-permissions.md)\n\n## Adding New Tools\n\n### Workflow\n\n```mermaid\ngraph TD\n    A[Find Graph API endpoint] --> B[Add to endpoints.json]\n    B --> C[Run npm run generate]\n    C --> D[Verify tool registration]\n    D --> E[Add tests if needed]\n    E --> F[Update documentation]\n```\n\n### Step 1: Identify the Endpoint\n\nLocate the desired operation in the [Microsoft Graph OpenAPI spec](https://github.com/microsoftgraph/msgraph-metadata).\n\n### Step 2: Register in endpoints.json\n\n```jsonc\n{\n  \"toolName\": \"list-something\",\n  \"pathPattern\": \"/something\",\n  \"method\": \"GET\",\n  \"appPermissions\": [\"Something.Read.All\"],\n  \"llmTip\": \"Optional hint shown to the LLM\",\n  \"riskLevel\": \"low\"\n}\n```\n\n### Step 3: Regenerate Code\n\n```bash\nnpm run generate\n```\n\n### Step 4: Verify Registration\n\n```bash\nnode dist/index.js --list-tools | grep list-something\nnode dist/index.js --list-permissions | grep Something\n```\n\n**资料来源:** [CONTRIBUTING.md:30-45](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n## Verification and Testing\n\n### List Tools\n\nDisplay all registered tools:\n\n```bash\nnode dist/index.js --list-tools\n```\n\n### List Permissions\n\nDisplay required Graph API permissions:\n\n```bash\nnode dist/index.js --list-permissions\n```\n\n### Preset Filtering\n\nList tools by preset category:\n\n```bash\nnode dist/index.js --preset security --list-tools\nnode dist/index.js --preset identity --list-tools\n```\n\n**Available presets:** `security`, `audit`, `health`, `reports`, `identity`, `exchange`, `intune`, `governance`, `compliance`, `response`, `ediscovery`, `cloudpc`, `callrecords`, `print`, `infoprotection`, `sharepointadmin`, `retention`, `teamsadmin`, `all`\n\n**资料来源:** [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Summary\n\nThe Code Generation Pipeline is the backbone of the ms-365-admin-mcp-server, enabling:\n\n| Capability | Description |\n|------------|-------------|\n| **Automation** | Eliminates manual TypeScript/Zod schema writing |\n| **Consistency** | Uniform tool naming and structure |\n| **Type Safety** | End-to-end TypeScript typing from OpenAPI to server |\n| **Extensibility** | Easy addition of new Graph API endpoints |\n| **Documentation** | Auto-generated descriptions and permission lists |\n\nBy maintaining `endpoints.json` as the single source of truth and running `npm run generate`, developers can keep the MCP server synchronized with the evolving Microsoft Graph API surface.\n\n---\n\n<a id='tool-categories'></a>\n\n## Tool Categories and Presets\n\n### 相关页面\n\n相关主题：[System Architecture](#system-architecture), [Security Model and Risk Classification](#security-model)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [src/endpoints.json](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/endpoints.json)\n</details>\n\n# Tool Categories and Presets\n\n## Overview\n\nTool Categories and Presets provide a logical grouping mechanism for the 515 tools exposed by the ms-365-admin-mcp-server. Categories use regex patterns to match tool names against predefined groups, enabling bulk operations, risk assessment, and organized documentation across different Microsoft 365 admin domains.\n\nThe system serves two primary purposes:\n- **Organization**: Grouping related tools by functional domain (security, identity, compliance, etc.)\n- **Risk governance**: Applying consistent risk levels and access controls across tool groupings\n\n资料来源：[src/tool-categories.ts:1-1]()\n\n## Architecture\n\n```mermaid\ngraph TD\n    A[endpoints.json] --> B[Tool Definitions]\n    B --> C{regex pattern matching}\n    D[tool-categories.ts] --> C\n    C --> E[ToolCategory Assignment]\n    E --> F[Risk Level Resolution]\n    G[risk-level.ts] --> F\n    F --> H[MCP Server Response]\n    \n    I[riskLevel from config] --> F\n    J[HTTP Method GET/POST/PUT/DELETE] --> G\n```\n\n### Core Components\n\n| Component | File | Responsibility |\n|-----------|------|----------------|\n| ToolCategory interface | `src/tool-categories.ts` | Defines the category schema |\n| TOOL_CATEGORIES registry | `src/tool-categories.ts` | Maps category names to regex patterns |\n| effectiveRiskLevel() | `src/risk-level.ts` | Resolves risk level per tool |\n| isToolAllowed() | `src/risk-level.ts` | Checks if tool passes max risk threshold |\n\n资料来源：[src/tool-categories.ts:1-15]()\n\n## ToolCategory Interface\n\n```typescript\nexport interface ToolCategory {\n  name: string;\n  pattern: RegExp;\n  description: string;\n}\n```\n\n| Field | Type | Purpose |\n|-------|------|---------|\n| `name` | `string` | Unique identifier for the category |\n| `pattern` | `RegExp` | Regex pattern tested against tool names |\n| `description` | `string` | Human-readable description for documentation |\n\n资料来源：[src/tool-categories.ts:1-5]()\n\n## Category Registry\n\nThe `TOOL_CATEGORIES` record contains all predefined categories. Each category uses a case-insensitive regex pattern to match tool names defined in `endpoints.json`.\n\n资料来源：[src/tool-categories.ts:7-40]()\n\n### Available Categories\n\n| Preset | Pattern Scope | Description |\n|--------|---------------|-------------|\n| `security` | `security\\|alert\\|incident\\|attack-simulation\\|threat-intel` | Security alerts, incidents, attack simulations, and threat intelligence (Microsoft 365 Defender) |\n| `audit` | `audit\\|sign-in\\|provisioning\\|directory\\|deleted-user\\|deleted-group` | Audit logs, deleted items (directory audits, sign-ins, provisioning) |\n| `health` | `service\\|health\\|issue\\|message` | Service health and Message Center announcements |\n| `reports` | `report\\|activity\\|usage` | Usage reports (Teams, Email, Active Users, SharePoint, OneDrive, Mailbox, M365 Apps) |\n| `identity` | Complex pattern (users, groups, roles, conditional access, PIM, devices, etc.) | Identity and access management (Entra ID users, groups, roles, devices, PIM, guest users, external identities) |\n\n资料来源：[src/tool-categories.ts:7-40]()\n\n## Risk Level System\n\n### Effective Risk Level Resolution\n\nThe `effectiveRiskLevel()` function determines the actual risk level for any tool:\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\n| Scenario | Result |\n|----------|--------|\n| `configuredRiskLevel` is set | Returns configured value |\n| Method is GET (case-insensitive) | Returns `low` |\n| Method is POST/PUT/DELETE, no config | Returns `critical` (fail-safe default) |\n\n资料来源：[src/risk-level.ts:10-18]()\n\n### Risk Level Hierarchy\n\n| Level | Criteria | Example Tools |\n|-------|----------|---------------|\n| `low` | Read-only operations | `list-users`, `get-security-alert` |\n| `medium` | Reversible mutations on single entities | `update-user`, `add-group-member` |\n| `high` | Significant impact, credential changes, or destructive operations | `revoke-user-sessions`, `update-conditional-access-policy` |\n| `critical` | Irreversible or tenant-wide impact | `delete-user`, `wipe-managed-device`, `delete-conditional-access-policy` |\n\n资料来源：[CONTRIBUTING.md:1-20]()\n\n### Tool Permission Check\n\nThe `isToolAllowed()` function compares the tool's effective risk against the server's configured maximum:\n\n```typescript\nexport function isToolAllowed(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string,\n  maxRiskLevel: RiskLevel\n): boolean {\n  return rank(effectiveRiskLevel(configuredRiskLevel, method)) <= rank(maxRiskLevel);\n}\n```\n\nThe `rank()` function (implied internal) orders risk levels: `low < medium < high < critical`.\n\n资料来源：[src/risk-level.ts:20-25]()\n\n## Category Matching Flow\n\n```mermaid\ngraph LR\n    A[Tool Name] --> B{Iterate TOOL_CATEGORIES}\n    B -->|match found| C[Assign Category]\n    B -->|no match| D[Uncategorized]\n    \n    E[Tool Method] --> F[effectiveRiskLevel]\n    F --> G{Method == GET?}\n    G -->|Yes| H[risk = low]\n    G -->|No| I{configuredRiskLevel?}\n    I -->|Yes| J[risk = configured]\n    I -->|No| K[risk = critical]\n```\n\n## Adding a New Preset\n\n### Step 1: Edit tool-categories.ts\n\nAdd a new entry to the `TOOL_CATEGORIES` object:\n\n```typescript\nexport const TOOL_CATEGORIES: Record<string, ToolCategory> = {\n  mypreset: {\n    name: 'mypreset',\n    pattern: /pattern-matching-tool-names/i,\n    description: 'Short human-readable description',\n  },\n  // ...existing categories\n};\n```\n\n资料来源：[CONTRIBUTING.md:25-35]()\n\n### Step 2: Validate the Pattern\n\n```bash\nnode dist/index.js --preset mypreset --list-tools\n```\n\nThis command tests the regex against all tools in `endpoints.json` and lists matches.\n\n资料来源：[CONTRIBUTING.md:37-38]()\n\n## Tool Definition Schema\n\nTools are defined in `endpoints.json` with the following structure:\n\n```json\n{\n  \"toolName\": {\n    \"method\": \"GET|POST|PUT|DELETE\",\n    \"appPermissions\": [\"Permission.Read.All\"],\n    \"llmTip\": \"Optional hint for LLM\",\n    \"riskLevel\": \"low|medium|high|critical\"  // only for non-GET\n  }\n}\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `method` | Yes | HTTP method for the Graph API call |\n| `appPermissions` | Yes | Minimum Graph API permissions |\n| `llmTip` | No | Hint displayed to LLM in tool description |\n| `riskLevel` | For non-GET | Risk classification per the rubric |\n\n资料来源：[CONTRIBUTING.md:55-65]()\n\n## Preset Index\n\n| Preset | Use Case File | Primary Tools |\n|--------|---------------|---------------|\n| `security` | `usecase-security.md` | Alerts, incidents, attack simulations, threat intel |\n| `audit` | `usecase-audit.md` | Directory audits, sign-ins, provisioning logs |\n| `health` | `usecase-health.md` | Service health, Message Center |\n| `reports` | `usecase-reports.md` | Teams, Email, SharePoint, OneDrive usage |\n| `identity` | `usecase-identity.md` | Users, groups, roles, devices, PIM |\n| `exchange` | `usecase-exchange.md` | Message traces, mailboxes |\n| `intune` | `usecase-intune.md` | Device management, compliance, configurations |\n| `governance` | `usecase-governance.md` | Access reviews, entitlement, lifecycle |\n| `compliance` | `usecase-compliance.md` | Licenses, Secure Score, Identity Protection |\n| `response` | `usecase-response.md` | Incident response operations |\n| `ediscovery` | `usecase-ediscovery.md` | eDiscovery cases (Purview) |\n| `cloudpc` | `usecase-cloudpc.md` | Cloud PC / Windows 365 |\n| `callrecords` | `usecase-callrecords.md` | Teams call records |\n| `print` | `usecase-print.md` | Universal Print |\n| `infoprotection` | `usecase-infoprotection.md` | BitLocker, sensitivity labels |\n| `sharepointadmin` | `usecase-sharepointadmin.md` | SharePoint tenant administration |\n| `retention` | `usecase-retention.md` | Records management |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md:1-50]()\n\n## Verification Commands\n\nAfter adding a new preset, verify registration:\n\n```bash\n# List tools matching the preset\nnode dist/index.js --list-tools | grep <pattern>\n\n# Check required permissions\nnode dist/index.js --list-permissions | grep <Permission>\n```\n\n资料来源：[CONTRIBUTING.md:66-72]()\n\n## Integration with MCP Server\n\nThe tool categories system integrates with the MCP server's execution pipeline:\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant MCPServer\n    participant RiskChecker\n    participant GraphAPI\n    \n    Client->>MCPServer: call_tool(toolName, params)\n    MCPServer->>MCPServer: Match toolName against TOOL_CATEGORIES\n    MCPServer->>RiskChecker: effectiveRiskLevel(configured, method)\n    RiskChecker-->>MCPServer: resolvedRiskLevel\n    MCPServer->>RiskChecker: isToolAllowed(resolvedRiskLevel, maxRiskLevel)\n    RiskChecker-->>MCPServer: allowed: boolean\n    \n    alt allowed == false\n        MCPServer-->>Client: Error: Tool exceeds max risk level\n    else allowed == true\n        MCPServer->>GraphAPI: Execute request\n        GraphAPI-->>MCPServer: Response\n        MCPServer-->>Client: Tool result\n    end\n\n---\n\n<a id='security-model'></a>\n\n## Security Model and Risk Classification\n\n### 相关页面\n\n相关主题：[Tool Categories and Presets](#tool-categories), [Azure Deployment Security](#azure-deployment-security)\n\n<details>\n<summary>Relevant Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\n- [docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n- [docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n- [docs/SECURITY_REVIEW_2026-04-25.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-25.md)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- [agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n</details>\n\n# Security Model and Risk Classification\n\n## Overview\n\nThe ms-365-admin-mcp-server implements a defense-in-depth security model centered on risk classification for all Graph API operations. Every tool exposed by the server is classified according to its potential impact, and the server enforces configurable risk caps to prevent accidental execution of destructive or high-impact operations.\n\nThe security model serves two primary purposes:\n\n1. **Operational Safety** — Prevent unintended destructive operations (deletes, wipes, credential changes) from executing without explicit confirmation\n2. **Prompt Injection Defense** — Protect against malicious data injected through Microsoft Graph responses into the LLM context window\n\n资料来源：[docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n\n## Risk Level Taxonomy\n\nThe server defines four risk levels in ascending order of severity. Each level corresponds to a specific operational threshold and requires explicit user action to execute.\n\n| Level | Criteria | Example Operations |\n|-------|----------|-------------------|\n| `low` | Read-only operations, reports, POST-only queries, or trivial annotations | `run-hunting-query`, `add-security-alert-comment`, listing operations |\n| `medium` | Reversible mutations affecting a single entity | `update-user`, `add-group-member`, `create-invitation` |\n| `high` | Significant impact: broad scope, credential change, or destructive | `revoke-user-sessions`, `update-conditional-access-policy`, `confirm-compromised-users` |\n| `critical` | Irreversible or tenant-wide impact | `delete-user`, `wipe-managed-device`, `delete-conditional-access-policy` |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Risk Level Rank\n\nRisk levels are ranked numerically for comparison purposes. Higher numbers indicate greater severity.\n\n```typescript\nconst RISK_RANK: Record<RiskLevel, number> = {\n  low: 0,\n  medium: 1,\n  high: 2,\n  critical: 3,\n};\n```\n\n资料来源：[src/risk-level.ts:1-5](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Risk Classification Algorithm\n\nThe effective risk level for any tool is determined by a deterministic algorithm that combines explicit configuration with method-based defaults.\n\n```typescript\nexport function effectiveRiskLevel(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string\n): RiskLevel {\n  if (configuredRiskLevel) return configuredRiskLevel;\n  return method.toUpperCase() === 'GET' ? 'low' : 'critical';\n}\n```\n\n**Decision Logic:**\n\n1. If `configuredRiskLevel` is explicitly set in `endpoints.json`, use it\n2. For GET requests without explicit configuration, default to `low` (safe reads)\n3. For non-GET requests (write operations) without explicit configuration, default to `critical` — this is a **fail-safe** design that prevents silently exposing unannotated write endpoints\n\n资料来源：[src/risk-level.ts:17-25](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Access Control Function\n\nThe `isToolAllowed` function determines whether a tool at a given risk level is permitted given a maximum risk cap.\n\n```typescript\nexport function isToolAllowed(\n  configuredRiskLevel: RiskLevel | undefined,\n  method: string,\n  maxRiskLevel: RiskLevel\n): boolean {\n  return rank(effectiveRiskLevel(configuredRiskLevel, method)) <= rank(maxRiskLevel);\n}\n```\n\nA tool is allowed when its effective risk level rank is **less than or equal to** the configured maximum risk level.\n\n资料来源：[src/risk-level.ts:27-32](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Server Configuration Flags\n\n### `--allow-writes`\n\nBy default, the server operates in **read-only mode**. The `--allow-writes` flag must be explicitly passed to enable any write operations, regardless of their risk level.\n\nThis flag is a prerequisite for risk-based filtering — even if `--max-risk-level medium` is set, no writes execute without `--allow-writes`.\n\n资料来源：[docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n\n### `--max-risk-level <level>`\n\nCaps the maximum risk level of tools registered at startup. Implies `--allow-writes`.\n\n| Cap Value | Effect |\n|-----------|--------|\n| `--max-risk-level low` | Only read operations (`low`) are exposed |\n| `--max-risk-level medium` | Adds medium-risk mutations; hides high/critical tools |\n| `--max-risk-level high` | Adds high-risk operations; critical tools hidden |\n| `--max-risk-level critical` | All tools exposed (default with `--allow-writes`) |\n\nWhen `--max-risk-level medium` is used:\n- BitLocker recovery keys (`high` read) are hidden\n- LAPS passwords (`high` read) are hidden\n- 15 additional medium-risk reads are filtered\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n## Security Controls (SEC-G Series)\n\n### SEC-G01 — Risk Level Cap\n\nThe `--max-risk-level` CLI flag caps the risk level of registered tools. Implies `--allow-writes`. Unannotated writes default to `critical` (fail-safe).\n\nThis control ensures that sensitive endpoints cannot be invoked even if an attacker somehow manipulates the tool invocation, because the server never registers them.\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n### SEC-G02 — Nonce-Enveloped Responses\n\nEvery successful Microsoft Graph tool response is wrapped in a nonce-delimited envelope with an untrusted-data preamble before reaching the LLM:\n\n```\n<graph_response_NN>\n[UNTRUSTED DATA - VERIFY BEFORE USE]\n<nonce>base64_encoded_random_bytes</nonce>\n<content>actual_response</content>\n</graph_response_NN>\n```\n\n- Per-call `crypto.randomBytes(8)` nonce prevents envelope escape\n- Defends against **prompt injection** through user-controlled Graph fields:\n  - `displayName`\n  - `mail` subject\n  - Chat body\n  - Site title\n  - OAuth app name\n  - Any other user-facing field\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n### SEC-G03 — Sensitive Read Annotations\n\n22 sensitive-read GET operations are annotated with explicit risk levels:\n\n| Category | Count | Risk Levels |\n|----------|-------|-------------|\n| BitLocker recovery keys | 1 | `high` |\n| LAPS passwords | 1 | `high` |\n| eDiscovery cases/custodians/searches | 4 | `high` |\n| Subject rights requests | 1 | `high` |\n| Auth methods | 3 | `medium` |\n| Sign-ins | 2 | `medium` |\n| Risk detections | 2 | `medium` |\n| Message traces | 2 | `medium` |\n| Federated credentials | 2 | `medium` |\n\nThese annotations feed SEC-G01: `--max-risk-level medium` automatically hides the `high`-level sensitive reads.\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)\n\n## Critical Operations by Category\n\nCritical-level operations require out-of-band sign-off and should never be executed based solely on chat confirmation.\n\n### Identity\n\n| Tool | Impact |\n|------|--------|\n| `delete-user` | Permanently removes user from tenant |\n| `delete-group` | Removes group and all memberships |\n| `add-directory-role-member` | Grants permanent privileged role |\n| `disable-user-account` | On privileged/break-glass accounts |\n\n### Compliance & Security\n\n| Tool | Impact |\n|------|--------|\n| `delete-conditional-access-policy` | Removes tenant-wide access controls |\n| `delete-ediscovery-case` | Permanently removes legal hold case |\n| `wipe-managed-device` | Remote wipe of enrolled device |\n| `clean-windows-device` | Removes device from Intune |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/tools-catalog.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/tools-catalog.md)\n\n## High-Risk Operations\n\nHigh-risk operations require explicit confirmation and dry-run before execution.\n\n### Confirmation Required\n\n| Tool | Risk | Requirement |\n|------|------|-------------|\n| `revoke-user-sessions` | high | Confirm before executing |\n| `confirm-compromised-users` | high | Confirm per case |\n| `confirm-safe-users` | high | Confirm per case |\n| `dismiss-risky-users` | high | Confirm per case |\n| `change-user-password` | high | Confirm with operator |\n| `update-device` | high | Confirm with operator |\n\n资料来源：[agent-skills/ms365-admin-mcp/references/usecase-compliance.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/usecase-compliance.md)\n\n## Security Architecture Flow\n\n```mermaid\ngraph TD\n    A[Tool Invocation Request] --> B{--allow-writes enabled?}\n    B -->|No| C[Reject All Writes]\n    B -->|Yes| D[Check effectiveRiskLevel]\n    D --> E{Lookup configuredRiskLevel<br/>in endpoints.json}\n    E -->|Found| F[Use Configured Level]\n    E -->|Not Found| G{Method = GET?}\n    G -->|Yes| H[Default: low]\n    G -->|No| I[Default: critical<br/>FAIL-SAFE]\n    F --> J[Calculate rank<br/>effectiveRiskLevel]\n    H --> J\n    I --> J\n    J --> K{rank ≤ maxRiskLevel?}\n    K -->|Yes| L[Execute Tool]\n    K -->|No| M[Block Tool<br/>Not Registered]\n    L --> N[Graph API Call]\n    N --> O[Wrap in Nonce Envelope<br/>SEC-G02]\n    O --> P[Return to LLM]\n```\n\n## Risk Level Inheritance\n\nThe risk classification follows a hierarchical inheritance model:\n\n```mermaid\ngraph LR\n    A[endpoints.json] --> B[Tool Registration]\n    B --> C{--max-risk-level}\n    C --> D[Tool Availability]\n    \n    E[GET Methods] --> F[Default: low<br/>unless overridden]\n    G[Write Methods] --> H[Default: critical<br/>fail-safe]\n```\n\n## Tool Categories and Risk Patterns\n\nThe server organizes tools into presets based on name patterns, each with distinct risk profiles.\n\n```typescript\n// From src/tool-categories.ts\nconst PATTERNS = {\n  security: /alert|incident|attack/i,\n  audit: /audit|sign-in|provisioning|deleted/i,\n  health: /serviceHealth|messageCenter/i,\n  response: /disable-user|revoke|block|reset|confirm|dismiss/i,\n  // ... more categories\n};\n```\n\n资料来源：[src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n\n## Verification Commands\n\nVerify tool registration and permissions:\n\n```bash\n# List all registered tools\nnode dist/index.js --list-tools\n\n# List required Graph permissions\nnode dist/index.js --list-permissions\n\n# Verify a specific preset\nnode dist/index.js --preset security --list-tools\n\n# Verify specific risk level tools\nnode dist/index.js --max-risk-level medium --list-tools\n```\n\n资料来源：[docs/RISK_MODEL.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/RISK_MODEL.md)\n\n## Security Review Process\n\nAll security-relevant changes undergo review per documented processes:\n\n| Review Date | Scope |\n|-------------|-------|\n| 2026-04-20 | Initial security review — SEC-G01, SEC-G02, SEC-G03 implementation |\n| 2026-04-25 | Follow-up review — permission scope reductions, `dismiss-risky-users` elevation |\n\nThe review identified and addressed:\n- Over-privileged permission scopes reduced to least-privilege\n- `dismiss-risky-users` elevated from `medium` to `high`\n- Query string sanitization to prevent secret leakage\n- Dead dependency removal\n\n资料来源：[docs/SECURITY_REVIEW_2026-04-20.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-20.md)  \n资料来源：[docs/SECURITY_REVIEW_2026-04-25.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/SECURITY_REVIEW_2026-04-25.md)\n\n## Best Practices for Operators\n\n1. **Start with `--max-risk-level medium`** — Only escalate when high-risk tools are required\n2. **Dry-run before high/critical operations** — Always read the target object first\n3. **Out-of-band confirmation for critical** — Use ticketing systems for delete/wipe operations\n4. **Review permissions quarterly** — Run `--list-permissions` to audit required scopes\n5. **Never run without understanding** — Each `references/usecase-*.md` file documents tool risk levels before use\n\n## Module Dependencies\n\nThe security model is implemented in pure, testable modules:\n\n| Module | Purpose |\n|--------|---------|\n| `src/risk-level.ts` | Risk level computation and comparison |\n| `src/user-token-authorization.ts` | User token validation |\n| `src/jwks-stale-cache.ts` | JWKS caching for token validation |\n| `src/upstream-error.ts` | Graph API error handling |\n| `src/untrusted-envelope.ts` | Nonce envelope wrapping |\n\nAll modules have unit test coverage (51 tests covering all security-critical paths).\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n---\n\n<a id='azure-deployment-security'></a>\n\n## Azure Deployment Security\n\n### 相关页面\n\n相关主题：[Security Model and Risk Classification](#security-model), [HTTP Transport and Deployment](#http-deployment), [Docker and Container Deployment](#docker-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [docs/AZURE_DEPLOYMENT_SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/AZURE_DEPLOYMENT_SECURITY.md)\n- [infra/main.bicep](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/infra/main.bicep)\n- [infra/parameters.example.jsonc](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/infra/parameters.example.jsonc)\n- [docs/CYSEC-1420/graph-permissions-baseline.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/graph-permissions-baseline.md)\n- [docs/CYSEC-1420/network-design-gate.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/network-design-gate.md)\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n- [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n</details>\n\n# Azure Deployment Security\n\n## Overview\n\nThe ms-365-admin-mcp-server provides a comprehensive Azure deployment security model designed to protect Microsoft 365 administrative operations. This documentation covers the security controls, network architecture, secret management, and compliance considerations for deploying the server in Azure Container Apps.\n\n## Core Security Principles\n\n### Defense in Depth\n\nThe security architecture implements multiple layers of protection:\n\n1. **Network Isolation** — Private networking with VNet integration and egress restrictions\n2. **Secret Management** — Azure Key Vault for all sensitive credentials\n3. **Authentication** — Microsoft Identity (MSAL) with client credentials flow\n4. **Authorization** — Role-based access with MCP permission scopes\n5. **Audit** — Comprehensive logging with PII redaction capabilities\n6. **Certificate Authentication** — Preference for certificates over client secrets\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n## Network Architecture\n\n### Private Endpoint Configuration\n\nThe deployment uses private networking to restrict communication paths. All egress traffic is routed through Azure Firewall or Network Security Groups (NSGs) to enforce granular control.\n\n```mermaid\ngraph TD\n    subgraph \"Azure Cloud\"\n        subgraph \"Virtual Network\"\n            CA[\"Container Apps<br/>Environment\"]\n            VNET[\"VNet Integration\"]\n        end\n        subgraph \" egress\"\n            FW[\"Azure Firewall\"]\n            PE[\"Private Endpoint<br/>Key Vault\"]\n        end\n    end\n    \n    subgraph \"Microsoft Services\"\n        AAD[\"Microsoft Identity<br/>login.microsoftonline.com\"]\n        GRAPH[\"Microsoft Graph<br/>graph.microsoft.com\"]\n    end\n    \n    CA --> VNET\n    VNET --> FW\n    FW --> AAD\n    FW --> GRAPH\n    CA --> PE\n    PE --> KV[\"Key Vault\"]\n    \n    style CA fill:#e1eff6\n    style FW fill:#fff3cd\n    style KV fill:#d4edda\n```\n\n### Required Egress Endpoints\n\nThe server requires outbound access to the following Microsoft endpoints:\n\n| Endpoint | Purpose | Sovereign Equivalent |\n|----------|---------|----------------------|\n| `login.microsoftonline.com` | Microsoft Entra authentication | `login.partner.microsoftonline.cn` |\n| `graph.microsoft.com` | Microsoft Graph API | `microsoftgraph.chinacloudapi.cn` |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md) | [docs/CYSEC-1420/network-design-gate.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/network-design-gate.md)\n\n### HTTP Mode Security\n\nWhen exposing the server via HTTP transport, strict controls apply:\n\n- **Never** expose on `0.0.0.0` without a reverse proxy enforcing TLS\n- **Always** pass `--allowed-clients` with the minimum set of Entra app IDs\n- Use `--allow-any-tenant-user` only when explicitly intended (defaults to deny)\n\n```bash\n# Example secure HTTP startup\nnode dist/index.js \\\n  --transport streamable-http \\\n  --allowed-clients \"app-id-1,app-id-2\" \\\n  --public-url https://mcp.example.com \\\n  --log-redact-upn\n```\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n## Secret Management\n\n### Azure Key Vault Integration\n\nAll sensitive credentials **must** be stored in Azure Key Vault rather than environment files or source control.\n\n| Secret Name | Description | Required |\n|-------------|-------------|----------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Entra application client ID | Yes |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Client secret (if not using cert) | Conditional |\n| `MS365_ADMIN_MCP_KEYVAULT_URL` | Key Vault base URL | Yes |\n| `AZURE_STORAGE_ACCOUNT_NAME` | Table storage for OAuth state | OAuth mode only |\n| `AZURE_STORAGE_TABLE_NAME` | Table name for PKCE state | OAuth mode only |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Certificate Authentication\n\nThe deployment **prefers** certificate-based authentication over client secrets:\n\n```mermaid\ngraph LR\n    A[\"Key Vault<br/>Certificate\"] --> B[\"Managed Identity\"]\n    B --> C[\"Container Apps<br/>Environment\"]\n    C --> D[\"Microsoft Graph<br/>API\"]\n```\n\nBenefits of certificate authentication:\n- No secret rotation required (certificate validity managed separately)\n- Federated credentials eliminate client secret storage entirely\n- Workload identity federation supported for GitHub Actions deployments\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Secret Rotation Policy\n\n| Credential Type | Rotation Interval |\n|----------------|-------------------|\n| Client Secrets | 90 days |\n| Certificates | Per certificate validity period |\n| Federated Credentials | No rotation required |\n\n## Identity and Access Management\n\n### Authentication Modes\n\nThe server supports two authentication modes:\n\n1. **Application Credentials (Default)** — Client ID + Secret/Certificate\n2. **OAuth Mode** — Full OAuth 2.0 authorization code flow with PKCE\n\n```mermaid\ngraph TD\n    subgraph \"OAuth Mode Flow\"\n        U[\"User/Browser\"] --> |\"1. GET /authorize\"| MCP[\"MCP Server\"]\n        MCP --> |\"2. Redirect to Entra\"| AAD[\"Microsoft Entra\"]\n        U --> |\"3. User Authentication\"| AAD\n        AAD --> |\"4. Auth Code + PKCE\"| MCP\n        MCP --> |\"5. Token Request\"| AAD\n        AAD --> |\"6. Access Token\"| MCP\n    end\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### OAuth Storage\n\nOAuth mode requires Azure Table Storage for PKCE state management:\n\n| Component | Configuration |\n|-----------|--------------|\n| Storage Account | Standard_LRS, TLS 1.2, OAuth-only authentication |\n| Table Name | `oauthstate` (configurable) |\n| Access | Managed Identity with Storage Table Data Contributor role |\n| PKCE Lifetime | 10 minutes |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Graph API Permissions\n\n### Least Privilege Model\n\nThe deployment follows a least-privilege approach with application permissions scoped to required operations only.\n\n资料来源：[docs/CYSEC-1420/graph-permissions-baseline.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/graph-permissions-baseline.md)\n\n### Application Permission Categories\n\n| Category | Permission Type | Example Operations |\n|----------|----------------|-------------------|\n| Directory | Read.All | list-users, list-groups |\n| Device Management | ReadWrite.All | update-device, wipe-managed |\n| Policy | ReadWrite.All | create-conditional-access-policy |\n| Security | Read.All / ReadWrite.All | list-risky-users, confirm-compromised |\n\n### Required Read Permissions (Default)\n\n```\nDirectory.Read.All\nGroup.Read.All\nUser.Read.All\nDevice.Read.All\nDeviceManagementRBAC.Read.All\nPolicy.Read.All\nAuditLog.Read.All\n```\n\n资料来源：[agent-skills/ms365-admin-mcp/references/graph-permissions.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/agent-skills/ms365-admin-mcp/references/graph-permissions.md)\n\n## Logging and Monitoring\n\n### PII-Aware Logging\n\nThe server provides built-in PII redaction for logs forwarded to SIEM systems:\n\n```bash\nnode dist/index.js --log-redact-upn\n```\n\nThis flag replaces UPN values in log lines with deterministic SHA-256 prefixes:\n\n```\nOriginal: \"Authenticated user alice@example.com\"\nRedacted: \"Authenticated user sha256:1a2b3c4d5e6f...\"\n```\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Audit Trail\n\nEnable verbose logging for complete audit trails:\n\n```bash\nnode dist/index.js -v  # Enable verbose logging\n```\n\nThe following audit operations are available via the MCP tools:\n\n| Tool | Purpose |\n|------|---------|\n| `list-directory-audits` | Directory sign-in and activity logs |\n| `list-intune-audit-events` | Intune device management events |\n| `list-sign-ins` | Conditional Access and sign-in logs |\n\n### Log Storage Configuration\n\nThe Winston logger uses a configurable log directory:\n\n```bash\nexport MS365_ADMIN_MCP_LOG_DIR=/var/log/ms365-admin-mcp\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Bicep Infrastructure Deployment\n\n### Deployment Architecture\n\n```mermaid\ngraph TD\n    subgraph \"Resource Group\"\n        subgraph \"Networking\"\n            VNET[\"Virtual Network\"]\n            SUBNET[\"Subnet\"]\n            FW[\"Azure Firewall\"]\n        end\n        subgraph \"Compute\"\n            ACA[\"Container Apps<br/>Environment\"]\n            APP[\"MCP Server<br/>Container\"]\n        end\n        subgraph \"Data\"\n            KV[\"Key Vault\"]\n            SA[\"Storage Account\"]\n            TBL[\"Table Storage\"]\n        end\n        subgraph \"Identity\"\n            UAMI[\"User-Assigned<br/>Managed Identity\"]\n        end\n    end\n    \n    APP --> SUBNET\n    APP --> KV\n    APP --> SA\n    APP --> UAMI\n    UAMI --> KV\n    UAMI --> SA\n    FW --> VNET\n    \n    style APP fill:#e1eff6\n    style KV fill:#d4edda\n    style FW fill:#fff3cd\n```\n\n### Required Bicep Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `allowedClients` | array | Yes | List of Entra app IDs permitted to connect |\n| `tags` | object | Yes | Tags propagated to all resources |\n| `acrLoginServer` | string | Yes | Azure Container Registry login server |\n| `location` | string | Yes | Azure region |\n| `environmentName` | string | Yes | Deployment environment |\n| `maxReplicas` | int | No | Maximum container replicas (default: 1) |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Storage Account Configuration\n\nThe Bicep template provisions a secure storage account for OAuth PKCE state:\n\n```json\n{\n  \"sku\": {\n    \"name\": \"Standard_LRS\"\n  },\n  \"properties\": {\n    \"minimumTlsVersion\": \"TLS1_2\",\n    \"allowSharedKeyAccess\": false,\n    \"defaultToOAuthAuthentication\": true\n  }\n}\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Private Container Registry\n\nThe deployment supports pulling images from private Azure Container Registry:\n\n```bicep\nregistries: {\n  loginServer: acrLoginServer\n  identity: uamiResourceId\n  passwordSecretRef: ''\n}\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Deployment Checklist\n\n### Pre-Deployment Security Review\n\n- [ ] Store all secrets in Azure Key Vault\n- [ ] Configure allowed clients (minimum Entra app IDs)\n- [ ] Enable PII redaction for log forwarding\n- [ ] Configure network segmentation with allowed egress endpoints\n- [ ] Apply Conditional Access to service principal (geofencing, sign-in risk)\n- [ ] Review and minimize Graph API permissions\n\n### Deployment Validation\n\n- [ ] Verify HTTP mode not exposed on `0.0.0.0`\n- [ ] Confirm managed identity access to Key Vault\n- [ ] Test OAuth PKCE flow with Table Storage\n- [ ] Validate verbose logging output\n- [ ] Verify allowed clients can connect\n\n### Post-Deployment Monitoring\n\n- [ ] Monitor `list-sign-ins` for anomalies on service principal\n- [ ] Enable directory audit log forwarding to SIEM\n- [ ] Set up alerts for critical tool invocations\n- [ ] Review access reviews for application owners\n\n## Migration Guide\n\n### From Version 0.1.0 to 0.2.x\n\n1. **Required**: Add `--allowed-clients` parameter (HTTP mode refuses startup without it)\n2. **Required for OAuth mode**: Add `--public-url` if behind reverse proxy\n3. **Review**: Check `--allow-any-tenant-user` if relying on implicit behavior\n4. **Optional**: Update Bicep to add Storage Account for OAuth PKCE bridge\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Scaling Considerations\n\n- Single replica is the default\n- For multi-replica deployments, externalize PKCE storage first\n- Run `az deployment group create` with updated Bicep for Storage Account provisioning\n\n## Related Documentation\n\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md) — Core security practices\n- [docs/APP_REGISTRATION.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/APP_REGISTRATION.md) — Application registration guide\n- [docs/CYSEC-1420/](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/docs/CYSEC-1420/) — Security compliance documentation\n\n---\n\n<a id='http-deployment'></a>\n\n## HTTP Transport and Deployment\n\n### 相关页面\n\n相关主题：[Docker and Container Deployment](#docker-deployment), [Azure Deployment Security](#azure-deployment-security), [Configuration Reference](#configuration)\n\n<details>\n<summary>Relevant Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\n- [CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n- [SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n- [CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n- [src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n- [src/tool-categories.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/tool-categories.ts)\n- [src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n</details>\n\n# HTTP Transport and Deployment\n\nThe ms-365-admin-mcp-server supports multiple transport mechanisms for exposing Microsoft 365 administration capabilities to MCP clients. The HTTP transport layer forms the foundation for remote deployments, OAuth-based authentication flows, and secure communication between clients and the server.\n\n## Overview\n\nThe server implements a flexible HTTP transport architecture that supports both local stdio connections and remote HTTP-based deployments. This dual-mode design enables the server to operate as a local desktop companion (via Claude Desktop) or as a scalable cloud-hosted service accessible to multiple users simultaneously.\n\n### Transport Modes\n\n| Transport Mode | Use Case | Authentication |\n|---------------|----------|----------------|\n| stdio | Local Claude Desktop integration | Direct client credentials |\n| StreamableHTTP | Claude.ai Web, Claude Desktop remote | OAuth 2.0 + PKCE proxy |\n| Remote HTTP | Containerized deployments (Azure Container Apps) | Device code bootstrap |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## HTTP Server Architecture\n\n### Core Components\n\nThe HTTP transport is implemented across several interconnected modules:\n\n| Module | Responsibility |\n|--------|----------------|\n| `http-server.ts` | Main HTTP server, routing, middleware, security headers |\n| `oauth-proxy.ts` | OAuth 2.0 discovery, PKCE proxy, Entra ID integration |\n| `token-validator.ts` | JWT validation, tenant verification, scope enforcement |\n| `auth-bootstrap.ts` | RFC 8628 device_code flow for remote authentication |\n\n资料来源：[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)\n\n### Request Flow\n\n```mermaid\ngraph TD\n    A[MCP Client] --> B[HTTP Server<br/>src/http-server.ts]\n    B --> C{Auth Mode}\n    C -->|OAuth| D[OAuth Proxy<br/>src/oauth-proxy.ts]\n    C -->|Device Code| E[Auth Bootstrap<br/>src/auth-bootstrap.ts]\n    C -->|Client Creds| F[Direct Auth]\n    D --> G[Token Validator<br/>src/token-validator.ts]\n    E --> G\n    F --> G\n    G --> H{Valid Token?}\n    H -->|Yes| I[Tool Executor]\n    H -->|No| J[401/403 Response]\n    I --> K[Microsoft Graph API]\n```\n\n## OAuth 2.0 Proxy Mode\n\nThe `--oauth-mode` flag enables Entra-backed OAuth 2.0 + PKCE proxy endpoints, allowing Claude Desktop, Claude Code, and Claude.ai Web to authenticate users through Microsoft Entra ID without client-side configuration beyond the server URL.\n\n### Discovery Endpoints\n\n| Endpoint | Purpose |\n|----------|---------|\n| `GET /.well-known/oauth-authorization-server` | OAuth 2.0 authorization server metadata |\n| `GET /.well-known/oauth-protected-resource` | Protected resource metadata for client discovery |\n| `GET /.well-known/microsoft-hosted-userpolicy` | Microsoft-hosted user policy information |\n\n资料来源：[CHANGELOG.md:73-75](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Authentication Headers\n\nThe server implements proper WWW-Authenticate header responses:\n\n| Scenario | Header Response |\n|----------|-----------------|\n| Missing token | `WWW-Authenticate: Bearer resource_metadata=\"...\"` |\n| Invalid token | `WWW-Authenticate: Bearer resource_metadata=\"...\", error=\"invalid_token\"` |\n\nWithout these headers, Claude clients could not discover the protected-resource metadata and would surface `Authorization with the MCP server failed` before ever reaching `/authorize`.\n\n资料来源：[CHANGELOG.md:81-85](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Required Configuration\n\nWhen running in OAuth mode, deployments must specify:\n\n```bash\n--oauth-mode\n--public-url https://<fqdn>  # Required when behind a reverse proxy\n--required-user-scopes <scopes>  # If callers request a specific scope\n```\n\nDeployments relying on the implicit \"any authenticated user\" behavior must add `--allow-any-tenant-user` to their startup command.\n\n资料来源：[CHANGELOG.md:34-37](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Remote HTTP Server with Device Code Authentication\n\nThe `ms-365-admin-mcp-auth` bootstrap tool implements RFC 8628 device_code flow to pre-seed the mcp-remote token cache, allowing Claude Desktop/Code to skip the browser flow for remote MCP servers.\n\n### Authentication Flow\n\n```mermaid\nsequenceDiagram\n    participant Client as Claude Desktop/Code\n    participant Auth as ms-365-admin-mcp-auth\n    participant Server as MCP Server (Remote)\n    participant Entra as Microsoft Entra ID\n\n    Client->>Auth: ms-365-admin-mcp-auth --server <url>\n    Auth->>Entra: POST /devicecode\n    Entra-->>Auth: device_code, verification_uri\n    Auth->>Client: Display verification URL\n    loop Poll until authenticated\n        Auth->>Entra: POST /token (device_code)\n        Entra-->>Auth: pending | success\n    end\n    Auth->>Server: Cached tokens stored locally\n    Client->>Server: MCP requests (uses cached tokens)\n```\n\n### Command Line Interface\n\n```bash\nms-365-admin-mcp-auth [options]\n\nRequired Options:\n  -s, --server <url>    MCP server URL (with or without /mcp suffix)\n\nOptions:\n  --scope <scope>       Override OAuth scope (defaults to server metadata)\n  --cache-dir <path>    Override cache directory\n  --timeout <minutes>   Authentication timeout (default: 8 minutes)\n```\n\n资料来源：[src/auth-bootstrap.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/auth-bootstrap.ts)\n\n### Token Cache Location\n\nTokens are cached at:\n```\n~/.mcp-auth/mcp-remote-<version>/\n├── <hash>_client_info.json\n└── <hash>_tokens.json\n```\n\nThe cache key is computed as `md5(serverUrl)`, matching mcp-remote's `getServerUrlHash` function exactly. File permissions are set to mode `0600` for security.\n\n资料来源：[CHANGELOG.md:56-58](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Exit Codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success |\n| 1 | Usage error |\n| 2 | Network failure |\n| 3 | Access denied |\n| 4 | Timeout |\n\nThese exit codes facilitate Docker and CI wrapper scripting.\n\n资料来源：[CHANGELOG.md:63-65](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Security Configuration\n\n### Security Headers\n\nAll HTTP responses include the following security headers:\n\n| Header | Value | Purpose |\n|--------|-------|---------|\n| `X-Content-Type-Options` | `nosniff` | Prevent MIME type sniffing |\n| `X-Frame-Options` | `DENY` | Prevent clickjacking |\n| `Cache-Control` | `no-store` | Prevent sensitive data caching |\n| Content-Security-Policy | `default-src 'none'` | Restrict resource loading |\n\n### Rate Limiting\n\nThe Express server is configured with `trust proxy` set to `1` to properly handle `X-Forwarded-For` headers from Azure Container Apps or reverse proxies. This prevents the `express-rate-limit` validator from incorrectly blocking requests due to unexpected forwarded headers.\n\n资料来源：[CHANGELOG.md:88-91](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Request Validation\n\n| Validation Type | Implementation |\n|-----------------|----------------|\n| Body size limit | 100 KB maximum |\n| Path traversal | Parameters checked for `../`, `/`, `\\`, `?`, `#`, `&` |\n| ReDoS protection | `--enabled-tools` regex capped at 500 characters |\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Token Validation\n\nThe token validator enforces:\n\n1. **Tenant isolation**: Tenant `common` is rejected; single-tenant mode required for client credentials\n2. **Scope verification**: Tokens must include required user scopes\n3. **Audience validation**: Token audience must match server configuration\n4. **Error logging**: Failed validations log `aud`, `tid`, and `upn` for debugging\n\n### Risk Classification for Write Operations\n\nThe HTTP transport integrates with the risk-level system to enforce write operation restrictions:\n\n| Risk Level | Description | Enforcement |\n|------------|-------------|-------------|\n| `low` | Read-only operations, reports | Allowed by default |\n| `medium` | Reversible mutations, single entity | Requires `--allow-writes` |\n| `high` | Significant impact, credential changes | Requires explicit cap |\n| `critical` | Irreversible or tenant-wide | Requires `--allow-critical` |\n\n资料来源：[src/risk-level.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)\n\n## Deployment Patterns\n\n### Local Deployment (Stdio)\n\nFor local use with Claude Desktop, the server operates in stdio mode:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-365-admin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@okapi-ca/ms-365-admin-mcp-server\"]\n    }\n  }\n}\n```\n\n### Remote HTTP Deployment (Container Apps)\n\n```bash\ndocker run -d \\\n  --name mcp-server \\\n  -e MS365_ADMIN_MCP_CLIENT_ID=<client-id> \\\n  -e MS365_ADMIN_MCP_CLIENT_SECRET=<secret> \\\n  -e MS365_ADMIN_MCP_TENANT_ID=<tenant-id> \\\n  -p 3000:3000 \\\n  ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n```\n\n### OAuth-Enabled Deployment\n\n```bash\nnpm start -- \\\n  --oauth-mode \\\n  --public-url https://mcp.contoso.com/mcp \\\n  --allow-any-tenant-user \\\n  --max-risk-level medium\n```\n\n## Command Line Options\n\n### Transport Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `--oauth-mode` | Enable OAuth 2.0 proxy | Disabled |\n| `--public-url` | Public URL for OAuth callbacks | Required in OAuth mode |\n| `--required-user-scopes` | Scopes required in user tokens | Empty (any scope) |\n| `--allow-any-tenant-user` | Allow users from any tenant | Disabled |\n| `--cache-dir` | Override token cache directory | `~/.mcp-auth/mcp-remote-<ver>` |\n\n### Security Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `--allow-writes` | Allow write operations up to medium risk | Disabled |\n| `--allow-critical` | Allow critical write operations | Disabled |\n| `--max-risk-level` | Maximum allowed risk level | `medium` |\n\n### Other Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `--enabled-tools` | Regex pattern to limit available tools | All tools |\n| `--preset` | Enable a tool category preset | None |\n| `--list-tools` | List available tools and exit | - |\n| `--list-permissions` | List required permissions and exit | - |\n\n## Troubleshooting\n\n### Common Issues\n\n| Symptom | Cause | Solution |\n|---------|-------|----------|\n| `Server disconnected` | Network connectivity or proxy issue | Check `docs/TROUBLESHOOTING.md` |\n| Platform SSO errors | Conditional Access policy blocking | Review device_code flow documentation |\n| `ERR_ERL_UNEXPECTED_X_FORWARDED_FOR` | Rate limiter not trusting proxy | Ensure `--public-url` is set behind reverse proxy |\n\n### Debugging Steps\n\n1. Verify `--public-url` is set correctly when behind a reverse proxy\n2. Check that Entra app registration exposes the `access_as_user` scope\n3. Confirm `--required-user-scopes` matches the scopes your callers request\n4. Review logs for token validation failures (includes `aud`, `tid`, `upn`)\n\n## See Also\n\n- [Authentication and Authorization](src/auth.ts)\n- [Token Validation](src/token-validator.ts)\n- [Risk Model](docs/RISK_MODEL.md)\n- [Troubleshooting Guide](docs/TROUBLESHOOTING.md)\n\n---\n\n<a id='docker-deployment'></a>\n\n## Docker and Container Deployment\n\n### 相关页面\n\n相关主题：[HTTP Transport and Deployment](#http-deployment), [Azure Deployment Security](#azure-deployment-security), [Installation Guide](#installation)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [Dockerfile](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/Dockerfile)\n- [.dockerignore](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/.dockerignore)\n- [src/storage/index.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/index.ts)\n- [src/storage/oauth-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/oauth-storage.ts)\n- [src/storage/memory-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/memory-storage.ts)\n- [src/storage/table-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/table-storage.ts)\n</details>\n\n# Docker and Container Deployment\n\nThis page documents the Docker and container deployment architecture for the Microsoft 365 Admin MCP Server. The server is published to both npm as `@okapi-ca/ms-365-admin-mcp-server` and to GitHub Container Registry (GHCR) as `ghcr.io/okapi-ca/ms-365-admin-mcp-server`, enabling flexible deployment options for enterprise environments.\n\n## Overview\n\nThe MCP server supports containerized deployment through Docker, which is essential for production environments requiring isolation, scalability, and consistent runtime behavior. Container deployment enables integration with enterprise systems including Azure Container Instances, Azure Kubernetes Service, and on-premises Docker infrastructure.\n\n### Deployment Modes\n\nThe server operates in two primary modes:\n\n| Mode | Transport | Use Case |\n|------|-----------|----------|\n| **stdio** | Standard I/O | Local development, MCP Inspector, direct client integration |\n| **HTTP** | HTTP/SSE | Production deployments, remote client access, enterprise integration |\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Docker Configuration\n\n### Base Image and Runtime\n\nThe Dockerfile configures a Node.js runtime environment optimized for the MCP server's requirements. The image uses a multi-stage build approach to minimize the final image size while ensuring all dependencies are properly installed.\n\n```dockerfile\n# Reference: Dockerfile structure from repository conventions\nFROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --only=production\nCOPY dist/ ./dist/\nCMD [\"node\", \"dist/index.js\"]\n```\n\n资料来源：[Dockerfile](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/Dockerfile)\n\n### Security Configuration\n\nThe container runs as a non-root user to comply with security best practices and enterprise compliance requirements. This prevents privilege escalation attacks and limits the blast radius of potential container compromises.\n\n> Non-root Docker user\n> - Security headers: `X-Content-Type-Options`, `X-Frame-Options: DENY`, `Cache-Control: no-store`, CSP `default-src 'none'`\n> - Body size limit: 100 KB\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n### Build Arguments and Environment Variables\n\n| Variable | Purpose | Required |\n|----------|---------|----------|\n| `MS365_ADMIN_MCP_CLIENT_ID` | Azure AD application client ID | Yes |\n| `MS365_ADMIN_MCP_CLIENT_SECRET` | Application secret | Yes |\n| `MS365_ADMIN_MCP_TENANT_ID` | Azure AD tenant identifier | Yes |\n| `NODE_ENV` | Runtime environment (`production`) | Recommended |\n| `MS365_ADMIN_MCP_LOG_DIR` | Log output directory | Optional |\n\n## Persistent Storage Architecture\n\nThe server requires persistent storage for OAuth tokens and authentication state. The storage implementation supports multiple backends to accommodate different deployment scenarios.\n\n```mermaid\ngraph TD\n    A[MCP Server] --> B[Storage Abstraction Layer]\n    B --> C[Memory Storage]\n    B --> D[File-based Storage]\n    B --> E[Azure Table Storage]\n    \n    D --> F[~/.mcp-auth/]\n    E --> G[Azure Table]\n    \n    C -->|Ephemeral| H[Pod/Container Restart]\n    D -->|Persistent| I[Volume Mount]\n    E -->|Distributed| J[Multi-instance]\n```\n\n资料来源：[src/storage/index.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/index.ts)\n\n### Storage Backend Selection\n\n| Backend | Use Case | Persistence | Multi-instance |\n|---------|----------|-------------|----------------|\n| **Memory** | Local dev, single-use | ❌ Lost on restart | ❌ Not supported |\n| **File-based** | Single instance, Docker with volumes | ✅ Survives restart | ❌ Not recommended |\n| **Azure Table** | Production multi-instance | ✅ Distributed | ✅ Recommended |\n\n资料来源：[src/storage/oauth-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/oauth-storage.ts)\n\n### File-based Storage Details\n\nWhen using file-based storage, the server creates a directory structure under `~/.mcp-auth/mcp-remote-<version>/` with the following files:\n\n| File | Purpose | Permissions |\n|------|---------|-------------|\n| `<hash>_client_info.json` | Client registration metadata | 0600 |\n| `<hash>_tokens.json` | OAuth tokens (access, refresh) | 0600 |\n\nThe cache key uses `md5(serverUrl)` matching `mcp-remote`'s `getServerUrlHash` implementation exactly, ensuring compatibility with existing tooling.\n\n> Cache key = `md5(serverUrl)`, matching `mcp-remote`'s `getServerUrlHash` exactly; a regression test locks the hash against the known production URL.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Azure Table Storage Backend\n\nFor production deployments requiring high availability and horizontal scaling, the server supports Azure Table Storage as a distributed state backend:\n\n```typescript\n// Storage interface contract\nexport interface OAuthStorage {\n  getClientInfo(serverUrl: string): Promise<ClientInfo | null>;\n  saveClientInfo(serverUrl: string, info: ClientInfo): Promise<void>;\n  getTokens(serverUrl: string): Promise<Tokens | null>;\n  saveTokens(serverUrl: string, tokens: Tokens): Promise<void>;\n  deleteTokens(serverUrl: string): Promise<void>;\n}\n```\n\n资料来源：[src/storage/table-storage.ts](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/storage/table-storage.ts)\n\n## Volume Mounts and Configuration\n\n### Host Path Bindings\n\nFor Docker deployments, the server honors the `--cache-dir` CLI flag and `MCP_REMOTE_CONFIG_DIR` environment variable to enable custom storage locations. This is essential for:\n\n- **Docker bind mounts**: Map host directories to container paths\n- **Multi-user setups**: Shared configuration directories\n- **Persistent logs**: Surviving container recreation\n\n> `--cache-dir` + `MCP_REMOTE_CONFIG_DIR` env var honoured, so Docker bind mounts and multi-user setups work without patches.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Recommended Volume Structure\n\n```yaml\nversion: '3.8'\nservices:\n  mcp-server:\n    image: ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest\n    volumes:\n      - ./config:/config:ro        # Application configuration\n      - mcp-auth:/root/.mcp-auth  # Persistent OAuth state\n      - mcp-logs:/root/.ms365-admin-mcp/logs  # Application logs\n    environment:\n      - MS365_ADMIN_MCP_CLIENT_ID=${CLIENT_ID}\n      - MS365_ADMIN_MCP_CLIENT_SECRET=${CLIENT_SECRET}\n      - MS365_ADMIN_MCP_TENANT_ID=${TENANT_ID}\n      - MCP_REMOTE_CONFIG_DIR=/config\n\nvolumes:\n  mcp-auth:\n  mcp-logs:\n```\n\n## Logging Configuration\n\nThe Winston logger default behavior was updated to support containerized environments where the standard home directory may not be accessible:\n\n> Winston logger now uses `MS365_ADMIN_MCP_LOG_DIR=/tmp/...` by default in the Bicep template, avoiding `EACCES` against `/nonexistent/.ms365-admin-mcp/logs` when the image runs as a rootless user without a home directory\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Log Directory Configuration\n\n| Environment | Default Path | Notes |\n|-------------|--------------|-------|\n| Bicep/Azure | `/tmp/ms365-admin-mcp/logs` | Avoids home directory issues |\n| Standard | `~/.ms365-admin-mcp/logs` | User's home directory |\n| Custom | Set via `MS365_ADMIN_MCP_LOG_DIR` | Override default |\n\n## Azure Deployment (Bicep)\n\nFor Azure-native deployments, the project includes Bicep templates supporting:\n\n### Required Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `allowedClients` | array | Required; HTTP mode refuses to start without it |\n| `tags` | object | Propagated to every resource; required by org-level policies |\n| `acrLoginServer` | string | Azure Container Registry login server |\n| `location` | string | Azure region |\n\n> `allowedClients` Bicep parameter (required; HTTP mode refuses to start without it)\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Container Registry Integration\n\nThe Bicep template configures Azure Container Registry pull access using a User-Assigned Managed Identity (UAMI):\n\n```bicep\nresource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = {\n  name: acrLoginServer\n}\n\nresource uami 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {\n  name: 'mcp-server-uami'\n}\n\nresource acrPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {\n  name: guid(acr.id, uami.id, 'acrpull')\n  scope: acr\n  properties: {\n    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')\n    principalId: uami.properties.principalId\n  }\n}\n```\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Exit Codes\n\nThe server defines specific exit codes for container orchestration and CI/CD integration:\n\n| Code | Meaning | Use Case |\n|------|---------|----------|\n| 0 | Success | Normal operation, clean shutdown |\n| 1 | Usage error | Invalid arguments, missing required parameters |\n| 2 | Network error | Azure AD connectivity failure |\n| 3 | Access denied | Authentication/authorization failure |\n| 4 | Timeout | Request timeout during Graph API calls |\n\n> Documented exit codes (0 ok, 1 usage, 2 network, 3 denied, 4 timeout) for Docker / CI wrappers.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## HTTP Server Configuration\n\nWhen deployed in HTTP mode, the server exposes an HTTP endpoint with specific security configurations:\n\n### Security Headers\n\n| Header | Value | Purpose |\n|--------|-------|---------|\n| `X-Content-Type-Options` | `nosniff` | Prevent MIME type sniffing |\n| `X-Frame-Options` | `DENY` | Prevent clickjacking |\n| `Cache-Control` | `no-store` | Prevent sensitive data caching |\n| CSP | `default-src 'none'` | Content Security Policy |\n\n### Request Validation\n\n- **Body size limit**: 100 KB maximum\n- **Path parameter validation**: Rejects traversal patterns (`../`, `/`, `\\`, `?`, `#`, `&`) for `skipEncoding` parameters\n- **ReDoS protection**: `--enabled-tools` regex capped at 500 characters\n\n> Path parameter validation against traversal (`../`, `/`, `\\`, `?`, `#`, `&`) for `skipEncoding` params\n\n资料来源：[SECURITY.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/SECURITY.md)\n\n## CI/CD Integration\n\n### Best-Effort Clipboard\n\nThe server includes clipboard functionality for copying authentication codes during device code flow. This behavior is automatically disabled in CI environments:\n\n```typescript\nconst clipboard = process.env.CI !== 'true' && process.stdout.isTTY\n  ? platformClipboard()\n  : null;\n```\n\n> Best-effort clipboard copy (`pbcopy` / `clip` / `wl-copy` / `xclip`), auto-disabled under `CI=true` or non-TTY.\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n### Environment Detection\n\n| Variable | Detection | Behavior |\n|----------|-----------|----------|\n| `CI=true` | CI pipeline | Disable clipboard |\n| `non-TTY` | Background process | Disable clipboard |\n| `CI=undefined` + TTY | Interactive shell | Enable clipboard |\n\n## Troubleshooting\n\n### Common Deployment Issues\n\n| Issue | Cause | Resolution |\n|-------|-------|------------|\n| `EACCES` on logs | Home directory inaccessible | Set `MS365_ADMIN_MCP_LOG_DIR=/tmp/...` |\n| Authentication failures | Missing `allowedClients` | Configure Bicep parameter |\n| Token loss on restart | Memory storage selected | Use file or table storage backend |\n| Slow cold starts | Large image size | Use multi-stage build, `--only=production` |\n\n### Docker Bind Mount Patterns\n\nFor Persistent storage, use named volumes or host bind mounts:\n\n```bash\n# Named volumes (recommended)\ndocker run -v mcp-auth:/root/.mcp-auth ghcr.io/okapi-ca/ms-365-admin-mcp-server\n\n# Host bind mount\ndocker run -v /data/mcp-config:/root/.mcp-auth ghcr.io/okapi-ca/ms-365-admin-mcp-server\n```\n\n> `docs/TROUBLESHOOTING.md` — full section covering Docker bind-mount patterns, Conditional Access caveat\n\n资料来源：[CHANGELOG.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CHANGELOG.md)\n\n## Development with Docker\n\n### Building Locally\n\n```bash\n# Clone repository\ngit clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git\ncd ms-365-admin-mcp-server\n\n# Install dependencies\nnpm install\n\n# Generate client from OpenAPI spec\nnpm run generate\n\n# Build TypeScript\nnpm run build\n\n# Build Docker image\ndocker build -t ms-365-admin-mcp-server:latest .\n```\n\n### Running with Docker Compose\n\n```bash\n# Create .env file\ncat > .env << EOF\nMS365_ADMIN_MCP_CLIENT_ID=your-client-id\nMS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret\nMS365_ADMIN_MCP_TENANT_ID=your-tenant-id\nEOF\n\n# Start server\ndocker-compose up -d\n\n# View logs\ndocker-compose logs -f\n```\n\n## See Also\n\n- [Architecture Documentation](./ARCHITECTURE.md)\n- [Security Model](./SECURITY.md)\n- [HTTP Deployment](./HTTP_DEPLOYMENT.md)\n- [Troubleshooting Guide](./TROUBLESHOOTING.md)\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：okapi-ca/ms-365-admin-mcp-server\n\n摘要：发现 9 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n\n## 5. 安全/权限坑 · 来源证据：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n- 对用户的影响：可能增加新用户试用和生产接入成本。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_103cf7f40efc40e99adfa2eb14d9717e | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/70 | 来源讨论提到 node 相关条件，需在安装/试用前复核。\n\n## 6. 安全/权限坑 · 来源证据：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n- 对用户的影响：可能影响授权、密钥配置或安全边界。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_6ede43fd3f7247e0981524934656dbeb | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71 | 来源类型 github_issue 暴露的待验证使用条件。\n\n## 7. 安全/权限坑 · 来源证据：SEC-005: Express body parser runs before authentication and rate limiting\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-005: Express body parser runs before authentication and rate limiting\n- 对用户的影响：可能影响授权、密钥配置或安全边界。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_e53044f4bde148d7882ccf83273f1e22 | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/72 | 来源类型 github_issue 暴露的待验证使用条件。\n\n## 8. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | issue_or_pr_quality=unknown\n\n## 9. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | release_recency=unknown\n\n<!-- canonical_name: okapi-ca/ms-365-admin-mcp-server; human_manual_source: deepwiki_human_wiki -->\n",
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "Human Manual / 人类版说明书"
    },
    "pitfall_log": {
      "asset_id": "pitfall_log",
      "filename": "PITFALL_LOG.md",
      "markdown": "# Pitfall Log / 踩坑日志\n\n项目：okapi-ca/ms-365-admin-mcp-server\n\n摘要：发现 9 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium\n\n## 5. 安全/权限坑 · 来源证据：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-003: uuid <14.0.0 transitive vulnerabilities via @azure/msal-node\n- 对用户的影响：可能增加新用户试用和生产接入成本。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_103cf7f40efc40e99adfa2eb14d9717e | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/70 | 来源讨论提到 node 相关条件，需在安装/试用前复核。\n\n## 6. 安全/权限坑 · 来源证据：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)\n- 对用户的影响：可能影响授权、密钥配置或安全边界。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_6ede43fd3f7247e0981524934656dbeb | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71 | 来源类型 github_issue 暴露的待验证使用条件。\n\n## 7. 安全/权限坑 · 来源证据：SEC-005: Express body parser runs before authentication and rate limiting\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：SEC-005: Express body parser runs before authentication and rate limiting\n- 对用户的影响：可能影响授权、密钥配置或安全边界。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_e53044f4bde148d7882ccf83273f1e22 | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/72 | 来源类型 github_issue 暴露的待验证使用条件。\n\n## 8. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | issue_or_pr_quality=unknown\n\n## 9. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | release_recency=unknown\n",
      "summary": "用户实践前最可能遇到的身份、安装、配置、运行和安全坑。",
      "title": "Pitfall Log / 踩坑日志"
    },
    "prompt_preview": {
      "asset_id": "prompt_preview",
      "filename": "PROMPT_PREVIEW.md",
      "markdown": "# ms-365-admin-mcp-server - Prompt Preview\n\n> Copy the prompt below into your AI host before installing anything.\n> Its purpose is to let you safely feel the project's workflow, not to claim the project has already run.\n\n## Copy this prompt\n\n```text\nYou are using an independent Doramagic capability pack for okapi-ca/ms-365-admin-mcp-server.\n\nProject:\n- Name: ms-365-admin-mcp-server\n- Repository: https://github.com/okapi-ca/ms-365-admin-mcp-server\n- Summary: MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)\n- Host target: mcp_host\n\nGoal:\nHelp me evaluate this project for the following task without installing it yet: MCP server for Microsoft 365 admin operations via Graph API application permissions (security, audit, reports, service health)\n\nBefore taking action:\n1. Restate my task, success standard, and boundary.\n2. Identify whether the next step requires tools, browser access, network access, filesystem access, credentials, package installation, or host configuration.\n3. Use only the Doramagic Project Pack, the upstream repository, and the source-linked evidence listed below.\n4. If a real command, install step, API call, file write, or host integration is required, mark it as \"requires post-install verification\" and ask for approval first.\n5. If evidence is missing, say \"evidence is missing\" instead of filling the gap.\n\nPreviewable capabilities:\n- Capability 1: Use the source-backed project context to guide one small, checkable workflow step.\n\nCapabilities that require post-install verification:\n- Capability 1: Use the source-backed project context to guide one small, checkable workflow step.\n\nCore service flow:\n1. overview: Project Overview. Produce one small intermediate artifact and wait for confirmation.\n2. configuration: Configuration Reference. Produce one small intermediate artifact and wait for confirmation.\n3. system-architecture: System Architecture. Produce one small intermediate artifact and wait for confirmation.\n4. tool-categories: Tool Categories and Presets. Produce one small intermediate artifact and wait for confirmation.\n5. security-model: Security Model and Risk Classification. Produce one small intermediate artifact and wait for confirmation.\n\nSource-backed evidence to keep in mind:\n- https://github.com/okapi-ca/ms-365-admin-mcp-server\n- https://github.com/okapi-ca/ms-365-admin-mcp-server#readme\n- agent-skills/ms365-admin-mcp/SKILL.md\n- README.md\n- package.json\n- src/index.ts\n- src/cli.ts\n- src/cloud-config.ts\n- src/secrets.ts\n- docs/ARCHITECTURE.md\n\nFirst response rules:\n1. Start Step 1 only.\n2. Explain the one service action you will perform first.\n3. Ask exactly three questions about my target workflow, success standard, and sandbox boundary.\n4. Stop and wait for my answers.\n\nStep 1 follow-up protocol:\n- After I answer the first three questions, stay in Step 1.\n- Produce six parts only: clarified task, success standard, boundary conditions, two or three options, tradeoffs for each option, and one recommendation.\n- End by asking whether I confirm the recommendation.\n- Do not move to Step 2 until I explicitly confirm.\n\nConversation rules:\n- Advance one step at a time and wait for confirmation after each small artifact.\n- Write outputs as recommendations or planned checks, not as completed execution.\n- Do not claim tests passed, files changed, commands ran, APIs were called, or the project was installed.\n- If the user asks for execution, first provide the sandbox setup, expected output, rollback, and approval checkpoint.\n```\n",
      "summary": "不安装项目也能感受能力节奏的安全试用 Prompt。",
      "title": "Prompt Preview / 安装前试用 Prompt"
    },
    "quick_start": {
      "asset_id": "quick_start",
      "filename": "QUICK_START.md",
      "markdown": "# Quick Start / 官方入口\n\n项目：okapi-ca/ms-365-admin-mcp-server\n\n## 官方安装入口\n\n### Node.js / npm · 官方安装入口\n\n```bash\nnpm install -g @okapi-ca/ms-365-admin-mcp-server\n```\n\n来源：https://github.com/okapi-ca/ms-365-admin-mcp-server#readme\n\n## 来源\n\n- repo: https://github.com/okapi-ca/ms-365-admin-mcp-server\n- docs: https://github.com/okapi-ca/ms-365-admin-mcp-server#readme\n",
      "summary": "从项目官方 README 或安装文档提取的开工入口。",
      "title": "Quick Start / 官方入口"
    }
  },
  "validation_id": "dval_678c9500d6074d149e9cde5a9883812a"
}
