Expose native /goal lifecycle over the Codex MCP server

Open 💬 2 comments Opened Jun 29, 2026 by thomaswitt

Summary

Please expose the native /goal lifecycle through the Codex MCP server.

Today, MCP clients can start Codex with the codex tool and continue a thread with codex-reply, but they cannot set, get, clear, or observe the native persisted goal state that /goal uses. The native goal API exists on the app-server protocol as thread/goal/{set,get,clear} with status, token budget, usage accounting, and lifecycle notifications, but that surface is not reachable over the MCP transport.

Current behavior

The Codex MCP server currently dispatches only standard MCP ClientRequest variants and exposes two tools:

  • codex-rs/mcp-server/src/message_processor.rs:96-165 handles standard MCP requests and returns METHOD_NOT_FOUND for custom requests.
  • codex-rs/mcp-server/src/message_processor.rs:313-349 exposes only codex and codex-reply via tools/list and tools/call.
  • codex-rs/mcp-server/src/codex_tool_runner.rs:324-326 explicitly ignores ThreadGoalUpdated events in the MCP tool runner.

The native goal API is available in the app-server protocol instead:

  • codex-rs/app-server-protocol/src/protocol/common.rs:533-546 defines thread/goal/set, thread/goal/get, and thread/goal/clear.
  • codex-rs/app-server-protocol/src/protocol/v2/thread.rs:734-832 defines the goal object, status, token budget, usage, and request/response payloads.
  • codex-rs/app-server-protocol/src/protocol/common.rs:1618-1619 defines thread/goal/updated and thread/goal/cleared notifications.
  • codex-rs/app-server/src/message_processor.rs:1159-1170 routes those app-server requests to ThreadGoalRequestProcessor.

So the feature exists, but only behind a different protocol and daemon lifecycle.

Why this matters

MCP-based Codex integrations cannot programmatically use native goals without becoming an MCP-to-app-server bridge. That is much larger and riskier than the integration should need to be, because app-server has a separate stdio/WebSocket protocol and thread lifecycle (thread/start -> thread/goal/set -> turn/start).

For integrations that already rely on the MCP server, this means /goal is effectively unavailable even though the agent can otherwise be started and resumed through MCP.

Workaround

The current workaround is to stay on MCP and inject objective/goal text through developer instructions or prompt conditioning, then advertise the active goal in follow-up turns.

That can steer behavior and persist across codex-reply, but it is not equivalent to the native goal feature:

  • no native goal status lifecycle (active, paused, blocked, complete, etc.)
  • no token budget or usage accounting
  • no ThreadGoalUpdated / ThreadGoalCleared notifications for MCP clients
  • no shared persisted goal state that other Codex surfaces can read as a first-class goal

Requested behavior

Expose native goal control over the Codex MCP transport. Any one of these shapes would solve the integration gap:

  • add MCP tools such as codex-goal-set, codex-goal-get, and codex-goal-clear that operate on a Codex MCP threadId
  • or add goal parameters to the existing codex / codex-reply tools where appropriate
  • or support an MCP-compatible custom request path for the existing thread/goal/* operations

The key requirement is that MCP clients can set/get/clear the same persisted native goal state used by /goal, including status and token budget, without switching transports or reimplementing app-server.

Acceptance criteria

  • An MCP client can start a Codex thread and set a native goal for that thread through MCP.
  • An MCP client can read and clear that goal through MCP.
  • Goal status and token budget use the same backing state as app-server /goal.
  • Goal update/clear events are exposed to MCP clients in some documented form, or the absence of event streaming is explicitly documented.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗