> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hellofriday.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Call MCP tools

> Configure MCP servers in your agent decorator and call tools via ctx.tools.

## Configure an MCP server

Declare required MCP servers in the `@agent` decorator:

```python theme={null}
from friday_agent_sdk import agent, ok

@agent(
    id="github-helper",
    version="1.0.0",
    description="Uses GitHub MCP server",
    mcp={
        "github": {
            "transport": {
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@modelcontextprotocol/server-github"],
            }
        }
    },
)
def execute(prompt, ctx):
    ...
```

## List Available Tools

```python theme={null}
tools = ctx.tools.list()

for tool in tools:
    print(f"  {tool.name}: {tool.description}")
    print(f"    Schema: {tool.input_schema}")
```

Returns a list of `ToolDefinition` objects:

```python theme={null}
tool.name          # Tool identifier
tool.description   # Human-readable description
tool.input_schema  # JSON Schema for arguments
```

## Call a Tool

```python theme={null}
result = ctx.tools.call(
    "search_issues",
    {
        "query": "is:open label:bug",
        "repo": "my-org/my-repo",
    },
)

# result is a dict parsed from the tool's JSON output
return ok({"issues": result["issues"]})
```

## Error Handling

Tool failures raise `ToolCallError`:

```python theme={null}
from friday_agent_sdk import ToolCallError, agent, err, ok

@agent(id="safe-caller", version="1.0.0", description="Handles tool errors")
def execute(prompt, ctx):
    try:
        result = ctx.tools.call("risky_operation", {"data": prompt})
    except ToolCallError as e:
        return err(f"Tool failed: {e}")

    return ok({"result": result})
```

## Real Example: Time Operations

```python theme={null}
@agent(
    id="time-agent",
    version="1.0.0",
    description="Time conversion agent",
    mcp={
        "time": {
            "transport": {
                "type": "stdio",
                "command": "uvx",
                "args": ["mcp-server-time", "--local-timezone", "UTC"],
            }
        }
    },
)
def execute(prompt, ctx):
    # Get current time in Tokyo
    result = ctx.tools.call(
        "get_current_time",
        {"timezone": "Asia/Tokyo"},
    )

    # Convert time
    converted = ctx.tools.call(
        "convert_time",
        {
            "source_timezone": "UTC",
            "time": "14:30",
            "target_timezone": "America/New_York",
        },
    )

    return ok({
        "tokyo_time": result,
        "converted": converted,
    })
```

## Multiple MCP Servers

```python theme={null}
@agent(
    id="multi-tool",
    version="1.0.0",
    description="Uses GitHub and database tools",
    mcp={
        "github": {
            "transport": {
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@modelcontextprotocol/server-github"],
            }
        },
        "postgres": {
            "transport": {
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@modelcontextprotocol/server-postgres"],
                "env": {
                    "DATABASE_URL": "postgresql://...",
                },
            }
        }
    },
)
def execute(prompt, ctx):
    tools = ctx.tools.list()
    # Tools from both servers are available
    github_tools = [t for t in tools if "github" in t.name]
    db_tools = [t for t in tools if "postgres" in t.name]
    ...
```

## Environment Variables in MCP

Pass environment variables directly to MCP server processes:

```python theme={null}
mcp={
    "github": {
        "transport": {
            "type": "stdio",
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-github"],
            "env": {
                "GITHUB_TOKEN": "your-github-token",
            }
        }
    }
}
```

To declare environment variables your agent code accesses via `ctx.env`, use the `environment` decorator field:

```python theme={null}
environment={
    "required": [
        {"name": "GITHUB_TOKEN", "description": "GitHub API token"},
    ]
}
```

## Stdio vs SSE Transport

Currently only `stdio` transport is supported. `sse` (Server-Sent Events) is planned.

## Tool Chaining

```python theme={null}
# Chain multiple tool calls
tools = ctx.tools.list()

# Find relevant tool by name
search_tool = next((t for t in tools if t.name == "search_issues"), None)
if not search_tool:
    return err("search_issues tool not available")

# Search
issues = ctx.tools.call("search_issues", {"query": prompt})

# For each issue, get details
for issue in issues["issues"][:5]:
    details = ctx.tools.call(
        "get_issue",
        {"owner": "my-org", "repo": "my-repo", "issue_number": issue["number"]},
    )
    # Process details...
```

<CardGroup cols={3}>
  <Card title="API Reference: ctx.tools" icon="book" href="/sdk/python-reference/tools-capability">
    Full tools capability API reference
  </Card>

  <Card title="MCP Specification" icon="globe" href="https://modelcontextprotocol.io/">
    Official MCP protocol documentation
  </Card>

  <Card title="MCP Servers Registry" icon="server" href="https://github.com/modelcontextprotocol/servers">
    Browse available MCP servers
  </Card>
</CardGroup>
