stackone-ai 0.3.1__tar.gz → 0.3.2__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.
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.github/workflows/lint.yml +11 -3
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.github/workflows/test.yml +12 -2
- stackone_ai-0.3.2/.release-please-manifest.json +3 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/CHANGELOG.md +7 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/PKG-INFO +34 -5
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/README.md +23 -1
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/pyproject.toml +15 -6
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/__init__.py +1 -1
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/meta_tools.py +2 -1
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/models.py +31 -22
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/server.py +23 -8
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/specs/parser.py +4 -1
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/toolset.py +3 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/uv.lock +1365 -247
- stackone_ai-0.3.1/.release-please-manifest.json +0 -3
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.cursor/rules/cursor-rules-location.mdc +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.cursor/rules/examples-standards.mdc +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.cursor/rules/no-relative-imports.mdc +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.cursor/rules/package-installation.mdc +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.cursor/rules/release-please-standards.mdc +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.cursor/rules/uv-scripts.mdc +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.env_example +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.github/workflows/docs.yml +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.github/workflows/release.yml +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.gitignore +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.mcp.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.pre-commit-config.yaml +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.release-please-config.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/.vscode/settings.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/CLAUDE.md +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/LICENSE +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/Makefile +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/available_tools.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/crewai_integration.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/custom_base_url.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/error_handling.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/file_uploads.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/index.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/langchain_integration.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/langgraph_tool_node.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/mcp_server.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/meta_tools_example.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/openai_integration.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/stackone_account_ids.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/examples/test_examples.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/mkdocs.yml +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/py.typed +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/scripts/build_docs.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/scripts/pull_oas.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/scripts/update_version.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/constants.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/ats.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/core.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/crm.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/documents.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/hris.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/iam.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/lms.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/oas/marketing.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/py.typed +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/stackone_ai/specs/loader.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/ats_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/core_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/crm_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/documents_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/hris_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/iam_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/lms_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/snapshots/test_parser/test_parse_all_oas_specs/marketing_tools.json +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/test_meta_tools.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/test_models.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/test_parser.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/test_tool_calling.py +0 -0
- {stackone_ai-0.3.1 → stackone_ai-0.3.2}/tests/test_toolset.py +0 -0
|
@@ -8,17 +8,25 @@ on:
|
|
|
8
8
|
jobs:
|
|
9
9
|
lint:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.9", "3.10"]
|
|
14
|
+
include:
|
|
15
|
+
- python-version: "3.9"
|
|
16
|
+
sync-extras: "--all-extras --no-extra mcp"
|
|
17
|
+
- python-version: "3.10"
|
|
18
|
+
sync-extras: "--all-extras"
|
|
11
19
|
steps:
|
|
12
20
|
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
13
21
|
|
|
14
22
|
- name: Install uv
|
|
15
23
|
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
|
16
24
|
with:
|
|
17
|
-
python-version:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
18
26
|
enable-cache: true
|
|
19
27
|
|
|
20
28
|
- name: Install dependencies
|
|
21
|
-
run: uv sync
|
|
29
|
+
run: uv sync ${{ matrix.sync-extras }}
|
|
22
30
|
|
|
23
31
|
- name: Run Ruff
|
|
24
32
|
uses: astral-sh/ruff-action@0c50076f12c38c3d0115b7b519b54a91cb9cf0ad # v3.5.0
|
|
@@ -26,4 +34,4 @@ jobs:
|
|
|
26
34
|
args: check .
|
|
27
35
|
|
|
28
36
|
- name: Run Mypy
|
|
29
|
-
run: uv run mypy stackone_ai
|
|
37
|
+
run: uv run mypy stackone_ai --exclude stackone_ai/server.py
|
|
@@ -8,6 +8,16 @@ on:
|
|
|
8
8
|
jobs:
|
|
9
9
|
test:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.9", "3.10", "3.13"]
|
|
14
|
+
include:
|
|
15
|
+
- python-version: "3.9"
|
|
16
|
+
test-extras: "--all-extras --no-extra mcp"
|
|
17
|
+
- python-version: "3.10"
|
|
18
|
+
test-extras: "--all-extras"
|
|
19
|
+
- python-version: "3.13"
|
|
20
|
+
test-extras: "--all-extras"
|
|
11
21
|
env:
|
|
12
22
|
STACKONE_API_KEY: ${{ secrets.STACKONE_API_KEY }}
|
|
13
23
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
@@ -17,11 +27,11 @@ jobs:
|
|
|
17
27
|
- name: Install uv
|
|
18
28
|
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
|
19
29
|
with:
|
|
20
|
-
python-version:
|
|
30
|
+
python-version: ${{ matrix.python-version }}
|
|
21
31
|
enable-cache: true
|
|
22
32
|
|
|
23
33
|
- name: Install dependencies
|
|
24
|
-
run: uv sync
|
|
34
|
+
run: uv sync ${{ matrix.test-extras }}
|
|
25
35
|
|
|
26
36
|
- name: Run tests
|
|
27
37
|
run: uv run pytest
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.2](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v0.3.1...stackone-ai-v0.3.2) (2025-08-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* support Python 3.9+ with optional MCP server support ([#28](https://github.com/StackOneHQ/stackone-ai-python/issues/28)) ([1a37776](https://github.com/StackOneHQ/stackone-ai-python/commit/1a377768c15223e25dbaf1e0bcd0c0e8bb0df2e8))
|
|
9
|
+
|
|
3
10
|
## [0.3.1](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v0.3.0...stackone-ai-v0.3.1) (2025-08-19)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stackone-ai
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: agents performing actions on your SaaS
|
|
5
5
|
Author-email: StackOne <support@stackone.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -8,24 +8,31 @@ Classifier: Development Status :: 4 - Beta
|
|
|
8
8
|
Classifier: Intended Audience :: Developers
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
16
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
|
-
Requires-Python: >=3.
|
|
17
|
+
Requires-Python: >=3.9
|
|
14
18
|
Requires-Dist: bm25s>=0.2.2
|
|
19
|
+
Requires-Dist: eval-type-backport; python_version < '3.10'
|
|
15
20
|
Requires-Dist: langchain-core>=0.1.0
|
|
16
|
-
Requires-Dist: mcp[cli]>=1.3.0
|
|
17
21
|
Requires-Dist: numpy>=1.24.0
|
|
18
22
|
Requires-Dist: pydantic>=2.10.6
|
|
19
23
|
Requires-Dist: requests>=2.32.3
|
|
24
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
20
25
|
Provides-Extra: docs
|
|
21
26
|
Requires-Dist: mkdocs-terminal>=4.7.0; extra == 'docs'
|
|
22
27
|
Requires-Dist: pygments>=2.12; extra == 'docs'
|
|
23
28
|
Requires-Dist: pymdown-extensions; extra == 'docs'
|
|
24
29
|
Provides-Extra: examples
|
|
25
|
-
Requires-Dist: crewai>=0.102.0; extra == 'examples'
|
|
30
|
+
Requires-Dist: crewai>=0.102.0; (python_version >= '3.10') and extra == 'examples'
|
|
26
31
|
Requires-Dist: langchain-openai>=0.3.6; extra == 'examples'
|
|
27
32
|
Requires-Dist: openai>=1.63.2; extra == 'examples'
|
|
28
33
|
Requires-Dist: python-dotenv>=1.0.1; extra == 'examples'
|
|
34
|
+
Provides-Extra: mcp
|
|
35
|
+
Requires-Dist: mcp[cli]>=1.3.0; (python_version >= '3.10') and extra == 'mcp'
|
|
29
36
|
Description-Content-Type: text/markdown
|
|
30
37
|
|
|
31
38
|
# StackOne AI SDK
|
|
@@ -48,12 +55,32 @@ StackOne AI provides a unified interface for accessing various SaaS tools throug
|
|
|
48
55
|
- CrewAI Tools
|
|
49
56
|
- LangGraph Tool Node
|
|
50
57
|
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- Python 3.9+ (core SDK functionality)
|
|
61
|
+
- Python 3.10+ (for MCP server and CrewAI examples)
|
|
62
|
+
|
|
51
63
|
## Installation
|
|
52
64
|
|
|
65
|
+
### Basic Installation
|
|
66
|
+
|
|
53
67
|
```bash
|
|
54
68
|
pip install stackone-ai
|
|
55
69
|
```
|
|
56
70
|
|
|
71
|
+
### Optional Features
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Install with MCP server support (requires Python 3.10+)
|
|
75
|
+
pip install 'stackone-ai[mcp]'
|
|
76
|
+
|
|
77
|
+
# Install with CrewAI examples (requires Python 3.10+)
|
|
78
|
+
pip install 'stackone-ai[examples]'
|
|
79
|
+
|
|
80
|
+
# Install everything
|
|
81
|
+
pip install 'stackone-ai[mcp,examples]'
|
|
82
|
+
```
|
|
83
|
+
|
|
57
84
|
## Quick Start
|
|
58
85
|
|
|
59
86
|
```python
|
|
@@ -112,10 +139,12 @@ for tool_call in response.tool_calls:
|
|
|
112
139
|
</details>
|
|
113
140
|
|
|
114
141
|
<details>
|
|
115
|
-
<summary>CrewAI Integration</summary>
|
|
142
|
+
<summary>CrewAI Integration (Python 3.10+)</summary>
|
|
116
143
|
|
|
117
144
|
CrewAI uses LangChain tools natively, making integration seamless:
|
|
118
145
|
|
|
146
|
+
> **Note**: CrewAI requires Python 3.10+. Install with `pip install 'stackone-ai[examples]'`
|
|
147
|
+
|
|
119
148
|
```python
|
|
120
149
|
from crewai import Agent, Crew, Task
|
|
121
150
|
from stackone_ai import StackOneToolSet
|
|
@@ -18,12 +18,32 @@ StackOne AI provides a unified interface for accessing various SaaS tools throug
|
|
|
18
18
|
- CrewAI Tools
|
|
19
19
|
- LangGraph Tool Node
|
|
20
20
|
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
- Python 3.9+ (core SDK functionality)
|
|
24
|
+
- Python 3.10+ (for MCP server and CrewAI examples)
|
|
25
|
+
|
|
21
26
|
## Installation
|
|
22
27
|
|
|
28
|
+
### Basic Installation
|
|
29
|
+
|
|
23
30
|
```bash
|
|
24
31
|
pip install stackone-ai
|
|
25
32
|
```
|
|
26
33
|
|
|
34
|
+
### Optional Features
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Install with MCP server support (requires Python 3.10+)
|
|
38
|
+
pip install 'stackone-ai[mcp]'
|
|
39
|
+
|
|
40
|
+
# Install with CrewAI examples (requires Python 3.10+)
|
|
41
|
+
pip install 'stackone-ai[examples]'
|
|
42
|
+
|
|
43
|
+
# Install everything
|
|
44
|
+
pip install 'stackone-ai[mcp,examples]'
|
|
45
|
+
```
|
|
46
|
+
|
|
27
47
|
## Quick Start
|
|
28
48
|
|
|
29
49
|
```python
|
|
@@ -82,10 +102,12 @@ for tool_call in response.tool_calls:
|
|
|
82
102
|
</details>
|
|
83
103
|
|
|
84
104
|
<details>
|
|
85
|
-
<summary>CrewAI Integration</summary>
|
|
105
|
+
<summary>CrewAI Integration (Python 3.10+)</summary>
|
|
86
106
|
|
|
87
107
|
CrewAI uses LangChain tools natively, making integration seamless:
|
|
88
108
|
|
|
109
|
+
> **Note**: CrewAI requires Python 3.10+. Install with `pip install 'stackone-ai[examples]'`
|
|
110
|
+
|
|
89
111
|
```python
|
|
90
112
|
from crewai import Agent, Crew, Task
|
|
91
113
|
from stackone_ai import StackOneToolSet
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "stackone-ai"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = "agents performing actions on your SaaS"
|
|
5
5
|
readme = "README.md"
|
|
6
|
-
requires-python = ">=3.
|
|
6
|
+
requires-python = ">=3.9"
|
|
7
7
|
authors = [
|
|
8
8
|
{ name = "StackOne", email = "support@stackone.com" }
|
|
9
9
|
]
|
|
@@ -12,16 +12,21 @@ classifiers = [
|
|
|
12
12
|
"Intended Audience :: Developers",
|
|
13
13
|
"License :: OSI Approved :: MIT License",
|
|
14
14
|
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.9",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
15
17
|
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
16
20
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
17
21
|
]
|
|
18
22
|
dependencies = [
|
|
19
23
|
"pydantic>=2.10.6",
|
|
20
24
|
"requests>=2.32.3",
|
|
21
25
|
"langchain-core>=0.1.0",
|
|
22
|
-
"mcp[cli]>=1.3.0",
|
|
23
26
|
"bm25s>=0.2.2",
|
|
24
27
|
"numpy>=1.24.0",
|
|
28
|
+
"typing-extensions>=4.0.0",
|
|
29
|
+
"eval-type-backport; python_version<'3.10'", # TODO: Remove when Python 3.9 support is dropped
|
|
25
30
|
]
|
|
26
31
|
|
|
27
32
|
[project.scripts]
|
|
@@ -41,8 +46,12 @@ packages = ["stackone_ai"]
|
|
|
41
46
|
"py.typed" = "py.typed"
|
|
42
47
|
|
|
43
48
|
[project.optional-dependencies]
|
|
49
|
+
# TODO: Remove python_version conditions when Python 3.9 support is dropped
|
|
50
|
+
mcp = [
|
|
51
|
+
"mcp[cli]>=1.3.0; python_version>='3.10'",
|
|
52
|
+
]
|
|
44
53
|
examples = [
|
|
45
|
-
"crewai>=0.102.0",
|
|
54
|
+
"crewai>=0.102.0; python_version>='3.10'",
|
|
46
55
|
"langchain-openai>=0.3.6",
|
|
47
56
|
"openai>=1.63.2",
|
|
48
57
|
"python-dotenv>=1.0.1",
|
|
@@ -82,7 +91,7 @@ markers = [
|
|
|
82
91
|
|
|
83
92
|
[tool.ruff]
|
|
84
93
|
line-length = 110
|
|
85
|
-
target-version = "
|
|
94
|
+
target-version = "py39"
|
|
86
95
|
|
|
87
96
|
[tool.ruff.lint]
|
|
88
97
|
select = [
|
|
@@ -96,7 +105,7 @@ select = [
|
|
|
96
105
|
]
|
|
97
106
|
|
|
98
107
|
[tool.mypy]
|
|
99
|
-
python_version = "3.
|
|
108
|
+
python_version = "3.9"
|
|
100
109
|
disallow_untyped_defs = true
|
|
101
110
|
disallow_incomplete_defs = true
|
|
102
111
|
check_untyped_defs = true
|
|
@@ -82,7 +82,8 @@ class ToolIndex:
|
|
|
82
82
|
|
|
83
83
|
# Process results
|
|
84
84
|
search_results = []
|
|
85
|
-
|
|
85
|
+
# TODO: Add strict=False when Python 3.9 support is dropped
|
|
86
|
+
for idx, score in zip(results[0], scores[0]):
|
|
86
87
|
if score < min_score:
|
|
87
88
|
continue
|
|
88
89
|
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
+
# TODO: Remove when Python 3.9 support is dropped
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
1
4
|
import asyncio
|
|
2
5
|
import base64
|
|
3
6
|
import json
|
|
4
7
|
from collections.abc import Sequence
|
|
5
8
|
from enum import Enum
|
|
6
9
|
from functools import partial
|
|
7
|
-
from typing import Annotated, Any,
|
|
10
|
+
from typing import Annotated, Any, cast
|
|
11
|
+
from urllib.parse import quote
|
|
8
12
|
|
|
9
13
|
import requests
|
|
10
14
|
from langchain_core.tools import BaseTool
|
|
11
15
|
from pydantic import BaseModel, BeforeValidator, Field, PrivateAttr
|
|
12
16
|
from requests.exceptions import RequestException
|
|
13
17
|
|
|
18
|
+
# TODO: Remove when Python 3.9 support is dropped
|
|
19
|
+
from typing_extensions import TypeAlias
|
|
20
|
+
|
|
14
21
|
# Type aliases for common types
|
|
15
22
|
JsonDict: TypeAlias = dict[str, Any]
|
|
16
23
|
Headers: TypeAlias = dict[str, str]
|
|
@@ -140,21 +147,24 @@ class StackOneTool(BaseModel):
|
|
|
140
147
|
for key, value in kwargs.items():
|
|
141
148
|
param_location = self._execute_config.parameter_locations.get(key)
|
|
142
149
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
if param_location == ParameterLocation.PATH:
|
|
151
|
+
# Safely encode path parameters to prevent SSRF attacks
|
|
152
|
+
encoded_value = quote(str(value), safe="")
|
|
153
|
+
url = url.replace(f"{{{key}}}", encoded_value)
|
|
154
|
+
elif param_location == ParameterLocation.QUERY:
|
|
155
|
+
query_params[key] = value
|
|
156
|
+
elif param_location in (ParameterLocation.BODY, ParameterLocation.FILE):
|
|
157
|
+
body_params[key] = value
|
|
158
|
+
else:
|
|
159
|
+
# Default behavior
|
|
160
|
+
if f"{{{key}}}" in url:
|
|
161
|
+
# Safely encode path parameters to prevent SSRF attacks
|
|
162
|
+
encoded_value = quote(str(value), safe="")
|
|
163
|
+
url = url.replace(f"{{{key}}}", encoded_value)
|
|
164
|
+
elif self._execute_config.method in {"GET", "DELETE"}:
|
|
147
165
|
query_params[key] = value
|
|
148
|
-
|
|
166
|
+
else:
|
|
149
167
|
body_params[key] = value
|
|
150
|
-
case _:
|
|
151
|
-
# Default behavior
|
|
152
|
-
if f"{{{key}}}" in url:
|
|
153
|
-
url = url.replace(f"{{{key}}}", str(value))
|
|
154
|
-
elif self._execute_config.method in {"GET", "DELETE"}:
|
|
155
|
-
query_params[key] = value
|
|
156
|
-
else:
|
|
157
|
-
body_params[key] = value
|
|
158
168
|
|
|
159
169
|
return url, body_params, query_params
|
|
160
170
|
|
|
@@ -355,13 +365,12 @@ class StackOneTool(BaseModel):
|
|
|
355
365
|
python_type: type = str # Default to str
|
|
356
366
|
if isinstance(details, dict):
|
|
357
367
|
type_str = details.get("type", "string")
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
python_type = bool
|
|
368
|
+
if type_str == "number":
|
|
369
|
+
python_type = float
|
|
370
|
+
elif type_str == "integer":
|
|
371
|
+
python_type = int
|
|
372
|
+
elif type_str == "boolean":
|
|
373
|
+
python_type = bool
|
|
365
374
|
|
|
366
375
|
field = Field(description=details.get("description", ""))
|
|
367
376
|
else:
|
|
@@ -480,7 +489,7 @@ class Tools:
|
|
|
480
489
|
"""
|
|
481
490
|
return [tool.to_langchain() for tool in self.tools]
|
|
482
491
|
|
|
483
|
-
def meta_tools(self) ->
|
|
492
|
+
def meta_tools(self) -> Tools:
|
|
484
493
|
"""Return meta tools for tool discovery and execution
|
|
485
494
|
|
|
486
495
|
Meta tools enable dynamic tool discovery and execution based on natural language queries.
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# TODO: Remove when Python 3.9 support is dropped
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
1
4
|
import argparse
|
|
2
5
|
import asyncio
|
|
3
6
|
import logging
|
|
@@ -5,12 +8,24 @@ import os
|
|
|
5
8
|
import sys
|
|
6
9
|
from typing import Any, TypeVar
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
# Check Python version for MCP server functionality
|
|
12
|
+
if sys.version_info < (3, 10):
|
|
13
|
+
raise RuntimeError(
|
|
14
|
+
"MCP server functionality requires Python 3.10+. Current version: {}.{}.{}".format(
|
|
15
|
+
*sys.version_info[:3]
|
|
16
|
+
)
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
try: # type: ignore[unreachable]
|
|
20
|
+
import mcp.types as types
|
|
21
|
+
from mcp.server import NotificationOptions, Server
|
|
22
|
+
from mcp.server.models import InitializationOptions
|
|
23
|
+
from mcp.server.stdio import stdio_server
|
|
24
|
+
from mcp.shared.exceptions import McpError
|
|
25
|
+
from mcp.types import EmbeddedResource, ErrorData, ImageContent, TextContent, Tool
|
|
26
|
+
except ImportError as e:
|
|
27
|
+
raise ImportError("MCP dependencies not found. Install with: pip install 'stackone-ai[mcp]'") from e
|
|
28
|
+
|
|
14
29
|
from pydantic import ValidationError
|
|
15
30
|
|
|
16
31
|
from stackone_ai import StackOneToolSet
|
|
@@ -41,7 +56,7 @@ def tool_needs_account_id(tool_name: str) -> bool:
|
|
|
41
56
|
return True
|
|
42
57
|
|
|
43
58
|
|
|
44
|
-
@app.list_tools()
|
|
59
|
+
@app.list_tools()
|
|
45
60
|
async def list_tools() -> list[Tool]:
|
|
46
61
|
"""List all available StackOne tools as MCP tools."""
|
|
47
62
|
if not toolset:
|
|
@@ -99,7 +114,7 @@ async def list_tools() -> list[Tool]:
|
|
|
99
114
|
) from e
|
|
100
115
|
|
|
101
116
|
|
|
102
|
-
@app.call_tool()
|
|
117
|
+
@app.call_tool()
|
|
103
118
|
async def call_tool(
|
|
104
119
|
name: str, arguments: dict[str, Any]
|
|
105
120
|
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# TODO: Remove when Python 3.9 support is dropped
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
1
4
|
import json
|
|
2
5
|
from pathlib import Path
|
|
3
6
|
from typing import Any
|
|
@@ -73,7 +76,7 @@ class OpenAPIParser:
|
|
|
73
76
|
visited = set()
|
|
74
77
|
|
|
75
78
|
# Handle primitive types (str, int, etc)
|
|
76
|
-
if not isinstance(schema, dict
|
|
79
|
+
if not isinstance(schema, (dict, list)):
|
|
77
80
|
return schema
|
|
78
81
|
|
|
79
82
|
if isinstance(schema, list):
|