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

# Expose one custom MCP tool

> Replace the eight built-in AgentOS MCP tools with one purpose-built tool.

Replace the eight built-in AgentOS MCP tools with one purpose-built tool. The tool routes a question through an agent while AgentOS owns the MCP transport, mount, and lifespan.

```python custom_tools.py theme={null}
"""
Expose one custom MCP tool
==========================

Replace the eight built-in AgentOS MCP tools with one purpose-built tool. The
tool routes a question through an agent while AgentOS owns the MCP transport,
mount, and lifespan.

Prerequisites: OPENAI_API_KEY
Run: .venvs/demo/bin/python cookbook/05_agent_os/14_mcp/custom_tools.py
Try: connect an MCP client to http://localhost:7777/mcp and call ask_workspace
"""

from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses
from agno.os import AgentOS, MCPConfig
from agno.tools import tool

# ---------------------------------------------------------------------------
# Create the custom tool
# ---------------------------------------------------------------------------

db = SqliteDb(
    id="mcp-custom-tools-db",
    db_file="tmp/mcp_custom_tools.db",
)

workspace_agent = Agent(
    id="workspace-agent",
    name="Workspace Agent",
    model=OpenAIResponses(id="gpt-5.5"),
    db=db,
    instructions="Answer workspace questions clearly and concisely.",
)


@tool(
    name="ask_workspace",
    title="Ask the Workspace Agent",
    description="Ask the workspace agent a question",
    # A custom tool publishes whatever it declares here and nothing more, so state all
    # three hints: a client that finds one missing falls back to a protocol default,
    # and a directory submission is rejected outright for leaving any of them unset.
    # These are true of this tool: the run persists a session (not read-only), it only
    # appends (nothing destroyed), and the agent calls a model over the network.
    annotations={
        "readOnlyHint": False,
        "destructiveHint": False,
        "openWorldHint": True,
    },
)
async def ask_workspace(question: str) -> str:
    """Route one question through the workspace agent."""
    response = await workspace_agent.arun(question)
    return response.content or ""


# ---------------------------------------------------------------------------
# Serve only the custom tool
# ---------------------------------------------------------------------------

agent_os = AgentOS(
    id="mcp-custom-tools-os",
    description="AgentOS exposing one purpose-built MCP tool.",
    db=db,
    agents=[workspace_agent],
    mcp=MCPConfig(
        tools=[ask_workspace],
        default_tools=False,
    ),
)
app = agent_os.get_app()

# ---------------------------------------------------------------------------
# Run Custom Tool AgentOS
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    agent_os.serve(app=app)
```

## Run the Example

<Steps>
  <Snippet file="create-venv-step.mdx" />

  <Step title="Install dependencies">
    ```bash theme={null}
    uv pip install -U "agno[mcp,os]" openai
    ```
  </Step>

  <Step title="Export your OpenAI API key">
    <CodeGroup>
      ```bash Mac/Linux theme={null}
      export OPENAI_API_KEY="your_openai_api_key_here"
      ```

      ```bash Windows theme={null}
      $Env:OPENAI_API_KEY="your_openai_api_key_here"
      ```
    </CodeGroup>
  </Step>

  <Step title="Run the example">
    Save the code above as `custom_tools.py`, then run:

    ```bash theme={null}
    python custom_tools.py
    ```
  </Step>
</Steps>

Full source: [cookbook/05\_agent\_os/14\_mcp/custom\_tools.py](https://github.com/agno-agi/agno/blob/v3.0.4/cookbook/05_agent_os/14_mcp/custom_tools.py)
