Buckets:
| <meta charset="utf-8" /><meta name="hf:doc:metadata" content="{"title":"MCP Environment Lifecycle","local":"mcp-environment-lifecycle","sections":[{"title":"The Short Answer","local":"the-short-answer","sections":[],"depth":2},{"title":"The Two Boundaries","local":"the-two-boundaries","sections":[],"depth":2},{"title":"How MCP Environments Handle Actions","local":"how-mcp-environments-handle-actions","sections":[],"depth":2},{"title":"Why step() May Look Like It Is Not Running","local":"why-step-may-look-like-it-is-not-running","sections":[],"depth":2},{"title":"What list_tools() and call_tool() Actually Do","local":"what-listtools-and-calltool-actually-do","sections":[{"title":"Client behavior","local":"client-behavior","sections":[],"depth":3},{"title":"Direct MCP behavior","local":"direct-mcp-behavior","sections":[],"depth":3}],"depth":2},{"title":"Which Pattern Should You Use?","local":"which-pattern-should-you-use","sections":[],"depth":2},{"title":"Concrete Examples","local":"concrete-examples","sections":[],"depth":2},{"title":"Recommended Mental Model","local":"recommended-mental-model","sections":[],"depth":2},{"title":"Debugging Checklist","local":"debugging-checklist","sections":[],"depth":2},{"title":"Related Reading","local":"related-reading","sections":[],"depth":2}],"depth":1}"> | |
| <link href="/docs/openenv/pr_749/en/_app/immutable/assets/0.e3b0c442.css" rel="modulepreload"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/entry/start.85477f45.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/scheduler.2b22cead.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/singletons.63566282.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/paths.dd876c7b.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/entry/app.51835dc5.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/preload-helper.0820fbc7.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/index.1a0e8013.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/nodes/0.167255c0.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/each.e59479a4.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/nodes/47.6d701e8b.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/Heading.c0d3f116.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/MermaidChart.svelte_svelte_type_style_lang.21bcf336.js"> | |
| <link rel="modulepreload" href="/docs/openenv/pr_749/en/_app/immutable/chunks/CodeBlock.c8d73295.js"><!-- HEAD_svelte-u9bgzb_START --><meta name="hf:doc:metadata" content="{"title":"MCP Environment Lifecycle","local":"mcp-environment-lifecycle","sections":[{"title":"The Short Answer","local":"the-short-answer","sections":[],"depth":2},{"title":"The Two Boundaries","local":"the-two-boundaries","sections":[],"depth":2},{"title":"How MCP Environments Handle Actions","local":"how-mcp-environments-handle-actions","sections":[],"depth":2},{"title":"Why step() May Look Like It Is Not Running","local":"why-step-may-look-like-it-is-not-running","sections":[],"depth":2},{"title":"What list_tools() and call_tool() Actually Do","local":"what-listtools-and-calltool-actually-do","sections":[{"title":"Client behavior","local":"client-behavior","sections":[],"depth":3},{"title":"Direct MCP behavior","local":"direct-mcp-behavior","sections":[],"depth":3}],"depth":2},{"title":"Which Pattern Should You Use?","local":"which-pattern-should-you-use","sections":[],"depth":2},{"title":"Concrete Examples","local":"concrete-examples","sections":[],"depth":2},{"title":"Recommended Mental Model","local":"recommended-mental-model","sections":[],"depth":2},{"title":"Debugging Checklist","local":"debugging-checklist","sections":[],"depth":2},{"title":"Related Reading","local":"related-reading","sections":[],"depth":2}],"depth":1}"><!-- HEAD_svelte-u9bgzb_END --> <p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg></button></div> </div> <h1 class="relative group"><a id="mcp-environment-lifecycle" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#mcp-environment-lifecycle"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>MCP Environment Lifecycle</span></h1> <p data-svelte-h="svelte-imgxth">This guide explains how MCP-backed environments work end to end in OpenEnv.</p> <p data-svelte-h="svelte-hfme07">It exists to answer a common question: if an environment exposes MCP tools, when does <code>step()</code> run, when does <code>step_async()</code> run, and when should you use <code>call_tool()</code> versus <code>step(CallToolAction(...))</code>?</p> <h2 class="relative group"><a id="the-short-answer" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#the-short-answer"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>The Short Answer</span></h2> <p data-svelte-h="svelte-1e6us6d">MCP environments in OpenEnv can be used in two layers:</p> <ul data-svelte-h="svelte-14d8d6z"><li><strong>Simulation layer</strong>: the OpenEnv training loop controls <code>reset()</code>, <code>step()</code>, and <code>state()</code>.</li> <li><strong>Tool layer</strong>: MCP tools are exposed through <code>ListToolsAction</code>, <code>CallToolAction</code>, <code>list_tools()</code>, and <code>call_tool()</code>.</li></ul> <p data-svelte-h="svelte-151yegk">If you are training or evaluating with episode control, the canonical pattern is still the OpenEnv step loop.</p> <p data-svelte-h="svelte-1qo8f93">If you are serving tools to an external client, the MCP layer is the interface the agent should see.</p> <h2 class="relative group"><a id="the-two-boundaries" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#the-two-boundaries"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>The Two Boundaries</span></h2> <p data-svelte-h="svelte-amolun">OpenEnv keeps a strict API split:</p> <ul data-svelte-h="svelte-14v4dym"><li><strong>Infrastructure boundary</strong>: Gym-like control over <code>/ws</code>, <code>reset()</code>, <code>step()</code>, and <code>state()</code></li> <li><strong>Agent boundary</strong>: MCP tools over <code>/mcp</code></li></ul> <p data-svelte-h="svelte-1p4vv0o">This means:</p> <ul data-svelte-h="svelte-1x8egja"><li>agents should use MCP tools</li> <li>orchestration and training infrastructure use the simulation control loop</li> <li><code>/ws</code> is not an agent-facing interface, even if it is available on the server</li></ul> <h2 class="relative group"><a id="how-mcp-environments-handle-actions" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#how-mcp-environments-handle-actions"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>How MCP Environments Handle Actions</span></h2> <p data-svelte-h="svelte-b86j2v"><code>MCPEnvironment</code> is still an OpenEnv environment.</p> <p data-svelte-h="svelte-rffmpi">It does not replace the step loop. Instead, it maps MCP actions into the step loop.</p> <p data-svelte-h="svelte-h8oh8e">In simulation mode, MCP tool usage is represented as normal environment actions:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class="language-python "><!-- HTML_TAG_START --><span class="hljs-keyword">from</span> openenv.core.env_server.mcp_types <span class="hljs-keyword">import</span> CallToolAction, ListToolsAction | |
| obs = env.step(ListToolsAction()) | |
| obs = env.step( | |
| CallToolAction( | |
| tool_name=<span class="hljs-string">"echo_message"</span>, | |
| arguments={<span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello"</span>}, | |
| ) | |
| )<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-15evgqz">That is why an MCP-backed environment can still participate in:</p> <ul data-svelte-h="svelte-1209afg"><li>rewards</li> <li><code>done</code> handling</li> <li>step counts</li> <li>trajectory logging</li></ul> <h2 class="relative group"><a id="why-step-may-look-like-it-is-not-running" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#why-step-may-look-like-it-is-not-running"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Why step() May Look Like It Is Not Running</span></h2> <p data-svelte-h="svelte-yrqbu8">This is the main source of confusion.</p> <p data-svelte-h="svelte-1qvswzu">On the server side, the WebSocket handler checks whether the environment overrides <code>step_async()</code>.</p> <ul data-svelte-h="svelte-1hs443m"><li>if <code>step_async()</code> is overridden, the WebSocket path calls <code>step_async()</code></li> <li>otherwise, it falls back to <code>step()</code></li></ul> <p data-svelte-h="svelte-1cc0ul4">That means an async client using the WebSocket session path may execute <code>step_async()</code> without hitting your synchronous <code>step()</code> instrumentation.</p> <p data-svelte-h="svelte-qshmoi">So if you add debug prints only to <code>step()</code> and use an async MCP client, it can look like “step is not being invoked” even though the action is being processed normally.</p> <p data-svelte-h="svelte-1o69lsa">For debugging, check both:</p> <ul data-svelte-h="svelte-1hkxn6d"><li><code>step()</code></li> <li><code>step_async()</code></li></ul> <p data-svelte-h="svelte-7b2fh2">The same rule applies to <code>reset()</code> and <code>reset_async()</code>.</p> <h2 class="relative group"><a id="what-listtools-and-calltool-actually-do" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#what-listtools-and-calltool-actually-do"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>What list_tools() and call_tool() Actually Do</span></h2> <p data-svelte-h="svelte-49mxjv">Environment-specific MCP clients such as <code>EchoEnv</code> and <code>FinQAEnv</code> inherit from <code>MCPToolClient</code>.</p> <p data-svelte-h="svelte-7q5enq">Those clients target a running environment server and expose convenience methods:</p> <ul data-svelte-h="svelte-1dugaf7"><li><code>list_tools()</code></li> <li><code>call_tool()</code> — <strong>async</strong>, must be awaited</li></ul> <p data-svelte-h="svelte-nyxqdw">These are helpers, not a separate environment lifecycle.</p> <h3 class="relative group"><a id="client-behavior" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#client-behavior"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Client behavior</span></h3> <p data-svelte-h="svelte-1k1er2d"><code>MCPToolClient</code> and its base <code>MCPClientBase</code> only support <code>mode="production"</code>; construction raises <code>ValueError</code> for other modes. For direct in-process training or eval code, instantiate the environment class and call <code>env.step(CallToolAction(...))</code> instead of using <code>MCPToolClient</code>.</p> <ul data-svelte-h="svelte-ly6eqv"><li><code>list_tools()</code> wraps <code>step(ListToolsAction())</code> and returns the <code>list[Tool]</code> directly.</li> <li><code>call_tool(name, **kwargs)</code> returns the <strong>unwrapped tool return value</strong> directly — not the <code>CallToolObservation</code>, and not the runtime result object you would get from <code>obs.result</code>.</li> <li><code>call_tool()</code> raises <code>RuntimeError</code> on any tool error. Use <code>step(CallToolAction(...))</code> when you need to inspect <code>ToolError.error_type</code> or continue after a failed tool call.</li></ul> <p data-svelte-h="svelte-11uoxqc">Remote <code>step(CallToolAction(...))</code> calls return a <code>StepResult</code>; the full observation is on <code>result.observation</code>, while <code>result.reward</code> carries the serialized reward field.</p> <h3 class="relative group"><a id="direct-mcp-behavior" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#direct-mcp-behavior"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Direct MCP behavior</span></h3> <p data-svelte-h="svelte-1en3uh7">When production MCP access is explicitly enabled on the client, the same convenience methods use the HTTP <code>/mcp</code> JSON-RPC endpoint directly.</p> <p data-svelte-h="svelte-lcq2hq">That path is for tool-serving behavior, not the training loop. It bypasses reward computation, step counts, trajectory tracking, and <code>done</code> handling.</p> <h2 class="relative group"><a id="which-pattern-should-you-use" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#which-pattern-should-you-use"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Which Pattern Should You Use?</span></h2> <p data-svelte-h="svelte-1ke5fxc">Use <code>step(CallToolAction(...))</code> when you need the full <code>CallToolObservation</code>:</p> <ul data-svelte-h="svelte-67294v"><li><code>reward</code></li> <li><code>done</code></li> <li>observation metadata</li> <li><code>obs.result</code>, a runtime result object typed as <code>Any</code>; FastMCP commonly returns <code>fastmcp.client.client.CallToolResult</code> with <code>.data</code>, <code>.content</code>, and <code>.structured_content</code>, but serialized clients or custom envs may surface a dict or plain value</li> <li>trajectory-compatible behavior</li></ul> <p data-svelte-h="svelte-11l21r8">Use <code>await env.call_tool(name, **kwargs)</code> when you only want the tool’s raw return value and do not need to inspect the full observation. It is async and unwraps the result for you.</p> <p data-svelte-h="svelte-9cazei">In other words:</p> <ul data-svelte-h="svelte-z2d9yo"><li><code>step(...)</code> is the canonical simulation pattern</li> <li><code>call_tool()</code> is an async convenience wrapper that returns the unwrapped tool output</li></ul> <h2 class="relative group"><a id="concrete-examples" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#concrete-examples"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Concrete Examples</span></h2> <p data-svelte-h="svelte-1s0yekq">Two good references in this repo are:</p> <ul data-svelte-h="svelte-788fos"><li><a href="../environments/echo">Echo environment</a></li> <li><a href="../environments/finqa">FinQA environment</a></li></ul> <p data-svelte-h="svelte-cmwpev">For a minimal simulation-mode example, see:</p> <ul data-svelte-h="svelte-fdx47n"><li><code>examples/echo_mcp_demo.py</code></li></ul> <p data-svelte-h="svelte-1hjvux1">Echo is useful because it shows the MCP mechanics with almost no domain logic.</p> <p data-svelte-h="svelte-itvl95">FinQA is useful because it shows an MCP environment where tool calls also participate in episode progression, rewards, and terminal submission.</p> <h2 class="relative group"><a id="recommended-mental-model" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#recommended-mental-model"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Recommended Mental Model</span></h2> <p data-svelte-h="svelte-1ow9wng">Think about MCP environments in OpenEnv like this:</p> <ol data-svelte-h="svelte-h56o9t"><li>The environment is still an OpenEnv environment.</li> <li>MCP tools are one kind of action the environment knows how to handle.</li> <li>In simulation mode, tool calls are part of the step loop.</li> <li>In production mode, MCP becomes the agent-facing boundary.</li> <li>The WebSocket simulation interface remains infrastructure-only and must not be given directly to agents.</li></ol> <h2 class="relative group"><a id="debugging-checklist" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#debugging-checklist"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Debugging Checklist</span></h2> <p data-svelte-h="svelte-pi237b">If an MCP environment “doesn’t call step”, check these first:</p> <ol data-svelte-h="svelte-152ui9x"><li>Are you using an async client path that triggers <code>step_async()</code>?</li> <li>Did you instrument both <code>step()</code> and <code>step_async()</code>?</li> <li>Are you using <code>call_tool()</code> and assuming it bypasses the step loop?</li> <li>Are you expecting the MCP tool layer to behave like a separate environment lifecycle?</li></ol> <p data-svelte-h="svelte-blq74p">Usually the action is flowing correctly, but through the async WebSocket path rather than the synchronous method you were watching.</p> <h2 class="relative group"><a id="related-reading" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#related-reading"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Related Reading</span></h2> <ul data-svelte-h="svelte-1i32593"><li><a href="../reference/core">Core API</a></li> <li><a href="../environments/echo">Echo environment</a></li> <li><a href="../environments/finqa">FinQA environment</a></li></ul> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/openenv/blob/main/docs/source/guides/mcp-environment-lifecycle.md" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg> <span data-svelte-h="svelte-zjs2n5"><span class="underline">Update</span> on GitHub</span></a> <p></p> | |
| <script> | |
| { | |
| __sveltekit_1qwoa43 = { | |
| assets: "/docs/openenv/pr_749/en", | |
| base: "/docs/openenv/pr_749/en", | |
| env: {} | |
| }; | |
| const element = document.currentScript.parentElement; | |
| const data = [null,null]; | |
| Promise.all([ | |
| import("/docs/openenv/pr_749/en/_app/immutable/entry/start.85477f45.js"), | |
| import("/docs/openenv/pr_749/en/_app/immutable/entry/app.51835dc5.js") | |
| ]).then(([kit, app]) => { | |
| kit.start(app, element, { | |
| node_ids: [0, 47], | |
| data, | |
| form: null, | |
| error: null | |
| }); | |
| }); | |
| } | |
| </script> | |
Xet Storage Details
- Size:
- 33.5 kB
- Xet hash:
- f2120a342864f24c143558ddb92da2bab4a8eff451870ed282148d8a6efd02e4
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.