Skip to content

Self-hosted model resume loses paused executions across MCP sessions #1778

Description

@micthiesen

Summary

Approval-gated tools called through execute pause correctly with elicitation_mode=model, but an immediate resume from a new MCP session returns execution_not_found.

ChatGPT creates a separate MCP session for the resume tool call. Executor self-host stores the paused execution only in the engine belonging to the original session, so the new session cannot find it.

Environment

  • Executor self-host v1.6.0
  • Image revision: 0ae7959fe03e8fb98d0b8a961438ad88e49fbd4b
  • Streamable HTTP MCP
  • ChatGPT developer app
  • Endpoint configured with ?elicitation_mode=model
  • Approval-gated tool imported from another MCP server

Reproduction

  1. Connect ChatGPT to Executor using elicitation_mode=model.
  2. Through execute, call an imported tool whose policy requires approval.
  3. Executor returns a paused result with an executionId.
  4. Approve the action and immediately call resume with that ID.
  5. Executor returns execution_not_found.

Repeating the flow with a fresh execution produces the same result.

Expected behavior

The authenticated client should be able to resume its paused execution even when the resume call arrives through a new MCP session.

Actual behavior

The paused execution is visible only to the engine attached to the original MCP session. A new session receives:

execution_not_found

Evidence

The self-host logs show the paused execute request in one MCP session at 20:00:00, followed by a new MCP initialization and the resume request at 20:00:04.

The current self-host implementation appears session-local:

  • makeInMemoryMcpSessionStore stores ExecutionEngine instances in an engines map keyed by MCP session ID.
  • Each MCP session builds its own server and engine.
  • resumeExecution calls engine.resume() on the current session's engine.
  • Self-host does not configure a cross-session resumeFallback.

Relevant files:

  • packages/hosts/mcp/src/in-memory-session-store.ts
  • packages/hosts/mcp/src/tool-server.ts
  • apps/host-selfhost/src/mcp/session-store.ts

Suggested direction

Maintain an identity- and resource-scoped directory from paused execution ID to its owning engine, then delegate cross-session resume to that engine. Entries should be removed when the execution settles, expires, or its owning session is disposed.

Persisted resumable execution state would also solve this and would survive process restarts.

Additional context

Native elicitation is not an alternative for this client because the ChatGPT runtime connection does not advertise elicitation.form. Model resume is therefore the intended compatibility path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions