diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8395236..bda9a40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] env: CLICK_TO_MCP_NO_LICENSE: "1" diff --git a/CHANGELOG.md b/CHANGELOG.md index ca30bfc..2a3f39f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to click-to-mcp will be documented in this file. ### Added +- Python 3.14 to CI test matrix and PyPI classifiers (#35) - npm wrapper (`package.json` + `cli.js`) for npm discoverability and publish workflow (#9) - Awesome Codex CLI listing badge (PR #29 merged) - `abortage/awesome-mcp` merged badge diff --git a/click_to_mcp/server.py b/click_to_mcp/server.py index 9da036b..9e44a4f 100644 --- a/click_to_mcp/server.py +++ b/click_to_mcp/server.py @@ -23,6 +23,12 @@ def _make_jsonrpc_response(request_id: Any, result: Any = None, error: dict | No return json.dumps(resp) +def _write_response(response: str) -> None: + """Write a JSON-RPC response to stdout and flush.""" + sys.stdout.write(response + "\n") + sys.stdout.flush() + + def serve_stdio( cli_group, name: str = "cli", description: str = "", prefix: str = "", ) -> None: @@ -77,15 +83,13 @@ def serve_stdio( }, "serverInfo": server_info, }) - sys.stdout.write(response + "\n") - sys.stdout.flush() + _write_response(response) elif method == "tools/list": response = _make_jsonrpc_response(req_id, { "tools": mcp_tool_list, }) - sys.stdout.write(response + "\n") - sys.stdout.flush() + _write_response(response) elif method == "tools/call": tool_name = params.get("name", "") @@ -97,8 +101,7 @@ def serve_stdio( "message": f"Unknown tool: {tool_name}", } response = _make_jsonrpc_response(req_id, error=error) - sys.stdout.write(response + "\n") - sys.stdout.flush() + _write_response(response) continue tool = tool_map[tool_name] @@ -127,14 +130,12 @@ def serve_stdio( } response = _make_jsonrpc_response(req_id, result) - sys.stdout.write(response + "\n") - sys.stdout.flush() + _write_response(response) elif method == "ping": # MCP spec: respond with empty result response = _make_jsonrpc_response(req_id, {}) - sys.stdout.write(response + "\n") - sys.stdout.flush() + _write_response(response) elif method == "notifications/initialized": # No response needed for notifications @@ -146,8 +147,7 @@ def serve_stdio( "message": f"Method not found: {method}", } response = _make_jsonrpc_response(req_id, error=error) - sys.stdout.write(response + "\n") - sys.stdout.flush() + _write_response(response) except Exception as e: error = { @@ -155,5 +155,4 @@ def serve_stdio( "message": f"Internal error: {e}", } response = _make_jsonrpc_response(req_id, error=error) - sys.stdout.write(response + "\n") - sys.stdout.flush() + _write_response(response) diff --git a/pyproject.toml b/pyproject.toml index d7fd978..482de7b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,12 +19,14 @@ keywords = ["mcp", "click", "cli", "model-context-protocol", "ai", "discovery", classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", "Topic :: Software Development :: Libraries :: Python Modules", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] [project.optional-dependencies] diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..2a9ad73 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for click-to-mcp — covers adapter, CLI, server, HTTP, and streamable HTTP transports."""