Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
26a4cce
WIP - add mcp example
yuval-qf Oct 13, 2025
bbaac20
Merge branch 'main' into feature/FIRE-800-mcp-support
yuval-qf Oct 19, 2025
da4e592
Fix mcp agent
yuval-qf Oct 19, 2025
40048a1
Fix mcp agent
yuval-qf Oct 19, 2025
a830b10
typing
yuval-qf Oct 19, 2025
442bb83
Add docs
yuval-qf Oct 19, 2025
2d7d54f
Add base logic to support different transports
yuval-qf Oct 19, 2025
c8c086b
Use local sdk for github action tests
yuval-qf Oct 19, 2025
d926a5b
Add TransportType to sdk __init__/__all__
yuval-qf Oct 19, 2025
ae56669
fix gh tests
yuval-qf Oct 19, 2025
d34d404
Fix cyclical import
yuval-qf Oct 19, 2025
3d06933
Add missing files
yuval-qf Oct 19, 2025
8b2cf93
Fix missing kwarg
yuval-qf Oct 20, 2025
ee76845
cicd fix
yuval-qf Oct 20, 2025
54fe40d
Fix import
yuval-qf Oct 20, 2025
81cec81
Merge branch 'main' into feature/FIRE-831-mcp-transport-support
yuval-qf Oct 20, 2025
43e0f56
Merge branch 'main' into feature/FIRE-800-mcp-support
yuval-qf Oct 20, 2025
67b11eb
Merge branch 'feature/FIRE-800-mcp-support' into feature/FIRE-831-mcp…
yuval-qf Oct 20, 2025
69e064a
Add mcp transport
yuval-qf Oct 20, 2025
8b80718
formatting
yuval-qf Oct 20, 2025
0430690
transport -> protocol
yuval-qf Oct 20, 2025
2692157
Merge branch 'main' into feature/FIRE-800-mcp-support
yuval-qf Oct 20, 2025
09e8181
formatting
yuval-qf Oct 20, 2025
f25ff97
Merge branch 'feature/FIRE-800-mcp-support' into feature/FIRE-831-mcp…
yuval-qf Oct 20, 2025
1524c80
Fix session id
yuval-qf Oct 20, 2025
eddf17a
Improve import time
yuval-qf Oct 20, 2025
84acb33
Rename example folder
yuval-qf Oct 20, 2025
0f313cc
Merge branch 'feature/FIRE-800-mcp-support' into feature/FIRE-831-mcp…
yuval-qf Oct 20, 2025
a7fb351
Merge branch 'main' into feature/FIRE-831-mcp-transport-support
yuval-qf Oct 20, 2025
ff31cb7
revert unreleated changes
yuval-qf Oct 20, 2025
712b93c
Rabbit cr
yuval-qf Oct 20, 2025
67ed649
Add transport support
yuval-qf Oct 21, 2025
23e8b6c
Improve import time
yuval-qf Oct 21, 2025
ebdf875
Rabbit cr
yuval-qf Oct 21, 2025
dfbb5ff
Update launch.json path
yuval-qf Oct 21, 2025
dd87e37
Add transport to a2a to create a clean convention
yuval-qf Oct 21, 2025
e67b99e
CR
yuval-qf Oct 22, 2025
c36e371
Fix partial import
yuval-qf Oct 22, 2025
6d18a8e
Run mcp example from maing
yuval-qf Oct 22, 2025
f669cd1
Merge branch 'main' into feature/FIRE-831-mcp-transport-support
yuval-qf Oct 22, 2025
473e0bb
Fix typo
yuval-qf Oct 22, 2025
f28b81b
Rabbit cr - Add click options to mcp examples
yuval-qf Oct 22, 2025
24f1e74
Merge branch 'main' into feature/FIRE-831-mcp-transport-support
yuval-qf Oct 22, 2025
b23a8f1
Fix uv step hang in github workflow
yuval-qf Oct 22, 2025
e28e865
Merge branch 'main' into feature/FIRE-831-mcp-transport-support
yuval-qf Oct 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/run-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ runs:
steps:
- name: "Run tests"
shell: bash
run: source .venv/bin/activate && uv run --dev pytest --junitxml=test-results.xml --cov=rogue --cov-report=xml
run: source .venv/bin/activate && pytest --junitxml=test-results.xml --cov=rogue --cov-report=xml

- name: "Upload Test Results"
uses: actions/upload-artifact@v4
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/rogue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
prune-cache: false

- name: Setup Python
uses: actions/setup-python@v5
Expand All @@ -49,7 +51,7 @@ jobs:
echo "πŸš€ Starting AI agent..."

# Not using uv because it will reinstall the sdk from pypi
source .venv/bin/activate && uv run python -m examples.tshirt_store_agent --host 0.0.0.0 --port 10001 &
source .venv/bin/activate && python -m examples.tshirt_store_agent --host 0.0.0.0 --port 10001 &
AGENT_PID=$!
echo "Agent started with PID: $AGENT_PID"
trap 'echo "πŸ›‘ Stopping agent..."; kill $AGENT_PID' EXIT
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ jobs:
- name: Create venv
run: uv venv

- name: Install rogue sdk
run: source .venv/bin/activate && uv pip install -e sdks/python --force-reinstall

- name: Install rogue server
run: source .venv/bin/activate && uv sync --dev
- name: Install rogue server with local sdk
run: |
source .venv/bin/activate
uv sync --dev
uv pip install -e .
uv pip uninstall rogue-ai-sdk
uv pip install -e sdks/python --force-reinstall

- name: Run tests
uses: ./.github/actions/run-tests
Expand Down
6 changes: 3 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@
"type": "debugpy",
"request": "launch",
"python": "./.venv/bin/python",
"program": "./examples/tshirt_store_agent",
"module": "examples.tshirt_store_agent",
"envFile": "${workspaceFolder}/examples/tshirt_store_agent/.env"
},
{
"name": "shirtify mcp",
"type": "debugpy",
"request": "launch",
"python": "./.venv/bin/python",
"program": "./examples/mcp/tshirt_store_mcp",
"envFile": "${workspaceFolder}/examples/mcp/tshirt_store_mcp/.env"
"module": "examples.mcp.tshirt_store_langgraph_mcp",
"envFile": "${workspaceFolder}/examples/mcp/tshirt_store_langgraph_mcp/.env"
}
]
}
23 changes: 18 additions & 5 deletions examples/mcp/tshirt_store_langgraph_mcp/__main__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
from typing import Literal

import click
from dotenv import load_dotenv
from mcp_agent_wrapper import mcp

from .mcp_agent_wrapper import get_mcp_server

load_dotenv()


def main() -> None:
@click.command()
@click.option("--host", "host", default="127.0.0.1", help="Host to run the server on")
@click.option("--port", "port", default=10001, help="Port to run the server on")
@click.option(
"--transport",
"transport",
default="streamable-http",
choices=["streamable-http", "sse"],
help="Transport to use for the mcp server",
)
def main(host: str, port: int, transport: Literal["streamable-http", "sse"]) -> None:
print("Starting MCP server...")
mcp = get_mcp_server(host=host, port=port)

# Can also be "sse".
# When using "sse", the url will be http://localhost:10001/sse
# When using "streamable-http", the url will be http://localhost:10001/mcp
# stdio isn't supported in this example, since rogue won't be able to connect to it.
mcp.run(transport="streamable-http")
# mcp.run(transport="sse")
mcp.run(transport=transport)


if __name__ == "__main__":
Expand Down
55 changes: 31 additions & 24 deletions examples/mcp/tshirt_store_langgraph_mcp/mcp_agent_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,45 @@
you only need to implement the send_message tool.
"""

from functools import lru_cache

from loguru import logger
from mcp.server.fastmcp import Context, FastMCP
from shirtify_agent import ShirtifyAgent
from starlette.requests import Request

agent = ShirtifyAgent()
mcp = FastMCP(
"shirtify_agent_mcp",
port=10001,
host="127.0.0.1",
)
from .shirtify_agent import ShirtifyAgent


@lru_cache(maxsize=1)
def get_mcp_server(host: str = "127.0.0.1", port: int = 10001) -> FastMCP:
agent = ShirtifyAgent()
mcp = FastMCP(
"shirtify_agent_mcp",
host=host,
port=port,
)

@mcp.tool()
def send_message(message: str, context: Context) -> str:
session_id: str | None = None
try:
request: Request = context.request_context.request # type: ignore

@mcp.tool()
def send_message(message: str, context: Context) -> str:
session_id: str | None = None
try:
request: Request = context.request_context.request # type: ignore
# The session id should be in the headers for streamable-http transport
session_id = request.headers.get("mcp-session-id")

# The session id should be in the headers for streamable-http transport
session_id = request.headers.get("mcp-session-id")
# The session id might also be in query param when using sse transport
if session_id is None:
session_id = request.query_params.get("session_id")
except Exception:
session_id = None
logger.exception("Error while extracting session id")

# The session id might also be in query param when using sse transport
if session_id is None:
session_id = request.query_params.get("session_id")
except Exception:
session_id = None
logger.exception("Error while extracting session id")
logger.error("Couldn't extract session id")

if session_id is None:
logger.error("Couldn't extract session id")
# Invoking our agent
response = agent.invoke(message, session_id)
return response.get("content", "")

# Invoking our agent
response = agent.invoke(message, session_id)
return response.get("content", "")
return mcp
2 changes: 1 addition & 1 deletion lefthook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pre-commit:

- name: isort
glob: "*.py"
run: isort {staged_files}
run: isort --profile black {staged_files}

- name: black
glob: "*.py"
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies = [
"click>=8.0.0",
"datasets==3.6.0",
"fastapi>=0.115.0",
"fastmcp>=2.12.5",
"google-adk==1.5.0",
"gradio==5.35.0",
"langchain-openai>=0.3.35",
Expand Down
18 changes: 16 additions & 2 deletions rogue/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ def common_parser() -> ArgumentParser:
parent_parser.add_argument(
"--example",
type=str,
choices=["tshirt_store"],
help="Run with an example agent (e.g., tshirt_store)",
choices=["tshirt_store", "tshirt_store_langgraph_mcp"],
help="Run with an example agent "
"(e.g., tshirt_store, tshirt_store_langgraph_mcp)",
)
parent_parser.add_argument(
"--example-host",
Expand Down Expand Up @@ -126,6 +127,19 @@ def start_example_agent(
"--port",
str(port),
]
elif example_name == "tshirt_store_langgraph_mcp":
# Use subprocess to run the example agent
cmd = [
sys.executable,
"-m",
"examples.mcp.tshirt_store_langgraph_mcp",
"--host",
host,
"--port",
str(port),
"--transport",
"streamable-http",
]
else:
logger.error(f"Unknown example: {example_name}")
return None
Expand Down
22 changes: 21 additions & 1 deletion rogue/evaluator_agent/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
from . import evaluator_agent, policy_evaluation, run_evaluator_agent
from . import (
a2a,
base_evaluator_agent,
evaluator_agent_factory,
mcp,
policy_evaluation,
run_evaluator_agent,
)
from .a2a import A2AEvaluatorAgent
from .mcp import MCPEvaluatorAgent

__all__ = [
"base_evaluator_agent",
"evaluator_agent_factory",
"policy_evaluation",
"run_evaluator_agent",
"a2a",
"mcp",
"A2AEvaluatorAgent",
"MCPEvaluatorAgent",
]
6 changes: 6 additions & 0 deletions rogue/evaluator_agent/a2a/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from . import a2a_evaluator_agent
from .a2a_evaluator_agent import A2AEvaluatorAgent

__all__ = [
"A2AEvaluatorAgent",
]
Loading
Loading