# Copyright 2020-2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 PYTHON_COMPAT=( python3_13 ) inherit python-single-r1 DESCRIPTION="MCP server for delegating tasks to Codex CLI subagents" HOMEPAGE="https://github.com/kky42/codex-as-mcp" # Archive tag is the raw git tag. This seed tag has no v prefix. SRC_URI=" https://github.com/kky42/codex-as-mcp/archive/refs/tags/v2026.6.29.1.tar.gz -> ${P}.tar.gz https://github.com/0x6d6e647a/mndz-overlay-assets/releases/download/codex-as-mcp-${PV}/codex-as-mcp-${PV}-deps.tar.xz " S="${WORKDIR}/${P}" LICENSE="MIT" SLOT="0" KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86" IUSE="external-codex test" RESTRICT="!test? ( test )" RDEPEND=" ${PYTHON_DEPS} dev-lang/python:3.13 !external-codex? ( dev-util/codex ) " DEPEND="${RDEPEND}" # PEP 517 backends are sdists in the deps tarball. The toolchain stays here. BDEPEND=" ${PYTHON_DEPS} dev-python/uv || ( dev-lang/rust-bin dev-lang/rust ) dev-libs/openssl dev-libs/libffi " src_unpack() { default # GitHub archive root is ${PN}-. Move it onto ${P} when the tag # spelling differs from PV (a v-prefixed tag). if [[ ! -d ${P} ]]; then local d for d in "${WORKDIR}/${PN}-"*; do [[ -d ${d} ]] || continue mv "${d}" "${WORKDIR}/${P}" || die break done fi } # uv sync --frozen selects the lock's wheels and checks the original sdist # hashes. cargo vendor rewrites the Rust sdists, so those hashes do not match. # Export the pins without hashes and build every distribution from sdists/. uv_install_from_sdists() { local venv=$1 shift export UV_OFFLINE=1 export UV_PYTHON_DOWNLOADS=never export CARGO_NET_OFFLINE=true export UV_CACHE_DIR="${T}/uv-cache" export CARGO_HOME="${T}/cargo" uv venv --python /usr/bin/python3.13 "${venv}" || die uv export \ --directory "${S}" \ --frozen \ "$@" \ --no-hashes \ --no-emit-project \ --offline \ --python /usr/bin/python3.13 \ -o "${T}/requirements.txt" || die # Portage exports PYTHON to the system interpreter. pydantic-core's # build.rs runs generate_self_schema.py with that variable when it is # set. The script imports typing_extensions, which the isolated build # env has and the system interpreter does not. maturin already sets # PYO3_PYTHON to the isolated interpreter. env -u PYTHON \ uv pip install \ --python "${venv}/bin/python" \ --offline \ --no-index \ --find-links "${WORKDIR}/sdists" \ --no-binary :all: \ -r "${T}/requirements.txt" || die } src_install() { local external=no venv site use external-codex && external=yes venv="${ED}/usr/lib/${PN}" uv_install_from_sdists "${venv}" --no-dev site="$("${venv}/bin/python" -c 'import sysconfig; print(sysconfig.get_path("purelib"))')" || die cp -a "${S}/src/codex_as_mcp" "${site}/" || die dodir /usr/bin cat > "${ED}/usr/bin/${PN}" <<-EOF || die #!/bin/sh if [ -n "\${CODEX_PATH+x}" ]; then base=\$(basename "\$CODEX_PATH") if [ "\$base" != codex ]; then echo "CODEX_PATH must name a codex executable" >&2 exit 1 fi PATH=\$(dirname "\$CODEX_PATH"):\$PATH elif [ "${external}" = no ]; then PATH=/usr/bin:\$PATH fi export PATH exec /usr/lib/${PN}/bin/python -m codex_as_mcp "\$@" EOF fperms 0755 "/usr/bin/${PN}" || die } src_test() { [[ -f tests/test_server.py ]] || return 0 local venv site venv="${T}/venv" uv_install_from_sdists "${venv}" --all-groups site="$("${venv}/bin/python" -c 'import sysconfig; print(sysconfig.get_path("purelib"))')" || die cp -a "${S}/src/codex_as_mcp" "${site}/" || die "${venv}/bin/python" -m pytest tests/test_server.py || die } pkg_postinst() { ewarn "${PN} launches Codex with approvals and the sandbox bypassed." }