stata-code 0.6.4__tar.gz → 0.6.5__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.
- {stata_code-0.6.4 → stata_code-0.6.5}/CHANGELOG.md +10 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/PKG-INFO +14 -1
- {stata_code-0.6.4 → stata_code-0.6.5}/README.md +13 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/pyproject.toml +1 -1
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/__init__.py +1 -1
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/mcp/server.py +1 -21
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_mcp.py +18 -15
- {stata_code-0.6.4 → stata_code-0.6.5}/.gitignore +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/LICENSE +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/LICENSE-POLICY.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/PUBLISHING.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/SCHEMA.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/docs/design/hard_timeout.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/examples/01-basic-regression.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/examples/02-did-card-krueger.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/examples/03-graphs.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/examples/04-multi-session.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/examples/05-large-matrix.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/examples/README.md +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/schema/run_result.schema.json +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/scripts/check_versions.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/scripts/export_schema.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/__init__.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/_pool.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/_refs.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/_runtime.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/errors.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/log_artifacts.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/notebook.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/run_index.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/runner.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/core/schema.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/kernel/__init__.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/kernel/__main__.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/kernel/assets/logo-32x32.png +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/kernel/assets/logo-64x64.png +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/kernel/assets/logo-svg.svg +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/kernel/kernel.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/mcp/__init__.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/stata_code/mcp/__main__.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/__init__.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/conftest.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/fixtures/.gitkeep +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_cancel.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_errors.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_kernel.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_log_artifacts.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_mcp_stdio.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_notebook.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_notebook_phase2.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_pool.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_public_api.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_run_index.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_runner.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_runtime_discovery.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_schema.py +0 -0
- {stata_code-0.6.4 → stata_code-0.6.5}/tests/test_schema_artifact.py +0 -0
|
@@ -6,6 +6,16 @@ to semver-major.minor for the result schema (see `SCHEMA.md` §6).
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.6.5 — 2026-05-22
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **OpenAI tool-schema compatibility.** `notebook_locate` and
|
|
14
|
+
`notebook_insert_cell` no longer advertise top-level `oneOf` constraints in
|
|
15
|
+
their MCP input schemas. OpenAI rejects those schemas during tool
|
|
16
|
+
registration, while the server-side runtime guards still enforce the
|
|
17
|
+
"exactly one query/anchor" rules.
|
|
18
|
+
|
|
9
19
|
## 0.6.4 — 2026-05-21
|
|
10
20
|
|
|
11
21
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stata-code
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.5
|
|
4
4
|
Summary: Agent-native Stata bridge — one core, multiple frontends (MCP, Jupyter, VSCode)
|
|
5
5
|
Project-URL: Homepage, https://github.com/brycewang-stanford/stata-code
|
|
6
6
|
Project-URL: Repository, https://github.com/brycewang-stanford/stata-code
|
|
@@ -263,6 +263,19 @@ When `stata-code-mcp` lives inside a project virtualenv (recommended for reprodu
|
|
|
263
263
|
|
|
264
264
|
For `uvx`-only setups, set `"command": "uvx"` and `"args": ["--from", "stata-code", "stata-code-mcp"]`.
|
|
265
265
|
|
|
266
|
+
#### MCP troubleshooting
|
|
267
|
+
|
|
268
|
+
If `stata_run` reports `adapter_crash` with `worker emitted non-JSON: '\n'`,
|
|
269
|
+
upgrade to `stata-code>=0.6.4`, then restart the MCP client so it launches a
|
|
270
|
+
fresh server process. Also check that the client is resolving the expected
|
|
271
|
+
`stata-code-mcp` binary; project virtualenv installs should use the absolute
|
|
272
|
+
`.venv/bin/stata-code-mcp` path instead of relying on a global `PATH` entry.
|
|
273
|
+
|
|
274
|
+
If an OpenAI-backed client reports `API Error: 400 Invalid schema for function
|
|
275
|
+
'mcp__stata-code__notebook_insert_cell'` and mentions a top-level `oneOf`,
|
|
276
|
+
upgrade to `stata-code>=0.6.5`, then restart the MCP client. Older server
|
|
277
|
+
processes keep advertising the stale schema until they are restarted.
|
|
278
|
+
|
|
266
279
|
The MCP server registers 15 tools:
|
|
267
280
|
|
|
268
281
|
| Tool | Purpose |
|
|
@@ -224,6 +224,19 @@ When `stata-code-mcp` lives inside a project virtualenv (recommended for reprodu
|
|
|
224
224
|
|
|
225
225
|
For `uvx`-only setups, set `"command": "uvx"` and `"args": ["--from", "stata-code", "stata-code-mcp"]`.
|
|
226
226
|
|
|
227
|
+
#### MCP troubleshooting
|
|
228
|
+
|
|
229
|
+
If `stata_run` reports `adapter_crash` with `worker emitted non-JSON: '\n'`,
|
|
230
|
+
upgrade to `stata-code>=0.6.4`, then restart the MCP client so it launches a
|
|
231
|
+
fresh server process. Also check that the client is resolving the expected
|
|
232
|
+
`stata-code-mcp` binary; project virtualenv installs should use the absolute
|
|
233
|
+
`.venv/bin/stata-code-mcp` path instead of relying on a global `PATH` entry.
|
|
234
|
+
|
|
235
|
+
If an OpenAI-backed client reports `API Error: 400 Invalid schema for function
|
|
236
|
+
'mcp__stata-code__notebook_insert_cell'` and mentions a top-level `oneOf`,
|
|
237
|
+
upgrade to `stata-code>=0.6.5`, then restart the MCP client. Older server
|
|
238
|
+
processes keep advertising the stale schema until they are restarted.
|
|
239
|
+
|
|
227
240
|
The MCP server registers 15 tools:
|
|
228
241
|
|
|
229
242
|
| Tool | Purpose |
|
|
@@ -95,7 +95,7 @@ from stata_code.core.runner import (
|
|
|
95
95
|
)
|
|
96
96
|
from stata_code.core.schema import RunResult
|
|
97
97
|
|
|
98
|
-
__version__ = "0.6.
|
|
98
|
+
__version__ = "0.6.5"
|
|
99
99
|
|
|
100
100
|
SERVER_INSTRUCTIONS = (
|
|
101
101
|
"Use stata-code for running and inspecting Stata code. Prefer structuredContent "
|
|
@@ -894,15 +894,6 @@ def _tool_definitions() -> list[Tool]:
|
|
|
894
894
|
},
|
|
895
895
|
},
|
|
896
896
|
"required": ["path"],
|
|
897
|
-
# Schema-level expression of the "exactly one of snippet /
|
|
898
|
-
# regex / error_text" rule. The runtime guard in
|
|
899
|
-
# notebook.locate_cells still enforces this for clients that
|
|
900
|
-
# don't validate inputs against the schema.
|
|
901
|
-
"oneOf": [
|
|
902
|
-
{"required": ["snippet"]},
|
|
903
|
-
{"required": ["regex"]},
|
|
904
|
-
{"required": ["error_text"]},
|
|
905
|
-
],
|
|
906
897
|
},
|
|
907
898
|
outputSchema=_NOTEBOOK_LOCATE_OUTPUT_SCHEMA,
|
|
908
899
|
annotations=ToolAnnotations(
|
|
@@ -989,17 +980,6 @@ def _tool_definitions() -> list[Tool]:
|
|
|
989
980
|
"at_end": {"type": "boolean"},
|
|
990
981
|
},
|
|
991
982
|
"required": ["path", "source"],
|
|
992
|
-
# Exactly one anchor must be present. Booleans for
|
|
993
|
-
# at_start/at_end must additionally be `true` to count as
|
|
994
|
-
# "specified" — the JSON Schema below treats them as
|
|
995
|
-
# required-presence; the runtime guard in
|
|
996
|
-
# notebook.insert_cell additionally rejects the false-y form.
|
|
997
|
-
"oneOf": [
|
|
998
|
-
{"required": ["after_cell_id"]},
|
|
999
|
-
{"required": ["before_cell_id"]},
|
|
1000
|
-
{"required": ["at_start"]},
|
|
1001
|
-
{"required": ["at_end"]},
|
|
1002
|
-
],
|
|
1003
983
|
},
|
|
1004
984
|
outputSchema=_NOTEBOOK_INSERT_OUTPUT_SCHEMA,
|
|
1005
985
|
annotations=ToolAnnotations(
|
|
@@ -87,30 +87,33 @@ class TestToolRegistry:
|
|
|
87
87
|
assert gg.annotations is not None
|
|
88
88
|
assert gg.annotations.readOnlyHint is True
|
|
89
89
|
|
|
90
|
-
def
|
|
90
|
+
def test_tool_input_schemas_avoid_openai_forbidden_top_level_keywords(self):
|
|
91
|
+
from stata_code.mcp.server import _tool_definitions
|
|
92
|
+
|
|
93
|
+
forbidden = {"oneOf", "anyOf", "allOf", "enum", "not"}
|
|
94
|
+
for tool in _tool_definitions():
|
|
95
|
+
schema = tool.inputSchema
|
|
96
|
+
assert schema is not None
|
|
97
|
+
assert schema.get("type") == "object"
|
|
98
|
+
assert forbidden.isdisjoint(schema), tool.name
|
|
99
|
+
|
|
100
|
+
def test_notebook_locate_schema_keeps_query_fields_optional(self):
|
|
91
101
|
from stata_code.mcp.server import _tool_definitions
|
|
92
102
|
|
|
93
103
|
loc = next(t for t in _tool_definitions() if t.name == "notebook_locate")
|
|
94
104
|
schema = loc.inputSchema
|
|
95
|
-
assert "
|
|
96
|
-
|
|
97
|
-
assert ("snippet",) in required_sets
|
|
98
|
-
assert ("regex",) in required_sets
|
|
99
|
-
assert ("error_text",) in required_sets
|
|
105
|
+
assert schema["required"] == ["path"]
|
|
106
|
+
assert {"snippet", "regex", "error_text"} <= set(schema["properties"])
|
|
100
107
|
|
|
101
|
-
def
|
|
108
|
+
def test_notebook_insert_cell_schema_keeps_anchor_fields_optional(self):
|
|
102
109
|
from stata_code.mcp.server import _tool_definitions
|
|
103
110
|
|
|
104
111
|
ins = next(t for t in _tool_definitions() if t.name == "notebook_insert_cell")
|
|
105
112
|
schema = ins.inputSchema
|
|
106
|
-
assert "
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
("before_cell_id",),
|
|
111
|
-
("at_start",),
|
|
112
|
-
("at_end",),
|
|
113
|
-
}
|
|
113
|
+
assert schema["required"] == ["path", "source"]
|
|
114
|
+
assert {"after_cell_id", "before_cell_id", "at_start", "at_end"} <= set(
|
|
115
|
+
schema["properties"]
|
|
116
|
+
)
|
|
114
117
|
|
|
115
118
|
def test_resource_templates_include_ref_shapes(self):
|
|
116
119
|
from stata_code.mcp.server import _resource_templates
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|