# Hub Nodes

> Applies to: ChengOS v0.2.0+ ｜ Last verified: 2026-09-25 ｜ Source: `crates/cheng-nodes/src/nodes/builtin/tools`

A hub is one node that stands for many callable operations, which is how an agent gets a toolbox
without the canvas growing a node per tool. `tools/tool_hub` exposes tools either as declared by the
active Skill or as configured by the workflow author. `tools/mcp_hub` does the same for tools served
by an MCP server, and `tools/skills_hub` discovers and manages Skills themselves. The preset nodes are
the smaller pair: list what is available, and request a switch.

## Tool Hub — `tools/tool_hub`

Unified policy-controlled gateway for executing registered tools. The workflow author configures each Tool Hub instance in one of two modes: - skill: tools are authorized by a selected Skill's canonical Tool Hub declaration. Global list_tools discovery is unavailable. Use Skills Hub list or search to select a Skill, call Skills Hub describe, then execute with the returned skill_name, tool identifier or unique short name, allowed operation, and arguments matching the returned schema. - user: tools are explicitly enabled by the workflow author. Use list_tools to discover this instance's executable tools, then call execute within that configured scope. For execute, provide action="execute", tool, operation when required, and arguments. Skill mode also requires skill_name. Do not guess tool identifiers, operations, or argument schemas. All calls are revalidated against the current trusted scope and runtime policy.

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `action` | enum | ✅ | — | Tool Hub action: list_tools or execute (required). Options: `list_tools` (List the executable tools of this node instance (user mode only).), `execute` (Execute one concrete tool command inside the trusted scope.) |
| `skill_name` | string | — | `null` | Skill whose Tool Hub declaration authorizes this command (skill mode execute) |
| `tool` | string | — | `null` | Tool type id or unique short name to execute (execute) |
| `operation` | string | — | `null` | Tool operation/action (execute) |
| `arguments` | any | — | `null` | Tool arguments object for execute. Pass a JSON object directly, never a JSON-encoded string. Use the selected tool's input schema to fill fields inside arguments. |
| `mode` | enum | — | `user` | Tool source mode: skill (Skill-defined) or user (author-configured). Options: `skill` (The selected Skill's canonical `tool_hub.tools` declaration defines the executable scope; `list_tools` is unavailable (use Skills Hub `describe`).), `user` (The workflow author's `enabled_tools` rows define the scope. The default: with no rows enabled the scope is empty (deny-all).) |
| `enabled_tools` | array&lt;object&gt; | — | `[]` | Author-enabled tool rows (user mode) |

### Outputs

| Field | Type | Description |
|---|---|---|
| `status` | string | Tool Hub status (closed enum; see node docs) |
| `mode` | string | Tool source mode of this node |
| `tools` | array&lt;object&gt; | Executable tool descriptors |
| `unavailable_tools` | array&lt;object&gt; | Configured but currently unavailable tools (diagnostics) |
| `result` | object | Runtime tool result (execute) |
| `approval` | object | Stable approval continuation token and action summary |
| `errors` | array&lt;string&gt; | Blocking errors |
| `warnings` | array&lt;string&gt; | Non-blocking warnings |
| `error_details` | any | Structured failure details such as received arguments and expected schema |

## MCP Hub — `tools/mcp_hub`

Connect one or more MCP servers in one place. Discover tools, manage visibility, and call tools with unified output.

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `server_registry` | array&lt;object&gt; | — | `[]` | 结构化 MCP 服务器列表。前端可渲染为“列表 + 独立弹窗编辑器”。 Control: `mcp-server-manager` |
| `action` | enum | — | `null` | LLM 调用模式：list（只列名字）/ describe（查描述与参数）/ call（执行）。 留空时按兼容规则推导：`discover_only` 为 true → list； 填了 tool_name/arguments → call；都没有 → 配置态（只返回服务器状态）。 Control: `select`. Options: `list` (List Tool Names), `describe` (Describe Tools), `call` (Call Tool) |
| `tool_name` | string | — | `""` | 要调用（或查询描述）的工具名。格式 "server_name:tool_name"（多服务器时明确指定） 或直接 "tool_name"（单服务器时自动选择）。 |
| `tool_names` | array&lt;string&gt; | — | `[]` | describe 模式下要查询的多个工具名。与 tool_name 合并去重。 |
| `arguments` | object \| array \| string \| number \| integer \| boolean | — | `null` | 工具参数（JSON 对象，由用户或 LLM 提供）. Control: `code-editor` |
| `tool_visibility` | string | — | `null` | 工具可见性配置（JSON 字符串，可选） 格式：{"server:tool": {"visible": true, "callable": true}, "*": {...}}. Control: `textarea` |
| `visibility_config` | object | — | `null` | 结构化工具可见性配置（推荐） 格式： { "servers": {"server-a": {"visible": true, "callable": true}, "*": {...}}, "tools": {"server-a:search": {"visible": true, "callable": true}, "*": {...}} }. Control: `mcp-visibility-editor` |
| `discover_only` | boolean | — | `false` | 发现模式开关：开启后只列出所有服务器的可用工具，不执行工具调用. Control: `switch` |
| `timeout_ms` | integer | — | `null` | 请求超时（毫秒，0 或留空表示不限时）. Control: `number` |
| `env_vars` | object | — | `null` | Env vars from the credential node. These values are used for ${env:KEY} placeholders in URL, authorization, headers, arguments, and env fields. |

### Outputs

| Field | Type | Description |
|---|---|---|
| `result` | any | Unified result with summary, server status, discovered tools, and optional tool call output. |

## Skills Hub — `tools/skills_hub`

Unified gateway for workspace Skill integration. Operations: - list: list discoverable Skills in the current workspace. - search: find Skills by capability, name, description, or tags. - describe: return a Skill's complete descriptor, required inputs, execution requirements, and declared Tool Hub tools. - credential_status: check whether required credentials are available. - approval_status: check whether execution requires human approval. - execute: execute a Skill with input_data. The Skill catalog is dynamic. Use list or search to discover Skills instead of assuming which Skills exist. Before invoking a tool declared by a Skill, call describe and use the returned tool identifiers, allowed operations, and argument schemas with Tool Hub. Do not guess Skill or tool contracts.

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `operation` | enum | ✅ | — | Which Hub operation to run. **Required**: a missing `operation` is rejected at deserialization rather than defaulting to `execute`, so a caller that supplies only `skill_name` can never accidentally trigger a skill execution. Options: `list` (List discoverable skills in the workspace (paginated, with optional filters).), `search` (Free-text search across discoverable skills.), `describe` (Full secret-free descriptor for one skill, including its Tool Hub tool declarations with filtered input schemas.), `credential_status` (Check whether the required credentials for a skill are bound and resolvable.), `approval_status` (Check whether a high-risk skill still needs human approval before execute.), `execute` (Execute a skill by slug (forwards to the shared execute pipeline).) |
| `skill_name` | string | — | `null` | Target skill slug |
| `query` | string | — | `null` | Search query (name/description) |
| `category` | string | — | `null` | Category filter |
| `tags` | array&lt;string&gt; | — | `[]` | Tag filters |
| `backend_type` | string | — | `null` | Backend type filter |
| `input_data` | any | — | `null` | Execute input data |
| `timeout_seconds` | integer | — | `3600` | Execute timeout, default 3600 |
| `async_execution` | boolean | — | `false` | Return after starting the workflow |
| `env_vars` | object | — | `null` | Transient credential env vars |
| `limit` | integer | — | `50` | Discovery page size, default 50 |
| `cursor` | string | — | `null` | Discovery pagination cursor |
| `audience` | enum | — | `llm` | Discovery visibility audience: llm (default) or human. Options: `llm` (Model-facing: excludes both `hidden` and `llm_hidden`. The default.), `human` (Human-facing: shows `llm_hidden` (still hides `hidden`).) |

### Outputs

| Field | Type | Description |
|---|---|---|
| `status` | string | Skill execution status (see SkillOutput::status docs for the closed enum and frontend mapping) |
| `skill_id` | string | Matched skill ID |
| `skill_name` | string | Matched skill name |
| `execution_id` | string | Workflow execution ID (if started) |
| `outputs` | any | Workflow output data |
| `instructions` | string | Skill usage instructions (returned when no associated workflow) |
| `next_action` | string | Suggested next action (for LLM reference) |
| `error` | string | Error message |
| `missing_binaries` | array | Required binaries that were not found on PATH; install them or run the skill on a host that has them. |
| `missing_credentials` | array | List of credential bindings that could not be resolved; rendered into the credential-setup UI. |
| `approval_outcome` | string | Approval gate outcome for high-risk skills |
| `normalization_status` | string | Canonical spec normalization status |
| `policy_warnings` | array&lt;string&gt; | Runtime policy warnings |
| `operation` | string | Hub operation that produced this output |
| `data` | any | Operation-specific payload (discovery page or status report) |

## List Available Presets — `tools/list_available_presets`

Scoped introspection: lists node presets an LLM may request a switch to, limited to the current workflow, the tools connected alongside the calling agent, and presets marked visible to LLMs.

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `target_node_id` | string | — | `null` | Optional target tool node id to scope the preset list to. |

### Outputs

| Field | Type | Description |
|---|---|---|
| `presets` | array&lt;object&gt; | List of available presets visible to the requesting agent |
| `count` | integer | Number of presets returned |
| `error` | string | Error message when the operation failed |

## Request Preset Switch — `tools/request_preset_switch`

Requests an approval-gated preset switch for a tool node connected alongside the calling agent. The preset is applied only after the user approves; the LLM can never apply it directly.

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `target_node_id` | string | — | `null` | Target tool node id. Optional if only one node of the preset's type exists. |
| `preset_id` | string | — | `""` | Preset id to switch to. Discover valid ids via list_available_presets. |
| `reason` | string | — | `null` | Optional reason for the switch, shown to the approver. |

### Outputs

| Field | Type | Description |
|---|---|---|
| `status` | string | Outcome status: applied, rejected, out_of_scope, or error |
| `applied` | boolean | Whether the preset was applied |
| `request_id` | string | Approval request identifier |
| `message` | string | Human-readable result message |
| `change_summary` | any | Key-by-key diff ({key: {from, to}}) presented for approval |

## Next steps

- [Tool Discovery & Tool Hub](/docs/agent-tools-and-hub)
- [Connecting MCP Servers](/docs/agent-mcp-integration)
- [Skill & Package Nodes](/docs/nodes-skills)
