Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,4 @@ fastagent.jsonl

# JetBrains IDEs
.idea/
tests/e2e/smoke/base/weather_location.txt
2 changes: 2 additions & 0 deletions src/mcp_agent/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ class LoggerSettings(BaseModel):
"""Show MCP Sever tool calls on the console"""
truncate_tools: bool = True
"""Truncate display of long tool calls"""
enable_markup: bool = True
"""Enable markup in console output. Disable for outputs that may conflict with rich console formatting"""


class Settings(BaseSettings):
Expand Down
13 changes: 7 additions & 6 deletions src/mcp_agent/ui/console_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(self, config=None) -> None:
config: Configuration object containing display preferences
"""
self.config = config
self._markup = config.logger.enable_markup if config else True

def show_tool_result(self, result: CallToolResult) -> None:
"""Display a tool result in a formatted panel."""
Expand All @@ -46,7 +47,7 @@ def show_tool_result(self, result: CallToolResult) -> None:
if len(str(result.content)) > 360:
panel.height = 8

console.console.print(panel)
console.console.print(panel, markup=self._markup)
console.console.print("\n")

def show_oai_tool_result(self, result) -> None:
Expand All @@ -67,7 +68,7 @@ def show_oai_tool_result(self, result) -> None:
if len(str(result)) > 360:
panel.height = 8

console.console.print(panel)
console.console.print(panel, markup=self._markup)
console.console.print("\n")

def show_tool_call(self, available_tools, tool_name, tool_args) -> None:
Expand All @@ -92,7 +93,7 @@ def show_tool_call(self, available_tools, tool_name, tool_args) -> None:
if len(str(tool_args)) > 360:
panel.height = 8

console.console.print(panel)
console.console.print(panel, markup=self._markup)
console.console.print("\n")

def _format_tool_list(self, available_tools, selected_tool_name):
Expand Down Expand Up @@ -172,7 +173,7 @@ async def show_assistant_message(
subtitle=display_server_list,
subtitle_align="left",
)
console.console.print(panel)
console.console.print(panel, markup=self._markup)
console.console.print("\n")

def show_user_message(
Expand All @@ -196,7 +197,7 @@ def show_user_message(
subtitle=subtitle_text,
subtitle_align="left",
)
console.console.print(panel)
console.console.print(panel, markup=self._markup)
console.console.print("\n")

async def show_prompt_loaded(
Expand Down Expand Up @@ -270,5 +271,5 @@ async def show_prompt_loaded(
subtitle_align="left",
)

console.console.print(panel)
console.console.print(panel, markup=self._markup)
console.console.print("\n")
54 changes: 54 additions & 0 deletions tests/integration/api/fastagent.config.markup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# FastAgent Configuration File

# Default Model Configuration:
#
# Takes format:
# <provider>.<model_string>.<reasoning_effort?> (e.g. anthropic.claude-3-5-sonnet-20241022 or openai.o3-mini.low)
# Accepts aliases for Anthropic Models: haiku, haiku3, sonnet, sonnet35, opus, opus3
# and OpenAI Models: gpt-4o-mini, gpt-4o, o1, o1-mini, o3-mini
#
# If not specified, defaults to "haiku".
# Can be overriden with a command line switch --model=<model>, or within the Agent constructor.

default_model: passthrough

# Logging and Console Configuration:
logger:
# level: "debug" | "info" | "warning" | "error"
# type: "none" | "console" | "file" | "http"
# path: "/path/to/logfile.jsonl"

# Switch the progress display on or off
progress_display: true

# Show chat User/Assistant messages on the console
show_chat: true
# Show tool calls on the console
show_tools: true
# Truncate long tool responses on the console
truncate_tools: true
enable_markup: false

# MCP Servers
mcp:
servers:
prompts:
command: "prompt-server"
args: ["playback.md"]
std_io:
command: "uv"
args: ["run", "integration_agent.py", "--server", "--transport", "stdio"]
sse:
transport: "sse"
url: "http://localhost:8723/sse"
card_test:
command: "uv"
args: ["run", "mcp_tools_server.py"]
hyphen-test:
command: "uv"
args: ["run", "mcp_tools_server.py"]
# borrows config from prompt-server
cwd_test:
command: "prompt-server"
args: ["multi.txt"]
cwd: "../prompt-server/"
38 changes: 38 additions & 0 deletions tests/integration/api/test_markup_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import pytest
from rich.errors import MarkupError

from mcp_agent.core.prompt import Prompt


@pytest.mark.integration
@pytest.mark.asyncio
async def test_markup_raises_an_error(fast_agent):
"""Test that the agent can process a multipart prompts using directory-specific config."""
# Use the FastAgent instance from the test directory fixture
fast = fast_agent

# Define the agent
@fast.agent(
"agent1",
instruction="You are a helpful AI Agent",
)
async def agent_function():
async with fast.run() as agent:
with pytest.raises(MarkupError):
assert "test1" in await agent.agent1.send(Prompt.user("'[/]test1"))

await agent_function()


@pytest.mark.integration
@pytest.mark.asyncio
async def test_markup_disabled_does_not_error(markup_fast_agent):
@markup_fast_agent.agent(
"agent2",
instruction="You are a helpful AI Agent",
)
async def agent_function():
async with markup_fast_agent.run() as agent:
assert "test2" in await agent.agent2.send(Prompt.user("'[/]test2"))

await agent_function()
36 changes: 35 additions & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,41 @@ def fast_agent(request):

# Explicitly create absolute path to the config file in the test directory
config_file = os.path.join(test_dir, "fastagent.config.yaml")


# Create agent with local config using absolute path
agent = FastAgent(
"Test Agent",
config_path=config_file, # Use absolute path to local config in test directory
ignore_unknown_args=True,
)

# Provide the agent
yield agent

# Restore original directory
os.chdir(original_cwd)


# Add a fixture that uses the test file's directory
@pytest.fixture
def markup_fast_agent(request):
"""
Creates a FastAgent with config from the test file's directory.
Automatically changes working directory to match the test file location.
"""
# Get the directory where the test file is located
test_module = request.module.__file__
test_dir = os.path.dirname(test_module)

# Save original directory
original_cwd = os.getcwd()

# Change to the test file's directory
os.chdir(test_dir)

# Explicitly create absolute path to the config file in the test directory
config_file = os.path.join(test_dir, "fastagent.config.markup.yaml")

# Create agent with local config using absolute path
agent = FastAgent(
"Test Agent",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
logging:
dir_path: null
file_path: null
level: DEBUG

mcp:
name: evaluator_optimizer_tests
name: evaluator_optimizer_tests
Loading