From aead6c6ecb971d3a49c0fd5b8c0b292e8270218c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=80=E5=A8=81?= Date: Thu, 9 Jul 2026 15:25:37 +0800 Subject: [PATCH 1/6] mcp_env dump support query --- .gitignore | 1 + rock/sdk/mcp/mcp_env.py | 10 ++++- tests/unit/sdk/mcp/test_mcp_env.py | 67 +++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 9c75575e38..d6cc5a93b6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .venv/ .idea/ .claude/* +.qoder/* !.claude/skills/ .worktrees/ .pytest_cache/ diff --git a/rock/sdk/mcp/mcp_env.py b/rock/sdk/mcp/mcp_env.py index 8a88bec706..e60a9d33cf 100644 --- a/rock/sdk/mcp/mcp_env.py +++ b/rock/sdk/mcp/mcp_env.py @@ -170,16 +170,22 @@ def get_urls(self) -> dict: return deepcopy(self.urls) - async def dump(self) -> dict: + async def dump(self, query: dict | None = None) -> dict: """ Export current MCP environment data. + Args: + query: Optional per-lifecycle query dict, keyed by lifecycle type. + For example ``{"woocommerce": {"type": "products", "fields": "id,name"}}`` + triggers a live API read instead of a local snapshot. + Returns: Layered data returned by configured data lifecycles. """ dumped_data = {} for lifecycle_type, lifecycle in self.data_lifecycles.items(): - lifecycle_data = lifecycle.dump() + lifecycle_query = (query or {}).get(lifecycle_type) + lifecycle_data = lifecycle.dump(lifecycle_query) if inspect.isawaitable(lifecycle_data): lifecycle_data = await lifecycle_data if lifecycle_data != {}: diff --git a/tests/unit/sdk/mcp/test_mcp_env.py b/tests/unit/sdk/mcp/test_mcp_env.py index 2577533f17..f42222029a 100644 --- a/tests/unit/sdk/mcp/test_mcp_env.py +++ b/tests/unit/sdk/mcp/test_mcp_env.py @@ -56,11 +56,13 @@ class RecordingDataLifecycle: def __init__(self): self.initialized_data = {} self.reset_calls = 0 + self.dump_queries: list = [] def init(self, data: dict) -> None: self.initialized_data = deepcopy(data) - def dump(self) -> dict: + def dump(self, query=None) -> dict: + self.dump_queries.append(query) return deepcopy(self.initialized_data) def reset(self) -> None: @@ -74,11 +76,13 @@ class AsyncRecordingDataLifecycle: def __init__(self): self.initialized_data = {} self.reset_calls = 0 + self.dump_queries: list = [] async def init(self, data: dict) -> None: self.initialized_data = deepcopy(data) - async def dump(self) -> dict: + async def dump(self, query=None) -> dict: + self.dump_queries.append(query) return deepcopy(self.initialized_data) async def reset(self) -> None: @@ -719,3 +723,62 @@ def test_mcp_env_supports_mixed_sync_and_async_lifecycles(monkeypatch): assert sync_lifecycle.reset_calls == 1 assert async_lifecycle.reset_calls == 1 assert asyncio.run(env.dump()) == {} + + +def test_mcp_env_dump_without_query_passes_none_to_lifecycles(monkeypatch): + mcp_env = reload_mcp_env(monkeypatch) + env = mcp_env.McpEnv(servers={"slack": slack_server_config()}) + lifecycle = RecordingDataLifecycle() + lifecycle.initialized_data = {"channels": ["general"]} + env.data_lifecycles["slack"] = lifecycle + + result = asyncio.run(env.dump()) + + assert result == {"slack": {"channels": ["general"]}} + assert lifecycle.dump_queries == [None] + + +def test_mcp_env_dump_with_query_passes_per_lifecycle_query(monkeypatch): + mcp_env = reload_mcp_env(monkeypatch) + env = mcp_env.McpEnv(servers={"slack": slack_server_config(), "github": slack_server_config()}) + slack_lifecycle = RecordingDataLifecycle() + slack_lifecycle.initialized_data = {"channels": ["general"]} + github_lifecycle = RecordingDataLifecycle() + github_lifecycle.initialized_data = {"repos": ["example"]} + env.data_lifecycles["slack"] = slack_lifecycle + env.data_lifecycles["github"] = github_lifecycle + + query = {"slack": {"type": "channels", "fields": "id,name"}} + result = asyncio.run(env.dump(query=query)) + + assert result == { + "slack": {"channels": ["general"]}, + "github": {"repos": ["example"]}, + } + assert slack_lifecycle.dump_queries == [{"type": "channels", "fields": "id,name"}] + assert github_lifecycle.dump_queries == [None] + + +def test_mcp_env_dump_with_query_ignores_unknown_lifecycle_keys(monkeypatch): + mcp_env = reload_mcp_env(monkeypatch) + env = mcp_env.McpEnv(servers={"slack": slack_server_config()}) + lifecycle = RecordingDataLifecycle() + lifecycle.initialized_data = {"channels": ["general"]} + env.data_lifecycles["slack"] = lifecycle + + result = asyncio.run(env.dump(query={"woocommerce": {"type": "products"}})) + + assert result == {"slack": {"channels": ["general"]}} + assert lifecycle.dump_queries == [None] + + +def test_mcp_env_dump_with_empty_query_dict_passes_none(monkeypatch): + mcp_env = reload_mcp_env(monkeypatch) + env = mcp_env.McpEnv(servers={"slack": slack_server_config()}) + lifecycle = RecordingDataLifecycle() + lifecycle.initialized_data = {"channels": ["general"]} + env.data_lifecycles["slack"] = lifecycle + + asyncio.run(env.dump(query={})) + + assert lifecycle.dump_queries == [None] From 1534e3845e7c8747120c71d92d543337b0ec09b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=80=E5=A8=81?= Date: Sun, 12 Jul 2026 17:03:51 +0800 Subject: [PATCH 2/6] upgrade image version v0.17.0 --- rock/sdk/mcp/rock_runtime.py | 2 +- tests/unit/sdk/mcp/test_rock_runtime.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rock/sdk/mcp/rock_runtime.py b/rock/sdk/mcp/rock_runtime.py index 8f8ed06d2b..69912a2222 100644 --- a/rock/sdk/mcp/rock_runtime.py +++ b/rock/sdk/mcp/rock_runtime.py @@ -66,7 +66,7 @@ def from_env(cls) -> RockRuntimeConfig: api_key=api_key, image=os.getenv( "ROCK_SANDBOX_IMAGE", - "rock-instances-registry-vpc.cn-shanghai.cr.aliyuncs.com/instance/rock-mcp-base:v0.16.0", + "rock-instances-registry-vpc.cn-shanghai.cr.aliyuncs.com/instance/rock-mcp-base:v0.17.0", ), user_id=user_id, experiment_id=os.getenv("ROCK_EXPERIMENT_ID", "mcpenv"), diff --git a/tests/unit/sdk/mcp/test_rock_runtime.py b/tests/unit/sdk/mcp/test_rock_runtime.py index adb51b2d0d..e1e6324597 100644 --- a/tests/unit/sdk/mcp/test_rock_runtime.py +++ b/tests/unit/sdk/mcp/test_rock_runtime.py @@ -41,7 +41,7 @@ def test_rock_runtime_config_reads_defaults_and_numeric_values(monkeypatch): assert config.api_key == "rock-key" assert config.user_id == "user-001" assert config.base_url == "https://xrl.alibaba-inc.com" - assert config.image == "rock-instances-registry-vpc.cn-shanghai.cr.aliyuncs.com/instance/rock-mcp-base:v0.16.0" + assert config.image == "rock-instances-registry-vpc.cn-shanghai.cr.aliyuncs.com/instance/rock-mcp-base:v0.17.0" assert config.experiment_id == "mcpenv" assert config.cluster == "vpc-nt-a" assert config.cpus == 4.0 From dca63a62cdde939c87d6d4fa028ff3bf1227cd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=80=E5=A8=81?= Date: Mon, 13 Jul 2026 10:20:37 +0800 Subject: [PATCH 3/6] feat: change version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 90da0f7ad6..152737e804 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" authors = [{ name = "chatos@alibaba" }] requires-python = "<4.0,>=3.10" name = "rl-rock" -version = "1.10.0.dev2026071001" +version = "1.17.0" description = "ROCK-Reinforcement Open Construction Kit" readme = "README.md" dependencies = [ From deb06dcbcace93a7090442c69e1a769edafa5030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=80=E5=A8=81?= Date: Mon, 13 Jul 2026 10:22:46 +0800 Subject: [PATCH 4/6] feat: change version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 152737e804..7e47a8d58e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" authors = [{ name = "chatos@alibaba" }] requires-python = "<4.0,>=3.10" name = "rl-rock" -version = "1.17.0" +version = "1.13.0.dev2026071310" description = "ROCK-Reinforcement Open Construction Kit" readme = "README.md" dependencies = [ From 44c19eab7a9e2bec1d7650ca764b2ec266f1d330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=80=E5=A8=81?= Date: Mon, 13 Jul 2026 10:41:06 +0800 Subject: [PATCH 5/6] feat: update version&uv.lock --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1b15732baf..73697482d4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" authors = [{ name = "chatos@alibaba" }] requires-python = "<4.0,>=3.10" name = "rl-rock" -version = "1.11.0.dev2026071217" +version = "1.11.0.dev2026071310" description = "ROCK-Reinforcement Open Construction Kit" readme = "README.md" dependencies = [ diff --git a/uv.lock b/uv.lock index ff13f3cfb4..fac699544a 100644 --- a/uv.lock +++ b/uv.lock @@ -4515,7 +4515,7 @@ wheels = [ [[package]] name = "rl-rock" -version = "1.11.0.dev2026071217" +version = "1.11.0.dev2026071310" source = { editable = "." } dependencies = [ { name = "anyio" }, From e0b2768b432af84cd13670f9e6abf3b59b5384d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=80=E5=A8=81?= Date: Wed, 15 Jul 2026 19:54:53 +0800 Subject: [PATCH 6/6] chore: bump scaffoldhub to 0.1.13 --- pyproject.toml | 2 +- tests/unit/sdk/mcp/test_packaging.py | 2 +- uv.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ba26b5e8cd..86af6b8f3a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,7 +93,7 @@ model-service = [ ] mcp = [ - "scaffoldhub>=0.1.12; python_version >= '3.11' and python_version < '3.13'", + "scaffoldhub>=0.1.13; python_version >= '3.11' and python_version < '3.13'", ] diff --git a/tests/unit/sdk/mcp/test_packaging.py b/tests/unit/sdk/mcp/test_packaging.py index 37b1c9e7bd..f108c311c7 100644 --- a/tests/unit/sdk/mcp/test_packaging.py +++ b/tests/unit/sdk/mcp/test_packaging.py @@ -11,7 +11,7 @@ def test_mcp_extra_declares_scaffoldhub_dependency(): mcp_dependencies = pyproject["project"]["optional-dependencies"]["mcp"] - assert "scaffoldhub>=0.1.12; python_version >= '3.11' and python_version < '3.13'" in mcp_dependencies + assert "scaffoldhub>=0.1.13; python_version >= '3.11' and python_version < '3.13'" in mcp_dependencies def test_scaffoldhub_resolves_from_artlab_index(): diff --git a/uv.lock b/uv.lock index 16fb16036c..40d8796cd4 100644 --- a/uv.lock +++ b/uv.lock @@ -4736,7 +4736,7 @@ requires-dist = [ { name = "rl-rock", extras = ["builder"], marker = "extra == 'all'" }, { name = "rl-rock", extras = ["rocklet"], marker = "extra == 'admin'" }, { name = "rl-rock", extras = ["rocklet"], marker = "extra == 'all'" }, - { name = "scaffoldhub", marker = "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'mcp'", specifier = ">=0.1.12", index = "https://artlab.alibaba-inc.com/1/pypi/simple" }, + { name = "scaffoldhub", marker = "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'mcp'", specifier = ">=0.1.13", index = "https://artlab.alibaba-inc.com/1/pypi/simple" }, { name = "sqlmodel", marker = "extra == 'admin'" }, { name = "sqlmodel", marker = "extra == 'sandbox-actor'" }, { name = "swebench", marker = "extra == 'builder'" }, @@ -4942,7 +4942,7 @@ wheels = [ [[package]] name = "scaffoldhub" -version = "0.1.12" +version = "0.1.13" source = { registry = "https://artlab.alibaba-inc.com/1/pypi/simple" } dependencies = [ { name = "circus", marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, @@ -4959,9 +4959,9 @@ dependencies = [ { name = "snowflake-connector-python", marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, { name = "uvicorn", marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, ] -sdist = { url = "https://artlab.alibaba-inc.com/1/pypi/simple/scaffoldhub/scaffoldhub-0.1.12.tar.gz", hash = "sha256:0241d12487de925a1919a8868cec47e948f4ab581d75352b9df682bfb6ea7d56" } +sdist = { url = "https://artlab.alibaba-inc.com/1/pypi/simple/scaffoldhub/scaffoldhub-0.1.13.tar.gz", hash = "sha256:7477e459dabfec41cb8dc00f290d4b3bf49ef26dd3584e85b01259bfff329920" } wheels = [ - { url = "https://artlab.alibaba-inc.com/1/pypi/simple/scaffoldhub/scaffoldhub-0.1.12-py3-none-any.whl", hash = "sha256:de366c384a5392b033f1ddaa532aa8fd99023d6548753bc32032b3613056358f" }, + { url = "https://artlab.alibaba-inc.com/1/pypi/simple/scaffoldhub/scaffoldhub-0.1.13-py3-none-any.whl", hash = "sha256:1436c599b415c6fb102b08b94af0553c7ca117baefd8efde702cc853068fc93e" }, ] [[package]]