diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..a9586729c --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +# Copy this file to .env (or export env vars) before running. +ALIAS=REPLACE_ME +GITHUB_REF_NAME=REPLACE_ME +MCP_CONFORMANCE_CONTEXT=REPLACE_ME +MCP_CONFORMANCE_SCENARIO=REPLACE_ME +PROJECT_VERSION=REPLACE_ME +VERSION=REPLACE_ME diff --git a/.github/workflows/baseline-ci.yml b/.github/workflows/baseline-ci.yml new file mode 100644 index 000000000..7a37efbe9 --- /dev/null +++ b/.github/workflows/baseline-ci.yml @@ -0,0 +1,160 @@ +name: Baseline CI + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + secret-scan: + name: Secret Scan + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Gitleaks + uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + quality: + name: Lint / Build / Test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + if: ${{ hashFiles('**/package.json') != '' }} + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Setup Python + if: ${{ hashFiles('**/requirements.txt', '**/pyproject.toml') != '' }} + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Setup Java + if: ${{ hashFiles('**/pom.xml', '**/build.gradle', '**/build.gradle.kts') != '' }} + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + + - name: Setup Go + if: ${{ hashFiles('**/go.mod') != '' }} + uses: actions/setup-go@v5 + with: + go-version: '1.22' + + - name: Lint + shell: bash + run: | + set -euo pipefail + ran=0 + + if [ -f package.json ]; then + npm ci || npm install + npm run lint --if-present + ran=1 + fi + + if [ -f requirements.txt ] || [ -f pyproject.toml ]; then + python -m pip install --upgrade pip + python -m pip install ruff || true + if command -v ruff >/dev/null 2>&1; then + ruff check . || true + fi + ran=1 + fi + + if [ -f go.mod ]; then + gofmt -l . | tee /tmp/gofmt.out + if [ -s /tmp/gofmt.out ]; then + echo 'gofmt reported unformatted files' + exit 1 + fi + ran=1 + fi + + if [ -f pom.xml ]; then + if [ -f mvnw ]; then chmod +x mvnw; ./mvnw -B -ntp -DskipTests validate; else mvn -B -ntp -DskipTests validate; fi + ran=1 + fi + + if [ "$ran" -eq 0 ]; then + echo 'No lint target detected, skip.' + fi + + - name: Build + shell: bash + run: | + set -euo pipefail + ran=0 + + if [ -f package.json ]; then + npm run build --if-present + ran=1 + fi + + if [ -f requirements.txt ] || [ -f pyproject.toml ]; then + python -m compileall -q . + ran=1 + fi + + if [ -f go.mod ]; then + go build ./... + ran=1 + fi + + if [ -f pom.xml ]; then + if [ -f mvnw ]; then chmod +x mvnw; ./mvnw -B -ntp -DskipTests package; else mvn -B -ntp -DskipTests package; fi + ran=1 + fi + + if [ "$ran" -eq 0 ]; then + echo 'No build target detected, skip.' + fi + + - name: Test + shell: bash + run: | + set -euo pipefail + ran=0 + + if [ -f package.json ]; then + npm test --if-present + ran=1 + fi + + if [ -f requirements.txt ] || [ -f pyproject.toml ]; then + python -m pip install pytest || true + if [ -d tests ] || [ -d test ]; then + pytest -q || true + else + python -m unittest discover -v || true + fi + ran=1 + fi + + if [ -f go.mod ]; then + go test ./... + ran=1 + fi + + if [ -f pom.xml ]; then + if [ -f mvnw ]; then chmod +x mvnw; ./mvnw -B -ntp test; else mvn -B -ntp test; fi + ran=1 + fi + + if [ "$ran" -eq 0 ]; then + echo 'No test target detected, skip.' + fi diff --git a/README.md b/README.md index 4873876a6..864b1cc9a 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,15 @@ The [MCP Annotations](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/ap The [MCP Security](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-security.html) - provides comprehensive OAuth 2.0 and API key-based security support for Model Context Protocol implementations in Spring AI. Bootstrap your AI applications with MCP support using [Spring Initializer](https://start.spring.io). +#### Using with Spring Boot + +If you are approaching the SDK from a Spring Boot application, the shortest path is usually: + +1. Start with the dependency and BOM guidance in [`docs/quickstart.md`](docs/quickstart.md). +2. Choose the [MCP Client Boot Starter](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-client-boot-starter-docs.html) or [MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-server-boot-starter-docs.html) based on whether your application consumes or exposes MCP endpoints. +3. Add [MCP Annotations](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-annotations-overview.html) if you want annotation-based handler wiring. +4. Add [MCP Security](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-security.html) when you need OAuth 2.0 or API key-based protection in a Spring deployment. + ## Development ### Building from Source