[project] name = "cli-bridge-mcp" version = "0.3.1" description = "Expose the other AI CLIs installed on your machine (Gemini, Codex, Claude Code, Mistral, opencode, Ollama…) as MCP tools. Spawns the official CLI; no API keys." readme = "README.md" license = { text = "Apache-2.0" } requires-python = ">=3.12" authors = [{ name = "JoaoBerné" }] keywords = ["mcp", "claude", "claude-code", "ai", "cli", "gemini", "codex", "gpt", "mistral", "qwen", "copilot", "opencode", "multi-model", "second-opinion"] classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", ] # Both majors are supported: mcp 2.0.0 removed the low-level decorators this server was built on # (list_tools/call_tool/list_prompts/get_prompt/list_resources/read_resource) and changed how a # handler gets its request context. `mcp_compat.py` is the ONLY module that branches on the # version — see its docstring for what 2.x makes us re-implement by hand. CI runs the full suite # on both legs. The <3 cap stays because a 3.0 would spring the same trap: an install that # resolves to an unsupported major is a server that dies on the first tool call, not one that # fails loudly at import (verified the hard way — 0.1.4 shipped uninstallable). dependencies = ["mcp>=1.2.0,<3"] [project.urls] Homepage = "https://github.com/JoaoBerne/cli-bridge-mcp" Issues = "https://github.com/JoaoBerne/cli-bridge-mcp/issues" [project.scripts] cli-bridge-mcp = "cli_bridge.server:main" cli-bridge = "cli_bridge.cli:main" cli-bridge-openai = "cli_bridge.bridges.openai_compatible:main" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/cli_bridge"] # Ship a lean source dist: the importable package + license/readme/changelog only. Excludes the # test suite, plus docs/benchmarks/assets/examples that aren't needed to build or install. CI runs # the tests from the checkout, not from the sdist. [tool.hatch.build.targets.sdist] exclude = ["/tests", "/docs", "/benchmarks", "/assets", "/examples", "/.github"] [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" [tool.ruff] line-length = 110 target-version = "py312" [tool.ruff.lint] # pyflakes (F), pycodestyle (E/W), isort (I), bugbear (B), pyupgrade (UP). select = ["E", "F", "W", "I", "B", "UP"] # E741: short loop vars are fine in tight comprehensions; B008: argparse default patterns. ignore = ["E741"] [tool.ruff.lint.per-file-ignores] # tests may shadow/leave locals and use bare asserts freely. "tests/*" = ["F841", "B011"] [tool.mypy] # Static type gate over the package (CI pins the mypy version so it can't drift). python_version = "3.12" # check against the minimum supported runtime files = ["src/cli_bridge"] [[tool.mypy.overrides]] # The MCP SDK's published types are incomplete in spots; never let a stub gap fail the gate. # jsonschema ships no stubs at all and comes in as a dependency OF mcp (used in mcp_compat to # reproduce the input validation mcp 1.x did for us) — same story, same treatment. module = ["mcp.*", "jsonschema"] ignore_missing_imports = true