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
42 changes: 42 additions & 0 deletions .github/workflows/cherry-pick-prompt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,48 @@ jobs:
echo "Cherry-pick failed due to conflicts"
fi

# A release branch carries bumped @frontmcp/* versions (e.g. 1.5.6) while main is
# still on its own line (e.g. 1.4.0) — create-release-branch.yml bumps the release
# branch only. Cherry-picking a commit that touched any package.json or yarn.lock
# therefore drags those release-line pins onto main, where every sibling package
# disagrees. Two things then break:
# 1. `yarn install --immutable` fails with YN0028 on the next push to main.
# 2. Yarn stops linking the mismatched siblings as workspaces and silently
# resolves them from the npm registry instead — main builds against published
# tarballs rather than local source.
# Rewriting the pins back to main's own version and refreshing the lockfile keeps
# the genuine change (new external deps, code) and drops only the version drag.
- name: Setup Node + Yarn
if: steps.prepare.outputs.conflict == 'false'
uses: ./.github/actions/setup-node-yarn
with:
node-version-file: ".nvmrc"
install: "false"

- name: Re-pin internal versions to the target branch line
if: steps.prepare.outputs.conflict == 'false'
shell: bash
run: |
set -euo pipefail

# No explicit version: the script infers the line held by the majority of
# workspace packages, which on main is main's line — the handful of manifests
# the cherry-pick contaminated are the minority and get corrected.
node scripts/normalize-internal-versions.mjs

# Rewrites the pins recorded in yarn.lock. Resolves offline for internal
# packages (they are workspace soft-links); only genuinely new external deps
# introduced by the cherry-pick hit the registry.
yarn install --mode=update-lockfile

if [ -n "$(git status --porcelain)" ]; then
git add -A
git commit --amend --no-edit
echo "Re-pinned internal versions and refreshed yarn.lock into the cherry-pick commit."
else
echo "No version drift introduced by this cherry-pick."
fi

- name: Push branch and create PR
if: steps.prepare.outputs.conflict == 'false'
env:
Expand Down
37 changes: 1 addition & 36 deletions .github/workflows/create-release-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ jobs:

- name: Normalize internal @frontmcp/* dep ranges
shell: bash
env:
VERSION: ${{ steps.version.outputs.initial_version }}
run: |
set -euo pipefail

Expand All @@ -137,40 +135,7 @@ jobs:
# nx release (preserveMatchingDependencyRanges), but they do NOT satisfy prereleases
# like 1.1.0-beta.1 per semver — which breaks the publish-release workflow downstream.
# Exact pins make later nx release version bumps replace cleanly for both stable and beta.
node <<'NODE'
const fs = require('fs');
const path = require('path');
const VERSION = process.env.VERSION;
const SECTIONS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
const dirs = ['libs', 'plugins'];
let totalChanged = 0;
for (const dir of dirs) {
if (!fs.existsSync(dir)) continue;
for (const entry of fs.readdirSync(dir)) {
const f = path.join(dir, entry, 'package.json');
if (!fs.existsSync(f)) continue;
const raw = fs.readFileSync(f, 'utf8');
const p = JSON.parse(raw);
let changed = false;
for (const s of SECTIONS) {
if (!p[s]) continue;
for (const k of Object.keys(p[s])) {
if (k.startsWith('@frontmcp/') && p[s][k] !== VERSION) {
console.log(` ${f} :: ${s}.${k}: ${p[s][k]} -> ${VERSION}`);
p[s][k] = VERSION;
changed = true;
}
}
}
if (changed) {
const trailingNewline = raw.endsWith('\n') ? '\n' : '';
fs.writeFileSync(f, JSON.stringify(p, null, 2) + trailingNewline);
totalChanged++;
}
}
}
console.log(`Normalized ${totalChanged} package.json file(s) to v${VERSION}`);
NODE
node scripts/normalize-internal-versions.mjs "${{ steps.version.outputs.initial_version }}"

- name: Update package versions
shell: bash
Expand Down
37 changes: 1 addition & 36 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,6 @@ jobs:

- name: Normalize internal @frontmcp/* dep ranges
shell: bash
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail

Expand All @@ -183,40 +181,7 @@ jobs:
# range untouched if its old value still satisfies the OLD package version, even when the
# NEW version no longer matches. That trips @nx/dependency-checks lint on the next push.
# We rewrite unconditionally so the working tree is internally consistent before commit.
node <<'NODE'
const fs = require('fs');
const path = require('path');
const VERSION = process.env.VERSION;
const SECTIONS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
const dirs = ['libs', 'plugins'];
let totalChanged = 0;
for (const dir of dirs) {
if (!fs.existsSync(dir)) continue;
for (const entry of fs.readdirSync(dir)) {
const f = path.join(dir, entry, 'package.json');
if (!fs.existsSync(f)) continue;
const raw = fs.readFileSync(f, 'utf8');
const p = JSON.parse(raw);
let changed = false;
for (const s of SECTIONS) {
if (!p[s]) continue;
for (const k of Object.keys(p[s])) {
if (k.startsWith('@frontmcp/') && p[s][k] !== VERSION) {
console.log(` ${f} :: ${s}.${k}: ${p[s][k]} -> ${VERSION}`);
p[s][k] = VERSION;
changed = true;
}
}
}
if (changed) {
const trailingNewline = raw.endsWith('\n') ? '\n' : '';
fs.writeFileSync(f, JSON.stringify(p, null, 2) + trailingNewline);
totalChanged++;
}
}
}
console.log(`Normalized ${totalChanged} package.json file(s) to v${VERSION}`);
NODE
node scripts/normalize-internal-versions.mjs "${{ steps.version.outputs.version }}"

- name: Refresh yarn.lock to match bumped versions
shell: bash
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ jobs:
id: node-version
run: echo "version=$(cat .nvmrc)" >> $GITHUB_OUTPUT

# Guards against a release branch's version pins leaking onto another line (the
# usual source is a cherry-pick from release/* onto main). When they do, the very
# first `yarn install --immutable` in every other job dies with a bare YN0028
# "The lockfile would have been modified by this install" — which says nothing
# about the actual cause. This job needs no install, so it fails first and names
# the drifted pins. See scripts/normalize-internal-versions.mjs.
version-consistency:
name: "Internal Version Consistency"
needs: setup
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Setup Node
uses: ./.github/actions/setup-node-yarn
with:
node-version: ${{ needs.setup.outputs.node-version }}
install: "false"

- name: Check internal @frontmcp/* version pins agree
run: node scripts/normalize-internal-versions.mjs --check

# Lint and format checks (fast, independent)
lint:
name: "Lint & Format Checks"
Expand Down
93 changes: 72 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,12 @@ scoped [Providers / DI][docs-providers].
stateful / stateless [sessions][docs-server] (JWT or UUID transport IDs).

**Connect & operate** — [Streamable HTTP + SSE transport][docs-transport],
capability [discovery][docs-discovery], [elicitation][docs-elicitation],
[hooks][docs-hooks], HTTP-discoverable [skills][docs-skills],
[external MCP sub-apps][docs-ext-apps], an in-process [Direct Client][docs-direct]
(`connectOpenAI` / `connectClaude`), and first-class [deployment][docs-deploy].
every [MCP protocol revision][docs-protocol] from `2024-11-05` through
`2026-07-28` on one endpoint, capability [discovery][docs-discovery],
[elicitation][docs-elicitation], [hooks][docs-hooks], HTTP-discoverable
[skills][docs-skills], [tool UI / MCP Apps][docs-ext-apps], an in-process
[Direct Client][docs-direct] (`connectOpenAI` / `connectClaude`), and
first-class [deployment][docs-deploy].

**Extend & tooling** — official [plugins][docs-plugins] (Cache, Remember, CodeCall,
Dashboard), the [OpenAPI adapter][docs-adapters], a [UI library][docs-ui] (HTML/React
Expand All @@ -90,18 +92,66 @@ widgets, SSR, MCP Bridge), an [E2E testing framework][docs-testing], and a

## Packages

| Package | Description |
| ------------------------------------- | ------------------------------------------------------ |
| [`@frontmcp/sdk`](libs/sdk) | Core framework — decorators, DI, flows, transport |
| [`@frontmcp/cli`](libs/cli) | CLI tooling (`frontmcp create`, `dev`, `build`) |
| [`@frontmcp/auth`](libs/auth) | Authentication, OAuth, JWKS, credential vault |
| [`@frontmcp/adapters`](libs/adapters) | OpenAPI adapter for auto-generating tools |
| [`@frontmcp/plugins`](libs/plugins) | Official plugins: Cache, Remember, CodeCall, Dashboard |
| [`@frontmcp/testing`](libs/testing) | E2E test framework with fixtures and matchers |
| [`@frontmcp/ui`](libs/ui) | React components, hooks, SSR renderers |
| [`@frontmcp/uipack`](libs/uipack) | React-free themes, build tools, platform adapters |
| [`@frontmcp/di`](libs/di) | Dependency injection container (internal) |
| [`@frontmcp/utils`](libs/utils) | Shared utilities — naming, URI, crypto, FS (internal) |
You install `frontmcp` (the CLI) and `@frontmcp/sdk`. Everything else is either
pulled in for you or opt-in.

### Core

| Package | Description |
| ----------------------------------- | --------------------------------------------------------------- |
| [`frontmcp`](libs/cli) | The CLI — `create`, `init`, `dev`, `build`, `inspect`, `doctor` |
| [`@frontmcp/sdk`](libs/sdk) | Core framework — decorators, DI, flows, transport, MCP protocol |
| [`@frontmcp/auth`](libs/auth) | Authentication, OAuth, JWKS, DCR/CIMD, credential vault |
| [`@frontmcp/testing`](libs/testing) | E2E test framework with fixtures and matchers |

### Extend

| Package | Description |
| ----------------------------------------------- | ------------------------------------------------------------- |
| [`@frontmcp/plugins`](libs/plugins) | Plugin authoring toolkit + official plugin re-exports |
| [`@frontmcp/adapters`](libs/adapters) | OpenAPI adapter — generate tools from an OpenAPI spec |
| [`@frontmcp/skills`](libs/skills) | Curated SKILL.md catalog for scaffolding and `skills install` |
| [`@frontmcp/guard`](libs/guard) | Policy/guard rules for tool inputs and outputs |
| [`@frontmcp/observability`](libs/observability) | Structured logging, metrics, and tracing helpers |

### UI

| Package | Description |
| --------------------------------- | ----------------------------------------------------- |
| [`@frontmcp/react`](libs/react) | React hooks + client for talking to a FrontMCP server |
| [`@frontmcp/ui`](libs/ui) | React components, SSR renderers, MCP Bridge |
| [`@frontmcp/uipack`](libs/uipack) | React-free themes, build tools, platform adapters |

### Runtime & storage

| Package | Description |
| ------------------------------------------------- | -------------------------------------------------------------- |
| [`@frontmcp/edge`](libs/edge) | Run a server on Cloudflare Workers / V8 isolates from a config |
| [`@frontmcp/storage-sqlite`](libs/storage-sqlite) | SQLite-backed session, task, and elicitation stores |
| [`@frontmcp/nx`](libs/nx-plugin) | Nx generators and executors for FrontMCP workspaces |

### Internal

Published so the packages above resolve, but not intended for direct use:

| Package | Description |
| ------------------------------------- | ------------------------------------------------------------ |
| [`@frontmcp/protocol`](libs/protocol) | The single boundary to the upstream MCP SDK — protocol types |
| [`@frontmcp/di`](libs/di) | Dependency injection container |
| [`@frontmcp/utils`](libs/utils) | Shared utilities — naming, URI, crypto, FS |
| [`@frontmcp/lazy-zod`](libs/lazy-zod) | Lazily-loaded Zod wrapper that keeps cold starts small |

### Official plugins

| Package | Description |
| -------------------------------------------------------------------- | -------------------------------------------- |
| [`@frontmcp/plugin-cache`](plugins/plugin-cache) | Cache tool results with a TTL |
| [`@frontmcp/plugin-remember`](plugins/plugin-remember) | Per-session memory (`this.remember`) |
| [`@frontmcp/plugin-approval`](plugins/plugin-approval) | Human approval gates before a tool runs |
| [`@frontmcp/plugin-codecall`](plugins/plugin-codecall) | Let the model compose tool calls as code |
| [`@frontmcp/plugin-dashboard`](plugins/plugin-dashboard) | Built-in web dashboard |
| [`@frontmcp/plugin-feature-flags`](plugins/plugin-feature-flags) | Toggle tools and apps at runtime |
| [`@frontmcp/plugin-skilled-openapi`](plugins/plugin-skilled-openapi) | OpenAPI → skills + meta-tools for large APIs |

## Version Alignment

Expand All @@ -120,7 +170,7 @@ PRs welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow, coding stand
[docs-home]: https://docs.agentfront.dev/frontmcp 'FrontMCP Docs'
[docs-install]: https://docs.agentfront.dev/frontmcp/getting-started/installation 'Installation'
[docs-quickstart]: https://docs.agentfront.dev/frontmcp/getting-started/quickstart 'Quickstart'
[docs-sdk-ref]: https://docs.agentfront.dev/frontmcp/sdk-reference/overview 'SDK Reference'
[docs-sdk-ref]: https://docs.agentfront.dev/frontmcp/sdk-reference/decorators/overview 'SDK Reference'
[docs-server]: https://docs.agentfront.dev/frontmcp/servers/server 'The FrontMCP Server'
[docs-apps]: https://docs.agentfront.dev/frontmcp/servers/apps 'Apps'
[docs-tools]: https://docs.agentfront.dev/frontmcp/servers/tools 'Tools'
Expand All @@ -130,15 +180,16 @@ PRs welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow, coding stand
[docs-elicitation]: https://docs.agentfront.dev/frontmcp/servers/elicitation 'Elicitation'
[docs-skills]: https://docs.agentfront.dev/frontmcp/servers/skills 'Skills'
[docs-discovery]: https://docs.agentfront.dev/frontmcp/servers/discovery 'Discovery'
[docs-protocol]: https://docs.agentfront.dev/frontmcp/fundamentals/protocol-versions 'Protocol Versions'
[docs-auth]: https://docs.agentfront.dev/frontmcp/authentication/overview 'Authentication'
[docs-direct]: https://docs.agentfront.dev/frontmcp/deployment/direct-client 'Direct Client'
[docs-transport]: https://docs.agentfront.dev/frontmcp/deployment/transport 'Transport'
[docs-ext-apps]: https://docs.agentfront.dev/frontmcp/servers/ext-apps 'Ext-Apps'
[docs-hooks]: https://docs.agentfront.dev/frontmcp/extensibility/hooks 'Hooks'
[docs-transport]: https://docs.agentfront.dev/frontmcp/deployment/transport-security 'Transport'
[docs-ext-apps]: https://docs.agentfront.dev/frontmcp/guides/building-tool-ui 'Tool UI / MCP Apps'
[docs-hooks]: https://docs.agentfront.dev/frontmcp/sdk-reference/decorators/hooks 'Hooks'
[docs-providers]: https://docs.agentfront.dev/frontmcp/extensibility/providers 'Providers'
[docs-plugins]: https://docs.agentfront.dev/frontmcp/plugins/overview 'Plugins'
[docs-adapters]: https://docs.agentfront.dev/frontmcp/adapters/overview 'Adapters'
[docs-testing]: https://docs.agentfront.dev/frontmcp/testing/overview 'Testing'
[docs-ui]: https://docs.agentfront.dev/frontmcp/ui/overview 'UI Library'
[docs-ui]: https://docs.agentfront.dev/frontmcp/react/overview 'React SDK'
[docs-deploy]: https://docs.agentfront.dev/frontmcp/deployment/local-dev-server 'Deployment'
[docs-production]: https://docs.agentfront.dev/frontmcp/deployment/production-build 'Production Build'
Loading
Loading