Skip to main content
Glama
benzkittisak

codex-async-mcp

by benzkittisak

codex_poll

Poll an asynchronous codex job to check its status and retrieve output. Use the job ID from codex_start to get real-time updates and trailing lines of output.

Instructions

Poll the status and output of a running (or finished) codex job.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
job_idYesThe job_id returned by codex_start.
tail_linesNoHow many trailing lines of output to return. Default: 100.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The MCP tool handler for 'codex_poll' – registered with @mcp.tool(), it delegates to poll_job() in job_manager.py.
    def codex_poll(job_id: str, tail_lines: int = 100) -> dict:
        """
        Poll the status and output of a running (or finished) codex job.
    
        Args:
            job_id: The job_id returned by codex_start.
            tail_lines: How many trailing lines of output to return. Default: 100.
    
        Returns a dict with status ('running' | 'done' | 'error' | 'cancelled'),
        exit_code, and the latest output.
        """
        return poll_job(job_id, tail_lines)
  • Registration of 'codex_poll' as an MCP tool via the @mcp.tool() decorator.
    @mcp.tool()
  • The core polling logic: reads job metadata, checks PID liveness as a fallback, reads output tail, and returns status.
    def poll_job(job_id: str, tail_lines: int = JOB_TAIL_LINES) -> dict:
        meta = _read_meta(job_id)
        if meta is None:
            return {"error": f"Job '{job_id}' not found"}
    
        # If meta still says running but monitor thread hasn't updated yet,
        # fall back to PID liveness check (covers server-restart case too).
        if meta["status"] == "running":
            with _lock:
                proc = _active_procs.get(job_id)
    
            if proc is None:
                pid = meta.get("pid")
                if pid and not _is_pid_alive(pid):
                    with _lock:
                        meta = _read_meta(job_id)
                        if meta and meta["status"] == "running":
                            meta["status"] = "done"
                            meta["finished_at"] = datetime.now(timezone.utc).isoformat()
                            _write_meta(job_id, meta)
    
        meta = _read_meta(job_id)
        output = _read_tail(job_id, tail_lines)
    
        return {
            "job_id": job_id,
            "status": meta["status"],
            "exit_code": meta.get("exit_code"),
            "output": output,
            "started_at": meta.get("started_at"),
            "finished_at": meta.get("finished_at"),
            "prompt": meta.get("prompt"),
            "cwd": meta.get("cwd"),
        }
  • Helper used by poll_job to read the trailing lines of output from a job's output file.
    def _read_tail(job_id: str, tail_lines: int = JOB_TAIL_LINES) -> str:
        output_path = _job_dir(job_id) / "output.txt"
        if not output_path.exists():
            return ""
        text = output_path.read_text(errors="replace")
        lines = text.splitlines()
        tail = "\n".join(lines[-tail_lines:])
        if len(tail) > MAX_OUTPUT_CHARS:
            tail = "...(truncated)...\n" + tail[-MAX_OUTPUT_CHARS:]
        return tail
  • Helper used by poll_job to read the job's metadata JSON file.
    def _read_meta(job_id: str) -> Optional[dict]:
        path = _job_dir(job_id) / "meta.json"
        if not path.exists():
            return None
        with open(path) as f:
            return json.load(f)
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states the purpose but lacks details on behavioral traits such as whether the tool is idempotent or safe to call repeatedly. Since annotations are absent, the description carries the burden, and it only provides minimal transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no extraneous words. It efficiently conveys the tool's purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, the description does not need to explain return values. It covers the essential purpose and scope, though it could mention that the tool can be called multiple times safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description adds no additional meaning beyond what the schema already provides for the two parameters. The description's mention of 'output' hints at tail_lines, but this is redundant with the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Poll' and the resource 'status and output of a running (or finished) codex job', which is specific and distinguishes it from sibling tools like codex_start, codex_cancel, and codex_list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage after a job is started, but does not explicitly provide when-not-to-use or alternatives. The context is clear enough for an agent to infer appropriate usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/benzkittisak/claude-codex-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server