Skip to main content

MCP server for Box admin-log analytics — external-sharing visibility, read-only

Project description

boxadm-mcp

English | 日本語

MCP (Model Context Protocol) server that surfaces external file flow from a Box admin's point of view. It reads Box's enterprise event log (admin_logs) to highlight "who shares a lot with the outside" and "which files get accessed from outside" — an early-warning signal for leakage, not a general-purpose file browser.

Read-only: it never revokes shares, deletes files, or otherwise mutates anything — it only surfaces risk. This is a different tool from a general-purpose Box file MCP (the official Box MCP, or the claude.ai Box connector): those operate on a user's own files and cannot see enterprise events, which is exactly what this server is for.

Named after the admin-console viewpoint (boxadm = Box admin), sibling of gwsadm-mcp.

Features

Tool Category Description
health_check version + auth_mode + Box auth + admin_logs scope probe + configured domain allowlist. Reports needs-login when not yet authenticated (OAuth mode)
recent_admin_events Diagnostic Raw recent enterprise events (for checking event types/fields). Supports manual pagination via stream_position
external_access_events Access (events, enterprise-wide) Aggregates external DOWNLOAD/PREVIEW within a window: top external accessors, top externally-accessed files, share-link count. Pass created_by_logins for DLP tracing of a specific account
external_collaborators Exposure (enumeration) Lists external collaborators (outside-org login or external invite email)
public_shared_links Exposure (enumeration) Lists items shared with an open (anyone-with-the-link) share link
top_external_sharers Exposure (enumeration) Ranks internal owners by external exposure (external collabs + public links)
daily_brief Combined Morning summary combining access (events) and exposure (enumeration)

Auth model

Two modes, selected via BOX_AUTH_MODE:

  • oauth — OAuth 2.0 (user auth). An admin authorizes once in a browser; the refresh token keeps it running unattended after that.
  • ccg — Client Credentials Grant (server-to-server). Simpler to run unattended if your Box tenant has an available server-authentication app slot.

admin_logs (enterprise events) is readable in either mode, provided the authorizing/impersonated user is an admin and the app has the Manage enterprise properties scope.

OAuth setup (one-time, by a Box admin)

  1. Developer Console → Create Platform App → Custom App → User Authentication (OAuth 2.0)
  2. Redirect URI: http://localhost:8787/callback
  3. Application Scopes: check Manage enterprise properties (required for admin_logs). Add Read all files and folders too if you also want collaboration/share-link enumeration (requires re-consent)
  4. Enable the app in the Admin Console (unpublished apps are disabled by default under most tenant policies)
  5. Note the Client ID / Client Secret
  6. First login: set BOX_AUTH_MODE=oauth etc., then run boxadm-mcp auth → authorize in the browser → a token cache is written to ~/.config/boxadm-mcp/token.json (chmod 600)

Setup

# uv
uv pip install boxadm-mcp

# pip
pip install boxadm-mcp

Or from source:

git clone https://github.com/shigechika/boxadm-mcp.git
cd boxadm-mcp

# uv
uv sync

# pip
pip install -e .

Configuration

Variable Required Description
BOX_AUTH_MODE oauth / ccg (default ccg)
BOX_CLIENT_ID App Client ID
BOX_CLIENT_SECRET App Client Secret
BOX_ENTERPRISE_ID ccg mode Enterprise ID (CCG subject; not needed for oauth)
BOX_OAUTH_REDIRECT_URI oauth redirect. Default http://localhost:8787/callback
BOX_TOKEN_CACHE oauth token cache path. Default ~/.config/boxadm-mcp/token.json
BOX_API_BASE Default https://api.box.com
BOX_ALLOWED_DOMAINS Internal email domains (comma-separated). No default — every address counts as external until you set this

Keep secrets out of .mcp.json (e.g. in a local env file sourced before launch); .mcp.json itself can reference ${BOX_CLIENT_ID}-style variables and be safely committed.

Scope and limits

  • Access tools (external_access_events, and the access half of daily_brief) read the enterprise-wide events stream. Hitting max_events sets capped: true (oldest-first scan).
  • Exposure (enumeration) tools only see folders visible to the co-admin account (not a guaranteed 100% of the enterprise), plus max_folders/max_depth limits (surfaced via capped). Requires the Read all files and folders scope.
  • Enumeration tools share a short-TTL scan memo across calls; public_shared_links skips collaboration calls entirely (optimization).

DLP tracing (reverse-lookup by accessor)

To answer "what did this external account download": pass created_by_logins (comma-separated logins) to external_access_events. It keeps only that accessor's events and returns per-file detail (matched_events: item id/name, owner, size in bytes+GB, timestamp, event_type, whether it was via a share link).

external_access_events(since_hours=26, created_by_logins="someone@example.com")
  • Since the accessor could appear anywhere in the window, a filtered call auto-extends the scan cap to up to 50,000 events (oldest-first) — but only matching events are kept, so memory stays bounded.
  • In this mode the response carries events_matched (match count) instead of events_scanned (no running total is kept; use capped to judge coverage). capped: true means the window wasn't fully scanned — raise max_events.
  • Box's admin_logs API has no created_by query parameter, so this is a client-side filter (fetch_admin_events(created_by_logins=...)).

Usage

Claude Code

Add to .mcp.json:

{
  "mcpServers": {
    "boxadm-mcp": {
      "type": "stdio",
      "command": "boxadm-mcp",
      "env": {
        "BOX_AUTH_MODE": "oauth",
        "BOX_CLIENT_ID": "${BOX_CLIENT_ID}",
        "BOX_CLIENT_SECRET": "${BOX_CLIENT_SECRET}",
        "BOX_ALLOWED_DOMAINS": "example.com"
      }
    }
  }
}

CLI Options

boxadm-mcp auth       # OAuth first-time login (opens a browser)
boxadm-mcp --version  # Print version and exit
boxadm-mcp            # Start MCP server (STDIO, default)

Development

git clone https://github.com/shigechika/boxadm-mcp.git
cd boxadm-mcp

# uv
uv sync --dev
uv run pytest -v
uv run ruff check .

# pip
python3 -m venv .venv
.venv/bin/pip install -e . && .venv/bin/pip install pytest respx ruff
.venv/bin/pytest -v
.venv/bin/ruff check .

Tests never touch Box — respx mocks the CCG/OAuth token endpoint and the admin_logs/enumeration APIs.

Releasing

Releases are automated with release-please. Merging Conventional Commits (feat:, fix:, …) to main keeps a release PR open with the next version and changelog. Merging that PR tags vX.Y.Z and publishes a GitHub Release, whose release: published event triggers the release workflow to build and publish to PyPI and the MCP Registry. release-please owns the version in boxadm_mcp/__init__.py and server.json (do not bump them by hand).

[!IMPORTANT] The release-please workflow should be given a repository secret RELEASE_PLEASE_TOKEN (a PAT with contents: write + pull-requests: write). The default GITHUB_TOKEN cannot create the Release that triggers the downstream release workflow (GitHub blocks workflow runs triggered by GITHUB_TOKEN), so without the PAT nothing gets published. The workflow falls back to GITHUB_TOKEN when the secret is unset so PR CI keeps working on forks.

Governance

Because this surfaces what users share, run it as authorized information-security monitoring with a clear purpose, a defined set of viewers, and a retention policy. Most external sharing is legitimate (collaborators, vendors), so treat findings as a risk ranking, not an alert queue — build an allowlist of known-OK sharers over time.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

boxadm_mcp-0.3.2.tar.gz (33.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

boxadm_mcp-0.3.2-py3-none-any.whl (24.0 kB view details)

Uploaded Python 3

File details

Details for the file boxadm_mcp-0.3.2.tar.gz.

File metadata

  • Download URL: boxadm_mcp-0.3.2.tar.gz
  • Upload date:
  • Size: 33.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for boxadm_mcp-0.3.2.tar.gz
Algorithm Hash digest
SHA256 e859287cedd7ca20794d334e5e5851bcdfb8e1cda42f40c97af0d1ee897bb7a9
MD5 f39a0b8f9491860d29feb56cafd500aa
BLAKE2b-256 c520b13ff2810017a460f7aeb5270edbd4635d18be6e50d0557ca8d2eb850650

See more details on using hashes here.

Provenance

The following attestation bundles were made for boxadm_mcp-0.3.2.tar.gz:

Publisher: release.yml on shigechika/boxadm-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file boxadm_mcp-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: boxadm_mcp-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 24.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for boxadm_mcp-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6af2a9ed526e2931332954d3a981790f82b9427340c35c186a66cdcf55b2d734
MD5 5f02c15e3066073cb5657323cb559dfe
BLAKE2b-256 4fa1145ad5154630c5ccf20376fc1f2bc16ce1e9ffb256ec09b72e5b4fbc5149

See more details on using hashes here.

Provenance

The following attestation bundles were made for boxadm_mcp-0.3.2-py3-none-any.whl:

Publisher: release.yml on shigechika/boxadm-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page