---
title: Call MCP Tool
sidebarTitle: "MCP: Call Tool"
description: Call a server-side tool from a UI interaction.
icon: wrench
---

import { ComponentPreview } from '/snippets/component-preview.mdx'

`CallTool` is the bridge between your UI and your server logic. When a user clicks a button or submits a form, `CallTool` invokes a server tool with the arguments you specify — the same tools you define with `@mcp.tool()`.

<ComponentPreview json={{"view":{"type":"Button","label":"Refresh Data","variant":"default","size":"default","disabled":false,"onClick":{"action":"toolCall","tool":"get_latest_data","arguments":{}}}}} playground="ZnJvbSBwcmVmYWJfdWkuY29tcG9uZW50cyBpbXBvcnQgQnV0dG9uCmZyb20gcHJlZmFiX3VpLmFjdGlvbnMubWNwIGltcG9ydCBDYWxsVG9vbAoKQnV0dG9uKCJSZWZyZXNoIERhdGEiLCBvbl9jbGljaz1DYWxsVG9vbCgiZ2V0X2xhdGVzdF9kYXRhIikpCg==">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Button
from prefab_ui.actions.mcp import CallTool

Button("Refresh Data", on_click=CallTool("get_latest_data"))
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "type": "Button",
    "label": "Refresh Data",
    "variant": "default",
    "size": "default",
    "disabled": false,
    "onClick": {"action": "toolCall", "tool": "get_latest_data", "arguments": {}}
  }
}
```
</CodeGroup>
</ComponentPreview>

The renderer proxies the call through the Prefab SDK, so the tool executes server-side with full access to your backend.

## Passing Arguments

Use `.rx` or `Rx("key")` to pass client state to the tool. Form controls with a `name` automatically sync to state — `Input(name="city")` updates `city` on every keystroke, no `SetState` needed.

<ComponentPreview json={{"view":{"cssClass":"gap-3","type":"Column","children":[{"name":"city","type":"Input","inputType":"text","placeholder":"Enter a city...","disabled":false,"readOnly":false,"required":false},{"type":"Button","label":"Get Weather","variant":"default","size":"default","disabled":false,"onClick":{"action":"toolCall","tool":"get_weather","arguments":{"location":"{{ city }}"}}}]}}} playground="ZnJvbSBwcmVmYWJfdWkuY29tcG9uZW50cyBpbXBvcnQgSW5wdXQsIEJ1dHRvbiwgQ29sdW1uCmZyb20gcHJlZmFiX3VpLmFjdGlvbnMubWNwIGltcG9ydCBDYWxsVG9vbAoKd2l0aCBDb2x1bW4oZ2FwPTMpOgogICAgY2l0eSA9IElucHV0KG5hbWU9ImNpdHkiLCBwbGFjZWhvbGRlcj0iRW50ZXIgYSBjaXR5Li4uIikKICAgIEJ1dHRvbigKICAgICAgICAiR2V0IFdlYXRoZXIiLAogICAgICAgIG9uX2NsaWNrPUNhbGxUb29sKAogICAgICAgICAgICAiZ2V0X3dlYXRoZXIiLAogICAgICAgICAgICBhcmd1bWVudHM9eyJsb2NhdGlvbiI6IGNpdHkucnh9LAogICAgICAgICksCiAgICApCg==">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Input, Button, Column
from prefab_ui.actions.mcp import CallTool

with Column(gap=3):
    city = Input(name="city", placeholder="Enter a city...")
    Button(
        "Get Weather",
        on_click=CallTool(
            "get_weather",
            arguments={"location": city.rx},
        ),
    )
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-3",
    "type": "Column",
    "children": [
      {
        "name": "city",
        "type": "Input",
        "inputType": "text",
        "placeholder": "Enter a city...",
        "disabled": false,
        "readOnly": false,
        "required": false
      },
      {
        "type": "Button",
        "label": "Get Weather",
        "variant": "default",
        "size": "default",
        "disabled": false,
        "onClick": {
          "action": "toolCall",
          "tool": "get_weather",
          "arguments": {"location": "{{ city }}"}
        }
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

Type a city name, click the button, and the current input value flows into the `location` argument.

## Combined with Client Actions

Pass a list to execute multiple actions from a single interaction. A common pattern: update UI state before making the server call, so the user sees immediate feedback.

```python Combined Actions
from prefab_ui.components import Button
from prefab_ui.actions import SetState
from prefab_ui.actions.mcp import CallTool
from prefab_ui.rx import Rx

dataset = Rx("dataset")

Button("Analyze", on_click=[
    SetState("status", "analyzing..."),
    CallTool("run_analysis", arguments={"data": dataset}),
])
```

The `SetState` executes first (instant), then `CallTool` fires the server request.

## API Reference

<Card icon="code" title="CallTool Parameters">
<ParamField body="tool" type="str" required>
  Name of the server tool to call. Can be passed as a positional argument.
</ParamField>

<ParamField body="arguments" type="dict[str, Any]" default="{}">
  Arguments to pass to the tool. Values support `{{ key }}` interpolation to reference client-side state at call time.
</ParamField>
</Card>

## Protocol Reference

```json CallTool
{
  "action": "toolCall",
  "tool": "string (required)",
  "arguments?": "object",
  "resultKey?": "string"
}
```

For the complete protocol schema, see [CallTool](/protocol/tool-call).
