datarobot_genai.drmcpbase.fastmcp_transforms.utils
utils
get_header_value
Read a header by lowercase name (FastMCP normalizes keys; scan only as fallback).
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
parse_bool_header
Parse an optional boolean header; unrecognized values fall back to default.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
parse_disabled_categories
Resolve the category-gate headers to the set of disabled category names.
Every gate defaults to enabled; only an explicit false disables its
category for this request.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
register_toolsets_allowlist_expander
Install async expansion of toolset bundle names → tool function names.
Global-mcp registers a mongo-backed expander once at startup. User-mcp leaves the
default, where a toolsets header resolves to no tools at all — see
:func:effective_tool_allowlist for what that means for the request. Pass None to
reset (tests).
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
expand_toolset_names_to_tools
async
Expand parsed toolset bundle names to tool function names for allowlisting.
Every failure resolves to the empty set, which :func:effective_tool_allowlist keeps
as an empty allowlist rather than "no allowlist" — degrading toward fewer tools, not
more.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
is_tool_allowed
Whether tool survives allowlist, taking into account how it was named.
Three ways in, and which apply depends on what kind of tool this is:
- an explicit name admits anything — the client asked for this tool by name;
- a derived name (from expanding a static category) admits only built-ins,
because the static taxonomy describes DataRobot's own tools. A user-authored
tool that merely shares a name is not what
dr_dbmeant; - a bucket admits a tool whose marker puts it there.
Ordered so the common paths never read the tool's marker: an explicit hit returns at once, and a name in neither set with no bucket requested is rejected before the marker is touched. Only a name that could match — or a request that named a bucket — pays for the lookup.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
filter_tools_by_allowlist
Apply allowlist to a whole catalog.
The fast path is not a second copy of the rule — it is the one case where the rule
provably collapses. With no derived names and no buckets, :func:is_tool_allowed
can only return name in explicit, so the marker is never consulted and this is
the same single set lookup per tool the allowlist has always cost.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
get_tool_category
Category name stamped by the providers, or None for untagged (built-in) tools.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
effective_tool_allowlist
async
Union x-datarobot-mcp-tools and expanded x-datarobot-mcp-toolsets names.
None means no allowlist — every tool is permitted — so it is only ever returned
when neither header narrowed the request. An empty frozenset is the opposite
answer: the caller asked to be narrowed and nothing survived, so nothing is permitted.
Collapsing those two is the failure this guards against. x-datarobot-mcp-toolsets
expands to nothing whenever Mongo is unreachable, the Tool Sets feature is off, this
server has no expander, or the named set was deleted — and if an empty expansion fell
through to ctx.tool_allowlist (None when the toolsets header was the only
filter sent), a session that asked for one bundle would silently receive the entire
catalog. Precedence is unchanged: an allowlist is still a hard cap in every mode.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
unfiltered_catalog_provider
Build a catalog provider that ignores the caller's x-datarobot-mcp-* headers.
For the describe-the-server REST routes (/static/tools/,
/static/categories/,
/metadata), which report what the server registers rather than what the current
request may call. list_tools(run_middleware=False) is not enough on its own —
FastMCP still applies registered catalog transforms, and
:class:DataRobotMCPCatalogTransform is exactly where the session filter is enforced.
Pre-seeding the per-request context cache with a neutral context is what turns the transform into a pass-through, because every branch of it reads the context from there. The token is reset on the way out, so an MCP call sharing the same context (there is none today, but the routes and the protocol do share a process) still resolves its own headers afterwards.
Source code in datarobot_genai/drmcpbase/fastmcp_transforms/utils.py
is_category_disabled_for_request
Return True when a category gate disables category_name for the current request.
Safe to call from providers, including outside an HTTP request (startup retrospection, in-process clients): any failure to read the request context means "no gates", preserving the default-enabled behavior.