MCP server instructions are not reliably exposed as server-wide agent guidance

Open 💬 2 comments Opened Jun 19, 2026 by naoto256

Summary

Codex documents support for MCP server instructions:

Codex reads the MCP instructions field returned during initialization and uses it as server-wide guidance alongside the server's tools.

In practice, MCP InitializeResult.instructions do not appear to be exposed to the model as instruction-level, server-wide guidance. They are not visible to the agent as a distinct instruction block, cannot be reliably recalled by the agent, and do not reliably affect behavior for MCP servers whose value depends on cross-tool usage policy.

This is especially painful for MCP servers such as code navigation or memory systems, where the important guidance is not tied to one tool schema but to when to use the server at all.

Why this matters

Some MCP servers need server-wide behavioral guidance, for example:

  • use structural code navigation before grep for definition/caller/type-hierarchy questions
  • use memory recall before asserting prior context is unavailable
  • distinguish "no results" from "index not ready" using server-wide readiness metadata
  • prefer semantic reference/caller queries over text search for specific classes of questions

Those are cross-tool policies. Duplicating them into every tool description is brittle and bloats tool schemas. tools/list result _meta is also not a viable workaround for model guidance.

Observed behavior

In a Codex Desktop session with MCP servers that return non-trivial InitializeResult.instructions, the agent could see the individual MCP tools and their tool descriptions, but when asked whether the MCP server instructions had been provided, it could not see or summarize the server-wide instruction text. It only had access to the tool-level descriptions.

After the instruction text was pasted into the conversation manually, the agent could follow it, which suggests the issue is not with the instruction content itself but with how it is ingested/exposed by Codex.

Source-level observation

From the current openai/codex implementation, Codex does read initialize_result.instructions, but it appears to route it through MCP tool namespace metadata rather than injecting it as instruction-level context.

Relevant paths:

  • codex-rs/codex-mcp/src/rmcp_client.rs
  • initialize_result.instructions is passed to list_tools_for_client_uncached(...)
  • for ordinary MCP servers, it becomes ToolInfo.namespace_description
  • codex-rs/core/src/tools/handlers/mcp.rs
  • namespace_description is used as ResponsesApiNamespace.description
  • it is also included in tool search text/source info

That means the data is not discarded, but it is effectively demoted from server-wide instructions to tool/namespace metadata. This does not provide the same semantics as instruction-level guidance, and it is not inspectable by the agent as "the MCP server instructions".

Expected behavior

For MCP servers that return InitializeResult.instructions, Codex should expose those instructions as reliable server-wide guidance to the model, with instruction-level priority comparable to other durable tool-use guidance.

At minimum, Codex should make the behavior explicit and inspectable:

  • show which MCP server instructions were accepted for the session
  • document whether they are injected as instructions, namespace descriptions, tool search metadata, or something else
  • expose truncation/precedence behavior if applicable

Actual behavior

The instructions appear to be available only indirectly as MCP namespace/tool metadata. In practice, the agent cannot reliably recall them or follow them as server-wide behavior.

Reproduction sketch

  1. Configure an MCP server that returns an instructions string during initialization, for example a distinctive sentinel plus a cross-tool rule such as: "For structural code questions, use this MCP server before grep."
  2. Start a new Codex Desktop or CLI session with that server enabled.
  3. Ask the agent what MCP server instructions it received.
  4. Ask a task that should trigger the server-wide rule.

Observed: the agent sees the tools, but does not reliably see or follow the server-wide instruction text unless it is also duplicated into individual tool descriptions or the user prompt.

Related but distinct

This is not the same as MCP prompts support. It concerns the standard MCP InitializeResult.instructions field, which Codex docs already describe as server-wide guidance.

View original on GitHub ↗

2 Comments

Necmttn · 2 months ago

Good place for an observability hook: after MCP initialize, Codex could persist a server manifest containing server id, instructions hash, instruction text length, freshness, and whether that block entered the model prompt. The model-visible tool inventory should include a distinct server-guidance section separate from tool descriptions. A debug view could compare initialize instructions with the actual prompt assembly.

---

_Generated with ax._

shigeki7777 · 2 months ago

Nice trace. One thing worth surfacing: this lines up with how the field is specified rather than how you'd hope it behaves. In the MCP spec, InitializeResult.instructions is an optional string that clients MAY add to the system prompt — it's framed explicitly as a hint, not a mandate. That "MAY" is why behavior varies so much across clients, and why server authors can't currently rely on it landing anywhere with instruction-level priority.

The demotion to namespace/tool metadata you found is probably also a deliberate trust boundary: server-supplied text gaining system-prompt-level authority is a prompt-injection surface, so injecting it verbatim at high priority isn't something a client wants on by default. That actually strengthens the minimum version of your ask — make the handling explicit, inspectable, and opt-in — over "always inject as instructions." An opt-in flag plus a provenance label ("from server X's instructions") would give you the reliable recall you're after without making every server's init string trusted by default.

As a stopgap for cross-tool-policy servers: rather than duplicating the whole policy into every schema (which you rightly flagged as brittle), a single pointer in each tool description to one read-first tool that returns the policy is much lighter, and it's recallable and reproducible today. Not as clean as real server-wide guidance, but it survives the current ingestion behavior. It'd also be worth filing the same observation upstream against the spec, since the inconsistency is as much an under-specification of instructions as it is a Codex implementation choice.