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