Skip to content

feat: mcp oauth 2.1 flow for HTTP/SSE servers #2105

feat: mcp oauth 2.1 flow for HTTP/SSE servers

feat: mcp oauth 2.1 flow for HTTP/SSE servers #2105

Workflow file for this run

name: PR Validation
on:
pull_request:
types: [opened, edited, synchronize, reopened]
branches: [main, develop, dev]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
pr-title-check:
name: Validate PR Title
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
pull-requests: read
steps:
- name: Check PR title follows conventional commits
uses: amannn/action-semantic-pull-request@e32d7e603df1aa1ba07e981f2a23455dee596825 # v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
style
refactor
perf
test
build
ci
chore
revert
requireScope: false
subjectPattern: ^(?![A-Z]).+$
subjectPatternError: |
The subject "{subject}" must not start with an uppercase letter.
Use lowercase like: "feat: add new feature"
pr-body-check:
name: Validate PR Description
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Validate PR description against template
id: validate
env:
# Pass the body via env, never interpolated into the shell, to avoid
# command injection from attacker-controlled PR descriptions.
PR_BODY: ${{ github.event.pull_request.body }}
PR_BODY_COMMENT_FILE: ${{ runner.temp }}/pr-body-comment.md
run: bun run scripts/validate-pr-body.ts
- name: Post or update failure comment
# Skip on forked PRs: GITHUB_TOKEN is read-only there, so the comment
# API calls would 403. Validation itself still gates forked PRs.
if: failure() && steps.validate.outcome == 'failure' && github.event.pull_request.head.repo.full_name == github.repository
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
with:
script: |
const fs = require('node:fs');
const marker = '<!-- pr-body-validation -->';
const path = `${process.env.RUNNER_TEMP}/pr-body-comment.md`;
let body;
try {
body = fs.readFileSync(path, 'utf8');
} catch {
body = `${marker}\n## ❌ PR description does not satisfy the template\n\nPlease fill in every required section of the PR template.`;
}
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number, per_page: 100 });
const existing = comments.find((c) => c.body && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
} else {
await github.rest.issues.createComment({ owner, repo, issue_number, body });
}
- name: Resolve failure comment on success
# Skip on forked PRs (read-only GITHUB_TOKEN) to avoid a 403 turning a
# passing validation into a failed job.
if: success() && github.event.pull_request.head.repo.full_name == github.repository
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
with:
script: |
const marker = '<!-- pr-body-validation -->';
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number, per_page: 100 });
const existing = comments.find((c) => c.body && c.body.includes(marker));
if (existing) {
const body = `${marker}\n## ✅ PR description satisfies the template\n\nThanks for filling it in.`;
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
}
validate:
name: Lint, Typecheck & Test
# Code jobs don't need to re-run when only the PR description is edited.
if: github.event.action != 'edited'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Install Bun dependencies
run: bun install --frozen-lockfile
- name: Biome (lint + format + imports)
run: bun run ci
- name: Typecheck
run: bun run typecheck
- name: Test
run: bun run test
acp-registry-bundle:
name: ACP Registry Bundle Freshness
if: github.event.action != 'edited'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Install Bun dependencies
run: bun install --frozen-lockfile
- name: Sync bundled ACP registry snapshot
run: bun run sync:acp-icons
- name: Format bundled ACP assets
run: bunx biome format --write src/renderer/assets/agent-icons/acp/
- name: Verify bundled registry artifacts match CDN registry
run: >
git diff --exit-code --
src/renderer/assets/agent-icons/acp/
src-tauri/src/acp_registry_snapshot.rs
rust-checks:
name: Rust Checks
if: github.event.action != 'edited'
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
libdbus-1-dev \
patchelf
- name: Setup Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
components: clippy
- name: Cache Rust
uses: swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
with:
workspaces: src-tauri
cache-on-failure: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Install Bun dependencies
run: bun install --frozen-lockfile
# Build the Vite web bundle BEFORE the Rust checks so rust-embed embeds a
# non-empty dist-web/ — the web::assets tests then exercise the embedded-
# serving OK-path (200 + correct Content-Type + caching), not just the
# empty-embed 404 branch. (A missing dist-web/ would still compile green
# in debug via allow_missing, but the OK-path assertions need the bundle.)
- name: Build web client (dist-web/)
run: bun run build:web
- name: Assert dist-web/index.html exists
run: test -f dist-web/index.html && test -s dist-web/index.html
- name: Cargo check
working-directory: src-tauri
run: cargo check --all-targets
- name: Cargo test
working-directory: src-tauri
run: cargo test
- name: Cargo clippy
working-directory: src-tauri
run: cargo clippy --all-targets -- -D warnings
web-build:
name: Web Client Build
if: github.event.action != 'edited'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Install Bun dependencies
run: bun install --frozen-lockfile
- name: Build web client (dist-web/)
run: bun run build:web
- name: Assert dist-web/index.html exists
run: test -f dist-web/index.html && test -s dist-web/index.html
standalone-server-build:
name: Standalone Server Build
if: github.event.action != 'edited'
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
libdbus-1-dev \
patchelf
- name: Setup Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- name: Cache Rust
uses: swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
with:
workspaces: src-tauri
cache-on-failure: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Install Bun dependencies
run: bun install --frozen-lockfile
# Build the Vite web bundle BEFORE the cargo build so rust-embed embeds a
# non-empty `dist-web/` (build sequencing). A release build with a missing
# bundle fails clearly via the `web_embed_missing` compile_error in
# assets.rs; this dev build compiles green regardless (allow_missing), but
# the embedded bundle is exercised with real content.
- name: Build web client (dist-web/)
run: bun run build:web
- name: Assert dist-web/index.html exists
run: test -f dist-web/index.html && test -s dist-web/index.html
- name: Build termul-server (native host)
working-directory: src-tauri
run: cargo build --bin termul-server --features standalone-server
- name: Clippy termul-server (feature on)
working-directory: src-tauri
run: cargo clippy --bin termul-server --features standalone-server -- -D warnings
rust-windows-check:
name: Rust Windows Smoke Check
if: github.event.action != 'edited'
runs-on: windows-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
components: clippy
- name: Cache Rust
uses: swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
with:
workspaces: src-tauri
cache-on-failure: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Install Bun dependencies
run: bun install --frozen-lockfile
- name: Build web client (dist-web/)
run: bun run build:web
- name: Assert dist-web/index.html exists
shell: bash
run: test -f dist-web/index.html && test -s dist-web/index.html
- name: Cargo check
working-directory: src-tauri
run: cargo check --all-targets
- name: Build termul-server (Windows host)
working-directory: src-tauri
run: cargo build --bin termul-server --features standalone-server
build-check:
name: Verify Tauri Frontend Build
if: github.event.action != 'edited'
needs: [validate, rust-checks, rust-windows-check, web-build, standalone-server-build]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.x
- name: Install Bun dependencies
run: bun install --frozen-lockfile
- name: Build Tauri frontend assets
run: bun run build:frontend:tauri