toolschema 1.0.0__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 (89) hide show
  1. toolschema-1.0.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  2. toolschema-1.0.0/.github/ISSUE_TEMPLATE/issue.yml +32 -0
  3. toolschema-1.0.0/.github/pull_request_template.md +7 -0
  4. toolschema-1.0.0/.github/workflows/ci.yml +68 -0
  5. toolschema-1.0.0/.gitignore +18 -0
  6. toolschema-1.0.0/AGENTS.md +165 -0
  7. toolschema-1.0.0/CODE_OF_CONDUCT.md +31 -0
  8. toolschema-1.0.0/CONTRIBUTING.md +55 -0
  9. toolschema-1.0.0/LICENSE +21 -0
  10. toolschema-1.0.0/PKG-INFO +428 -0
  11. toolschema-1.0.0/README.md +377 -0
  12. toolschema-1.0.0/SECURITY.md +33 -0
  13. toolschema-1.0.0/docs/claude-desktop.md +115 -0
  14. toolschema-1.0.0/docs/pre-pep-alignment.md +32 -0
  15. toolschema-1.0.0/docs/provider-quirks.md +27 -0
  16. toolschema-1.0.0/docs/tutorials/01-getting-started.md +79 -0
  17. toolschema-1.0.0/docs/tutorials/02-mcp-server.md +107 -0
  18. toolschema-1.0.0/docs/tutorials/03-langchain-integration.md +68 -0
  19. toolschema-1.0.0/docs/tutorials/04-multi-provider-export.md +82 -0
  20. toolschema-1.0.0/docs/tutorials/README.md +16 -0
  21. toolschema-1.0.0/examples/01_basic.py +16 -0
  22. toolschema-1.0.0/examples/02_mcp_server.py +66 -0
  23. toolschema-1.0.0/examples/03_langchain.py +61 -0
  24. toolschema-1.0.0/examples/04_multi_provider.py +24 -0
  25. toolschema-1.0.0/examples/deep_agents_demo.py +84 -0
  26. toolschema-1.0.0/examples/demo_tools.py +38 -0
  27. toolschema-1.0.0/examples/verify_package.py +135 -0
  28. toolschema-1.0.0/pyproject.toml +80 -0
  29. toolschema-1.0.0/src/toolschema/__init__.py +29 -0
  30. toolschema-1.0.0/src/toolschema/__main__.py +4 -0
  31. toolschema-1.0.0/src/toolschema/_decorator.py +46 -0
  32. toolschema-1.0.0/src/toolschema/_fields.py +65 -0
  33. toolschema-1.0.0/src/toolschema/_init_scaffold.py +70 -0
  34. toolschema-1.0.0/src/toolschema/_introspect.py +93 -0
  35. toolschema-1.0.0/src/toolschema/_ir.py +61 -0
  36. toolschema-1.0.0/src/toolschema/_schema_utils.py +11 -0
  37. toolschema-1.0.0/src/toolschema/_standard.py +107 -0
  38. toolschema-1.0.0/src/toolschema/_types.py +164 -0
  39. toolschema-1.0.0/src/toolschema/_validate.py +289 -0
  40. toolschema-1.0.0/src/toolschema/adapters/__init__.py +6 -0
  41. toolschema-1.0.0/src/toolschema/adapters/_inline_refs.py +46 -0
  42. toolschema-1.0.0/src/toolschema/adapters/anthropic.py +67 -0
  43. toolschema-1.0.0/src/toolschema/adapters/gemini.py +58 -0
  44. toolschema-1.0.0/src/toolschema/adapters/mcp.py +28 -0
  45. toolschema-1.0.0/src/toolschema/adapters/openai.py +32 -0
  46. toolschema-1.0.0/src/toolschema/cli.py +193 -0
  47. toolschema-1.0.0/src/toolschema/integrations/__init__.py +21 -0
  48. toolschema-1.0.0/src/toolschema/integrations/fastmcp.py +37 -0
  49. toolschema-1.0.0/src/toolschema/integrations/langchain.py +26 -0
  50. toolschema-1.0.0/src/toolschema/integrations/openai_agents.py +79 -0
  51. toolschema-1.0.0/src/toolschema/integrations/pydantic_ai.py +44 -0
  52. toolschema-1.0.0/src/toolschema/templates/__init__.py +0 -0
  53. toolschema-1.0.0/src/toolschema/templates/mcp_server/README.md +47 -0
  54. toolschema-1.0.0/src/toolschema/templates/mcp_server/claude_desktop_config.example.json +9 -0
  55. toolschema-1.0.0/src/toolschema/templates/mcp_server/pyproject.toml +16 -0
  56. toolschema-1.0.0/src/toolschema/templates/mcp_server/src/PACKAGE/__init__.py +1 -0
  57. toolschema-1.0.0/src/toolschema/templates/mcp_server/src/PACKAGE/__main__.py +50 -0
  58. toolschema-1.0.0/src/toolschema/templates/mcp_server/src/PACKAGE/tools.py +19 -0
  59. toolschema-1.0.0/tests/complex_fixtures.py +62 -0
  60. toolschema-1.0.0/tests/deep_harness.py +255 -0
  61. toolschema-1.0.0/tests/deep_mcp_server.py +21 -0
  62. toolschema-1.0.0/tests/fixtures.py +11 -0
  63. toolschema-1.0.0/tests/snapshots/add_anthropic.json +20 -0
  64. toolschema-1.0.0/tests/snapshots/add_canonical.json +24 -0
  65. toolschema-1.0.0/tests/snapshots/add_gemini.json +20 -0
  66. toolschema-1.0.0/tests/snapshots/add_mcp.json +23 -0
  67. toolschema-1.0.0/tests/snapshots/add_openai.json +23 -0
  68. toolschema-1.0.0/tests/snapshots/add_openai_strict.json +24 -0
  69. toolschema-1.0.0/tests/snapshots/search_github_anthropic.json +24 -0
  70. toolschema-1.0.0/tests/snapshots/search_github_canonical.json +31 -0
  71. toolschema-1.0.0/tests/snapshots/search_github_gemini.json +24 -0
  72. toolschema-1.0.0/tests/snapshots/search_github_mcp.json +30 -0
  73. toolschema-1.0.0/tests/snapshots/search_github_openai.json +27 -0
  74. toolschema-1.0.0/tests/snapshots/search_github_openai_strict.json +28 -0
  75. toolschema-1.0.0/tests/snapshots/search_products_mcp.json +104 -0
  76. toolschema-1.0.0/tests/test_adapters.py +97 -0
  77. toolschema-1.0.0/tests/test_bootstrap.py +5 -0
  78. toolschema-1.0.0/tests/test_cli.py +82 -0
  79. toolschema-1.0.0/tests/test_complex_e2e.py +169 -0
  80. toolschema-1.0.0/tests/test_core.py +156 -0
  81. toolschema-1.0.0/tests/test_deep_agents.py +105 -0
  82. toolschema-1.0.0/tests/test_init.py +64 -0
  83. toolschema-1.0.0/tests/test_integrations.py +83 -0
  84. toolschema-1.0.0/tests/test_mcp_smoke.py +85 -0
  85. toolschema-1.0.0/tests/test_parity.py +159 -0
  86. toolschema-1.0.0/tests/test_standard.py +47 -0
  87. toolschema-1.0.0/tests/test_types_extended.py +82 -0
  88. toolschema-1.0.0/tests/test_validate.py +52 -0
  89. toolschema-1.0.0/uv.lock +3490 -0
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Discussions & questions
4
+ url: https://github.com/false200/toolschema/issues
5
+ about: Open an issue with a clear title and description.
@@ -0,0 +1,32 @@
1
+ name: Issue
2
+ description: Report a bug or request a feature
3
+ title: "[Issue]: "
4
+ labels: []
5
+ body:
6
+ - type: input
7
+ id: title_summary
8
+ attributes:
9
+ label: Title
10
+ description: Short summary of the issue (also edit the issue title above).
11
+ placeholder: "MCP adapter leaves $ref in inputSchema"
12
+ validations:
13
+ required: true
14
+
15
+ - type: textarea
16
+ id: description
17
+ attributes:
18
+ label: Description
19
+ description: What happened, what you expected, and steps to reproduce (if applicable).
20
+ placeholder: |
21
+ ## What happened
22
+
23
+ ## What you expected
24
+
25
+ ## Steps to reproduce
26
+
27
+ ## Environment
28
+ - Python version:
29
+ - toolschema version:
30
+ - Integration (FastMCP / LangChain / etc.):
31
+ validations:
32
+ required: true
@@ -0,0 +1,7 @@
1
+ ## Title
2
+
3
+ <!-- Short summary of the change (also edit the PR title above) -->
4
+
5
+ ## Description
6
+
7
+ <!-- What changed, why, and how you tested it -->
@@ -0,0 +1,68 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.10", "3.12"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v5
19
+ with:
20
+ version: "latest"
21
+
22
+ - name: Set up Python
23
+ run: uv python install ${{ matrix.python-version }}
24
+
25
+ - name: Install dependencies
26
+ run: uv sync --extra dev
27
+
28
+ - name: Ruff check
29
+ run: uv run ruff check src tests
30
+
31
+ - name: Pytest
32
+ run: uv run pytest -v
33
+
34
+ integration:
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+
39
+ - name: Install uv
40
+ uses: astral-sh/setup-uv@v5
41
+ with:
42
+ version: "latest"
43
+
44
+ - name: Set up Python
45
+ run: uv python install 3.12
46
+
47
+ - name: Install dependencies with integration extras
48
+ run: uv sync --extra dev --extra fastmcp --extra langchain --extra openai-agents --extra pydantic-ai
49
+
50
+ - name: Ruff check
51
+ run: uv run ruff check src tests
52
+
53
+ - name: Integration, MCP smoke, parity, and deep agent tests
54
+ run: uv run pytest -v tests/test_integrations.py tests/test_parity.py tests/test_mcp_smoke.py tests/test_init.py tests/test_deep_agents.py
55
+
56
+ - name: Example smoke checks
57
+ run: |
58
+ uv run python examples/02_mcp_server.py --check
59
+ uv run python examples/03_langchain.py
60
+ uv run python examples/deep_agents_demo.py
61
+
62
+ - name: Init scaffold smoke
63
+ run: |
64
+ uv run toolschema init ci-smoke-test --path /tmp
65
+ cd /tmp/ci-smoke-test
66
+ uv add --editable "${{ github.workspace }}[fastmcp]"
67
+ uv sync
68
+ uv run python -m ci_smoke_test --check
@@ -0,0 +1,18 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .coverage
8
+ htmlcov/
9
+ dist/
10
+ build/
11
+ *.egg-info/
12
+ .eggs/
13
+ *.egg
14
+ .mypy_cache/
15
+ .DS_Store
16
+ Thumbs.db
17
+ .idea/
18
+ .vscode/
@@ -0,0 +1,165 @@
1
+ # AGENTS.md — Instructions for AI coding agents
2
+
3
+ This file tells automated agents (Cursor, Claude Code, Copilot, etc.) **how to implement `toolschema`** without breaking design intent.
4
+
5
+ ## Mission
6
+
7
+ Build **Layer 1 only**: `(Python function + type hints) → canonical JSON Schema → provider-specific adapters`.
8
+
9
+ Do **not** build agent orchestration, MCP transport, or replace Pydantic validation.
10
+
11
+ ## Read first
12
+
13
+ 1. [README.md](./README.md) — full problem, architecture, build plan
14
+ 2. [Pre-PEP thread](https://discuss.python.org/t/pre-pep-discussion-typing-tool-inspect-tool-schema-close-the-zod-gap-for-python-agent-dev/107431) — target API shape
15
+
16
+ ## Hard rules
17
+
18
+ | Rule | Reason |
19
+ |------|--------|
20
+ | Core package MUST NOT import FastMCP, LangChain, OpenAI SDK | Zero framework lock-in |
21
+ | All provider output goes through `ToolDefinition` IR | Single source of truth |
22
+ | JSON Schema 2020-12 is canonical internal dialect | Pre-PEP alignment |
23
+ | MCP adapter defaults `inline_refs=True` | Claude Desktop / Copilot break on `$ref` |
24
+ | Every type mapping needs a unit test | Schema bugs break agents silently |
25
+ | Golden snapshot tests for each adapter | Prevent regressions |
26
+ | Match Pre-PEP API: `schema(fn)`, `@tool` | Future stdlib migration |
27
+
28
+ ## Implementation order
29
+
30
+ ```
31
+ Phase 0: pyproject.toml, CI, empty package
32
+ Phase 1: _introspect.py, _types.py, _ir.py, @tool, schema()
33
+ Phase 2: adapters/openai.py, adapters/mcp.py
34
+ Phase 3: cli.py inspect command
35
+ Phase 4: integrations/* (optional extras)
36
+ Phase 5: PyPI, examples, docs
37
+ ```
38
+
39
+ **Do not start Phase 4 before Phase 1–2 tests pass.**
40
+
41
+ ## Key types
42
+
43
+ ```python
44
+ # src/toolschema/_ir.py
45
+ @dataclass(frozen=True)
46
+ class ToolDefinition:
47
+ name: str
48
+ description: str
49
+ parameters: dict[str, Any]
50
+ output: dict[str, Any] | None = None
51
+
52
+ def to_json_schema(self) -> dict: ...
53
+ def to_openai(self, *, strict: bool = False) -> dict: ...
54
+ def to_mcp(self, *, inline_refs: bool = True) -> dict: ...
55
+ def to_anthropic(self) -> dict: ...
56
+ def to_gemini(self) -> dict: ...
57
+ ```
58
+
59
+ ## Type → JSON Schema mapping (Phase 1)
60
+
61
+ | Python | JSON Schema |
62
+ |--------|-------------|
63
+ | `str` | `{"type": "string"}` |
64
+ | `int` | `{"type": "integer"}` |
65
+ | `float` | `{"type": "number"}` |
66
+ | `bool` | `{"type": "boolean"}` |
67
+ | `T \| None` | `{"anyOf": [schema(T), {"type": "null"}]}` |
68
+ | `list[T]` | `{"type": "array", "items": schema(T)}` |
69
+ | `dict[str, T]` | `{"type": "object", "additionalProperties": schema(T)}` |
70
+ | `Literal["a"]` | `{"enum": ["a"]}` |
71
+ | default value | `"default"` key; omit from `"required"` |
72
+
73
+ ## Annotated / Field
74
+
75
+ ```python
76
+ Annotated[str, Field(description="...", min_length=1)]
77
+ # → {"type": "string", "description": "...", "minLength": 1}
78
+ ```
79
+
80
+ Support plain string in Annotated as shorthand (Pre-PEP + Claude SDK pattern):
81
+
82
+ ```python
83
+ Annotated[str, "City name"] # → description only
84
+ ```
85
+
86
+ ## OpenAI strict adapter
87
+
88
+ When `strict=True`:
89
+
90
+ - Set `"additionalProperties": false` on parameters object
91
+ - Every property key must appear in `"required"`
92
+
93
+ ## MCP adapter
94
+
95
+ Output shape:
96
+
97
+ ```json
98
+ {
99
+ "name": "...",
100
+ "description": "...",
101
+ "inputSchema": { "type": "object", ... },
102
+ "outputSchema": { ... }
103
+ }
104
+ ```
105
+
106
+ Run `$ref` inlining before return if `inline_refs=True`.
107
+
108
+ ## Test fixtures
109
+
110
+ Create `tests/fixtures.py`:
111
+
112
+ ```python
113
+ def add(a: int, b: int = 1) -> int:
114
+ """Add two numbers."""
115
+ return a + b
116
+
117
+ def search_github(repo: str, query: str, limit: int = 10) -> list[dict]:
118
+ """Search issues in a GitHub repository."""
119
+ ...
120
+ ```
121
+
122
+ Use these in all snapshot tests.
123
+
124
+ ## Commands
125
+
126
+ ```bash
127
+ uv sync
128
+ uv run pytest -v
129
+ uv run ruff check src tests
130
+ uv run ruff format src tests
131
+ ```
132
+
133
+ ## What NOT to do
134
+
135
+ - ❌ Add LangChain import to `src/toolschema/_types.py`
136
+ - ❌ Generate schema separately in each adapter (use IR only)
137
+ - ❌ Full Pydantic validation in core (thin `validate()` optional in Phase 2+)
138
+ - ❌ Support every Python type in MVP (defer ParamSpec, generics)
139
+ - ❌ Change golden snapshots without explaining in PR
140
+
141
+ ## Success definition
142
+
143
+ An agent can run:
144
+
145
+ ```python
146
+ from toolschema import tool, schema
147
+
148
+ @tool
149
+ def greet(name: str) -> str:
150
+ """Say hello."""
151
+ return f"Hello, {name}"
152
+
153
+ assert schema(greet).to_mcp()["name"] == "greet"
154
+ assert "name" in schema(greet).to_openai()["function"]["parameters"]["properties"]
155
+ ```
156
+
157
+ And:
158
+
159
+ ```bash
160
+ uv run pytest # all green
161
+ ```
162
+
163
+ ## Questions?
164
+
165
+ Open a GitHub issue with label `design` before large architectural changes.
@@ -0,0 +1,31 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to a positive environment:
10
+
11
+ - Using welcoming and inclusive language
12
+ - Being respectful of differing viewpoints and experiences
13
+ - Gracefully accepting constructive criticism
14
+ - Focusing on what is best for the community
15
+ - Showing empathy toward other community members
16
+
17
+ Examples of unacceptable behavior:
18
+
19
+ - The use of sexualized language or imagery, and sexual attention or advances of any kind
20
+ - Trolling, insulting or derogatory comments, and personal or political attacks
21
+ - Public or private harassment
22
+ - Publishing others' private information without explicit permission
23
+ - Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Enforcement
26
+
27
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the maintainers via [GitHub Issues](https://github.com/false200/toolschema/issues). All complaints will be reviewed and investigated promptly and fairly.
28
+
29
+ ## Attribution
30
+
31
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,55 @@
1
+ # Contributing to toolschema
2
+
3
+ Thanks for helping improve toolschema. PRs and issues are welcome.
4
+
5
+ ## Before you start
6
+
7
+ 1. Read [README.md](README.md) for scope and API overview.
8
+ 2. Read [AGENTS.md](AGENTS.md) if you use an AI coding agent — it defines hard design rules.
9
+ 3. Search [existing issues](https://github.com/false200/toolschema/issues) to avoid duplicate work.
10
+
11
+ ## Development setup
12
+
13
+ ```sh
14
+ git clone https://github.com/false200/toolschema.git
15
+ cd toolschema
16
+ uv sync --extra dev --extra fastmcp --extra langchain --extra openai-agents --extra pydantic-ai
17
+ ```
18
+
19
+ ## Making changes
20
+
21
+ 1. Fork the repo and create a branch from `main`.
22
+ 2. Make focused changes — one feature or fix per PR.
23
+ 3. Add or update tests for behavior you change.
24
+ 4. Run checks before opening a PR:
25
+
26
+ ```sh
27
+ uv run pytest -v
28
+ uv run ruff check src tests
29
+ uv run ruff format src tests
30
+ ```
31
+
32
+ 5. If adapter output changes intentionally, update golden snapshots in `tests/snapshots/` and explain why in the PR.
33
+
34
+ ## Design rules (summary)
35
+
36
+ - **Layer 1 only** — schema generation, not agent orchestration.
37
+ - **No framework imports in core** — FastMCP, LangChain, OpenAI SDK belong in `integrations/` only.
38
+ - **Single IR** — all adapters read from `ToolDefinition`; never regenerate schema in an adapter.
39
+ - **MCP defaults** — `inline_refs=True` for Claude Desktop / Copilot compatibility.
40
+
41
+ ## Pull requests
42
+
43
+ Use the [pull request template](.github/pull_request_template.md). Keep PRs small and describe:
44
+
45
+ - What changed
46
+ - Why it changed
47
+ - How you tested it
48
+
49
+ ## Issues
50
+
51
+ Use the [issue template](.github/ISSUE_TEMPLATE/issue.yml). A clear title and short description is enough to get started.
52
+
53
+ ## License
54
+
55
+ By contributing, you agree that your contributions will be licensed under the [MIT License](LICENSE).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 toolschema contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.