Fix local Echo example MCP usage#990
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
There was a problem hiding this comment.
Alignment Review Report
Reviewed the migration of examples/local_echo_env.py from the removed EchoAction API to the MCP tool-calling API. I verified everything end-to-end against a live server (python -m echo_env.server.app).
Automated Checks
- Lint: PASS (this PR).
examples/local_echo_env.pypassesruff check,ruff format --check, andusort check, and byte-compiles. Thelint.shhook exits non-zero, but every file it flags is pre-existing formatting drift in unrelated envs (opencode_env,chat_env,repl_env,textarena_env, …) — none is this PR's file. Noteexamples/is outside both CI (src/ tests/) and the hook's scope, so I checked the changed file directly. - Debug code: CLEAN.
check-debug.shonly scanssrc/; all hits are pre-existing there. Theprint()calls in this file are intentional demo output.
Open RFCs Context
- RFC 003 — MCP Support (In Review; @Darktex, @pankit-eng): directly relevant, and this change aligns with it — the example now drives the env purely through MCP tools (
list_tools()/call_tool()), i.e. the "MCP as universal standard" direction. No conflict. - RFC 010 ("ECHO") is env-token world-modeling, unrelated to
echo_env.
Tier 1: Fixes Required
None. Verified against a running server:
- The old example was broken at import time —
from echo_env import EchoActionraisesImportError(echo_env exports onlyEchoEnv,CallToolAction,ListToolsAction). This PR fixes a genuinely non-running example. - The new example runs cleanly (exit 0). Output confirmed correct: reset →
status='ready',message='Echo environment ready!',reward=0.0,done=False; both tools listed with descriptions; echoes correct; lengths 13 / 24 / 16.
Tier 2: Alignment Discussion
Principle Conflicts
None identified. Client-only example (imports EchoEnv, never server/) → client-server separation intact. Uses the Gym-style reset() plus MCP tools; no external reward computation introduced.
RFC Conflicts
None identified (aligns with RFC 003, above).
Summary
- 0 mechanical issues to fix
- 0 alignment points for human review
- 0 RFC conflicts
Nice cleanup. Beyond fixing the import, the migration also sidesteps two known echo_env gotchas: it reads results via call_tool (which unwraps the FastMCP envelope to .data) rather than the raw observation.result, and it drops the per-tool-call reward print (tool steps return reward=None, not 0.0 — only reset() is 0.0).
Optional, non-blocking (out of scope here): a few other spots still use the pre-MCP echo observation shape (echoed_message / message_length) — notably src/openenv/core/containers/test_local_docker_provider.py (already TODO-marked for removal and Docker-gated) and the env-generation templates under src/openenv/cli/templates/openenv_env/ and .claude/skills/generate-openenv-env/assets/. Flagging only for awareness.
Sent by Cursor Automation: Pre-review
| print("\n1. Reset:") | ||
| result = client.reset() | ||
| print(f" Message: {result.observation.echoed_message}") | ||
| print(f" Status: {result.observation.metadata.get('status')}") |
There was a problem hiding this comment.
Verified correct against a running server: EchoEnvironment.reset() returns Observation(reward=0.0, metadata={'status': 'ready', 'message': 'Echo environment ready!'}), so both metadata.get(...) lookups resolve as intended (printed Status: ready / Message: Echo environment ready!).
|
|
||
| for i, msg in enumerate(messages, 1): | ||
| result = client.step(EchoAction(message=msg)) | ||
| echoed = client.call_tool("echo_message", message=msg) |
There was a problem hiding this comment.
Good use of the call_tool convenience method — it unwraps the FastMCP result envelope to .data, so echoed is the plain string and with_length (line 67) is the plain {'message': ..., 'length': N} dict (verified: lengths 13/24/16). This avoids the raw observation.result envelope gotcha, and dropping the per-call reward print is correct since MCP tool steps return reward=None (only reset() is 0.0).


Updates the local Echo example to use the supported MCP client methods and sync wrapper against a running Echo server.