Skip to content
Open
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
56 changes: 56 additions & 0 deletions examples/echo_mcp_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Example: Using Echo Environment with MCP

This example demonstrates:
1. Connecting to echo_env server
2. Listing available tools via MCP
3. Calling tools using the step() API
"""

import asyncio

try:
from core.env_server.types import CallToolAction, ListToolsAction
except ImportError:
from openenv_core.env_server.types import CallToolAction, ListToolsAction

from envs.echo_env import EchoEnv


async def main():
# Connect to echo_env (assumes server is running on localhost:8000)
# To start the server: uvicorn envs.echo_env.server.app:app
client = EchoEnv(base_url="http://localhost:8000")

print("=== Echo Environment MCP Demo ===\n")

# Reset the environment
print("1. Resetting environment...")
result = client.reset()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is resetting a pre-req to list_tools call? Or in other words, does reset() semantically have any impact on the list_tools?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep in mind that list_tools() should be removed since instead we are just going to allow env.step(ListToolsAction()). Apart from that, hmmm I think that we may still want you to call .reset() first to initialize the env, in case some of your tools require state (e.g. a driving sim)

print(f" Reset result: {result.observation.metadata}\n")

# List available tools using step API
print("2. Listing available tools...")
list_action = ListToolsAction()
list_result = client.step(list_action)
for tool in list_result.observation.tools:
print(f" - {tool['name']}: {tool['description']}")
print()

# Call echo_message tool using step API
print("3. Calling echo_message tool...")
call_action = CallToolAction(tool_name="echo_message", parameters={"message": "Hello from MCP!"})
call_result = client.step(call_action)
print(f" Result: {call_result.observation.result}\n")

# Check environment state
print("4. Checking environment state...")
state = client.state
print(f" Episode ID: {state.episode_id}")
print(f" Step count: {state.step_count}\n")

print("Demo complete!")


if __name__ == "__main__":
asyncio.run(main())
60 changes: 60 additions & 0 deletions examples/test_mcp_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""Quick test script to verify MCP integration works."""

import asyncio
import sys
sys.path.insert(0, 'src')

from envs.echo_env.server.echo_environment import EchoEnvironment
from core.env_server.types import ListToolsAction, CallToolAction


async def main():
print("=" * 60)
print("Testing MCP Integration")
print("=" * 60)

# Create echo environment (MCPEnvironment handles MCP setup automatically)
print("\n1. Creating Echo Environment...")
env = EchoEnvironment()

# Test list tools
print("\n2. Testing ListToolsAction...")
list_action = ListToolsAction()
obs = await env._handle_mcp_action(list_action)
print(f" - Done: {obs.done}")
print(f" - Has 'tools' attribute: {hasattr(obs, 'tools')}")
if hasattr(obs, "tools"):
print(f" - Number of tools: {len(obs.tools)}")
print(f" - Tool names: {[t['name'] for t in obs.tools]}")
else:
print(" - ERROR: No 'tools' attribute!")
return False

# Test call tool
print("\n3. Testing CallToolAction...")
call_action = CallToolAction(
tool_name="echo_message",
parameters={"message": "Hello MCP!"}
)
obs = await env._handle_mcp_action(call_action)
print(f" - Done: {obs.done}")
print(f" - Has 'result' attribute: {hasattr(obs, 'result')}")
print(f" - Error: {obs.error}")
if hasattr(obs, "result") and obs.result is not None:
result = obs.result
print(f" - Result type: {type(result)}")
print(f" - Result: {result}")
else:
print(" - ERROR: No 'result' attribute or result is None!")
return False

print("\n" + "=" * 60)
print("✅ All tests passed!")
print("=" * 60)
return True


if __name__ == "__main__":
success = asyncio.run(main())
sys.exit(0 if success else 1)
Loading