Skip to main content

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.

Configure an MCP server

Declare required MCP servers in the @agent decorator:
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

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:
tool.name          # Tool identifier
tool.description   # Human-readable description
tool.input_schema  # JSON Schema for arguments

Call a Tool

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:
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

@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

@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:
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:
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

# 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...

API Reference: ctx.tools

Full tools capability API reference

MCP Specification

Official MCP protocol documentation

MCP Servers Registry

Browse available MCP servers