Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.git
.github
git-backup-*
docs
briefs
*.md
!README.md
java/build
java/.gradle
adapters/node_modules
adapters/dist
dist
*.db
*.sqlite
*.log
.env*
56 changes: 9 additions & 47 deletions .github/workflows/mcphub-ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: MCPHUB CI
name: MCPHUB Internal CI

on:
pull_request:
Expand All @@ -10,53 +10,15 @@ permissions:
contents: read

jobs:
java-test:
name: Java Tests (Gradle)
validate:
name: Validate Docs
runs-on: ubuntu-latest
defaults:
run:
working-directory: java
steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('java/**/*.gradle*', 'java/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Compile Java
run: ./gradlew compileJava

- name: Run Java tests
run: ./gradlew test

go-build:
name: Go Build & Vet
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'

- name: Go build
run: go build ./...

- name: Go vet
run: go vet ./...
- name: Check required docs exist
run: |
for f in CLAUDE.md docs/ lessons.md; do
[ -e "$f" ] || { echo "MISSING: $f"; exit 1; }
done
echo "All required docs present."
91 changes: 91 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Release

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Release tag to build (for example: v0.2.1-relpipe-test)'
required: true
type: string
product_name:
description: 'Product/archive binary name'
required: false
default: mcphub
type: string
prerelease:
description: 'Mark the GitHub Release as a prerelease'
required: false
default: true
type: boolean

permissions:
contents: write

jobs:
release:
name: Build and publish release assets
runs-on: ubuntu-latest
env:
PRODUCT_NAME: ${{ inputs.product_name || 'mcphub' }}
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
steps:
- name: Checkout release source
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
fetch-depth: 0

- name: Set up Java 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm
cache-dependency-path: adapters/package-lock.json

- name: Derive release version
id: release_meta
run: echo "version=${RELEASE_TAG#v}" >> "$GITHUB_OUTPUT"

- name: Build release archives
run: make release VERSION="${{ steps.release_meta.outputs.version }}" PRODUCT_NAME="$PRODUCT_NAME"

- name: Verify release artifact manifest
run: |
set -euo pipefail
cd dist/release
expected=(
"${PRODUCT_NAME}-${{ steps.release_meta.outputs.version }}-linux-amd64.tar.gz"
"${PRODUCT_NAME}-${{ steps.release_meta.outputs.version }}-darwin-amd64.tar.gz"
"${PRODUCT_NAME}-${{ steps.release_meta.outputs.version }}-darwin-arm64.tar.gz"
"sha256sums.txt"
)
for file in "${expected[@]}"; do
test -f "$file" || { echo "missing release asset: $file"; exit 1; }
done
actual_tar_count=$(ls "${PRODUCT_NAME}-${{ steps.release_meta.outputs.version }}"-*.tar.gz | wc -l | tr -d ' ')
test "$actual_tar_count" = "3" || { echo "expected 3 tar.gz assets, got $actual_tar_count"; exit 1; }
sha256sum -c sha256sums.txt

- name: Publish GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.RELEASE_TAG }}
name: ${{ env.RELEASE_TAG }}
prerelease: ${{ inputs.prerelease || contains(env.RELEASE_TAG, '-') }}
files: |
dist/release/${{ env.PRODUCT_NAME }}-${{ steps.release_meta.outputs.version }}-*.tar.gz
dist/release/sha256sums.txt
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ credentials*
*.sqlite3

# Logs
*.log
*.log
# Git backup directories
git-backup-*/
8 changes: 8 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title = "MCPHUB curated export gitleaks allowlist"

[allowlist]
description = "Synthetic test fixtures documented as non-real credentials."
paths = [
'''java/src/test/java/dev/sorted/mcphub/SecretScannerTest\.java''',
'''java/src/test/java/dev/sorted/mcphub/McpHandlerTest\.java''',
]
5 changes: 5 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# P1-pre curated export fixture allowlist notes.
# SecretScannerTest.java and McpHandlerTest.java contain synthetic test fixtures
# documented as non-real credentials. Current gitleaks directory-scan
# fingerprints include absolute output paths, so deterministic fixture
# allowlisting is enforced in .gitleaks.toml below.
61 changes: 61 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# MCPHUB Docker Image — BL-07
# Multi-stage build: build everything, then create minimal runtime image.
#
# Build: docker build -t mcphub .
# Run: docker run --rm -it -v /tmp/mcphub:/data mcphub
# Bridge: docker run --rm -i mcphub bridge

# ──────────────────────────────────────────────────
# Stage 1: Build
# ──────────────────────────────────────────────────
FROM eclipse-temurin:21-jdk AS java-build
WORKDIR /build/java
COPY java/ .
RUN chmod +x gradlew && ./gradlew jar --no-daemon

FROM golang:1.25-bookworm AS go-build
WORKDIR /build
COPY go.mod ./
COPY cmd/ cmd/
RUN go build -o mcphub ./cmd/mcphub

FROM node:20-slim AS ts-build
WORKDIR /build/adapters
COPY adapters/package.json adapters/package-lock.json* ./
RUN npm install --silent
COPY adapters/ .
RUN npx tsc --build

# ──────────────────────────────────────────────────
# Stage 2: Runtime
# ──────────────────────────────────────────────────
FROM eclipse-temurin:21-jre-noble

RUN apt-get update && apt-get install -y --no-install-recommends \
nodejs \
&& rm -rf /var/lib/apt/lists/*

# Create non-root user
RUN useradd -m -s /bin/bash mcphub

# Distribution layout: bin/ lib/ adapters/
WORKDIR /opt/mcphub

COPY --from=go-build /build/mcphub bin/mcphub
COPY --from=java-build /build/java/build/libs/mcphub-core-*.jar lib/mcphub-core.jar
COPY --from=ts-build /build/adapters/dist/ adapters/
COPY README.md LICENSE ./

RUN chmod +x bin/mcphub && chown -R mcphub:mcphub /opt/mcphub

USER mcphub

# Data directory
RUN mkdir -p /home/mcphub/.local/share/mcphub

ENV PATH="/opt/mcphub/bin:${PATH}"
ENV MCPHUB_DATA_DIR="/home/mcphub/.local/share/mcphub"
ENV MCPHUB_ADAPTER_DIR="/opt/mcphub/adapters"

ENTRYPOINT ["mcphub"]
CMD ["_daemon"]
Loading
Loading