Skip to content
Draft
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
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CI

on:
push:
branches: ['*']
pull_request:
branches: ['main']

permissions:
contents: read

jobs:
test-mcp:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: '1.25'
cache-dependency-path: go.sum

- name: Build MCP binary
run: go build -o penopt-mcp ./cmd/penopt-mcp

- name: Run MCP tests
run: go test -v -timeout 120s ./cmd/penopt-mcp/...

- name: Vet
run: go vet ./cmd/penopt-mcp/...
82 changes: 78 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ permissions:
contents: write

jobs:
# ── GUI: Linux ──
build-linux:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.25'

- uses: actions/setup-node@v4
with:
Expand Down Expand Up @@ -47,14 +48,15 @@ jobs:
name: penopt-linux
path: build/bin/penopt-linux-amd64

# ── GUI: Windows ──
build-windows:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.25'

- uses: actions/setup-node@v4
with:
Expand Down Expand Up @@ -85,6 +87,7 @@ jobs:
name: penopt-windows
path: build/bin/penopt-windows-amd64.exe

# ── GUI: macOS ──
build-macos:
strategy:
matrix:
Expand All @@ -95,7 +98,7 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.25'

- uses: actions/setup-node@v4
with:
Expand All @@ -121,8 +124,46 @@ jobs:
name: penopt-macos-${{ matrix.arch }}
path: build/bin/penopt-darwin-${{ matrix.arch }}

# ── MCP Server: cross-compile from a single ubuntu runner ──
build-mcp:
strategy:
matrix:
include:
- goos: linux
goarch: amd64
ext: ""
- goos: windows
goarch: amd64
ext: ".exe"
- goos: darwin
goarch: amd64
ext: ""
- goos: darwin
goarch: arm64
ext: ""
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: '1.25'
cache-dependency-path: go.sum

- name: Build MCP binary
run: |
GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \
go build -o penopt-mcp-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }} \
./cmd/penopt-mcp

- uses: actions/upload-artifact@v4
with:
name: penopt-mcp-${{ matrix.goos }}-${{ matrix.goarch }}
path: penopt-mcp-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }}

# ── Create GitHub Release ──
release:
needs: [build-linux, build-windows, build-macos]
needs: [build-linux, build-windows, build-macos, build-mcp]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
Expand All @@ -147,18 +188,47 @@ jobs:
name: penopt-macos-arm64
path: artifacts/

- uses: actions/download-artifact@v4
with:
name: penopt-mcp-linux-amd64
path: artifacts/

- uses: actions/download-artifact@v4
with:
name: penopt-mcp-windows-amd64
path: artifacts/

- uses: actions/download-artifact@v4
with:
name: penopt-mcp-darwin-amd64
path: artifacts/

- uses: actions/download-artifact@v4
with:
name: penopt-mcp-darwin-arm64
path: artifacts/

- name: Generate release notes
run: |
cat > release-notes.md << 'EOF'
## Downloads

### Desktop App (GUI)
| Platform | Arch | Binary |
|---|---|---|
| Linux | amd64 | `penopt-linux-amd64` |
| Windows | amd64 | `penopt-windows-amd64.exe` |
| macOS | Intel | `penopt-darwin-amd64` |
| macOS | Apple Silicon | `penopt-darwin-arm64` |

### MCP Server (AI Assistant Integration)
| Platform | Arch | Binary |
|---|---|---|
| Linux | amd64 | `penopt-mcp-linux-amd64` |
| Windows | amd64 | `penopt-mcp-windows-amd64.exe` |
| macOS | Intel | `penopt-mcp-darwin-amd64` |
| macOS | Apple Silicon | `penopt-mcp-darwin-arm64` |

Full changelog: https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md
EOF

Expand All @@ -173,3 +243,7 @@ jobs:
artifacts/penopt-windows-amd64.exe
artifacts/penopt-darwin-amd64
artifacts/penopt-darwin-arm64
artifacts/penopt-mcp-linux-amd64
artifacts/penopt-mcp-windows-amd64.exe
artifacts/penopt-mcp-darwin-amd64
artifacts/penopt-mcp-darwin-arm64
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ frontend/dist/
# ── Build output ────────────────────────────────────────────
build/bin/
build/*/bin/
/penopt-mcp*

# ── Dependencies ────────────────────────────────────────────
node_modules/
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ All notable changes to PenOpt will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.0] - 2026-05-15

### Added

- **MCP server** (`penopt-mcp`): headless binary for AI assistant integration
- `load_mesh` — load STL/OBJ files, parse, center, build BVH, return metadata
- `get_mesh_info` — return mesh metadata without reloading
- `evaluate_orientation` — score a single (θ, φ) orientation
- `run_optimization` — full coarse→fine grid search with progress notifications
- Context cancellation: search stops cleanly if client disconnects
- Progress sent via MCP notifications and stderr
- Input validation with LLM-friendly error messages
- GitHub Actions CI/CD for MCP server:
- `ci.yml` — build + test + vet on every push and PR
- `release.yml` — cross-compile MCP binaries for linux, windows, darwin (amd64 + arm64)
- 8 binaries per release: 4 GUI + 4 MCP

### Changed

- Bumped minimum Go version from 1.23 to 1.25 (required by go-sdk dependency)
- `search.Run()` now accepts `context.Context` for cancellation support

## [0.2.0] - 2026-05-14

### Changed
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,34 @@ The UI uses a dark theme with Inter and JetBrains Mono, material filter tabs wit

---

## AI Integration (MCP)

PenOpt ships a headless **MCP server** that lets AI assistants like Claude load meshes and run CT orientation optimization directly. Your mesh data never leaves your machine — communication is over local stdin/stdout.

```bash
# Download penopt-mcp from the latest release, then configure:
claude mcp add penopt -- /usr/local/bin/penopt-mcp
```

Then just ask:

> *"Load /home/user/part.stl and find the optimal CT scan orientation."*

**Supported clients:** Claude Desktop, Claude Code, and any MCP-compatible AI client.

[Full setup guide →](cmd/penopt-mcp/README.md)

### Available Tools

| Tool | What it does |
|---|---|
| `load_mesh` | Load STL/OBJ file, parse, center, build BVH |
| `get_mesh_info` | Return mesh metadata |
| `evaluate_orientation` | Score a single (θ, φ) orientation |
| `run_optimization` | Full coarse→fine grid search with diagnostics |

---

## Worked Example

> **Scenario:** A 50 mm Inconel 718 turbine blade, scanned at 450 kV with a 1 mm Cu pre-filter on a Nikon XTH 225. The default orientation (as-printed, upright) yields a maximum X-ray path length of ~85 mm through the thickest cross-section.
Expand Down
Loading
Loading