






















@@ -329,8 +329,12 @@ type CodeModeFailedResult = {
329329};
330330```
331331332-`exec` returns `waiting` when the QuickJS VM suspends with resumable state. The
333-result includes a `runId` for `wait`.
332+`exec` returns `waiting` when the QuickJS VM suspends with resumable state that
333+still needs a model-visible continuation. The result includes a `runId` for
334+`wait`. Namespace bridge calls, including MCP namespace calls, are auto-drained
335+inside the same `exec`/`wait` call while they are ready, so a compact code block
336+can inspect `$api()` and call an MCP tool without forcing one model tool call per
337+namespace await.
334338335339`exec` returns `completed` only when the guest VM has no pending work and the
336340final value is JSON-compatible after OpenClaw's output adapter runs.
@@ -436,18 +440,55 @@ const hits = await tools.web_search({ query: "OpenClaw code mode" });
436440```
437441438442MCP catalog entries are not callable through `tools.call(...)` or convenience
439-functions in code mode. Use the generated `MCP` namespace instead:
443+functions in code mode. They are exposed only through the generated `MCP`
444+namespace, which includes TypeScript-style API headers for discovery:
440445441446```typescript
447+const servers = await MCP.$api();
448+const githubApi = await MCP.github.$api();
449+const createIssueApi = await MCP.github.$api("createIssue", { schema: true });
450+442451const issue = await MCP.github.createIssue({
443452 owner: "openclaw",
444453 repo: "openclaw",
445454 title: "Investigate gateway logs",
446455});
447456448457const snapshot = await MCP.chromeDevtools.takeSnapshot({ output: "markdown" });
449-const resource = await MCP.docs.resources.read("memo://one");
450-const prompt = await MCP.docs.prompts.get("brief", { topic: "release" });
458+const resource = await MCP.docs.resources.read({ uri: "memo://one" });
459+const prompt = await MCP.docs.prompts.get({
460+ name: "brief",
461+ arguments: { topic: "release" },
462+});
463+```
464+465+`MCP.<server>.$api()` returns a compact header inferred from MCP tool metadata:
466+467+```typescript
468+type McpToolResult = {
469+ content?: unknown[];
470+ structuredContent?: unknown;
471+ isError?: boolean;
472+ [key: string]: unknown;
473+};
474+475+declare namespace MCP.github {
476+/** Return this TypeScript-style API header. */
477+function $api(toolName?: string, options?: { schema?: boolean }): Promise<McpApiHeader>;
478+479+/**
480+ * Create a GitHub issue.
481+ * @param owner Repository owner
482+ * @param repo Repository name
483+ * @param title Issue title
484+ */
485+function createIssue(input: {
486+ owner: string;
487+ repo: string;
488+ title: string;
489+ body?: string;
490+ }): Promise<McpToolResult>;
491+}
451492```
452493453494The guest runtime must not expose host objects directly. Inputs and outputs cross
@@ -493,8 +534,9 @@ run follows this path:
4935346. Guest calls suspend through the worker bridge, resolve the namespace path on
494535 the host, map the call to a declared plugin-owned catalog tool, and execute
495536 that tool through `ToolSearchRuntime.call`.
496-7. `wait` resumes the same namespace runtime when a code-mode run suspended on
497- nested tool work.
537+7. OpenClaw auto-drains ready namespace bridge calls inside the active
538+`exec`/`wait` tool call. If namespace work is still pending at the timeout or
539+ the guest yields explicitly, `wait` resumes the same namespace runtime later.
4985408. Plugin rollback or uninstall calls `clearCodeModeNamespacesForPlugin(pluginId)`
499541 so stale globals do not survive a failed plugin load.
500542@@ -701,9 +743,10 @@ This prevents recursion and keeps the model-facing contract narrow.
701743702744MCP entries stay in the run-scoped catalog so policy, approvals, hooks,
703745telemetry, transcript projection, and exact tool ids remain shared with normal
704-tool execution. The guest-facing `tools.call(...)` bridge rejects MCP entries;
705-the generated `MCP.<server>.<tool>(...)` namespace resolves back to the exact
706-catalog id and then dispatches through the same executor path.
746+tool execution. The guest-facing `ALL_TOOLS`, `tools.search(...)`,
747+`tools.describe(...)`, and `tools.call(...)` views omit MCP entries. The
748+generated `MCP.<server>.<tool>({ ...input })` namespace resolves back to the
749+exact catalog id and then dispatches through the same executor path.
707750708751## Tool Search interaction
709752@@ -716,8 +759,9 @@ When `tools.codeMode.enabled` is true and code mode activates:
716759 or `tool_call` as model-visible tools.
717760- The same cataloging idea moves inside the guest runtime.
718761- The guest runtime receives compact `ALL_TOOLS` metadata and search, describe,
719- and call helpers.
720-- MCP calls use the generated `MCP` namespace instead of `tools.call(...)`.
762+ and call helpers for non-MCP tools.
763+- MCP calls use the generated `MCP` namespace and its `$api()` headers instead
764+ of `tools.call(...)`.
721765- Nested calls dispatch through the same OpenClaw executor path that Tool Search
722766 uses.
723767@@ -934,11 +978,13 @@ Code mode coverage should prove:
934978 active for the run
935979- raw no-tool runs, `disableTools`, and empty allowlists do not trigger code-mode
936980 payload enforcement
937-- all effective tools appear in `ALL_TOOLS`
981+- all effective non-MCP tools appear in `ALL_TOOLS`
938982- denied tools do not appear in `ALL_TOOLS`
939983- `tools.search`, `tools.describe`, and `tools.call` work for OpenClaw tools
940-- MCP namespace calls work for visible MCP tools and direct MCP `tools.call`
941- attempts fail closed
984+- MCP namespace `$api()` returns TypeScript-style headers inferred from MCP
985+ schemas
986+- MCP namespace calls work for visible MCP tools with one object input, while
987+ direct MCP catalog entries are absent from `tools.*`
942988- Tool Search control tools are hidden from both the model surface and the hidden
943989 catalog
944990- nested calls preserve approval and hook behavior
@@ -968,14 +1014,16 @@ Run these as integration or end-to-end tests when changing the runtime:
96810147. In `exec`, read `ALL_TOOLS` and assert the effective test tools are present.
96910158. In `exec`, call OpenClaw/plugin/client tools through `tools.search`,
9701016`tools.describe`, and `tools.call`.
971-9. In `exec`, call MCP tools through `MCP.<server>.<tool>(...)` and assert direct
972- MCP `tools.call(...)` attempts fail.
973-10. Assert denied tools are absent and cannot be called by guessed id.
974-11. Start a nested tool call that resolves after `exec` returns `waiting`.
975-12. Call `wait` and assert the restored VM receives the tool result.
976-13. Assert the final answer contains output produced after restore.
977-14. Assert timeout, abort, and snapshot expiry clean up runtime state.
978-15. Export trajectory and assert nested calls are visible under the parent
1017+9. In `exec`, call `MCP.$api()` and `MCP.<server>.$api()` and assert the headers
1018+ describe visible MCP tools.
1019+10. In `exec`, call MCP tools through `MCP.<server>.<tool>({ ...input })` and
1020+ assert direct MCP catalog entries are absent from `ALL_TOOLS` and `tools.*`.
1021+11. Assert denied tools are absent and cannot be called by guessed id.
1022+12. Start a nested tool call that resolves after `exec` returns `waiting`.
1023+13. Call `wait` and assert the restored VM receives the tool result.
1024+14. Assert the final answer contains output produced after restore.
1025+15. Assert timeout, abort, and snapshot expiry clean up runtime state.
1026+16. Export trajectory and assert nested calls are visible under the parent
9791027 code-mode call.
98010289811029Docs-only changes to this page should still run `pnpm check:docs`.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。