From c875a1ae101f61d965406a3b94c3ad15f9446820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Wed, 21 Oct 2026 17:35:06 +0200 Subject: [PATCH 1/2] web-algebra mcp runs the MCP server; the registry entry runs it A registry client starts a PyPI package as uvx web-algebra, which on its own starts the planner. server.json passes mcp to it. Version 2.0.1. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 9 +++++++++ README.md | 2 ++ pyproject.toml | 2 +- server.json | 10 ++++++++-- src/web_algebra/main.py | 12 ++++++++++++ tests/test_mcp_server.py | 14 ++++++++++++-- tests/test_packaging.py | 5 +++++ uv.lock | 2 +- 8 files changed, 50 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4f87b6..16d69f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to Web Algebra are recorded here. The format follows [Semantic Versioning](https://semver.org/). The normative definition of every operation is [formal-semantics.md](formal-semantics.md). +## [2.0.1] - Unreleased + +### Added + +- **`web-algebra mcp`** runs the MCP server on stdio, as `web-algebra-mcp` + does. The MCP Registry entry (`server.json`) runs it: a registry client + starts a PyPI package as `uvx web-algebra`, which on its own starts the + planner. + ## [2.0.0] - 2026-10-21 Web Algebra now has a formal semantics, and the Python implementation conforms diff --git a/README.md b/README.md index a58acc0..a46b614 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,8 @@ or with Claude Code: claude mcp add web-algebra -e CERT_PEM_PATH=/path/to/LinkedDataHub/ssl/owner/cert.pem -e CERT_PASSWORD=******** -- uvx --from web-algebra web-algebra-mcp ``` +`uvx web-algebra mcp` runs the same server. + Environment variables: | Name | Required | Description | diff --git a/pyproject.toml b/pyproject.toml index 1da98c5..4436787 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "web-algebra" -version = "2.0.0" +version = "2.0.1" description = "Composable RDF operations in JSON" readme = "README.md" license = "Apache-2.0" diff --git a/server.json b/server.json index 66f1cd3..e598b0b 100644 --- a/server.json +++ b/server.json @@ -7,13 +7,19 @@ "url": "https://github.com/AtomGraph/Web-Algebra", "source": "github" }, - "version": "2.0.0", + "version": "2.0.1", "packages": [ { "registryType": "pypi", "identifier": "web-algebra", - "version": "2.0.0", + "version": "2.0.1", "runtimeHint": "uvx", + "packageArguments": [ + { + "type": "positional", + "value": "mcp" + } + ], "transport": { "type": "stdio" }, diff --git a/src/web_algebra/main.py b/src/web_algebra/main.py index 1ec68fc..568e726 100644 --- a/src/web_algebra/main.py +++ b/src/web_algebra/main.py @@ -135,6 +135,12 @@ def main(settings: BaseSettings, json_data: Optional[str]): def cli() -> None: parser = argparse.ArgumentParser(description="Run the AI-powered DSL interpreter.") + parser.add_argument( + "command", + nargs="?", + choices=["mcp"], + help="mcp: run the MCP server on stdio, as web-algebra-mcp does", + ) parser.add_argument( "--from-json", type=str, @@ -152,6 +158,12 @@ def cli() -> None: ) args = parser.parse_args() + if args.command == "mcp": + from web_algebra.__main__ import main as serve + + serve() + return + # the flags override CERT_PEM_PATH / CERT_PASSWORD, which the settings # read from the environment, as the MCP server and the tests do overrides = { diff --git a/tests/test_mcp_server.py b/tests/test_mcp_server.py index 6ec9213..d1d23b2 100644 --- a/tests/test_mcp_server.py +++ b/tests/test_mcp_server.py @@ -48,9 +48,9 @@ def mcp_tools(): class Stdio: - def __init__(self): + def __init__(self, command=("-m", "web_algebra")): self.proc = subprocess.Popen( - [sys.executable, "-m", "web_algebra"], + [sys.executable, *command], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, @@ -106,6 +106,16 @@ def test_initialize_names_the_server_and_its_version(stdio): assert info["version"] == version("web-algebra") +def test_the_cli_mcp_command_is_the_stdio_server(): + # `web-algebra mcp` is what an MCP Registry client runs (server.json) + server = Stdio(("-m", "web_algebra.main", "mcp")) + try: + answer = server.request("initialize", INITIALIZE, timeout=60) + finally: + server.close() + assert answer["result"]["serverInfo"]["name"] == "web-algebra" + + def test_initialize_offers_tools(stdio): assert "tools" in stdio.initialized["result"]["capabilities"] diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 3085af5..3c59802 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -39,6 +39,11 @@ def test_server_json_names_the_pypi_package(): assert [p["identifier"] for p in SERVER["packages"] if p["registryType"] == "pypi"] == ["web-algebra"] +def test_server_json_runs_the_mcp_command(): + # `uvx web-algebra` alone would start the planner, not the server + assert [p.get("packageArguments") for p in SERVER["packages"]] == [[{"type": "positional", "value": "mcp"}]] + + def test_readme_carries_the_server_name(): assert f"mcp-name: {SERVER['name']} " in (ROOT / "README.md").read_text().replace("-->", " -->") diff --git a/uv.lock b/uv.lock index c199dae..2cbf56e 100644 --- a/uv.lock +++ b/uv.lock @@ -1426,7 +1426,7 @@ wheels = [ [[package]] name = "web-algebra" -version = "2.0.0" +version = "2.0.1" source = { editable = "." } dependencies = [ { name = "elementpath" }, From 60715889753e7529b086e39899e55d4e8a0d3784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Wed, 21 Oct 2026 17:35:23 +0200 Subject: [PATCH 2/2] CHANGELOG: date 2.0.1 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16d69f2..438504f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to Web Algebra are recorded here. The format follows [Semantic Versioning](https://semver.org/). The normative definition of every operation is [formal-semantics.md](formal-semantics.md). -## [2.0.1] - Unreleased +## [2.0.1] - 2026-10-21 ### Added