cursus.mcp.registry¶
The canonical tool registry for cursus.mcp.
Every tool is declared as a ToolDef (name, description, JSON schema, handler)
and collected into one registry keyed by dotted name ("catalog.list_steps"). The
registry is the single source of truth: the MCP server, an OpenAI/Claude tool list, and
(eventually) the CLI can all be generated from it.
call_tool is the in-process invoker. It enforces the tool contract:
- light JSON-schema validation of arguments (required keys, no unknown keys),
- handlers may raise ToolError for handled failures (-> ToolResult.error),
- any other exception is caught and wrapped as an internal_error ToolResult so a
tool call never crashes the caller.
- class ToolDef(name, description, schema, handler, destructive=False, tags=(), when='', examples=(), writes=False, exec_code=False, network=False)[source]¶
Bases:
objectDeclarative definition of one agent-callable tool.
- schema¶
JSON Schema (draft-07 style
{"type": "object", "properties": {...}, "required": [...]}) describing the arguments.- Type:
Dict[str, Any]
- handler¶
Callable taking the validated arg dict, returning a
ToolResult.- Type:
Callable[[Dict[str, Any]], cursus.mcp.envelope.ToolResult]
- namespace¶
Leading segment of
name(derived;"compile").
- destructive¶
True if the tool mutates external state (e.g. upserts/starts a SageMaker pipeline). Agents/servers may gate these behind confirmation.
- Type:
- when¶
One-line “call this when …” cue — the trigger condition, complementing the what in
description. Optional; surfaced by help/describe and exporters.- Type:
- examples¶
Copy-paste invocation strings showing real calls, e.g.
'catalog.list_steps {"framework": "xgboost"} # every XGBoost step'. Stored as a tuple so this frozen dataclass field is truly immutable (a list could be mutated in place); surfaced by help/describe and folded into exported tool descriptions so external MCP/OpenAI clients see them too.- Type:
- property wire_name: str¶
The on-the-wire tool name for MCP hosts (dotted
.->__).Host tool-calling APIs (Anthropic
^[a-zA-Z0-9_-]{1,128}$, OpenAI^[a-zA-Z0-9_-]+$) reject the.in the internal dotted names, so every externally-exposed name uses__instead. It round-trips unambiguously — no tool or namespace name contains a literal__— viaget_tool().
- get_registry(force_reload=False)[source]¶
Return the canonical
name -> ToolDefmap, building it once and caching.
- get_namespaces()[source]¶
Return the
namespace -> one-line descriptionmap (built with the registry).
- list_tools(namespace=None)[source]¶
List all registered tools, optionally filtered to one namespace.
- call_tool(name, args=None)[source]¶
Invoke a registered tool by name with an argument dict.
Returns a
ToolResultin all cases — unknown tool, invalid args, handledToolError, or unexpected exception are all converted to error envelopes.
- render_description(td)[source]¶
Compose a tool’s full-text description: description + ‘When’ + ‘Examples’.
External MCP/OpenAI clients only receive a single description string per tool, so the
whencue andexamplesare folded in here (they are otherwise only reachable via the in-process help/describe tools). In-process agents get the fields structured; this keeps external agents from missing the usage guidance.
- export_openai_tools(namespace=None)[source]¶
Export tools in OpenAI / Claude function-calling shape.
The phase
tags(planner/validator/programmer) are surfaced under the function’smetadataso an agent can group/route tools by lifecycle phase rather than scanning every description. Thewhen/examplesguidance is folded into the description (seerender_description()) so external clients see it too.
- export_mcp_tools(namespace=None)[source]¶
Export tools in MCP
list_toolsshape (name / description / inputSchema).Includes the phase
tagsso agents can filter by planner/validator/programmer, and folds thewhen/examplesguidance into the description (seerender_description()) so external MCP clients see it too.