agentic-data-contracts 0.2.1__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/CHANGELOG.md +17 -0
  2. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/PKG-INFO +8 -7
  3. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/README.md +5 -4
  4. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/docs/architecture.md +1 -1
  5. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/pyproject.toml +2 -2
  6. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/__init__.py +7 -1
  7. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/core/contract.py +15 -0
  8. agentic_data_contracts-0.2.3/src/agentic_data_contracts/tools/sdk.py +71 -0
  9. agentic_data_contracts-0.2.3/tests/test_core/test_sdk_config.py +36 -0
  10. agentic_data_contracts-0.2.3/tests/test_tools/test_sdk.py +116 -0
  11. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/uv.lock +9 -9
  12. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/.github/dependabot.yml +0 -0
  13. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/.github/workflows/ci.yml +0 -0
  14. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/.gitignore +0 -0
  15. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/.pre-commit-config.yaml +0 -0
  16. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/.python-version +0 -0
  17. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/CLAUDE.md +0 -0
  18. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/LICENSE +0 -0
  19. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/examples/revenue_agent/agent.py +0 -0
  20. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/examples/revenue_agent/contract.yml +0 -0
  21. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/examples/revenue_agent/semantic.yml +0 -0
  22. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/examples/revenue_agent/setup_db.py +0 -0
  23. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/adapters/__init__.py +0 -0
  24. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/adapters/base.py +0 -0
  25. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/adapters/duckdb.py +0 -0
  26. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/bridge/__init__.py +0 -0
  27. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/bridge/compiler.py +0 -0
  28. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/core/__init__.py +0 -0
  29. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/core/schema.py +0 -0
  30. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/core/session.py +0 -0
  31. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/py.typed +0 -0
  32. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/semantic/__init__.py +0 -0
  33. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/semantic/base.py +0 -0
  34. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/semantic/cube.py +0 -0
  35. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/semantic/dbt.py +0 -0
  36. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/semantic/yaml_source.py +0 -0
  37. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/tools/__init__.py +0 -0
  38. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/tools/factory.py +0 -0
  39. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/tools/middleware.py +0 -0
  40. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/validation/__init__.py +0 -0
  41. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/validation/checkers.py +0 -0
  42. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/validation/explain.py +0 -0
  43. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/src/agentic_data_contracts/validation/validator.py +0 -0
  44. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/__init__.py +0 -0
  45. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/conftest.py +0 -0
  46. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/fixtures/minimal_contract.yml +0 -0
  47. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/fixtures/sample_cube_schema.yml +0 -0
  48. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/fixtures/sample_dbt_manifest.json +0 -0
  49. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/fixtures/semantic_source.yml +0 -0
  50. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/fixtures/valid_contract.yml +0 -0
  51. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_adapters/__init__.py +0 -0
  52. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_adapters/test_duckdb.py +0 -0
  53. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_bridge/__init__.py +0 -0
  54. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_bridge/test_compiler.py +0 -0
  55. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_core/__init__.py +0 -0
  56. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_core/test_contract.py +0 -0
  57. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_core/test_load_semantic_source.py +0 -0
  58. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_core/test_schema.py +0 -0
  59. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_core/test_session.py +0 -0
  60. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_core/test_system_prompt_metrics.py +0 -0
  61. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_public_api.py +0 -0
  62. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_semantic/__init__.py +0 -0
  63. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_semantic/test_cube.py +0 -0
  64. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_semantic/test_dbt.py +0 -0
  65. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_semantic/test_search.py +0 -0
  66. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_semantic/test_yaml_source.py +0 -0
  67. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_tools/__init__.py +0 -0
  68. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_tools/test_auto_load.py +0 -0
  69. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_tools/test_factory.py +0 -0
  70. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_tools/test_middleware.py +0 -0
  71. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_tools/test_semantic_tools.py +0 -0
  72. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_validation/__init__.py +0 -0
  73. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_validation/test_checkers.py +0 -0
  74. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_validation/test_explain.py +0 -0
  75. {agentic_data_contracts-0.2.1 → agentic_data_contracts-0.2.3}/tests/test_validation/test_validator.py +0 -0
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.2.3] - 2026-03-29
6
+
7
+ ### Added
8
+
9
+ - **SDK MCP server convenience method**: `create_sdk_mcp_server(contract, adapter=...)` wraps all 10 tools with the SDK's `@tool` decorator and bundles them into a ready-to-use MCP server for `ClaudeAgentOptions.mcp_servers`
10
+ - **Top-level export**: `from agentic_data_contracts import create_sdk_mcp_server`
11
+
12
+ ### Changed
13
+
14
+ - **SDK dependency**: Bumped `claude-agent-sdk` minimum to `>=0.1.52`
15
+
16
+ ## [0.2.2] - 2026-03-28
17
+
18
+ ### Added
19
+
20
+ - **SDK config generation**: `DataContract.to_sdk_config()` maps contract limits to Claude Agent SDK options (`token_budget` → `task_budget`, `max_retries` → `max_turns`)
21
+
5
22
  ## [0.2.1] - 2026-03-28
6
23
 
7
24
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-data-contracts
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: YAML-first data contract governance for AI agents
5
5
  Project-URL: Homepage, https://github.com/flyersworder/agentic-data-contracts
6
6
  Project-URL: Repository, https://github.com/flyersworder/agentic-data-contracts
@@ -27,10 +27,10 @@ Requires-Dist: thefuzz>=0.22.1
27
27
  Provides-Extra: agent-contracts
28
28
  Requires-Dist: ai-agent-contracts>=0.2.0; extra == 'agent-contracts'
29
29
  Provides-Extra: agent-sdk
30
- Requires-Dist: claude-agent-sdk; extra == 'agent-sdk'
30
+ Requires-Dist: claude-agent-sdk>=0.1.52; extra == 'agent-sdk'
31
31
  Provides-Extra: all
32
32
  Requires-Dist: ai-agent-contracts>=0.2.0; extra == 'all'
33
- Requires-Dist: claude-agent-sdk; extra == 'all'
33
+ Requires-Dist: claude-agent-sdk>=0.1.52; extra == 'all'
34
34
  Requires-Dist: duckdb; extra == 'all'
35
35
  Requires-Dist: google-cloud-bigquery; extra == 'all'
36
36
  Requires-Dist: psycopg2-binary; extra == 'all'
@@ -150,25 +150,26 @@ adapter = DuckDBAdapter("analytics.duckdb")
150
150
  tools = create_tools(dc, adapter=adapter)
151
151
  ```
152
152
 
153
- ### 3. Use with the Claude Agent SDK
153
+ ### 3. Use with the Claude Agent SDK (requires `claude-agent-sdk>=0.1.52`)
154
154
 
155
155
  ```python
156
156
  import asyncio
157
+ from agentic_data_contracts import create_sdk_mcp_server
157
158
  from claude_agent_sdk import (
158
159
  ClaudeAgentOptions,
159
160
  AssistantMessage,
160
161
  TextBlock,
161
- create_sdk_mcp_server,
162
162
  query,
163
163
  )
164
164
 
165
- server = create_sdk_mcp_server(name="data-contracts", version="1.0.0", tools=tools)
165
+ # One-liner: wraps all 10 tools and bundles into an SDK MCP server
166
+ server = create_sdk_mcp_server(dc, adapter=adapter)
166
167
 
167
168
  options = ClaudeAgentOptions(
168
169
  model="claude-sonnet-4-6",
169
170
  system_prompt=f"You are a revenue analytics assistant.\n\n{dc.to_system_prompt()}",
170
171
  mcp_servers={"dc": server},
171
- allowed_tools=[f"mcp__dc__{t.name}" for t in tools],
172
+ **dc.to_sdk_config(), # token_budget task_budget, max_retries → max_turns
172
173
  )
173
174
 
174
175
  async def run(prompt: str) -> None:
@@ -97,25 +97,26 @@ adapter = DuckDBAdapter("analytics.duckdb")
97
97
  tools = create_tools(dc, adapter=adapter)
98
98
  ```
99
99
 
100
- ### 3. Use with the Claude Agent SDK
100
+ ### 3. Use with the Claude Agent SDK (requires `claude-agent-sdk>=0.1.52`)
101
101
 
102
102
  ```python
103
103
  import asyncio
104
+ from agentic_data_contracts import create_sdk_mcp_server
104
105
  from claude_agent_sdk import (
105
106
  ClaudeAgentOptions,
106
107
  AssistantMessage,
107
108
  TextBlock,
108
- create_sdk_mcp_server,
109
109
  query,
110
110
  )
111
111
 
112
- server = create_sdk_mcp_server(name="data-contracts", version="1.0.0", tools=tools)
112
+ # One-liner: wraps all 10 tools and bundles into an SDK MCP server
113
+ server = create_sdk_mcp_server(dc, adapter=adapter)
113
114
 
114
115
  options = ClaudeAgentOptions(
115
116
  model="claude-sonnet-4-6",
116
117
  system_prompt=f"You are a revenue analytics assistant.\n\n{dc.to_system_prompt()}",
117
118
  mcp_servers={"dc": server},
118
- allowed_tools=[f"mcp__dc__{t.name}" for t in tools],
119
+ **dc.to_sdk_config(), # token_budget task_budget, max_retries → max_turns
119
120
  )
120
121
 
121
122
  async def run(prompt: str) -> None:
@@ -1,7 +1,7 @@
1
1
  # Agentic Data Contracts — Architecture
2
2
 
3
3
  **Date:** 2026-03-28
4
- **Status:** Implemented (v0.2.1)
4
+ **Status:** Implemented (v0.2.2)
5
5
  **Author:** Qing Ye + Claude
6
6
 
7
7
  ## Problem Statement
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentic-data-contracts"
3
- version = "0.2.1"
3
+ version = "0.2.3"
4
4
  description = "YAML-first data contract governance for AI agents"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -41,7 +41,7 @@ Issues = "https://github.com/flyersworder/agentic-data-contracts/issues"
41
41
  Documentation = "https://github.com/flyersworder/agentic-data-contracts/blob/main/docs/architecture.md"
42
42
 
43
43
  [project.optional-dependencies]
44
- agent-sdk = ["claude-agent-sdk"]
44
+ agent-sdk = ["claude-agent-sdk>=0.1.52"]
45
45
  agent-contracts = ["ai-agent-contracts>=0.2.0"]
46
46
  bigquery = ["google-cloud-bigquery"]
47
47
  snowflake = ["snowflake-connector-python"]
@@ -3,5 +3,11 @@
3
3
  from agentic_data_contracts.core.contract import DataContract
4
4
  from agentic_data_contracts.tools.factory import create_tools
5
5
  from agentic_data_contracts.tools.middleware import contract_middleware
6
+ from agentic_data_contracts.tools.sdk import create_sdk_mcp_server
6
7
 
7
- __all__ = ["DataContract", "create_tools", "contract_middleware"]
8
+ __all__ = [
9
+ "DataContract",
10
+ "create_tools",
11
+ "contract_middleware",
12
+ "create_sdk_mcp_server",
13
+ ]
@@ -60,6 +60,21 @@ class DataContract:
60
60
  r for r in self.schema.semantic.rules if r.enforcement == Enforcement.LOG
61
61
  ]
62
62
 
63
+ def to_sdk_config(self) -> dict[str, object]:
64
+ """Generate Claude Agent SDK configuration from contract limits.
65
+
66
+ Returns a dict of SDK options derived from contract resource/temporal
67
+ constraints, suitable for passing to ClaudeAgentOptions.
68
+ """
69
+ config: dict[str, object] = {}
70
+ res = self.schema.resources
71
+ if res:
72
+ if res.token_budget is not None:
73
+ config["task_budget"] = res.token_budget
74
+ if res.max_retries is not None:
75
+ config["max_turns"] = res.max_retries
76
+ return config
77
+
63
78
  def load_semantic_source(self) -> SemanticSource | None:
64
79
  """Auto-load the semantic source from the contract's source config.
65
80
 
@@ -0,0 +1,71 @@
1
+ """Claude Agent SDK integration — wraps ToolDefs into an SDK MCP server."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from agentic_data_contracts.adapters.base import DatabaseAdapter
8
+ from agentic_data_contracts.core.contract import DataContract
9
+ from agentic_data_contracts.core.session import ContractSession
10
+ from agentic_data_contracts.semantic.base import SemanticSource
11
+ from agentic_data_contracts.tools.factory import ToolDef, create_tools
12
+
13
+
14
+ def create_sdk_mcp_server(
15
+ contract: DataContract,
16
+ *,
17
+ adapter: DatabaseAdapter | None = None,
18
+ semantic_source: SemanticSource | None = None,
19
+ session: ContractSession | None = None,
20
+ tools: list[ToolDef] | None = None,
21
+ server_name: str = "data-contracts",
22
+ server_version: str = "1.0.0",
23
+ ) -> Any:
24
+ """Create a Claude Agent SDK MCP server from a DataContract.
25
+
26
+ Wraps all 10 contract tools with the SDK's @tool decorator and
27
+ bundles them into an MCP server ready for ClaudeAgentOptions.mcp_servers.
28
+
29
+ Args:
30
+ contract: The data contract to enforce.
31
+ adapter: Optional database adapter for query execution.
32
+ semantic_source: Optional semantic source (auto-loaded if not given).
33
+ session: Optional session for tracking enforcement state.
34
+ tools: Pre-built ToolDefs (if None, created via create_tools).
35
+ server_name: Name for the MCP server.
36
+ server_version: Version for the MCP server.
37
+
38
+ Returns:
39
+ McpSdkServerConfig ready for ClaudeAgentOptions.mcp_servers.
40
+
41
+ Raises:
42
+ ImportError: If claude-agent-sdk is not installed.
43
+ """
44
+ try:
45
+ from claude_agent_sdk import create_sdk_mcp_server as _create_server
46
+ from claude_agent_sdk import tool as sdk_tool
47
+ except ImportError:
48
+ msg = (
49
+ "claude-agent-sdk is required for SDK integration. "
50
+ "Install with: pip install agentic-data-contracts[agent-sdk]"
51
+ )
52
+ raise ImportError(msg) from None
53
+
54
+ if tools is None:
55
+ tools = create_tools(
56
+ contract,
57
+ adapter=adapter,
58
+ semantic_source=semantic_source,
59
+ session=session,
60
+ )
61
+
62
+ sdk_tools = []
63
+ for t in tools:
64
+ decorated = sdk_tool(t.name, t.description, t.input_schema)(t.callable)
65
+ sdk_tools.append(decorated)
66
+
67
+ return _create_server(
68
+ name=server_name,
69
+ version=server_version,
70
+ tools=sdk_tools,
71
+ )
@@ -0,0 +1,36 @@
1
+ """Tests for DataContract.to_sdk_config()."""
2
+
3
+ from pathlib import Path
4
+
5
+ from agentic_data_contracts.core.contract import DataContract
6
+ from agentic_data_contracts.core.schema import (
7
+ DataContractSchema,
8
+ ResourceConfig,
9
+ SemanticConfig,
10
+ )
11
+
12
+
13
+ def test_sdk_config_from_full_contract(fixtures_dir: Path) -> None:
14
+ dc = DataContract.from_yaml(fixtures_dir / "valid_contract.yml")
15
+ config = dc.to_sdk_config()
16
+ assert config["task_budget"] == 50000
17
+ assert config["max_turns"] == 3
18
+
19
+
20
+ def test_sdk_config_no_resources() -> None:
21
+ schema = DataContractSchema(name="test", semantic=SemanticConfig())
22
+ dc = DataContract(schema)
23
+ config = dc.to_sdk_config()
24
+ assert config == {}
25
+
26
+
27
+ def test_sdk_config_partial_resources() -> None:
28
+ schema = DataContractSchema(
29
+ name="test",
30
+ semantic=SemanticConfig(),
31
+ resources=ResourceConfig(token_budget=10000),
32
+ )
33
+ dc = DataContract(schema)
34
+ config = dc.to_sdk_config()
35
+ assert config["task_budget"] == 10000
36
+ assert "max_turns" not in config
@@ -0,0 +1,116 @@
1
+ """Tests for Claude Agent SDK MCP server integration."""
2
+
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+
7
+ from agentic_data_contracts.adapters.duckdb import DuckDBAdapter
8
+ from agentic_data_contracts.core.contract import DataContract
9
+ from agentic_data_contracts.core.schema import (
10
+ AllowedTable,
11
+ DataContractSchema,
12
+ SemanticConfig,
13
+ )
14
+ from agentic_data_contracts.tools.factory import create_tools
15
+ from agentic_data_contracts.tools.sdk import create_sdk_mcp_server
16
+
17
+
18
+ @pytest.fixture
19
+ def contract_no_source() -> DataContract:
20
+ """Contract without a semantic source — avoids file path issues."""
21
+ schema = DataContractSchema(
22
+ name="test",
23
+ semantic=SemanticConfig(
24
+ allowed_tables=[
25
+ AllowedTable.model_validate(
26
+ {"schema": "analytics", "tables": ["orders"]}
27
+ ),
28
+ ],
29
+ ),
30
+ )
31
+ return DataContract(schema)
32
+
33
+
34
+ @pytest.fixture
35
+ def contract_with_source(fixtures_dir: Path) -> DataContract:
36
+ """Contract with semantic source pointing to real fixture."""
37
+ from agentic_data_contracts.core.schema import (
38
+ SemanticSource as SemanticSourceConfig,
39
+ )
40
+
41
+ schema = DataContractSchema(
42
+ name="test",
43
+ semantic=SemanticConfig(
44
+ source=SemanticSourceConfig(
45
+ type="yaml",
46
+ path=str(fixtures_dir / "semantic_source.yml"),
47
+ ),
48
+ allowed_tables=[
49
+ AllowedTable.model_validate(
50
+ {"schema": "analytics", "tables": ["orders"]}
51
+ ),
52
+ ],
53
+ ),
54
+ )
55
+ return DataContract(schema)
56
+
57
+
58
+ @pytest.fixture
59
+ def adapter() -> DuckDBAdapter:
60
+ db = DuckDBAdapter(":memory:")
61
+ db.connection.execute(
62
+ """
63
+ CREATE SCHEMA IF NOT EXISTS analytics;
64
+ CREATE TABLE analytics.orders (
65
+ id INTEGER, amount DECIMAL(10,2), tenant_id VARCHAR
66
+ );
67
+ INSERT INTO analytics.orders VALUES (1, 100.00, 'acme');
68
+ """
69
+ )
70
+ return db
71
+
72
+
73
+ def test_create_sdk_mcp_server_returns_config(
74
+ contract_no_source: DataContract, adapter: DuckDBAdapter
75
+ ) -> None:
76
+ server = create_sdk_mcp_server(contract_no_source, adapter=adapter)
77
+ assert server is not None
78
+
79
+
80
+ def test_create_sdk_mcp_server_with_prebuilt_tools(
81
+ contract_no_source: DataContract, adapter: DuckDBAdapter
82
+ ) -> None:
83
+ tools = create_tools(contract_no_source, adapter=adapter)
84
+ server = create_sdk_mcp_server(contract_no_source, tools=tools)
85
+ assert server is not None
86
+
87
+
88
+ def test_create_sdk_mcp_server_with_semantic_source(
89
+ contract_with_source: DataContract, adapter: DuckDBAdapter
90
+ ) -> None:
91
+ server = create_sdk_mcp_server(contract_with_source, adapter=adapter)
92
+ assert server is not None
93
+
94
+
95
+ def test_create_sdk_mcp_server_auto_creates_tools(
96
+ contract_no_source: DataContract,
97
+ ) -> None:
98
+ server = create_sdk_mcp_server(contract_no_source)
99
+ assert server is not None
100
+
101
+
102
+ def test_create_sdk_mcp_server_custom_name(
103
+ contract_no_source: DataContract,
104
+ ) -> None:
105
+ server = create_sdk_mcp_server(
106
+ contract_no_source,
107
+ server_name="my-server",
108
+ server_version="2.0.0",
109
+ )
110
+ assert server is not None
111
+
112
+
113
+ def test_top_level_import() -> None:
114
+ from agentic_data_contracts import create_sdk_mcp_server as fn
115
+
116
+ assert fn is not None
@@ -9,7 +9,7 @@ resolution-markers = [
9
9
 
10
10
  [[package]]
11
11
  name = "agentic-data-contracts"
12
- version = "0.2.0"
12
+ version = "0.2.3"
13
13
  source = { editable = "." }
14
14
  dependencies = [
15
15
  { name = "pydantic" },
@@ -57,7 +57,7 @@ snowflake = [
57
57
  requires-dist = [
58
58
  { name = "agentic-data-contracts", extras = ["agent-sdk", "agent-contracts", "bigquery", "snowflake", "postgres", "duckdb"], marker = "extra == 'all'" },
59
59
  { name = "ai-agent-contracts", marker = "extra == 'agent-contracts'", specifier = ">=0.2.0" },
60
- { name = "claude-agent-sdk", marker = "extra == 'agent-sdk'" },
60
+ { name = "claude-agent-sdk", marker = "extra == 'agent-sdk'", specifier = ">=0.1.52" },
61
61
  { name = "duckdb", marker = "extra == 'dev'" },
62
62
  { name = "duckdb", marker = "extra == 'duckdb'" },
63
63
  { name = "google-cloud-bigquery", marker = "extra == 'bigquery'" },
@@ -412,19 +412,19 @@ wheels = [
412
412
 
413
413
  [[package]]
414
414
  name = "claude-agent-sdk"
415
- version = "0.1.50"
415
+ version = "0.1.52"
416
416
  source = { registry = "https://pypi.org/simple" }
417
417
  dependencies = [
418
418
  { name = "anyio" },
419
419
  { name = "mcp" },
420
420
  ]
421
- sdist = { url = "https://files.pythonhosted.org/packages/24/eb/42a7027a02d3827c6e49f97375a00e6da4708f81295d9afa1a0009ce4abd/claude_agent_sdk-0.1.50.tar.gz", hash = "sha256:e15157792857ecb55274a71f08981efcfda2e169bee7894cbdc245d05ac43203", size = 99070, upload-time = "2026-03-20T23:00:58.646Z" }
421
+ sdist = { url = "https://files.pythonhosted.org/packages/b1/d7/a56b7ba793918e5cc557447b25f2d428e11d6f025b6c0c7b1e6e3fa373c0/claude_agent_sdk-0.1.52.tar.gz", hash = "sha256:c27f35d850521c7cff18448b38ff0dd5e899a4aeb6de9d28c0b2a66863eaf134", size = 116267, upload-time = "2026-03-29T02:40:25.554Z" }
422
422
  wheels = [
423
- { url = "https://files.pythonhosted.org/packages/b2/97/66bc98d5026dbed68b7469a4990de71d8c40d19713e37dafacf32ba3be3b/claude_agent_sdk-0.1.50-py3-none-macosx_11_0_arm64.whl", hash = "sha256:858b1822451209b2c3ad8df27458168d29ac19fd628680853f7707ea017fea73", size = 58223299, upload-time = "2026-03-20T23:01:01.742Z" },
424
- { url = "https://files.pythonhosted.org/packages/35/0d/65dda40016faa30a63a950d48b400ad26913e8e333e418651faf04d20673/claude_agent_sdk-0.1.50-py3-none-macosx_11_0_x86_64.whl", hash = "sha256:44e75b9d076bd6030742729f99eb38777b80f052b22338d0a028d8190fc59e52", size = 61019645, upload-time = "2026-03-20T23:01:04.742Z" },
425
- { url = "https://files.pythonhosted.org/packages/ec/c0/e5c7c6b9e378553fe24bb5367caede725e274a494b6d126e719971c53b8b/claude_agent_sdk-0.1.50-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:7363d431dc6efd83fa658a045e14fa4357440352b548002bfb9096d8f04d143c", size = 74590847, upload-time = "2026-03-20T23:01:07.899Z" },
426
- { url = "https://files.pythonhosted.org/packages/3d/af/658a28cb070e0b59ac98e88411536f6f9b8d81e8ddde9a8340106b0b8b0f/claude_agent_sdk-0.1.50-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:493d8cc43f4166291606749cf47b03e822f03b7f371cc77af697564017ccf579", size = 75231505, upload-time = "2026-03-20T23:01:11.45Z" },
427
- { url = "https://files.pythonhosted.org/packages/41/44/ff1f2c137406392fa0a69e3c3ff37150267da664decddb6dee83b80ba162/claude_agent_sdk-0.1.50-py3-none-win_amd64.whl", hash = "sha256:2e44caf3e5bce56e26a18158acf3e1c2c2784cf8fa15e425afe92816c987eb1a", size = 75846174, upload-time = "2026-03-20T23:01:15.277Z" },
423
+ { url = "https://files.pythonhosted.org/packages/31/e0/6759f98c699ef5da84750b93de543a839f3e3b905b5ce20424a5033c58fa/claude_agent_sdk-0.1.52-py3-none-macosx_11_0_arm64.whl", hash = "sha256:0f15c91319c20831f881fd4b6bcec1772a3599d66da5e7c057d79945bf603e1a", size = 57872944, upload-time = "2026-03-29T02:40:28.742Z" },
424
+ { url = "https://files.pythonhosted.org/packages/cd/e8/d3c3ef7cb104d3ebb6348a82eab7574b8c0eaddb683efd3f606f3c22bc21/claude_agent_sdk-0.1.52-py3-none-macosx_11_0_x86_64.whl", hash = "sha256:f32ca2ca95e312678af63ee60a5fb1b765f98ed47825ea3ba90322ceb26736ff", size = 59615855, upload-time = "2026-03-29T02:40:31.765Z" },
425
+ { url = "https://files.pythonhosted.org/packages/f0/b7/2c4def1c5c67b9bad8966b8839d6d9da812a6458050650dbaba3526d3824/claude_agent_sdk-0.1.52-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:97c238fda13f0bea057e546895a3dc67468fc1acdbbc00d0b53a46cb3ba588dc", size = 71217617, upload-time = "2026-03-29T02:40:35.127Z" },
426
+ { url = "https://files.pythonhosted.org/packages/44/9e/4be542b58610bd74056dfed37dbdc5a12224a2fbde41a333ddbcd8255a8a/claude_agent_sdk-0.1.52-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:4cd3f2e6fd5b272b16114fbc8dcd4348cbe8615dcc1b3bea251a7d489bf83a5d", size = 71292911, upload-time = "2026-03-29T02:40:38.919Z" },
427
+ { url = "https://files.pythonhosted.org/packages/93/73/4601d43d57354bd6e664444970bd5c1de8003542745a4388cf84611c9f26/claude_agent_sdk-0.1.52-py3-none-win_amd64.whl", hash = "sha256:a8a5455d248b76c17126abee0f69d0f9870cbc0d52cb2f8ad5eb3deddb05af39", size = 73447753, upload-time = "2026-03-29T02:40:42.786Z" },
428
428
  ]
429
429
 
430
430
  [[package]]