-
Notifications
You must be signed in to change notification settings - Fork 3
Boilerplate: Add software tests and CI configuration #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5889281
ea07ab3
69fccc9
6b6b989
dab14f7
5727a27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # To get started with Dependabot version updates, you'll need to specify which | ||
| # package ecosystems to update and where the package manifests are located. | ||
| # Please see the documentation for all configuration options: | ||
| # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates | ||
|
|
||
| version: 2 | ||
| updates: | ||
| - package-ecosystem: "pip" | ||
| directory: "/" | ||
| schedule: | ||
| interval: "daily" | ||
|
|
||
| - package-ecosystem: "github-actions" | ||
| directory: "/" | ||
| schedule: | ||
| interval: "monthly" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # Use Trusted Publishing to stage Python packages through GitHub Actions (GHA) to the Python Package Index (PyPI). | ||
| name: "Release: Python package" | ||
|
|
||
| on: | ||
|
|
||
| # Build and publish packages when running a release. | ||
| push: | ||
| tags: | ||
| - '*' | ||
|
|
||
| # Build packages on each pull request for validation purposes. | ||
| pull_request: | ||
|
|
||
| # Build packages each night for validation purposes. | ||
| schedule: | ||
| - cron: '0 4 * * *' | ||
|
|
||
| # Allow the job to be triggered manually. | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| build-and-publish: | ||
| name: "Build and publish to PyPI" | ||
| runs-on: ${{ matrix.os }} | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| os: ["ubuntu-latest"] | ||
| python-version: ["3.13"] | ||
| env: | ||
| OS_TYPE: ${{ matrix.os }} | ||
| PYTHON_VERSION: ${{ matrix.python-version }} | ||
|
|
||
| # Trusted publishing. | ||
| # Specifying a GitHub environment is optional, but strongly encouraged. | ||
| environment: pypi | ||
| # IMPORTANT: This permission is mandatory for Trusted Publishing. | ||
| permissions: | ||
| id-token: write | ||
|
|
||
| steps: | ||
| - name: Acquire sources | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up uv | ||
| uses: astral-sh/setup-uv@v6 | ||
| with: | ||
| cache-dependency-glob: | | ||
| pyproject.toml | ||
| cache-suffix: ${{ matrix.python-version }} | ||
| enable-cache: true | ||
| version: "latest" | ||
|
|
||
| - name: Build package | ||
| run: | | ||
| uv build | ||
|
|
||
| - name: Publish package to TestPyPI | ||
| run: | | ||
| # `uv publish` does not understand `--skip-existing`. | ||
| # https://github.com/astral-sh/uv/issues/7917 | ||
| # https://github.com/astral-sh/uv/issues/12369 | ||
| uvx twine upload --non-interactive --repository-url https://test.pypi.org/legacy/ --skip-existing dist/* | ||
|
|
||
| - name: Publish package to PyPI | ||
| if: startsWith(github.event.ref, 'refs/tags') | ||
| run: | | ||
| uv publish |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| name: "Tests" | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main ] | ||
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
|
|
||
| test: | ||
| name: " | ||
| Python ${{ matrix.python-version }} | ||
| " | ||
| runs-on: ${{ matrix.os }} | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| os: ['ubuntu-latest'] | ||
| python-version: [ | ||
| '3.10', | ||
| '3.13', | ||
| ] | ||
| cratedb-version: [ | ||
| 'nightly', | ||
| ] | ||
|
|
||
| env: | ||
| OS: ${{ matrix.os }} | ||
| PYTHON: ${{ matrix.python-version }} | ||
| UV_SYSTEM_PYTHON: true | ||
|
|
||
| services: | ||
| cratedb: | ||
| image: crate/crate:${{ matrix.cratedb-version }} | ||
| ports: | ||
| - 4200:4200 | ||
| - 5432:5432 | ||
| env: | ||
| CRATE_HEAP_SIZE: 4g | ||
|
|
||
| steps: | ||
|
|
||
| - name: Acquire sources | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
|
|
||
| - name: Set up uv | ||
| uses: astral-sh/setup-uv@v6 | ||
| with: | ||
| cache-dependency-glob: | | ||
| pyproject.toml | ||
| cache-suffix: ${{ matrix.python-version }} | ||
| enable-cache: true | ||
| version: "latest" | ||
|
|
||
| - name: Set up project | ||
| run: | | ||
| uv pip install --editable='.[all,develop,test]' | ||
| - name: Run linter and software tests | ||
| run: poe check | ||
|
|
||
| # https://github.com/codecov/codecov-action | ||
| - name: Upload coverage results to Codecov | ||
| uses: codecov/codecov-action@v5 | ||
| env: | ||
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | ||
| with: | ||
| env_vars: OS,PYTHON | ||
| fail_ci_if_error: true | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # CrateDB MCP changelog | ||
|
|
||
| ## Unreleased | ||
|
|
||
| ## v0.0.1 - 2025-05-xx | ||
| - Project: Established project layout | ||
| - Features: First working version | ||
| - Packaging: Adjusted package dependencies for interoperability | ||
| - Packaging: Added basic CLI entry point and server launcher `cratedb-mcp` | ||
| - Documentation: Show a simple Claude Desktop configuration | ||
| - MCP documentation: Add reference to medium-sized llms.txt context file | ||
| - Boilerplate: Added software tests and CI configuration | ||
| - Documentation: Added development sandbox section |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Development documentation | ||
|
|
||
| ## Sandbox | ||
|
|
||
| Use those commands to set up a development sandbox and install the | ||
| project in editable mode. | ||
| ```shell | ||
| git clone https://github.com/crate/cratedb-mcp | ||
| cd cratedb-mcp | ||
| uv venv --python 3.13 --seed .venv | ||
| source .venv/bin/activate | ||
| uv pip install --upgrade --editable='.[develop,test]' | ||
| ``` | ||
|
|
||
| ## Software tests | ||
|
|
||
| The project uses the [poethepoet] task runner, which provides convenience entry | ||
| points for invoking linters and software tests. The top-level one-shot command | ||
| will invoke both and is also used on CI/GHA. | ||
| ```shell | ||
| poe check | ||
| ``` | ||
|
|
||
| To invoke individual software tests for working on the spot, use a | ||
| traditional `pytest` invocation. Examples: | ||
| ```shell | ||
| pytest --no-cov tests/test_knowledge.py | ||
| ``` | ||
| ```shell | ||
| pytest --no-cov -k query | ||
| ``` | ||
|
|
||
| ## Release | ||
|
|
||
| The project uses [versioningit] so you don't need to do any version bumping | ||
| within files because the version number will be derived from the Git tag. | ||
|
|
||
| However, you need to designate the new release within the [CHANGES.md](./CHANGES.md) | ||
| file, and commit it. The release procedure currently looks like this: | ||
| ```shell | ||
| git commit -m 'Release v0.0.1' | ||
| git tag v0.0.1 | ||
| git push && git push --tags | ||
| ``` | ||
|
|
||
|
|
||
| [poethepoet]: https://pypi.org/project/poethepoet/ | ||
| [versioningit]: https://pypi.org/project/versioningit/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,12 @@ | ||
| # CrateDB MCP Server | ||
|
|
||
| [![Bluesky][badge-bluesky]][target-bluesky] | ||
| [![Release Notes][badge-release-notes]][project-release-notes] | ||
|
|
||
| [![Status][badge-status]][target-project] | ||
| [![License][badge-license]][target-license] | ||
| [![CI][badge-ci]][project-ci] | ||
| [![Coverage][badge-coverage]][project-coverage] | ||
|
|
||
| » [Documentation] | ||
| | [Releases] | ||
|
|
@@ -43,23 +47,36 @@ our recommendation. | |
|
|
||
| # Install | ||
| ```shell | ||
| uv pip install --upgrade git+https://github.com/crate/cratedb-mcp | ||
| uv tool install --upgrade git+https://github.com/crate/cratedb-mcp | ||
| ``` | ||
| Note: We recommend to use `uv tool install` to install the program "user"-wide | ||
| into your environment so you can use it across your terminal or MCP client | ||
| sessions like Claude. | ||
|
|
||
| # Configure | ||
|
|
||
| Configure the `CRATEDB_MCP_HTTP_URL` environment variable to match your CrateDB instance. | ||
| For example, when connecting to CrateDB Cloud, use a value like | ||
| `https://admin:[email protected]:4200/`. | ||
| When connecting to CrateDB on localhost, use `http://localhost:4200/`. | ||
| ```shell | ||
| export CRATEDB_MCP_HTTP_URL=https://example.aks1.westeurope.azure.cratedb.net:4200 | ||
| export CRATEDB_MCP_HTTP_URL="http://localhost:4200/" | ||
| ``` | ||
| ```shell | ||
| export CRATEDB_MCP_HTTP_URL="https://example.aks1.westeurope.azure.cratedb.net:4200" | ||
| ``` | ||
|
|
||
| # Usage | ||
| Start MCP server with `stdio` transport (default). | ||
| ```shell | ||
| CRATEDB_MCP_TRANSPORT=stdio uv run cratedb-mcp | ||
| CRATEDB_MCP_TRANSPORT=stdio cratedb-mcp | ||
| ``` | ||
| Start MCP server with `sse` transport. | ||
| ```shell | ||
| CRATEDB_MCP_TRANSPORT=sse uv run cratedb-mcp | ||
| CRATEDB_MCP_TRANSPORT=sse cratedb-mcp | ||
| ``` | ||
| Note: If you are unable to use `uv tool install`, please use | ||
| `uv run cratedb-mcp` to acquire and run the package ephemerally. | ||
|
|
||
| # Simple Claude configuration | ||
| To use the MCP version within Claude Desktop, you can use the following configuration: | ||
|
|
@@ -79,13 +96,10 @@ To use the MCP version within Claude Desktop, you can use the following configur | |
| } | ||
| ``` | ||
|
|
||
| You might have to change `CRATEDB_MCP_HTTP_URL` to match your CrateDB instance. For example, when connecting to CrateDB Cloud, use a value like https://admin:[email protected]:4200/. | ||
|
|
||
|
|
||
| NB: You can use `uv tool install` to install the program "system"-wide, | ||
| so you can use it across your terminal or Claude sessions. In this case, | ||
| omit the `uv run` prefix displayed above. | ||
| ## Development | ||
|
|
||
| To learn how to set up a development sandbox, see the [development documentation](./DEVELOP.md). | ||
|
|
||
|
|
||
| [CrateDB]: https://cratedb.com/database | ||
|
|
@@ -99,11 +113,15 @@ omit the `uv run` prefix displayed above. | |
| [Source code]: https://github.com/crate/cratedb-mcp | ||
| [Releases]: https://github.com/surister/cratedb-mcp/releases | ||
|
|
||
| [badge-ci]: https://github.com/crate/cratedb-mcp/actions/workflows/tests.yml/badge.svg | ||
| [badge-coverage]: https://codecov.io/gh/crate/cratedb-mcp/branch/main/graph/badge.svg | ||
| [badge-bluesky]: https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff&label=Follow%20%40CrateDB | ||
| [badge-issues]: https://img.shields.io/github/issues/crate/cratedb-mcp | ||
| [badge-license]: https://img.shields.io/github/license/crate/cratedb-mcp | ||
| [badge-release-notes]: https://img.shields.io/badge/Release%20Notes-v0.0.0-blue | ||
| [badge-release-notes]: https://img.shields.io/github/release/crate/cratedb-mcp?label=Release+Notes | ||
| [badge-status]: https://img.shields.io/badge/status--alpha-orange | ||
| [project-ci]: https://github.com/crate/cratedb-mcp/actions/workflows/tests.yml | ||
| [project-coverage]: https://app.codecov.io/gh/crate/cratedb-mcp | ||
| [project-release-notes]: https://github.com/crate/cratedb-mcp/releases | ||
| [target-bluesky]: https://bsky.app/search?q=cratedb | ||
| [target-license]: https://github.com/crate/cratedb-mcp/blob/main/LICENSE | ||
| [target-project]: https://github.com/crate/cratedb-mcp | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,20 @@ | ||
| import os | ||
|
|
||
| import httpx | ||
|
|
||
| from mcp.server.fastmcp import FastMCP | ||
|
|
||
| from .constants import Queries, DOCUMENTATION_INDEX | ||
| from .knowledge import DOCUMENTATION_INDEX, Queries | ||
| from .settings import HTTP_URL | ||
|
|
||
| mcp = FastMCP("cratedb-mcp") | ||
|
|
||
|
|
||
| def query_cratedb(query: str) -> list[dict]: | ||
| return httpx.post(f'{os.getenv("CRATEDB_MCP_HTTP_URL")}/_sql', json={'stmt': query}).json() | ||
| return httpx.post(f'{HTTP_URL}/_sql', json={'stmt': query}).json() | ||
|
|
||
|
|
||
| @mcp.tool(description="Send a SQL query to CrateDB, only 'SELECT' queries are allows, queries that" | ||
| " modify data, columns or are otherwise deemed un-safe are rejected.") | ||
| def query_sql(query: str): | ||
| if not 'select' in query.lower(): | ||
| if 'select' not in query.lower(): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: for future reference, this is very low effort way to avoid un-safe queries and very easy to bypass. We mostly depend on the LLM to understand the description, checking if 'select' is present is weak.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think you've seen GH-11 already, which aims to make it a bit stronger. |
||
| raise ValueError('Only queries that have a SELECT statement are allowed.') | ||
| return query_cratedb(query) | ||
|
|
||
|
|
@@ -29,7 +27,7 @@ def get_cratedb_documentation_index(): | |
| ' Only used to download CrateDB docs.') | ||
| def fetch_cratedb_docs(link: str): | ||
| """Fetches a CrateDB documentation link from GitHub raw content.""" | ||
| if not 'https://raw.githubusercontent.com/crate/crate/' in link: | ||
| if 'https://raw.githubusercontent.com/crate/crate/' not in link: | ||
| raise ValueError('Only github cratedb links can be fetched.') | ||
| return httpx.get(link).text | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| # ruff: noqa: E501 | ||
|
|
||
| class Queries: | ||
| TABLES_METADATA = """ | ||
| WITH partitions_health AS (SELECT table_name, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import os | ||
|
|
||
| HTTP_URL: str = os.getenv("CRATEDB_MCP_HTTP_URL", "http://localhost:4200") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Consider expanding the Python version matrix for comprehensive compatibility testing.
The PR summary mentions support for Python 3.10 through 3.13, but the test matrix only includes 3.10 and 3.13. Adding 3.11 and 3.12 would provide more comprehensive coverage and ensure compatibility across all supported versions.
🌐 Web query:
💡 Result:
As of May 10, 2025, the maintenance statuses for Python versions 3.10, 3.11, 3.12, and 3.13 are as follows:
Python 3.10: Released on October 4, 2021, Python 3.10 has completed its active support phase and is now in the security support phase. This means it receives only security updates and no new features or general bug fixes. Security updates are provided irregularly in source-only form until October 2026. (peps.python.org)
Python 3.11: Released on October 24, 2022, Python 3.11 has also completed its active support phase and is now in the security support phase. Similar to Python 3.10, it receives only security updates in source-only form until October 2027. (endoflife.date)
Python 3.12: Released on October 2, 2023, Python 3.12 is currently in its active support phase, which includes regular bug fixes and security updates. Active support is scheduled to end on April 2, 2025, after which it will enter the security support phase, receiving only security updates until October 2, 2028. (peps.python.org)
Python 3.13: Released on October 7, 2024, Python 3.13 is the latest stable release and is currently in its active support phase, receiving regular updates and new features. Active support is scheduled to end on October 1, 2026, after which it will enter the security support phase, receiving only security updates until October 10, 2029. (endoflife.date)
For the most current information on Python release schedules and support phases, you can refer to the official Python website or the Python Enhancement Proposals (PEPs) related to release schedules.
Citations:
Include Python 3.11 and 3.12 in the CI test matrix
All supported versions (3.10–3.13) are still receiving maintenance—3.10 and 3.11 in security-only support, 3.12 and 3.13 in active support—so we should validate compatibility across the full range.
.github/workflows/tests.yml(lines 20–30)python-versionmatrix:📝 Committable suggestion
🤖 Prompt for AI Agents (early access)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@surister: What do you think about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3.10-3.13 is my range 🔥🔥