Skip to main content
Glama
shigechika

boxadm-mcp

by shigechika

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
BOX_API_BASENoAPI base URL (default https://api.box.com)
BOX_AUTH_MODENooauth or ccg (default ccg)
BOX_CLIENT_IDYesApp Client ID
BOX_TOKEN_CACHENoOAuth token cache path (default ~/.config/boxadm-mcp/token.json)
BOX_CLIENT_SECRETYesApp Client Secret
BOX_ENTERPRISE_IDNoEnterprise ID (required for ccg mode)
BOX_ALLOWED_DOMAINSYesInternal email domains (comma-separated)
BOX_OAUTH_REDIRECT_URINoOAuth redirect URI (default http://localhost:8787/callback)

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
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.

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.

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

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": ...}.

public_shared_linksA

List items with an open ("anyone with the link") shared link (enumeration).

Walks folders the authenticating co-admin user can see and reports files and folders whose shared link access is open — reachable by anyone with the URL, the highest-exposure sharing mode.

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 truncation. max_depth: Folder recursion depth (default 1 = top-level only; raise to reach file links inside folders).

Coverage note: limited to content the co-admin user can access and to 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), count, and public_shared_links (item type/id/name, owner, access, can_download). On failure returns {"error": ...}.

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": ...}.

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.

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": ...}.

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.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

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