Skip to content

feat(component): kbagent component sync-action — run synchronous component actions (port run_sync_action) #395

Description

@padak

Part of #390.

Summary

Add kbagent component sync-action to execute synchronous component actions (e.g. testConnection, getTables, list endpoints/schemas), porting the run_sync_action MCP tool.

MCP source (keboola-mcp-server @ agent-v1.60.0)

  • Tool: src/keboola_mcp_server/tools/components/tools.py (run_sync_action).
  • Client: clients/sync_actions.pyPOST {root}/actions on a dedicated host sync-actions.{stack-suffix} (NOT the queue / encryption / docker-runner host).
  • Body: {"configData": {"parameters": …, "storage": …}, "componentId": …, "action": …, "branchId": …}.
  • Shallow-merge of root config + row (top-level only, NOT deep): parameters = {**root_params, **row_params} and storage = {**root_storage, **row_storage} — only when configuration_row_id is given.
  • action_name is freeform (no allow-list in code); valid actions are component-defined and surfaced via component detail synchronous_actions.
  • Auth: X-StorageAPI-Token. Response: opaque pass-through (dict or list).

What kbagent already has

  • Truly absent today — no sync-action client method, service, or command (only docstring mentions of testConnection).
  • But client.py KeboolaClient already multiplexes sibling services (queue, query, encryption) off the stack URL via the same derivation kbagent uses (_derive_service_url(stack_url, prefix) in http_base.py) with lazy per-service sub-clients. A sync-actions prefix slots in mechanically (mirror the _encrypt_request pattern); sub-clients inherit the X-StorageApi-Token headers automatically.
  • get_config_detail and get_config_row already exist (both honor branch_id) for the merge.

Proposed command

kbagent component sync-action ACTION_NAME \
    --component-id ID --config-id ID [--row-id ID] \
    --project ALIAS [--branch ID]

ACTION_NAME positional, freeform (matches MCP). Optional --config-data JSON|@file|- override is a possible enhancement (out of MCP scope).

Implementation sketch (3-layer)

  • L3 KeboolaClient.run_sync_action(component_id, action, config_data, branch_id) → new sync-actions sub-client + _sync_actions_request wrapper → POST /actions.
  • L2 ComponentService.run_sync_action(...): fetch root config (+ row), do the shallow merge (replicate MCP exactly — {**root, **row} for parameters and storage independently), call the client.
  • L1 thin command in commands/component.py, dual output (JSON = raw result; human = panel with JSON/syntax block since shape is action-specific).

Effort: S–M

Client method ≈ the _encrypt_request pattern; service reuses two existing fetchers + a 4-line merge; the M part is permissions registration + doc-sync + E2E.

Acceptance criteria

Risks / open questions

  • Permission category: transport is POST of indeterminate blast radius (an action could write). Recommend registering component.sync-action as write in OPERATION_REGISTRY (consistent with tool.call="write", encrypt.values="write"), so --deny-writes blocks it. Confirm with maintainer.
  • Use SHALLOW merge, not kbagent's deep-merge — semantics must match MCP, else row storage.input.tables would merge instead of replace.
  • Never log config_data — the merged payload carries the stored configuration's parameters (possibly secrets). Rely on masking infra; don't echo the request body in verbose mode.
  • branchId: MCP always sends it (default 'default'); kbagent's idiom is to omit branch scoping for production. Recommend omit-when-None; verify the API treats absent branchId as default branch.
  • Nice-to-have: surface synchronous_actions in component detail so users can discover valid actions (kbagent's component detail doesn't expose it today).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions