Skip to main content
Glama
shigechika

boxadm-mcp

by shigechika

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.

Documentation: https://shigechika.github.io/boxadm-mcp/

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)

list_folder_items

One folder (ls)

Names, upload time, size, who uploaded, and a direct link per item. Filter by uploader or upload-time window. Reads no file content

get_user

Account state (lookup)

One account by its exact login: status, role, enterprise, quota, timestamps. Answers "is this account disabled?" without an admin console

daily_brief

Combined

Morning summary combining access (events) and exposure (enumeration)

Related MCP server: gwsadm-mcp

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, and Manage users if you want the get_user lookup (each scope change requires re-consent via boxadm-mcp auth)

  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). Any other value falls back to ccg; health_check reports the mode in effect, so a typo shows up there as ccg rather than as what was typed

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_SCAN_CONCURRENCY

Parallel per-folder lookups in the enumeration scan. Default 8, clamped 132

BOX_SCAN_DEADLINE

Soft wall-clock budget (seconds) for one enumeration scan. Default 45; 0/negative disables it. When hit, the scan returns a disclosed partial (capped=true) instead of running until the tool call times out

BOX_HTTP_TIMEOUT

Per-request HTTP timeout (seconds). Default 30. Lower it (with BOX_SCAN_DEADLINE) so one slow endpoint can't stretch the final in-flight scan batch past a gateway timeout

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.

  • The scan fans its per-folder lookups out concurrently (BOX_SCAN_CONCURRENCY), since Box has no enterprise-wide collaboration listing — this widens how many folders finish inside a tool-call timeout, but coverage is still bounded by the caps. The read path retries 429 (honoring Retry-After) and transient 5xx with jittered backoff, so a passing throttle recovers instead of degrading coverage; a folder dropped by a per-folder API error that outlasts those retries (e.g. a persistent 403) is counted in fetch_errors: coverage is complete only when capped is false and fetch_errors is 0.

  • Enumeration tools share a short-TTL scan memo across calls; public_shared_links skips collaboration calls entirely (optimization).

  • get_user reads the enterprise user directory instead — one request, no paging, and structurally not an enumerator (it answers about the login you pass and nothing else). Its capped flag discloses a truncated search, so a found: false from a truncated result reads as inconclusive rather than negative.

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=...)).

One folder's contents (list_folder_items)

An ls, not a cat. Written for a help desk answering a submitted enquiry whose attachments land in a Box folder: instead of a human going to find that folder, the answer names the attachments and links straight to them. File content is never read, and no shared link is ever created — an existing one is reported because it is an exposure finding, not a convenience.

Who uploaded an item is not where you would look for it. For an upload made through a File Request, Box records no user at all: created_by and modified_by both read "Anonymous User", and owned_by is the application's own service account — identical on every row. The only field carrying the submitter is uploader_display_name, and despite its name the value observed in practice was an email address. It is therefore matched as an opaque string (exact, case-insensitive) and never parsed or validated as an address. For a file uploaded by a signed-in user the reverse holds, so created_by is the fallback.

Ordering and time bounds are computed here rather than by Box:

  • Box documents sort as the second sort attribute — items order by type first, so a subfolder precedes every file regardless of date. Measured against a real folder, sort=date also matched neither created_at nor modified_at order, so it cannot honestly be presented as "newest".

  • since / until are compared as instants, not text. Box stamps items in its own UTC offset while a caller asks in theirs, so a lexicographic comparison is wrong by that difference at every date boundary and silent about it. Both bounds must carry an offset; a bare date is refused rather than guessed.

limit bounds what is RETURNED, not what is searched — a full page is fetched first, so an uploader's item is found even when it is not among the newest. Truncation is disclosed twice over, because they are different truths: returned vs matched is the caller's own limit, while capped means the folder holds more than one page and a miss is inconclusive rather than negative.

Per-account lookup (get_user)

Every other tool reads the event stream or walks folders, so an account with no recent activity cannot be asked about at all. get_user answers directly — "is this account disabled, and is its quota full?" — in one request:

get_user(login="someone@example.com")

login is the account's full Box login (an email address), matched exactly and case-insensitively. That matching is the point, not an implementation detail: Box's underlying filter_term is a prefix search over display name and login, so the endpoint readily returns a colleague whose name starts with the same letters. Only an exact login match lands in user; everything else is counted in other_prefix_hits and never identified. A term that is not email-shaped is refused before the request is made — filter_term has no minimum length, so a one-character term would otherwise return a page of real accounts.

One drift it cannot find: the same person under a second login at another domain. filter_term prefix-matches the whole term, so alice@old.example can never return alice@new.example; that would need a search on the local part alone, which is the directory-wide prefix search this tool refuses by design.

Field

Meaning

found

The only field that says whether the account exists. false is a normal answer, not an error

user

The account when found, else null: status, role, enterprise, space_used / space_amount, created_at, modified_at

other_prefix_hits

Count of further prefix matches. A count only: those are different accounts and are deliberately not identified

capped

The search was truncated, so found: false is inconclusive rather than negative

search_hits, note

How many entries came back, and a plain-language reading

NOTE

Inoauth mode this endpoint's requirement is verified end-to-end: the app must hold the "Manage users" application scope. Without it /2.0/users answers 403 even when the authorising user is a co-admin who can manage users; with it, 200. Two caveats: the effective permission is still capped by the authorising user's own role, and a scope added in the Developer Console does not reach tokens minted from an existing refresh token — the app must be re-authorised interactively (boxadm-mcp auth) before the new scope takes effect. Under ccg the endpoint remains unverified. A permission failure returns likely_cause saying all of this rather than a bare HTTP status.

Usage

Claude Code (plugin)

This repository doubles as a single-plugin marketplace, so Claude Code can install the server for you:

/plugin marketplace add shigechika/boxadm-mcp
/plugin install boxadm-mcp@boxadm-mcp

The plugin launches uvx boxadm-mcp and reads the same environment variables described in Configuration; export BOX_CLIENT_ID, BOX_CLIENT_SECRET, BOX_ENTERPRISE_ID (ccg mode), and BOX_ALLOWED_DOMAINS before starting Claude Code. The plugin ships with BOX_AUTH_MODE=ccg by default — switch to oauth only after running boxadm-mcp auth once yourself, since the plugin cannot provision that browser step or the resulting token cache file for you.

uvx must be on the PATH of the process that runs Claude Code — a login shell usually has it, but a GUI-launched app may not; install uv system-wide if the plugin fails to start.

Claude Code (manual)

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.

Live smoke test

That isolation is the point of the unit tests, and also their limit: they cannot tell you that a tool has stopped returning real data. scripts/smoke_test.py runs every registered tool against the configured enterprise and fails on empty, malformed or error answers:

# needs the same BOX_* environment variables as the server
uv run python scripts/smoke_test.py
uv run python scripts/smoke_test.py --only shared_links --traceback
  • Read-only. Every tool here reads; nothing in Box is changed. A future tool that writes must be listed as state-changing and skipped, and a test enforces that.

  • No payloads in the report. Tool names, statuses and row counts only; server-authored error text is redacted too, since Box errors quote the account or item they were asked about.

  • Bounded. These tools page the event stream and walk the folder tree, so each probe passes explicit small caps instead of the interactive defaults (5000 events, 150 folders) — enforced by a test that finds the bounding parameters from the source.

  • Nothing enterprise-specific in the specs. A test bans address shapes (login, URL, hostname, IPv4, IPv6) and the parameters that carry an account name, because this repository is public. Two literals identify nobody and are allowed: folder id 0, the root folder in every enterprise, and the made-up term get_user is probed with — an account that cannot exist, so the probe asserts the not-found path rather than naming a real person.

  • An empty answer passes: no public links and no external collaborators is the desired state, so probes assert the accounting envelope (count, folders_scanned, window_hours) rather than a row count.

  • CI enforces the cheap half: a tool registered without a probe spec fails the build (tests/test_smoke_probes.py), so adding a tool forces the question "how would we know it works?".

  • scripts/smoke_harness.py is the engine and holds no Box knowledge: it is kept identical across the servers that share it, so fix engine bugs once and sync the file rather than patching this copy.

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 secretRELEASE_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

Available Tools

9 tools
daily_briefA

Morning DLP brief: external access (events) + external-sharing state (enumeration).

One call that combines:

  • access (enterprise-wide, events): external DOWNLOAD/PREVIEW in the last since_hours, with top external accessors and top externally-accessed files.

  • exposure (co-admin visible folders, enumeration): current external collaborations, open ("anyone with the link") shared links, and the owners most externally exposed.

Reuses the cached folder scan, so calling this alongside the other enumeration tools doesn't re-walk. Args mirror the underlying tools; top defaults to 5 for a compact summary. Coverage/caps caveats are the same (capped flags + enumeration limited to the co-admin's visible content). On failure returns {"error": ...}.

ParametersJSON Schema
NameRequiredDescriptionDefault
topNo
max_depthNo
max_eventsNo
max_foldersNo
since_hoursNo

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite no annotations, the description thoroughly discloses behavioral traits: it reuses a cached folder scan, returns an error object on failure, mentions coverage/caps caveats (capped flags, enumeration limited to co-admin visible content), and explains default behavior (top defaults to 5 for compact summary).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with bullet points and clear sections, and the main purpose is front-loaded. It is slightly lengthy but each part adds value (purpose, behavioral notes, caveats).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema is provided, so the description should explain the return format. It mentions an error object on failure but does not describe the success response structure (e.g., fields, format of 'access' and 'exposure' data). This is a notable gap given the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains 'since_hours' (last N hours) and 'top' (defaults to 5 for compact summary) but only vaguely states 'Args mirror the underlying tools' for other parameters like max_depth, max_events, max_folders, lacking individual explanations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it provides a combined brief of external access events and external-sharing state (enumeration). It distinguishes from siblings like external_access_events and external_collaborators by explicitly saying it combines two underlying tools into one call.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context on when to use it (e.g., morning DLP brief, reuses cached folder scan alongside other enumeration tools). However, it does not explicitly state when not to use it or mention alternative tools by name, only implying they are the individual underlying tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

external_access_eventsA

Surface external file access (DOWNLOAD / PREVIEW) from enterprise admin_logs.

Enterprise-wide (events stream): over the window, flags each access whose actor (created_by.login) is outside the org domain allowlist — an external party, or an anonymous open-link visitor (no login) — and whether it came via a shared link. Aggregates to the top externally-accessed files and the top external accessors, so an admin can spot unusual outbound data pulls.

Args: since_hours: Look-back window in hours (default 24). max_events: Cap on DOWNLOAD/PREVIEW events scanned (default 5000); the result's capped flag is true when more existed (never silently truncated). top: How many top files / accessors to return (default 20). created_by_logins: Comma-separated accessor logins to trace (empty = all). When set, switches to DLP-tracing mode (see below).

Returns window_hours, events_scanned, capped, external_access_count, via_shared_link, top_external_accessors (login + count + bytes), and top_externally_accessed_files (item id/name/ owner + external-access count). On failure returns {"error": ...} (incl. needs-login for an expired OAuth session).

Notes:

  • via_shared_link counts ALL scanned accesses that went through a shared link (internal and external), not just external ones.

  • Events are scanned oldest-first from the window start. When capped is true the aggregates reflect only the scanned (earliest) slice, NOT the full window — raise max_events for a complete picture.

  • DLP tracing (created_by_logins set): scans up to the wider of max_events and 50000 events (the accessor may sit anywhere in the window) but keeps only that accessor's events, so the answer to "which files did this account pull" is exact and bounded. The result reports events_matched (not events_scanned — this mode doesn't track the scanned total; judge coverage by capped), filtered_logins and matched_events (per access: item id/name, owner, size bytes+GB, created_at, event_type, accessor, via_shared_link); the aggregate is scoped to the filtered accessor(s). capped true means the window was not fully scanned (raise max_events).

ParametersJSON Schema
NameRequiredDescriptionDefault
topNo
max_eventsNo
since_hoursNo
created_by_loginsNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behaviors: scan window and capping, via_shared_link counting details, oldest-first scanning, DLP mode behavior changes, and error handling (needs-login). This is comprehensive and goes beyond basic annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is verbose but well-structured with sections (Args, Returns, Notes). It is front-loaded with the main purpose. Some redundancy exists (e.g., DLP mode repeated), but the complexity justifies the length. Minor conciseness improvements possible.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multiple modes, 4 parameters, no output schema), the description is exceptionally complete. It details all return fields, error conditions, and behavioral nuances like capped flag and DLP mode changes. No gaps for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description compensates fully by explaining each parameter: since_hours (look-back window), max_events (cap with capped flag), top (number of results), created_by_logins (DLP mode). This adds significant meaning beyond the schema's type and default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it 'Surface external file access (DOWNLOAD / PREVIEW) from enterprise admin_logs.' It specifies the verb 'surface' and resource 'external file access', distinguishing it from siblings like 'external_collaborators' and 'top_external_sharers' by focusing on admin log events.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for use: 'so an admin can spot unusual outbound data pulls.' It explains normal mode and DLP tracing mode, but does not explicitly state when not to use this tool or mention alternative tools, leaving some ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

external_collaboratorsA

List external collaborators on Box folders (current state, enumeration).

Walks folders the authenticating co-admin user can see (default from the root "All Files") and reports collaborations whose collaborator is outside the org domain allowlist — accepted external users or pending external invites. Useful to review who outside the organization has standing access.

Args: root_folder_id: Folder to start from ("0" = the user's root). A Box folder id: decimal digits only, as shown at the end of a Box folder URL. Anything else is refused with {"error": ...} before any request is made, rather than being reported as an empty result. max_folders: Cap on folders visited (default 150); capped discloses when coverage was cut short. max_depth: Folder recursion depth (default 1 = top-level folders only).

Externally-owned folders (this org is only a guest, not the owner) are out of scope and skipped — we cannot govern their collaborations, and their "external collaborators" are just the owner's own org accounts. They are reported separately under skipped_externally_owned (never silently dropped) and do not consume the max_folders budget.

Coverage note: limited to content the co-admin user can access (not provably 100% of the enterprise) and to the depth/folders caps. Returns folders_scanned, capped, fetch_errors (count of folders whose lookup hit an API error that outlasted the client's retries, e.g. a persistent 403 or a sustained throttle — coverage is complete only when capped is false AND fetch_errors is 0), count, external_collaborators (folder, owner, collaborator, role, status, expires_at), and skipped_externally_owned (folder_id, folder_name, owner). On failure returns {"error": ...}.

ParametersJSON Schema
NameRequiredDescriptionDefault
max_depthNo
max_foldersNo
root_folder_idNo0

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses extensive behavior: it refuses invalid root_folder_id with an error, skips externally-owned folders with separate reporting, and explains the max_folders cap via the `capped` field. Error handling for fetch errors is also detailed, covering persistent API errors and retries—all beyond what any annotation could provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a one-sentence summary, followed by structured details organized into coherent paragraphs. Each sentence contributes new information, such as coverage limitations and return fields, justifying its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema and no annotations, the description provides a thorough account of return values, error behavior, and limitations (e.g., coverage only reflects co-admin's accessible folders). It covers all critical aspects an agent needs to invoke and interpret results correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the Args section richly explains each parameter: root_folder_id's format and validation, max_folders' default and `capped` disclosure, and max_depth's recursion semantics. This fully compensates for the sparse schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first line 'List external collaborators on Box folders (current state, enumeration)' uses a specific verb and resource, clearly distinguishing the tool's purpose. Though siblings like external_access_events exist, the description unambiguously defines what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear context is provided about walking folders from the root 'All Files' and the tool's usefulness for reviewing external standing access. However, no explicit alternatives or when-not-to-use conditions are given, aside from the out-of-scope externally-owned folders, which is more about tool behavior than usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_userA

Look up ONE Box account by its exact login (the account's email address).

Answers "what is this account's state?" — the question behind a ticket that says "my Box account is disabled". Every other tool here reads the event stream or walks folders, so an account with no recent events is invisible to them; this is one request against the user directory and the only tool that answers about an account directly. Use it when a specific account is named. It cannot list, search or enumerate accounts: it takes one login and answers about that login only.

Args: login: The account's full Box login, i.e. its email address (someone@example.com) — not a display name, not a user id. Matched EXACTLY, case-insensitively. A partial login does not match.

This server is downstream of an identity provider, not the master. Read what comes back as "what Box currently believes", and compare it against the IdP's own record (which is authoritative for who the account is). A disagreement is the finding, and is usually drift on the Box side rather than a mistyped address:

  • enterprise absent/null — the account is no longer in the enterprise (it has become a free personal account), so enterprise SSO no longer applies to it even though the IdP still authenticates the person. Box classes such an account as external and returns it only on a COMPLETE login match, which is exactly what this tool asks for — so it is reachable here, and a partial login would silently lose it.

  • status other than active — the IdP authenticates, Box refuses.

  • is_platform_access_only true — an App User, which cannot sign in interactively at all.

One drift this tool cannot find for you: the same person under a second login at another domain (an alias, or a duplicate left by a migration). filter_term prefix-matches the WHOLE term, so a search for alice@old.example can never return alice@new.example. Finding that would take a search on the local part alone, which is a prefix search over the directory and is refused here by design. Ask the identity provider which login it asserts, and look that one up.

Returns two shapes, distinguished by whether the lookup completed.

On a completed lookup:

  • requested_login — what was asked for, echoed back.

  • found — bool. The only field that says whether the account was found.

  • user — the account when found is true, else null: id, name, login, status (active / inactive / …, the usual answer to "why can't I sign in"), role, enterprise, space_used / space_amount (quota exhaustion is another recurring cause), created_at, modified_at.

  • other_prefix_hits — how many further accounts the prefix search matched. A COUNT ONLY: those are different accounts and are deliberately not identified, so this can never be used to browse the directory.

  • search_hits — how many entries the search returned.

  • capped — true when the search result was truncated, so found: false is inconclusive rather than negative (note says so).

  • note — plain-language reading of the above.

Why the filtering matters: Box's filter_term is a prefix search over display name AND login, not a lookup, so it happily returns somebody else — a colleague whose display name starts with the same letters. user is therefore only ever an exact login match, no other hit is ever identified, and a term that is not email-shaped is refused before the request is made (a one-character term would otherwise return a page of real accounts).

On failure the other shape is returned: {"error": ...} (missing env / needs-login for an expired OAuth session / a Box API error), plus likely_cause when the failure was a permission one. found is absent from that shape on purpose — a failed lookup is not a negative answer, and must never be read as "no such account". Auth caveat: this server supports two auth modes, and under oauth the effective permission is the authorising user's. In oauth mode the requirement IS verified end-to-end: the app must hold the "Manage users" application scope (without it /2.0/users answers 403 even when the authorising user is a co-admin who can manage users), and a scope added in the Developer Console only reaches tokens from a fresh interactive authorisation — refresh-token rotation keeps the original grant's scopes. Under ccg the endpoint remains unverified for this server.

ParametersJSON Schema
NameRequiredDescriptionDefault
loginYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

There are no annotations, so the description carries the full transparency burden. It discloses exact and case-insensitive matching, the prefix-search pitfall that can return other users, the meaning of absent enterprise, non-active status, is_platform_access_only, truncated search results, and the deliberate absence of a 'found' field on error.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with the core action, and each major behavioral point has its own section. However, it is quite long for a one-parameter tool and repeats the prefix-search/filtering caveat in multiple places, so a little trimming would earn the top score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotations, the description must be the complete contract, and it is. It fully documents the success shape, the error shape, auth caveats, return field meanings, and the distinction between 'not found' and 'lookup failed'.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema gives only a type and title, so this description is the complete semantic source. It fully explains the 'login' parameter: full email address, not display name or user id, exact case-insensitive match, and how a partial login will not match.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific operation: 'Look up ONE Box account by its exact login.' It directly distinguishes itself from siblings by stating that every other tool reads the event stream or walks folders, while this tool is the only one that answers directly about an account.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use the tool: 'Use it when a specific account is named.' It also tells the agent what the tool cannot do — list, search, or enumerate accounts — and advises consulting the identity provider when a duplicate or alias login is suspected.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

health_checkA

Report server version, Box connectivity/auth, and configuration.

Call this at session start (or after a tool-call timeout) to confirm the MCP is up, see which version is running, verify the Box enterprise token can be obtained (CCG) and that the admin_logs event scope is actually granted, and view the org domain allowlist used for external detection. Lightweight: one token request plus a single-row events probe — it does not scan history.

Always returns the same keys: status (healthy / degraded / error), service, version, auth_mode (ccg / oauth — the mode in effect, so an unrecognised BOX_AUTH_MODE reads as ccg, which is what the server falls back to), box_api_base, enterprise_id, auth (ok / error / missing-env / needs-login), events_accessible (bool), and allowed_domains. On a degraded or error result, detail carries the reason.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavior: it makes one token request, probes events, and returns standardized keys. It also explains degraded/error states and auth_mode fallback, ensuring the agent knows exactly what to expect.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with an initial summary, usage guidance, and detailed return keys. It is slightly lengthy but every sentence is informative; could be slightly more concise but remains clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simplicity of the tool and lack of output schema, the description is complete: covers purpose, when to use, behavior, and all return keys. No gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters, so schema coverage is 100% trivially. The description adds all meaning by detailing the return structure and behavior, fully compensating for the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reports server version, connectivity/auth, and configuration. It distinguishes itself from sibling tools that focus on admin events, external access, etc., by being a health check for the server itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly advises 'Call this at session start (or after a tool-call timeout)' and notes it is lightweight with one token request and a single-row events probe. Does not provide explicit when-not or alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_folder_itemsA

List ONE Box folder's contents, newest first, with who uploaded each item.

An ls, not a cat: names, timestamps, sizes, uploader and a direct link per item. File CONTENT is not read and no shared link is ever created.

Written for a help desk answering a submitted enquiry whose attachments land in a Box folder. Instead of a human going to find that folder, the answer can name the attachments and link straight to them.

Args: folder_id: The folder's Box id — decimal digits, the number at the end of a Box folder URL. "0" is the caller's own root ("All Files"), the same convention the enumeration tools use. Anything else — a name, a label, a whole URL — is refused before any request is made. uploaded_by: Optional. Return only items uploaded by this person, matched EXACTLY and case-insensitively against uploaded_by below. Use it when the enquiry names its submitter. since: Optional lower bound on upload time (created_at), inclusive. until: Optional upper bound on upload time (created_at), inclusive. Both MUST carry a UTC offset (2026-08-14T00:00:00+09:00): a bare date names a different instant in every timezone, and this server has no basis for choosing one. Compared as instants, not as text. limit: How many rows to RETURN after filtering (default 100). It does not bound what is searched — a full page is always fetched first, so a match for uploaded_by is found even when it is not among the newest items.

On uploaded_by: Box populates uploader_display_name for an upload made through a File Request, where no Box user is involved — created_by and modified_by both read "Anonymous User" and the owner is the application's service account, so neither identifies anybody. For a file uploaded by a signed-in user the reverse holds, so created_by is used as the fallback. Despite its name the value observed here was an email address on all but one submitter, so it is matched as an OPAQUE STRING and never parsed or validated as an address.

Treat name and uploaded_by as text the submitter chose. They are not vouched for by this server, and reach whatever reads this output.

Returns, on a completed listing:

  • folder_id / folder_name / folder_url

  • items — the rows, newest created_at first

  • returned / matched — rows returned, and rows that matched the filters. returned < matched means limit cut the answer.

  • total_in_folder — Box's own count for the folder, before filtering

  • capped — true when the folder holds more than one page, so the filters were applied to part of it and a "no match" is inconclusive rather than negative. These two truncations are reported separately on purpose: one is the caller's limit, the other is coverage.

  • note — the above in words

On failure the shape is {"error": ...} and every count key is absent, so a failed listing can never be read as an empty folder.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
sinceNo
untilNo
folder_idYes
uploaded_byNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully discloses behavior: it does not read file content or create shared links, explains case-insensitive matching, details truncation flags (capped, returned < matched), and specifies the failure shape where count keys are absent, ensuring a failed listing cannot be misread as empty.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (overview, use case, arguments, return details) but is somewhat verbose, repeating certain points like 'newest first' and the explanation of uploaded_by behavior. Despite slight redundancy, it remains focused and front-loaded with the essence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete given the tool's complexity: it covers the input parameters in depth, spells out the return shape (folder_id, items, returned/matched, total_in_folder, capped, note), and explains error handling. No output schema exists, so the description fully compensates.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds extensive meaning beyond the schema, which only provides types and defaults. Each parameter is explained: folder_id format including '0' as root, uploaded_by exact matching case-insensitively, since/until date handling with UTC offset requirement, and limit only affecting return count not search scope. This goes far beyond the schema's raw attributes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states exactly what the tool does: 'List ONE Box folder's contents, newest first, with who uploaded each item.' It uses a specific verb (list) and resource (Box folder), and distinguishes itself from sibling tools like health_check and external_access_events by focusing on folder contents.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly frames when to use the tool: 'Written for a help desk answering a submitted enquiry whose attachments land in a Box folder.' It also differentiates from 'enumeration tools' by noting the same convention for folder IDs, giving clear contextual guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

recent_admin_eventsA

Fetch recent enterprise admin_logs events (raw passthrough).

Diagnostic/starter tool: returns Box events verbatim so the real event types and field shapes can be confirmed before analytics tools are layered on. For external-sharing work the event types of interest are typically COLLABORATION_INVITE / COLLAB_ADD_COLLABORATOR, SHARED_LINK_CREATED / ITEM_SHARED_CREATE, and DOWNLOAD / PREVIEW.

Args: event_types: Comma-separated Box event_type filter (empty = all types). since_hours: Look-back window in hours (default 24). limit: Max events to return in this page (default 100). stream_position: Continue a previous page by passing back the next_stream_position from the prior call (empty = first page). Box caps a single page at 500, so manual paging is needed to walk a busy window — or use external_access_events which pages for you.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
event_typesNo
since_hoursNo
stream_positionNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavior: it returns raw Box events verbatim, Box caps a single page at 500, manual paging is needed, and lists typical event types for external-sharing work. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured: a one-line summary followed by a paragraph explaining its diagnostic purpose, then a clear bullet-style args list, and a note on paging with sibling reference. No superfluous text; every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description explains that results are raw events verbatim and gives examples of relevant event types. It also covers pagination limitations and directs to a sibling for automatic paging. Complete for a diagnostic tool of this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Though schema description coverage is 0%, the description provides detailed explanations for all 4 parameters: 'event_types' as comma-separated filter, 'since_hours' as look-back window, 'limit' as max events per page, and 'stream_position' for pagination. This fully compensates for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it fetches recent enterprise admin_logs events as a raw passthrough. It distinguishes itself from sibling tools like 'external_access_events' by noting that this tool requires manual paging, while the sibling pages automatically.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly positions itself as a diagnostic/starter tool to confirm event types and field shapes before using analytics tools. Specifically mentions when to prefer 'external_access_events' for automatic paging, providing clear when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

top_external_sharersA

Rank internal owners by their external exposure (enumeration).

One traversal (same as external_collaborators / public_shared_links), then ranks internal file/folder owners by how much external exposure they hold: external collaborations + open shared links on content they own. Surfaces the people whose content is most exposed outside the organization.

Args: root_folder_id / max_folders / max_depth: traversal bounds (see external_collaborators). top: How many owners to return (default 20).

Coverage note: limited to the co-admin user's visible content and the caps. Returns folders_scanned, capped, fetch_errors (count of folders whose lookup hit an API error; coverage is complete only when capped is false AND fetch_errors is 0), and top_external_sharers (owner, external_collaborations, public_links, total). On failure {"error": ...}.

ParametersJSON Schema
NameRequiredDescriptionDefault
topNo
max_depthNo
max_foldersNo
root_folder_idNo0

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden. It discloses that coverage is limited to the co-admin user's visible content and caps, and that fetch errors indicate incomplete coverage. However, it does not explicitly state that the tool is read-only, though the context implies no side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and covers purpose, usage, parameters, coverage limitations, and return format in a logical flow. It is slightly verbose but every sentence adds value, and it remains clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description thoroughly explains the return structure (folders_scanned, capped, fetch_errors, top_external_sharers) and error handling. Parameters are fully explained, and limitations are clearly stated. It is complete enough for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaning beyond the schema (which has 0% coverage) by explaining all four parameters: root_folder_id, max_folders, max_depth as traversal bounds (referencing external_collaborators), and top as the number of owners. The explanation is adequate, though it relies on knowledge of another tool for full parameter details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool ranks internal owners by external exposure, using a traversal method similar to sibling tools. The verb 'rank' and resource 'internal owners by external exposure' are specific, and it distinguishes itself by focusing on owners rather than just listing collaborators or links.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the tool is built on the same traversal as external_collaborators/public_shared_links, implying use when you need aggregated exposure per owner. However, it does not explicitly state when not to use it (e.g., if only raw lists are needed) or provide direct alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv0.9.0
    • Addedget_user
    • Addedlist_folder_items
  2. 7 tool updatesv0.1.0
    • First observeddaily_brief
    • First observedexternal_access_events
    • First observedexternal_collaborators
    • First observedhealth_check
    • First observedpublic_shared_links
    • First observedrecent_admin_events
    • First observedtop_external_sharers

TDQS

A4.4/5.0
Disambiguation5/5

Each tool targets a distinct aspect: health_check for server status, recent_admin_events for raw event logs, external_access_events for aggregated external access, external_collaborators for current external collaborators, public_shared_links for open shared links, top_external_sharers for ranking owners, get_user for a single user lookup, daily_brief as a combined summary, and list_folder_items for folder contents. No two tools overlap in purpose.

Naming Consistency3/5

All names use snake_case and are descriptive, but there's a mix of verb-first (health_check, get_user, list_folder_items) and noun/adjective-first (recent_admin_events, external_collaborators, daily_brief) patterns. This inconsistency makes the naming convention less predictable than a uniform verb_noun style.

Tool Count5/5

The 9 tools are well-suited to the server's purpose of Box admin monitoring and external access analysis. Neither too few to be thin nor too many to be unwieldy, each tool has a clear role.

Completeness4/5

The surface covers the full lifecycle of external access monitoring: raw event access, aggregated access analysis, current external collaboration state, open shared link enumeration, ranking by exposure, individual user lookup, folder listing, and a combined daily brief. Minor gaps exist, such as no tool to modify permissions or list all users, but these are likely outside the server's read-only monitoring scope.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    D
    maintenance
    A local MCP server for the LimaCharlie security platform that provides investigation, administration, and content-review workflows via a broad read-only tool surface with explicit organization scoping and audit logging.
    100
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Google Workspace security-audit MCP server — read-only visibility into account locks, suspicious logins, and external file sharing, built on the Admin SDK Reports API (audit activities).
    14
    MIT
  • F
    license
    A
    quality
    C
    maintenance
    A secure, read-only MCP server for AI-powered system monitoring. It provides real-time OS metrics, config discovery, and safe log tailing to enable autonomous infrastructure audits without shell access risks.
    4
    1
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shigechika/boxadm-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server