Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ Versioning and uses Git tags as its release channel.

## [Unreleased]

## [0.1.1] - 2026-09-14

- Fixed `doctor` incorrectly treating a normal Codex project trust entry as a
recursive MCP server registration.

## [0.1.0] - 2026-09-14

- Added the `codex` and `codex-reply` MCP tools over stdio.
Expand All @@ -14,5 +19,6 @@ Versioning and uses Git tags as its release channel.
- Added structured results with a text fallback for MCP clients including OpenCode.
- Validated the pinned SDK against fake App Server contract tests and live Codex runtime tests.

[Unreleased]: https://github.com/PyYoshi/codex-app-mcp/compare/v0.1.0...HEAD
[Unreleased]: https://github.com/PyYoshi/codex-app-mcp/compare/v0.1.1...HEAD
[0.1.1]: https://github.com/PyYoshi/codex-app-mcp/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/PyYoshi/codex-app-mcp/releases/tag/v0.1.0
6 changes: 3 additions & 3 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ Codex 連携が提供されていないツールから、Codex を協働エー

```sh
cd /absolute/path/to/target-project
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.0 \
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.1 \
codex-app-mcp init
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.0 \
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.1 \
codex-app-mcp doctor
```

Expand Down Expand Up @@ -150,7 +150,7 @@ claude mcp add codex -- \

注意:

- PyPIには公開しない。`uvx --from git+https://...@v0.1.0`でGitHubのtagを固定する。
- PyPIには公開しない。`uvx --from git+https://...@v0.1.1`でGitHubのtagを固定する。
- 自動探索はbridge起動directoryから親へ向かう。固定したい場合は従来どおり
`serve --config /absolute/path/to/bridge.toml`を指定できる。
- Codex 側(`~/.codex/config.toml` の `mcp_servers`)にこの bridge を登録すると再帰的自己接続になり得る。bridge は子 runtime 環境の `CODEX_APP_MCP_CHILD=1` で起動拒否するが、その構成自体を推奨しない。
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ Create a safe project-local configuration from the target repository:

```sh
cd /absolute/path/to/target-project
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.0 \
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.1 \
codex-app-mcp init
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.0 \
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.1 \
codex-app-mcp doctor
```

Expand All @@ -72,13 +72,13 @@ the client should launch the bridge in its workspace and leave it unset. See
## MCP client configuration

Use an executable plus an argument array, not a shell command string. Before the
`v0.1.0` tag exists, replace it with a commit SHA.
`v0.1.1` tag exists, replace it with a commit SHA.

### Claude Code

```sh
claude mcp add codex -- \
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.0 \
uvx --from git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.1 \
codex-app-mcp serve
```

Expand All @@ -91,7 +91,7 @@ claude mcp add codex -- \
"type": "local",
"command": [
"uvx", "--from",
"git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.0",
"git+https://github.com/PyYoshi/codex-app-mcp.git@v0.1.1",
"codex-app-mcp", "serve"
],
"enabled": true
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "codex-app-mcp"
version = "0.1.0"
version = "0.1.1"
description = "Local MCP bridge exposing Codex App Server threads/turns as the codex / codex-reply MCP tools (noninteractive compatibility subset)"
readme = "README.md"
requires-python = ">=3.14,<3.15"
Expand Down
2 changes: 1 addition & 1 deletion src/codex_app_mcp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
compatibility subset; see ``docs/`` for the specification.
"""

__version__ = "0.1.0"
__version__ = "0.1.1"

CHILD_ENV_FLAG = "CODEX_APP_MCP_CHILD"
"""Set in the child runtime environment to break recursive self-connections."""
23 changes: 20 additions & 3 deletions src/codex_app_mcp/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import os
import re
import sys
import tomllib
from pathlib import Path
from typing import Any

Expand All @@ -36,6 +37,23 @@ def _check(ok: bool, detail: str, *, level_on_fail: str = FAIL) -> dict[str, str
return {"status": _OK if ok else level_on_fail, "detail": detail}


def _contains_bridge_reference(value: object) -> bool:
if isinstance(value, str):
return re.search(r"codex[-_]app[-_]mcp", value) is not None
if isinstance(value, dict):
return any(_contains_bridge_reference(item) for item in value.values())
if isinstance(value, list):
return any(_contains_bridge_reference(item) for item in value)
return False


def _codex_mcp_references_bridge(config_toml: Path) -> bool:
"""Inspect MCP server definitions without matching unrelated project paths."""
with config_toml.open("rb") as stream:
config = tomllib.load(stream)
return _contains_bridge_reference(config.get("mcp_servers", {}))


async def run_doctor(
*, config_path: str | None = None, skip_runtime: bool = False
) -> dict[str, Any]:
Expand Down Expand Up @@ -124,8 +142,7 @@ async def run_doctor(
config_toml = codex_home / "config.toml"
if config_toml.is_file():
try:
text = config_toml.read_text(encoding="utf-8", errors="replace")
if re.search(r"codex[-_]app[-_]mcp", text):
if _codex_mcp_references_bridge(config_toml):
checks.append(
_check(
False,
Expand All @@ -136,7 +153,7 @@ async def run_doctor(
)
else:
checks.append({"status": _OK, "detail": "no self-reference in Codex config"})
except OSError as exc:
except (OSError, tomllib.TOMLDecodeError) as exc:
checks.append(_check(False, f"cannot read {config_toml}: {exc}", level_on_fail=WARN))

# --- Authentication presence (contents never displayed) --------------------
Expand Down
19 changes: 18 additions & 1 deletion tests/unit/test_config_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
load_bridge_config,
user_config_path,
)
from codex_app_mcp.doctor import _is_supported_python
from codex_app_mcp.doctor import _codex_mcp_references_bridge, _is_supported_python
from codex_app_mcp.errors import (
CONFIG_KEY_DENIED,
MODEL_NOT_ALLOWED,
Expand Down Expand Up @@ -138,6 +138,23 @@ def test_config_example_file_loads():
assert config.limits.max_active_turns == 1


def test_doctor_self_reference_check_only_inspects_mcp_servers(tmp_path):
config = tmp_path / "config.toml"
config.write_text(
'[projects."/src/codex-app-mcp"]\ntrust_level = "trusted"\n',
encoding="utf-8",
)
assert not _codex_mcp_references_bridge(config)

config.write_text(
'[mcp_servers.codex]\ncommand = "uvx"\n'
'args = ["--from", "git+https://example.test/codex-app-mcp", '
'"codex-app-mcp", "serve"]\n',
encoding="utf-8",
)
assert _codex_mcp_references_bridge(config)


def test_config_discovery_prefers_explicit_then_nearest_then_user(tmp_path):
home = tmp_path / "home"
xdg = home / "xdg"
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.