[Feature Request] MCP in Playground
lmh87883819 opened this issue · comments
Problem Description
In the context of using Playground, what is the procedure for creating multiple agents that utilize MCP within it?
app = Playground(
agents=agents
)
Proposed Solution
/
Alternatives Considered
/
Additional context
/
Would you like to work on this?
/
Hey @lmh87883819,
Thank you for using Agno and for reaching out to us!
We appreciate you taking the time to raise this feature request. We'll discuss it internally and get back to you shortly.
Thank you for your reply and look forward to your team's discussion @monali7-d
This is also a problem for me. An easy way to unblock people is to give up on auto reload functionality and let people call the async endpoint directly to run the playground endpoint.
https://github.com/oraios/serena seems to have worked around the problem by just not plugging their MCP into agno at all, and instead writing their code so they can target Agno Tool directly. But IMO this is bad, if MCP is the standard better to only publish MCP...
So for example, this works:
import asyncio
from pathlib import Path
from textwrap import dedent
from agno.agent import Agent
from agno.playground import Playground
from agno.models.anthropic import Claude
from agno.tools.mcp import MCPTools
from mcp import StdioServerParameters
from typing import Union
from urllib.parse import quote
from fastapi import FastAPI
from rich import box
from rich.panel import Panel
from agno.api.playground import PlaygroundEndpointCreate, create_playground_endpoint
from agno.cli.console import console
from agno.cli.settings import agno_cli_settings
from agno.utils.log import logger
async def serve_playground_app_async(
app: Union[str, FastAPI],
*,
scheme: str = "http",
host: str = "localhost",
port: int = 7777,
reload: bool = False,
prefix="/v1",
**kwargs,
):
import uvicorn
try:
create_playground_endpoint(
playground=PlaygroundEndpointCreate(
endpoint=f"{scheme}://{host}:{port}", playground_data={"prefix": prefix}
),
)
except Exception as e:
logger.error(f"Could not create playground endpoint: {e}")
logger.error("Please try again.")
return
logger.info(f"Starting playground on {scheme}://{host}:{port}")
# Encode the full endpoint (host:port)
encoded_endpoint = quote(f"{host}:{port}")
# Create a panel with the playground URL
url = f"{agno_cli_settings.playground_url}?endpoint={encoded_endpoint}"
panel = Panel(
f"[bold green]Playground URL:[/bold green] [link={url}]{url}[/link]",
title="Agent Playground",
expand=False,
border_style="cyan",
box=box.HEAVY,
padding=(2, 2),
)
# Print the panel
console.print(panel)
config = uvicorn.Config(app=app, host=host, port=port, reload=reload, **kwargs)
server = uvicorn.Server(config)
await server.serve()
async def main():
async with MCPTools(f"/Users/ezyang/Dev/codemcp-prod/.venv/bin/python -m codemcp.hot_reload_entry") as codemcp:
agent = Agent(
model=Claude(id="claude-3-7-sonnet-20250219"),
tools=[codemcp],
instructions="init codemcp /Users/ezyang/Dev/refined-claude",
markdown=True,
show_tool_calls=True,
)
playground = Playground(agents=[agent]).get_app()
await serve_playground_app_async(playground)
if __name__ == "__main__":
asyncio.run(main())
Hey @lmh87883819,
Thank you for reaching out and for using Agno!
We’ve recently added an example that might be helpful for you:
https://github.com/agno-agi/agno/blob/main/cookbook/playground/mcp_demo.py
Feel free to check it out, and let us know if you have any questions or need further clarification — happy to help!
I don't see how the example can work, won't you deadlock the outer async loop
Hey @ezyang, the example seems to work fine, although I see it uses our (sync) version of serve_playground_app
- Can that setup work for you?
- Else, what exactly is the problem? would love to dive into this and help you
Hey.. i am trying to use the playground feature..with "sse" mcp, and I am running into issues.
Used the same sample as this
https://github.com/agno-agi/agno/blob/main/cookbook/playground/mcp_demo.py
below is the code that i am trying to execute
import asyncio
from os import getenv
from textwrap import dedent
import nest_asyncio
from agno.agent import Agent
from agno.models.google import Gemini
from agno.playground import Playground, serve_playground_app
from agno.storage.agent.sqlite import SqliteAgentStorage
from agno.tools.mcp import MCPTools
# Allow nested event loops
nest_asyncio.apply()
agent_storage_file: str = "tmp/agents.db"
server_url = "http://remote_server:8001/sse"
async def run_server() -> None:
"""Run the GitHub agent server."""
async with MCPTools(url=server_url, transport="sse") as mcp_tools:
agent = Agent(
name="MCP Agent",
tools=[mcp_tools],
instructions=dedent("""\
You are a SQL assistant. Help users explore SQL databases.
- Use headings to organize your responses
- Be concise and focus on relevant information
- Use markdown formatting for your responses
"""),
model=Gemini(id="gemini-2.5-flash-preview-05-20"),
storage=SqliteAgentStorage(
table_name="basic_agent",
db_file=agent_storage_file,
auto_upgrade_schema=True,
),
add_history_to_messages=True,
num_history_responses=3,
add_datetime_to_instructions=True,
markdown=True,
)
playground = Playground(
agents=[agent],
name="MCP Demo",
description="A playground for MCP",
app_id="mcp-demo",
)
playground.get_app()
# Serve the app while keeping the MCPTools context manager alive
playground.serve(app="mcp_demo:app")
if __name__ == "__main__":
asyncio.run(run_server())error i run into
memory git:(main) ✗ python mcp_demo.py
INFO Starting playground on http://localhost:7777
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Agent Playground ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ ┃
┃ Playground URL: https://app.agno.com/playground?endpoint=localhost%3A7777/v1 ┃
┃ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
ERROR: Error loading ASGI app. Attribute "app" not found in module "mcp_demo".could you please help me understand if I am doing it incorrectly.
Thanks in advance
In your specific case, the problem lies in your:
playground.serve(app="mcp_demo:app")The mcp_demo must be your module name and "app" must be the variable inside your module that must be (I believe) available outside of the if __name__ == '__main__' part.
How to solve this exactly in your case I don't know, but the following works for a normal agent:
#filename: my_agents
<your agent>
app = Playground(agents=[<your agent>]).get_app()
if __name__ == "__main__":
from agno.playground import serve_playground_app
serve_playground_app('my_agents:app', reload=True)Thanks a ton for pointing this out! this helped me fix the issue!!!
@rajuptvs Can you please share how you managed to fix this issue?
@ezyang the script below works . @rajuptvs is it what you're thinking about?
import os
from contextlib import asynccontextmanager
from textwrap import dedent
import nest_asyncio
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.playground import Playground
from agno.tools.mcp import MCPTools
nest_asyncio.apply()
COMPANY_MCP_URL = "http://192.168.16.244:8080/mcp/company"
app = None
mcp_tools = None
@asynccontextmanager
async def lifespan(app):
global mcp_tools
print("Initializing MCP tools...")
mcp_tools = MCPTools(
url=COMPANY_MCP_URL,
transport='streamable-http',
timeout_seconds=5*60
)
await mcp_tools.__aenter__()
simple_agent.set_tools([mcp_tools])
print("MCP tools initialized successfully")
try:
yield
finally:
print("Cleaning up MCP tools...")
if mcp_tools:
await mcp_tools.__aexit__(None, None, None)
mcp_tools = None
simple_agent = Agent(
name="MCP Company Agent",
instructions=dedent("""\
You are a Company assistant. Help users explore company information.
- Use headings to organize your responses
- Be concise and focus on relevant information\
"""),
model=OpenAIChat(
id="deepseek-v3",
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL")
),
add_history_to_messages=True,
num_history_responses=3,
add_datetime_to_instructions=True,
markdown=True,
)
playground = Playground(
agents=[simple_agent],
name="MCP Demo",
description="A playground for MCP",
app_id="mcp-demo",
)
app = playground.get_app()
app.router.lifespan_context = lifespan
if __name__ == "__main__":
playground.serve(app="mcp_demo:app", reload=True)Hey @lmh87883819, Thank you for reaching out and for using Agno!
We’ve recently added an example that might be helpful for you: https://github.com/agno-agi/agno/blob/main/cookbook/playground/mcp_demo.py
Feel free to check it out, and let us know if you have any questions or need further clarification — happy to help!
URL is outdated.
New URL: https://github.com/agno-agi/agno/blob/main/cookbook/apps/playground/mcp_demo.py