Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .changeset/clean-jobs-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cybermem/dashboard": minor
"@cybermem/cli": minor
"@cybermem/mcp": minor
---

Moved server tools usage to FastMCP
Comment thread
mikhailkogan17 marked this conversation as resolved.
11 changes: 6 additions & 5 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "mikhailkogan17/cybermem" }],
"commit": false,
"fixed": [],
"linked": [
["@cybermem/cli", "@cybermem/mcp", "@cybermem/dashboard"]
"changelog": [
"@changesets/changelog-github",
{ "repo": "mikhailkogan17/cybermem" }
],
"commit": false,
"fixed": [["@cybermem/cli", "@cybermem/mcp", "@cybermem/dashboard"]],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
Expand Down
144 changes: 62 additions & 82 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@ name: Publish

on:
workflow_dispatch:
inputs:
version_type:
description: "Bump type (patch, minor, major, none)"
type: choice
options:
- patch
- minor
- major
- none
default: patch

# Prevent concurrent publish workflows
concurrency:
Expand All @@ -36,20 +26,14 @@ jobs:
with:
fetch-depth: 0

- name: Verify Changesets Exist
- name: Verify Prerequisites
run: |
# If version_type is NOT 'none', we will auto-generate a changeset if needed.
# If version_type IS 'none', we require existing changesets if we want to publish.
if [ "${{ github.event.inputs.version_type }}" != "none" ] && [ "${{ github.event.inputs.version_type }}" != "" ]; then
echo "✅ version_type is '${{ github.event.inputs.version_type }}'; proceeding with auto-changeset capability."
exit 0
fi

if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
echo "❌ ERROR: No changesets found! Please create one with 'npm run changeset' or use workflow_dispatch with a version_type."
exit 1
# Patch-by-default: if no changesets exist, we'll auto-create a patch changeset later
if [ -n "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
echo "✅ Changesets found — will apply as-is (minor/major/patch per changeset)"
else
echo "✅ No changesets found — will auto-create patch bump"
fi
echo "✅ Changesets found and ready to publish."

# ==================================================================
# 2. E2E CHECKS
Expand Down Expand Up @@ -103,50 +87,42 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Auto-generate changeset if version_type is provided and no changesets exist
if [ "${{ github.event.inputs.version_type }}" != "none" ] && [ "${{ github.event.inputs.version_type }}" != "" ]; then
if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
echo "📝 Creating automated changeset for ${{ github.event.inputs.version_type }} bump"
cat > .changeset/automated-bump.md << 'CHANGESET'
# Patch-by-default: auto-create patch changeset if none exist
if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
echo "📝 No changesets found — creating automated patch bump"
cat > .changeset/automated-patch.md << 'CHANGESET'
---
"@cybermem/cli": ${{ github.event.inputs.version_type }}
"@cybermem/mcp": ${{ github.event.inputs.version_type }}
"@cybermem/dashboard": ${{ github.event.inputs.version_type }}
"@cybermem/cli": patch
"@cybermem/mcp": patch
"@cybermem/dashboard": patch
---

Automated ${{ github.event.inputs.version_type }} version bump.
Automated patch version bump.
CHANGESET
fi
fi
Comment thread
mikhailkogan17 marked this conversation as resolved.

# Check for changesets
if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
echo "⚠️ No changesets to apply"
echo "has_changesets=false" >> $GITHUB_OUTPUT
# Use current version as-is
VERSION=$(node -p "require('./packages/cli/package.json').version")
else
echo "has_changesets=true" >> $GITHUB_OUTPUT

# Apply changesets to bump versions and update per-package CHANGELOGs
npm run version

# Regenerate package-lock.json to reflect updated package.json files
npm install --package-lock-only
# Apply changesets to bump versions
npm run version
npm install --package-lock-only
VERSION=$(node -p "require('./packages/cli/package.json').version")
echo "📦 Version after changesets: $VERSION"

VERSION=$(node -p "require('./packages/cli/package.json').version")
echo "📦 Version after changesets: $VERSION"
fi

# Check if this version is already published on npm
# Safety: check if this version is already published on npm
NPM_CHECK_OUTPUT=$(npm view "@cybermem/cli@$VERSION" version 2>&1) || true
if [ -n "$NPM_CHECK_OUTPUT" ] && echo "$NPM_CHECK_OUTPUT" | grep -qE "^[0-9]+\.[0-9]+\.[0-9]+"; then
echo "⚠️ Version $VERSION already published on npm — auto-bumping patch"
echo "⚠️ Version $VERSION already published on npm — auto-bumping via changeset"
BUMP_ID=$(node -p "require('crypto').randomUUID()")
cat > ".changeset/${BUMP_ID}.md" << 'CHANGESET'
---
"@cybermem/cli": patch
"@cybermem/mcp": patch
"@cybermem/dashboard": patch
---

# Bump patch across all workspaces (no git tag)
npm version patch --workspaces --no-git-tag-version
Auto-bump: previous version already published.
CHANGESET
npm run version
npm install --package-lock-only

VERSION=$(node -p "require('./packages/cli/package.json').version")
echo "📦 Auto-bumped to: $VERSION"
Comment thread
mikhailkogan17 marked this conversation as resolved.
else
Expand Down Expand Up @@ -422,47 +398,51 @@ jobs:
CURRENT_VERSION="${{ steps.branch.outputs.current_version }}"
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT

# Auto-generate changeset if version_type is provided and no changesets exist
if [ "${{ github.event.inputs.version_type }}" != "none" ] && [ "${{ github.event.inputs.version_type }}" != "" ]; then
if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
echo "📝 Creating automated changeset for ${{ github.event.inputs.version_type }} bump"
cat > .changeset/automated-bump.md << 'CHANGESET'
# Patch-by-default: auto-create patch changeset if none exist
if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
echo "📝 No changesets found — creating automated patch bump"
cat > .changeset/automated-patch.md << 'CHANGESET'
---
"@cybermem/cli": ${{ github.event.inputs.version_type }}
"@cybermem/mcp": ${{ github.event.inputs.version_type }}
"@cybermem/dashboard": ${{ github.event.inputs.version_type }}
"@cybermem/cli": patch
"@cybermem/mcp": patch
"@cybermem/dashboard": patch
---

Automated ${{ github.event.inputs.version_type }} version bump.
Automated patch version bump.
CHANGESET
fi
fi

# Apply changesets — this bumps versions in package.json files and generates per-package CHANGELOGs
if [ -n "$(ls -A .changeset/*.md 2>/dev/null | grep -v README.md)" ]; then
npm run version
npm install --package-lock-only
echo "✅ Changesets applied"
else
echo "⚠️ No changesets to apply"
fi
# Apply changesets — bumps versions in package.json
npm run version
npm install --package-lock-only
echo "✅ Changesets applied"

# Align package.json versions to match what was actually published.
# This handles the auto-bump case where publish-npm bumped beyond what changesets produced.
# Align package.json versions to match what was actually published
CHANGESET_VERSION=$(node -p "require('./packages/cli/package.json').version")
if [ "$CHANGESET_VERSION" != "$CURRENT_VERSION" ]; then
echo "📦 Aligning package versions: changesets=$CHANGESET_VERSION -> published=$CURRENT_VERSION"
npm version "$CURRENT_VERSION" --workspaces --no-git-tag-version
npm install --package-lock-only
fi

# Extract release notes from CLI package CHANGELOG.md (changesets creates package-level CHANGELOGs)
# 1. awk: extract content between "## VERSION" and the next "## " header
# 2. awk: strip leading blank lines (skip until first non-empty)
# 3. awk: strip trailing blank lines (buffer all, print up to last non-empty)
CHANGELOG_FILE="packages/cli/CHANGELOG.md"
if [ -f "$CHANGELOG_FILE" ] && grep -q "## $CURRENT_VERSION" "$CHANGELOG_FILE"; then
awk "/## $CURRENT_VERSION/,/^## / {if (/^## $CURRENT_VERSION/) next; if (/^## /) exit; print}" "$CHANGELOG_FILE" > release_notes_raw.md
# Move CHANGELOG [Unreleased] → [VERSION]
CHANGELOG_FILE="CHANGELOG.md"
DATE=$(date +%Y-%m-%d)
if [ -f "$CHANGELOG_FILE" ] && grep -q '\[Unreleased\]' "$CHANGELOG_FILE"; then
echo "📝 Moving [Unreleased] to [$CURRENT_VERSION] in CHANGELOG.md"
# Replace [Unreleased] header with [VERSION] - DATE, and add fresh [Unreleased]
# Note: sed -i with \n works on GNU sed (Linux/GitHub Actions runners)
sed -i "s/## \[Unreleased\]/## [Unreleased]\n\n### Changed\n\n### Fixed\n\n## [$CURRENT_VERSION] - $DATE/" "$CHANGELOG_FILE"
Comment thread
mikhailkogan17 marked this conversation as resolved.
fi

# Extract release notes from root CHANGELOG.md (SSoT)
if grep -q "## \[$CURRENT_VERSION\]" "$CHANGELOG_FILE"; then
awk "
BEGIN { in_section=0 }
/^## \[$CURRENT_VERSION\]/ { in_section=1; next }
/^## \[/ && in_section { exit }
in_section { print }
" "$CHANGELOG_FILE" > release_notes_raw.md
awk 'NF {p=1} p' release_notes_raw.md | awk '{a[NR]=$0} END {while(NR && !a[NR]) NR--; for(i=1;i<=NR;i++) print a[i]}' > release_notes.md
rm -f release_notes_raw.md
else
Expand Down
97 changes: 16 additions & 81 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,29 @@
# Changelog

All notable changes to this project will be documented in this file.
## [Unreleased]

### Added

- **MCP**: Migrated to `FastMCP` for better DX and session management.
- **MCP**: Added `httpStream` session tracking with 2-step handshake (POST /mcp -> GET /mcp).
- **MCP**: Added `X-Client-Name` authentication to FastMCP core.
- **MCP**: New `postbuild.js` script for portable shebang enforcement.

### Changed

- **MCP**: Default transport endpoint moved from `/sse` to `/mcp`.
- **Infrastructure**: Renamed `operation` column to `tool` in all audit tables.
- **E2E**: Realignment of global setup and test suites with the new handshake protocol.

### Fixed

- **MCP**: Robust database migrations using `PRAGMA table_info`.
- **Dashboard**: Added fallback support for legacy database schemas missing the `tool` column.
- **CLI**: Restored `ollama` profile gating in docker-compose templates.


## [0.13.16] - 2026-02-11

### Added

### Changed

### Fixed

### Removed


## [0.13.14] - 2026-02-10

### Added

### Changed

### Fixed

### Removed


## [0.13.13] - 2026-02-09

### Added

### Changed

### Fixed

### Removed


## [0.13.12] - 2026-02-09

### Added

### Changed

### Fixed

### Removed


## [0.13.11] - 2026-02-09

### Added
## [Unreleased]

### Changed

### Fixed

### Removed


## [0.13.10] - 2026-02-09

### Added

### Changed
- **MCP**: Migrated from custom Express server to **FastMCP** framework
- **MCP**: Switched transport from legacy SSE to Streamable HTTP (`httpStream`)
- **MCP**: Added native FastMCP authentication support
- **MCP**: Disabled `stateless` mode to enable proper `mcp-session-id` generation
- **MCP**: Made database migration errors fatal (`process.exit(1)`)
- **E2E**: Extracted shared `FastMCPHandshakeTransport` test utility
- **E2E**: Replaced hardcoded delays with event-driven stream readiness
- **E2E**: Added MCP JSON-RPC protocol verification to `global-setup.ts`
- **Release**: Switched to patch-by-default publish (no manual version_type input)
- **Release**: Added `npm run version:minor` / `version:major` scripts for explicit bumps
Comment thread
mikhailkogan17 marked this conversation as resolved.

### Fixed

### Removed


- **MCP**: Fixed `stateless: true` suppressing session IDs in httpStream mode
- **MCP**: Fixed CI E2E failures caused by missing `mcp-session-id` header
- **MCP**: Fixed `update_memory` tool missing validation for required fields
- **MCP**: Fixed migration logic for `cybermem_stats` table missing `tool` column fallback
- **Dashboard**: Added fallback for legacy databases missing `tool` column in audit logs

## [0.13.9] - 2026-02-09

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"mcp:dev": "npm run dev -w packages/mcp",
"changeset": "changeset",
"version": "changeset version",
"version:minor": "node -e \"const fs=require('fs');const{randomUUID}=require('crypto');const id=randomUUID();const file='.changeset/'+id+'.md';fs.writeFileSync(file,'---\\n\\\"@cybermem/cli\\\": minor\\n\\\"@cybermem/mcp\\\": minor\\n\\\"@cybermem/dashboard\\\": minor\\n---\\n\\nMinor version bump.\\n');console.log('✅ Created minor changeset: '+file)\"",
"version:major": "node -e \"const fs=require('fs');const{randomUUID}=require('crypto');const id=randomUUID();const file='.changeset/'+id+'.md';fs.writeFileSync(file,'---\\n\\\"@cybermem/cli\\\": major\\n\\\"@cybermem/mcp\\\": major\\n\\\"@cybermem/dashboard\\\": major\\n---\\n\\nMajor version bump.\\n');console.log('✅ Created major changeset: '+file)\"",
"release": "npm run build && changeset publish"
},
"devDependencies": {
Expand Down