openapi-cli4ai 0.1.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.
- openapi_cli4ai-0.1.0/.github/CODEOWNERS +2 -0
- openapi_cli4ai-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- openapi_cli4ai-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- openapi_cli4ai-0.1.0/.github/dependabot.yml +21 -0
- openapi_cli4ai-0.1.0/.github/workflows/ci.yml +36 -0
- openapi_cli4ai-0.1.0/.github/workflows/codeql.yml +23 -0
- openapi_cli4ai-0.1.0/.github/workflows/publish.yml +49 -0
- openapi_cli4ai-0.1.0/.gitignore +43 -0
- openapi_cli4ai-0.1.0/CHANGELOG.md +25 -0
- openapi_cli4ai-0.1.0/CONTRIBUTING.md +50 -0
- openapi_cli4ai-0.1.0/LICENSE +21 -0
- openapi_cli4ai-0.1.0/PKG-INFO +315 -0
- openapi_cli4ai-0.1.0/README.md +287 -0
- openapi_cli4ai-0.1.0/SECURITY.md +30 -0
- openapi_cli4ai-0.1.0/demo.gif +0 -0
- openapi_cli4ai-0.1.0/examples/profiles.toml.example +94 -0
- openapi_cli4ai-0.1.0/openapi-cli4ai +9 -0
- openapi_cli4ai-0.1.0/pyproject.toml +52 -0
- openapi_cli4ai-0.1.0/src/openapi_cli4ai/__init__.py +6 -0
- openapi_cli4ai-0.1.0/src/openapi_cli4ai/__main__.py +5 -0
- openapi_cli4ai-0.1.0/src/openapi_cli4ai/cli.py +1311 -0
- openapi_cli4ai-0.1.0/tests/__init__.py +0 -0
- openapi_cli4ai-0.1.0/tests/conftest.py +94 -0
- openapi_cli4ai-0.1.0/tests/fixtures/petstore_spec.json +1270 -0
- openapi_cli4ai-0.1.0/tests/test_auth.py +152 -0
- openapi_cli4ai-0.1.0/tests/test_caching.py +103 -0
- openapi_cli4ai-0.1.0/tests/test_integration.py +295 -0
- openapi_cli4ai-0.1.0/tests/test_profile_management.py +89 -0
- openapi_cli4ai-0.1.0/tests/test_spec_parsing.py +203 -0
- openapi_cli4ai-0.1.0/tests/test_sse_streaming.py +134 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Report a bug or unexpected behavior
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### What happened?
|
|
8
|
+
|
|
9
|
+
A clear description of the bug.
|
|
10
|
+
|
|
11
|
+
### Steps to reproduce
|
|
12
|
+
|
|
13
|
+
1. Run `./openapi-cli4ai ...`
|
|
14
|
+
2. ...
|
|
15
|
+
|
|
16
|
+
### Expected behavior
|
|
17
|
+
|
|
18
|
+
What you expected to happen.
|
|
19
|
+
|
|
20
|
+
### Actual behavior
|
|
21
|
+
|
|
22
|
+
What actually happened. Include the full error output if applicable.
|
|
23
|
+
|
|
24
|
+
### Environment
|
|
25
|
+
|
|
26
|
+
- OS:
|
|
27
|
+
- Python version (`python3 --version`):
|
|
28
|
+
- uv version (`uv --version`):
|
|
29
|
+
|
|
30
|
+
### API spec (if relevant)
|
|
31
|
+
|
|
32
|
+
The OpenAPI spec URL or a minimal example that reproduces the issue.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
about: Suggest a new feature or improvement
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### Problem or use case
|
|
8
|
+
|
|
9
|
+
What are you trying to do? Why is the current behavior insufficient?
|
|
10
|
+
|
|
11
|
+
### Proposed solution
|
|
12
|
+
|
|
13
|
+
How should it work?
|
|
14
|
+
|
|
15
|
+
### Alternatives considered
|
|
16
|
+
|
|
17
|
+
Any other approaches you've thought about.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "github-actions"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
commit-message:
|
|
8
|
+
prefix: "ci"
|
|
9
|
+
groups:
|
|
10
|
+
actions:
|
|
11
|
+
patterns: ["*"]
|
|
12
|
+
|
|
13
|
+
- package-ecosystem: "pip"
|
|
14
|
+
directory: "/"
|
|
15
|
+
schedule:
|
|
16
|
+
interval: "weekly"
|
|
17
|
+
commit-message:
|
|
18
|
+
prefix: "deps"
|
|
19
|
+
groups:
|
|
20
|
+
python-deps:
|
|
21
|
+
patterns: ["*"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
20
|
+
- uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
|
|
21
|
+
with:
|
|
22
|
+
enable-cache: true
|
|
23
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
24
|
+
run: uv python install ${{ matrix.python-version }}
|
|
25
|
+
- name: Run unit tests
|
|
26
|
+
run: uv run --python ${{ matrix.python-version }} --with pytest --with pyyaml --with typer --with httpx --with rich --with click --with tomli-w --with python-dotenv pytest tests/ -m "not integration" -v
|
|
27
|
+
|
|
28
|
+
lint:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
32
|
+
- uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
|
|
33
|
+
- name: Ruff check
|
|
34
|
+
run: uvx ruff check .
|
|
35
|
+
- name: Ruff format check
|
|
36
|
+
run: uvx ruff format --check .
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1" # weekly Monday 6am UTC
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
security-events: write
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
analyze:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
20
|
+
- uses: github/codeql-action/init@480db559a14342288b67e54bd959dd52dc3ee68f # v3
|
|
21
|
+
with:
|
|
22
|
+
languages: python
|
|
23
|
+
- uses: github/codeql-action/analyze@480db559a14342288b67e54bd959dd52dc3ee68f # v3
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions: {}
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
name: Build distribution
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
17
|
+
- uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
|
|
18
|
+
- name: Build sdist and wheel
|
|
19
|
+
run: uv build
|
|
20
|
+
- name: Upload artifacts
|
|
21
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
22
|
+
with:
|
|
23
|
+
name: dist
|
|
24
|
+
path: dist/
|
|
25
|
+
retention-days: 5
|
|
26
|
+
|
|
27
|
+
publish:
|
|
28
|
+
name: Publish to PyPI
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment:
|
|
32
|
+
name: pypi
|
|
33
|
+
url: https://pypi.org/p/openapi-cli4ai
|
|
34
|
+
permissions:
|
|
35
|
+
id-token: write
|
|
36
|
+
attestations: write
|
|
37
|
+
contents: read
|
|
38
|
+
steps:
|
|
39
|
+
- name: Download artifacts
|
|
40
|
+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
41
|
+
with:
|
|
42
|
+
name: dist
|
|
43
|
+
path: dist/
|
|
44
|
+
- name: Generate attestations
|
|
45
|
+
uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2
|
|
46
|
+
with:
|
|
47
|
+
subject-path: dist/*
|
|
48
|
+
- name: Publish to PyPI
|
|
49
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg-info/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
|
|
16
|
+
# IDE
|
|
17
|
+
.idea/
|
|
18
|
+
.vscode/
|
|
19
|
+
*.swp
|
|
20
|
+
*.swo
|
|
21
|
+
*~
|
|
22
|
+
|
|
23
|
+
# OS
|
|
24
|
+
.DS_Store
|
|
25
|
+
Thumbs.db
|
|
26
|
+
|
|
27
|
+
# Environment / secrets
|
|
28
|
+
.env
|
|
29
|
+
.env.*
|
|
30
|
+
*.pem
|
|
31
|
+
credentials.json
|
|
32
|
+
|
|
33
|
+
# Profiles
|
|
34
|
+
profiles.yaml
|
|
35
|
+
!*.example
|
|
36
|
+
|
|
37
|
+
# Cache
|
|
38
|
+
.cache/
|
|
39
|
+
|
|
40
|
+
# Test
|
|
41
|
+
.pytest_cache/
|
|
42
|
+
.coverage
|
|
43
|
+
htmlcov/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - 2026-03-25
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Installable PyPI package (`uv pip install openapi-cli4ai` / `uvx openapi-cli4ai`)
|
|
12
|
+
- Profile management with TOML config at `~/.openapi-cli4ai.toml`
|
|
13
|
+
- Endpoint discovery with search and tag filtering (`endpoints`)
|
|
14
|
+
- API calling with query params, headers, JSON body, and file body (`call`)
|
|
15
|
+
- Auth support: bearer token, OAuth token endpoint, API key, basic auth
|
|
16
|
+
- Token caching with automatic refresh
|
|
17
|
+
- Auto-fetch spec after login for auth-gated APIs
|
|
18
|
+
- SSE streaming support
|
|
19
|
+
- OpenAPI spec caching with TTL
|
|
20
|
+
- JSON and compact output formats
|
|
21
|
+
- `python -m openapi_cli4ai` support
|
|
22
|
+
- Dependabot for automated dependency and GitHub Actions updates
|
|
23
|
+
- CodeQL code scanning workflow
|
|
24
|
+
- Trusted Publisher release workflow with Sigstore attestation
|
|
25
|
+
- All GitHub Actions pinned to commit SHAs
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Contributing to openapi-cli4ai
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing!
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Fork the repository
|
|
8
|
+
2. Clone your fork
|
|
9
|
+
3. Install [uv](https://docs.astral.sh/uv/) if you don't have it
|
|
10
|
+
4. Install in editable mode: `uv pip install -e .`
|
|
11
|
+
5. Run `openapi-cli4ai --help` to verify everything works
|
|
12
|
+
|
|
13
|
+
## Project Structure
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/openapi_cli4ai/
|
|
17
|
+
__init__.py # Package exports
|
|
18
|
+
__main__.py # python -m support
|
|
19
|
+
cli.py # All CLI code lives here
|
|
20
|
+
openapi-cli4ai # Standalone shim (imports from package)
|
|
21
|
+
tests/ # pytest tests
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The core code lives in `src/openapi_cli4ai/cli.py`. The standalone `openapi-cli4ai` script is a thin shim that imports from the package.
|
|
25
|
+
|
|
26
|
+
## Testing
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pytest tests/ -m "not integration" -v
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Submitting a Pull Request
|
|
33
|
+
|
|
34
|
+
1. Create a feature branch (`git checkout -b my-feature`)
|
|
35
|
+
2. Make your changes
|
|
36
|
+
3. Run the tests
|
|
37
|
+
4. Commit with a clear message
|
|
38
|
+
5. Push and open a PR
|
|
39
|
+
|
|
40
|
+
## Reporting Issues
|
|
41
|
+
|
|
42
|
+
Open an issue on GitHub. Include:
|
|
43
|
+
- What you tried
|
|
44
|
+
- What happened
|
|
45
|
+
- What you expected
|
|
46
|
+
- The API spec you were using (if relevant)
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DBGorilla
|
|
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.
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openapi-cli4ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Turn any REST API with an OpenAPI spec into an AI-ready CLI
|
|
5
|
+
Project-URL: Homepage, https://github.com/dbgorilla/openapi-cli4ai
|
|
6
|
+
Project-URL: Repository, https://github.com/dbgorilla/openapi-cli4ai
|
|
7
|
+
Project-URL: Issues, https://github.com/dbgorilla/openapi-cli4ai/issues
|
|
8
|
+
Author: DBGorilla
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai,api,cli,llm,mcp,openapi,rest
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: httpx<1,>=0.28
|
|
22
|
+
Requires-Dist: python-dotenv<2,>=1.0
|
|
23
|
+
Requires-Dist: pyyaml<7,>=6
|
|
24
|
+
Requires-Dist: rich<15,>=13
|
|
25
|
+
Requires-Dist: tomli-w<2,>=1.0
|
|
26
|
+
Requires-Dist: typer<1,>=0.12
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
_ _ _ _ _ _
|
|
31
|
+
___ _ __ ___ _ __ __ _ _ __ (_) ___| (_) || | __ _(_)
|
|
32
|
+
/ _ \| '_ \ / _ \ '_ \ / _` | '_ \| |_____ / __| | | || |_ / _` | |
|
|
33
|
+
| (_) | |_) | __/ | | | (_| | |_) | |_____| (__| | |__ _| (_| | |
|
|
34
|
+
\___/| .__/ \___|_| |_|\__,_| .__/|_| \___|_|_| |_| \__,_|_|
|
|
35
|
+
|_| |_|
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Turn any REST API with an OpenAPI spec into an AI-ready CLI. No MCP server. No custom integration. Just point it at a URL.
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Requires uv (https://docs.astral.sh/uv/)
|
|
46
|
+
uv pip install openapi-cli4ai
|
|
47
|
+
|
|
48
|
+
# Or run directly without installing
|
|
49
|
+
uvx openapi-cli4ai --help
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Point it at any API with an OpenAPI spec
|
|
56
|
+
openapi-cli4ai init petstore --url https://petstore3.swagger.io/api/v3
|
|
57
|
+
|
|
58
|
+
# Discover endpoints
|
|
59
|
+
openapi-cli4ai endpoints
|
|
60
|
+
|
|
61
|
+
# Search endpoints
|
|
62
|
+
openapi-cli4ai endpoints -s pet
|
|
63
|
+
|
|
64
|
+
# Call an endpoint
|
|
65
|
+
openapi-cli4ai call GET /pet/findByStatus --query status=available
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## How It Works
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Your AI Agent (Claude, GPT, Cursor, etc.)
|
|
72
|
+
|
|
|
73
|
+
| 1. "endpoints -s users" <-- discover what's available
|
|
74
|
+
| 2. reads the endpoint list
|
|
75
|
+
| 3. "call GET /users/123" <-- makes the API call
|
|
76
|
+
|
|
|
77
|
+
v
|
|
78
|
+
+---------------------+ +----------------------+
|
|
79
|
+
| openapi-cli4ai |-------->| Your API Server |
|
|
80
|
+
| | | (any REST API) |
|
|
81
|
+
| * Fetches spec |<--------| |
|
|
82
|
+
| * Caches it | +----------------------+
|
|
83
|
+
| * Routes calls |
|
|
84
|
+
| * Handles auth |
|
|
85
|
+
+---------------------+
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The agent uses `endpoints` to discover what's available, then `call` to hit the right endpoint with the right parameters. That's the entire integration. The agent already knows how to use a CLI — you just give it this one and point it at your API.
|
|
89
|
+
|
|
90
|
+
## Why Not MCP?
|
|
91
|
+
|
|
92
|
+
Every MCP tool you connect injects its schema into the prompt. Every parameter, every description, every type definition. Connect a few MCP servers and your agent is burning tokens on tool descriptions before it even starts thinking about your task.
|
|
93
|
+
|
|
94
|
+
For large API surfaces, there's a better pattern: **pull-based discovery**.
|
|
95
|
+
|
|
96
|
+
Nothing is injected into the prompt upfront. The agent pulls what it needs, when it needs it. It sees a compact endpoint index, picks the right endpoint, and calls it. This works with APIs of any size — including 10MB+ specs — without stuffing everything into context.
|
|
97
|
+
|
|
98
|
+
This isn't MCP vs. OpenAPI. It's about having both tools and reaching for the right one. For quick integrations, MCP is great. For large or unfamiliar API surfaces, an OpenAPI spec and a thin CLI is the better play.
|
|
99
|
+
|
|
100
|
+
## Commands
|
|
101
|
+
|
|
102
|
+
### `init` — Point it at an API
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Auto-detect OpenAPI spec location
|
|
106
|
+
openapi-cli4ai init myapi --url https://api.example.com
|
|
107
|
+
|
|
108
|
+
# Specify spec path
|
|
109
|
+
openapi-cli4ai init myapi --url https://api.example.com --spec /v2/openapi.json
|
|
110
|
+
|
|
111
|
+
# Specify auth type
|
|
112
|
+
openapi-cli4ai init myapi --url https://api.example.com --auth bearer
|
|
113
|
+
|
|
114
|
+
# Use a remote spec URL
|
|
115
|
+
openapi-cli4ai init myapi --url https://api.example.com --spec-url https://example.com/spec.json
|
|
116
|
+
|
|
117
|
+
# Skip SSL verification (internal/staging APIs)
|
|
118
|
+
openapi-cli4ai -k init myapi --url https://staging.internal.example.com
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `endpoints` — Discover API endpoints
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# List all endpoints
|
|
125
|
+
openapi-cli4ai endpoints
|
|
126
|
+
|
|
127
|
+
# Search by keyword
|
|
128
|
+
openapi-cli4ai endpoints -s pet
|
|
129
|
+
|
|
130
|
+
# Filter by tag
|
|
131
|
+
openapi-cli4ai endpoints --tag store
|
|
132
|
+
|
|
133
|
+
# Output as JSON (useful for AI agents)
|
|
134
|
+
openapi-cli4ai endpoints --format json
|
|
135
|
+
|
|
136
|
+
# Compact one-line-per-endpoint view
|
|
137
|
+
openapi-cli4ai endpoints --format compact
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `call` — Call any endpoint
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# GET request
|
|
144
|
+
openapi-cli4ai call GET /pet/findByStatus --query status=available
|
|
145
|
+
|
|
146
|
+
# POST with JSON body
|
|
147
|
+
openapi-cli4ai call POST /pet --body '{"name": "Rex", "status": "available"}'
|
|
148
|
+
|
|
149
|
+
# POST with body from file
|
|
150
|
+
openapi-cli4ai call POST /pet --body @payload.json
|
|
151
|
+
|
|
152
|
+
# Multiple query parameters
|
|
153
|
+
openapi-cli4ai call GET /pet/findByStatus --query status=available --query limit=10
|
|
154
|
+
|
|
155
|
+
# Custom headers
|
|
156
|
+
openapi-cli4ai call GET /resource --header "X-Custom:value"
|
|
157
|
+
|
|
158
|
+
# Stream SSE responses
|
|
159
|
+
openapi-cli4ai call POST /chat --body '{"message": "hello"}' --stream
|
|
160
|
+
|
|
161
|
+
# Raw output (no formatting)
|
|
162
|
+
openapi-cli4ai call GET /pet/1 --raw
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### `profile` — Manage API profiles
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# List profiles
|
|
169
|
+
openapi-cli4ai profile list
|
|
170
|
+
|
|
171
|
+
# Switch active profile
|
|
172
|
+
openapi-cli4ai profile use myapi
|
|
173
|
+
|
|
174
|
+
# Show profile config
|
|
175
|
+
openapi-cli4ai profile show
|
|
176
|
+
|
|
177
|
+
# Add a profile manually
|
|
178
|
+
openapi-cli4ai profile add myapi --url https://api.example.com
|
|
179
|
+
|
|
180
|
+
# Remove a profile
|
|
181
|
+
openapi-cli4ai profile remove myapi
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### `login` / `logout` — Authentication
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Login (for APIs with OAuth/token endpoints)
|
|
188
|
+
openapi-cli4ai login --username admin
|
|
189
|
+
|
|
190
|
+
# Login with password from file (for automation)
|
|
191
|
+
openapi-cli4ai login --username admin --password-file /path/to/secret
|
|
192
|
+
|
|
193
|
+
# Login with password from stdin
|
|
194
|
+
echo "my-password" | openapi-cli4ai login --username admin --password-stdin
|
|
195
|
+
|
|
196
|
+
# Logout (clear cached tokens)
|
|
197
|
+
openapi-cli4ai logout
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Configuration
|
|
201
|
+
|
|
202
|
+
Profiles are stored in `~/.openapi-cli4ai.toml`. Secrets are referenced via environment variables — never stored in the config file.
|
|
203
|
+
|
|
204
|
+
```toml
|
|
205
|
+
active_profile = "myapi"
|
|
206
|
+
|
|
207
|
+
[profiles.myapi]
|
|
208
|
+
base_url = "https://api.example.com"
|
|
209
|
+
openapi_path = "/openapi.json"
|
|
210
|
+
|
|
211
|
+
[profiles.myapi.auth]
|
|
212
|
+
type = "bearer"
|
|
213
|
+
token_env_var = "MYAPI_TOKEN"
|
|
214
|
+
|
|
215
|
+
[profiles.stripe]
|
|
216
|
+
base_url = "https://api.stripe.com"
|
|
217
|
+
openapi_url = "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json"
|
|
218
|
+
|
|
219
|
+
[profiles.stripe.auth]
|
|
220
|
+
type = "api-key"
|
|
221
|
+
env_var = "STRIPE_SECRET_KEY"
|
|
222
|
+
header = "Authorization"
|
|
223
|
+
prefix = "Bearer "
|
|
224
|
+
|
|
225
|
+
[profiles.internal-app]
|
|
226
|
+
base_url = "http://localhost:8000"
|
|
227
|
+
verify_ssl = false
|
|
228
|
+
|
|
229
|
+
[profiles.internal-app.auth]
|
|
230
|
+
type = "bearer"
|
|
231
|
+
token_endpoint = "/api/auth/token"
|
|
232
|
+
refresh_endpoint = "/api/auth/refresh"
|
|
233
|
+
|
|
234
|
+
[profiles.internal-app.auth.payload]
|
|
235
|
+
username = "{username}"
|
|
236
|
+
password = "{password}"
|
|
237
|
+
tenant = "{env:MY_TENANT}"
|
|
238
|
+
account_type = "USERNAME"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Payload placeholders: `{username}` and `{password}` come from the login prompt. `{env:VAR_NAME}` pulls from environment variables or a `.env` file (loaded automatically).
|
|
242
|
+
|
|
243
|
+
### Auth Types
|
|
244
|
+
|
|
245
|
+
| Type | Use Case | Config Fields |
|
|
246
|
+
|------|----------|---------------|
|
|
247
|
+
| `none` | Public APIs | — |
|
|
248
|
+
| `bearer` | Token from env var | `token_env_var` |
|
|
249
|
+
| `bearer` | OAuth token endpoint | `token_endpoint`, `refresh_endpoint`, `payload` |
|
|
250
|
+
| `api-key` | API key in header | `env_var`, `header`, `prefix` |
|
|
251
|
+
| `basic` | HTTP Basic auth | `username_env_var`, `password_env_var` |
|
|
252
|
+
|
|
253
|
+
## Tested With
|
|
254
|
+
|
|
255
|
+
| API | Endpoints | Auth | Example |
|
|
256
|
+
|-----|-----------|------|---------|
|
|
257
|
+
| [Petstore](https://petstore3.swagger.io) | 19 | None | `init petstore --url https://petstore3.swagger.io/api/v3` |
|
|
258
|
+
| [NWS Weather](https://api.weather.gov) | 60 | None | `init nws --url https://api.weather.gov` |
|
|
259
|
+
| [PokéAPI](https://pokeapi.co) | 97 | None | `init pokeapi --url https://pokeapi.co --spec-url ...` |
|
|
260
|
+
| [D&D 5e](https://www.dnd5eapi.co) | 47 | None | `init dnd --url https://www.dnd5eapi.co --spec-url ...` |
|
|
261
|
+
| [Nager.Date Holidays](https://date.nager.at) | 8 | None | `init holidays --url https://date.nager.at --spec /openapi/v3.json` |
|
|
262
|
+
| [GitHub](https://api.github.com) | 1,080 | Bearer | `init github --url https://api.github.com --spec-url ... --auth bearer` |
|
|
263
|
+
| [Jira Cloud](https://developer.atlassian.com/cloud/jira/platform/rest/v3/) | 581 | Basic | `init jira --url https://your-domain.atlassian.net --spec-url ... --auth basic` |
|
|
264
|
+
| [OpenRouter](https://openrouter.ai) | 36 | Bearer | `init openrouter --url https://openrouter.ai/api/v1 --spec-url ... --auth bearer` |
|
|
265
|
+
| [DBGorilla](https://dbgorilla.com) | 500+ | Token endpoint | See `examples/profiles.toml.example` |
|
|
266
|
+
|
|
267
|
+
Works with any AI agent that has shell access — Claude Code, Cursor, GitHub Copilot, or anything that can run `endpoints` and `call`.
|
|
268
|
+
|
|
269
|
+
### Claude Code Setup
|
|
270
|
+
|
|
271
|
+
Add this to your global `~/.claude/CLAUDE.md` so every Claude Code session knows about the tool — regardless of which repo you're working in:
|
|
272
|
+
|
|
273
|
+
```markdown
|
|
274
|
+
## API Access
|
|
275
|
+
|
|
276
|
+
You have `openapi-cli4ai` installed for interacting with REST APIs.
|
|
277
|
+
|
|
278
|
+
- Discover endpoints: `openapi-cli4ai endpoints -s <keyword>`
|
|
279
|
+
- Call endpoints: `openapi-cli4ai call <METHOD> <path> [--query key=value] [--body '{}']`
|
|
280
|
+
- List profiles: `openapi-cli4ai profile list`
|
|
281
|
+
- Switch profile: `openapi-cli4ai profile use <name>`
|
|
282
|
+
- Login (if needed): `openapi-cli4ai login`
|
|
283
|
+
|
|
284
|
+
Use `openapi-cli4ai endpoints` to explore before making calls.
|
|
285
|
+
Use `--format json` when you need to parse the output programmatically.
|
|
286
|
+
Use `-k` flag for APIs with self-signed or internal certificates.
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
This works because `~/.claude/CLAUDE.md` is loaded into every conversation context, not just the current repo.
|
|
290
|
+
|
|
291
|
+
## Development
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
git clone https://github.com/dbgorilla/openapi-cli4ai.git
|
|
295
|
+
cd openapi-cli4ai
|
|
296
|
+
uv pip install -e .
|
|
297
|
+
pytest tests/ -m "not integration" -v
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Security
|
|
301
|
+
|
|
302
|
+
- All credentials stay local — profiles reference env var names, not values
|
|
303
|
+
- Token cache protected with restricted file permissions (0600)
|
|
304
|
+
- PyPI releases use [Trusted Publishers](https://docs.pypi.org/trusted-publishers/) with Sigstore attestation
|
|
305
|
+
- All CI actions pinned to commit SHAs
|
|
306
|
+
- Dependabot monitors dependencies weekly
|
|
307
|
+
- See [SECURITY.md](SECURITY.md) for vulnerability reporting
|
|
308
|
+
|
|
309
|
+
## Attribution
|
|
310
|
+
|
|
311
|
+
This project was inspired by [@tomleavy](https://github.com/tomleavy), who originated the idea that an OpenAPI spec and a thin CLI is all an AI agent needs to talk to any API.
|
|
312
|
+
|
|
313
|
+
## License
|
|
314
|
+
|
|
315
|
+
MIT — see [LICENSE](LICENSE).
|