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
88 changes: 88 additions & 0 deletions .github/workflows/build-mcpb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,91 @@ jobs:
files: limner-mcp.mcpb
name: ${{ github.ref_name }}
generate_release_notes: true

# Re-publish the official MCP Registry entry so it advertises this release's
# .mcpb package. Registry versions are immutable, so each release must carry a
# new version string (server.json / package.json bump); a re-run of an already
# published version is tolerated rather than failed. us.limner is a DNS-verified
# namespace, so this authenticates with the ECDSA-P384 DNS key (NOT github-oidc,
# which only covers io.github.* namespaces).
#
# Prereq (one-time, manual): store the DNS private key as a repo secret —
# gh secret set MCP_REGISTRY_DNS_KEY < ~/.secrets/limner/mcp-registry-dns.pem
# Until that secret exists this job runs green and no-ops.
#
# NB: confirm the `mcp-publisher` install asset name and `login dns` flag names
# against the installed CLI version during the first manual publish; adjust if
# the CLI surface has changed.
publish-registry:
name: Publish to MCP Registry
needs: pack
if: startsWith(github.ref, 'refs/tags/mcpb-v')
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Download packed bundle
uses: actions/download-artifact@v7
with:
name: limner-mcp.mcpb

- name: Gate on DNS key secret
id: gate
env:
MCP_REGISTRY_DNS_KEY: ${{ secrets.MCP_REGISTRY_DNS_KEY }}
run: |
if [ -n "$MCP_REGISTRY_DNS_KEY" ]; then
echo "has_key=true" >> "$GITHUB_OUTPUT"
else
echo "has_key=false" >> "$GITHUB_OUTPUT"
echo "::notice::MCP_REGISTRY_DNS_KEY not set; skipping registry publish."
fi

- name: Install mcp-publisher
if: steps.gate.outputs.has_key == 'true'
run: |
set -euo pipefail
curl -fsSL -o mcp-publisher.tar.gz \
"https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz"
tar -xzf mcp-publisher.tar.gz mcp-publisher
sudo install -m 0755 mcp-publisher /usr/local/bin/mcp-publisher

- name: Pin server.json to this release asset
if: steps.gate.outputs.has_key == 'true'
run: |
set -euo pipefail
VERSION="${GITHUB_REF_NAME#mcpb-v}"
SHA="$(shasum -a 256 limner-mcp.mcpb | cut -d' ' -f1)"
URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/limner-mcp.mcpb"
tmp="$(mktemp)"
jq --arg v "$VERSION" --arg url "$URL" --arg sha "$SHA" '
.version = $v
| .packages = [ ((.packages[0] // {}) + {
registry_type: "mcpb",
identifier: $url,
file_sha256: $sha
}) ]
' server.json > "$tmp" && mv "$tmp" server.json
echo "Prepared server.json for ${VERSION}:"
cat server.json

- name: Authenticate (DNS)
if: steps.gate.outputs.has_key == 'true'
env:
MCP_REGISTRY_DNS_KEY: ${{ secrets.MCP_REGISTRY_DNS_KEY }}
run: |
set -euo pipefail
umask 077
printf '%s' "$MCP_REGISTRY_DNS_KEY" > mcp-dns.pem
mcp-publisher login dns --domain limner.us --private-key mcp-dns.pem --algorithm ecdsap384

- name: Publish (tolerate already-published version)
if: steps.gate.outputs.has_key == 'true'
run: |
mcp-publisher publish || echo "::warning::mcp-publisher publish returned non-zero (version may already be published); continuing."

- name: Scrub key
if: always()
run: rm -f mcp-dns.pem
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.0.1] - 2026-07-07

Distribution and documentation release. Generation, composition, memory, and
transport behavior are unchanged from 1.0.0; the `.mcpb` bundle and Workers
surface are functionally identical.

### Added
- Privacy Policy section in the README and a `privacy_policies` entry in the
`.mcpb` manifest, covering bring-your-own-key handling, provider calls,
durable memory, and artifact storage (a Claude Connectors Directory
prerequisite).
- The official MCP Registry entry now advertises the downloadable `.mcpb`
package alongside the hosted remote: `server.json` gains an `mcpb` package
pinned to the release asset by SHA-256.
- CI re-publishes the registry entry on each `mcpb-v*` tag, so registry metadata
tracks releases instead of drifting.

## [1.0.0] - 2026-06-29

v1.0.0 is the first public release — the foundation (`rasa`) variant of the
Expand Down Expand Up @@ -97,5 +114,6 @@ state (D-RA-04, D-RA-15), and the CMA→D1 memory migration.
outside the test suite (Workers: modules now statically imported and attached
to the bundle; stdio: loaded via `createRequire` at boot). (r1)

[Unreleased]: https://github.com/vinsonconsulting/limner/compare/v1.0.0...HEAD
[Unreleased]: https://github.com/vinsonconsulting/limner/compare/v1.0.1...HEAD
[1.0.1]: https://github.com/vinsonconsulting/limner/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/vinsonconsulting/limner/releases/tag/v1.0.0
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ family. You deploy rasa as your own instance: free as in beer, no strings or dat
- [Tool Surface](#tool-surface)
- [Memory](#memory)
- [Security](#security)
- [Privacy Policy](#privacy-policy)
- [Prerequisites](#prerequisites)
- [Quickstart](#quickstart)
- [Testing and feedback](#testing-and-feedback)
Expand Down Expand Up @@ -160,6 +161,34 @@ own instance:
and no credentials; only the generation tools and the five `cf*` ops reach
outside the isolate, and only with the provider key you supplied.

## Privacy Policy

Limner is bring-your-own-key software. It collects no analytics and sends no
telemetry to the author. Anything that leaves your machine leaves only because
a tool you called needs it:

- **Provider calls.** When you run a generation tool, the prompt text and any
reference images you pass are sent to the provider that backs it: OpenAI for
`limner_generate_dalle`, Recraft for `limner_generate_recraft` and the
`limner_upscale` / `limner_vectorize` tools. Those providers process that data
under their own privacy terms. `limner_generate_midjourney` builds a prompt
string locally and calls nothing. In-isolate composition (`limner_compose`,
apart from the five `cf*` ops that use Cloudflare Images) needs no network and
no credentials.
- **Your keys.** OpenAI and Recraft API keys are read from your local
configuration (environment variables or the client's `user_config`) and used
only to authenticate those provider calls. They are never written to logs or
sent anywhere else.
- **Durable memory and projects.** Facts, decisions, and notes you save persist
in Cloudflare D1 on the Workers transport, or in a local SQLite file (default
`~/.limner/limner.db`) on the stdio and `.mcpb` builds. This data stays until
you remove it with `limner_forget` or delete the database.
- **Generated artifacts.** On the hosted Workers transport, images are stored in
Cloudflare R2 and served behind HMAC-signed capability URLs with a short TTL.
On local transports, artifacts stay on your machine.

Questions or requests about data handling go to jim@vinson.org.

## Prerequisites

For a self-deployed Workers stack:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "limner",
"version": "1.0.0",
"version": "1.0.1",
"description": "MCP image generation agent. Foundation of the Limner family.",
"license": "Apache-2.0",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/limner-cma-tools/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@limner/cma-tools",
"version": "1.0.0",
"version": "1.0.1",
"description": "Limner CMA sandbox custom tools (TS + zod) wrapping @limner/core pipelines.",
"license": "Apache-2.0",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/limner-cma-tools/src/version.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// GENERATED by scripts/sync-version.mjs — do not edit by hand.
// Run `pnpm sync-version` after bumping the root package.json version.
export const VERSION = '1.0.0' as const;
export const VERSION = '1.0.1' as const;
2 changes: 1 addition & 1 deletion packages/limner-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@limner/core",
"version": "1.0.0",
"version": "1.0.1",
"description": "Shared TypeScript foundation for Limner: types, bindings, memory and project stores (D1 + local SQLite).",
"license": "Apache-2.0",
"private": true,
Expand Down
5 changes: 4 additions & 1 deletion packages/limner-mcp/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": "0.3",
"name": "limner-mcp",
"display_name": "Limner — MCP image generation",
"version": "1.0.0",
"version": "1.0.1",
"description": "Image generation pipelines (DALL·E, Recraft, Midjourney) plus a hybrid V8 composition stack — all behind the Model Context Protocol.",
"long_description": "Limner exposes a single MCP surface that orchestrates third-party image generation APIs and composition primitives:\n\n- **Pipelines**: `limner_generate_dalle`, `limner_generate_midjourney` (prompt-only), `limner_generate_recraft` (composed via Recraft's first-party MCP).\n- **Composition**: `limner_compose` tool wraps a hybrid V8 stack — Photon, jSquash codecs, Satori + resvg-wasm, Cloudflare Images Transformations.\n- **Memory + projects**: durable storage of generation context, decisions, and notes (D1 on the Workers transport; local node:sqlite in this stdio bundle).\n- **Discovery**: `limner_list_pipelines`, `limner_pipeline_capabilities`, `limner_health`, `limner_version`.\n\nLimner is third-party software, independent of Anthropic and Cloudflare.",
"author": {
Expand All @@ -16,6 +16,9 @@
"homepage": "https://github.com/vinsonconsulting/limner#readme",
"documentation": "https://github.com/vinsonconsulting/limner/blob/main/packages/limner-mcp/README.md",
"support": "https://github.com/vinsonconsulting/limner/issues",
"privacy_policies": [
"https://github.com/vinsonconsulting/limner/blob/main/README.md#privacy-policy"
],
"license": "Apache-2.0",
"keywords": [
"mcp",
Expand Down
2 changes: 1 addition & 1 deletion packages/limner-mcp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@limner/mcp",
"version": "1.0.0",
"version": "1.0.1",
"description": "Limner MCP server: Workers Streamable HTTP + stdio + .mcpb bundle.",
"license": "Apache-2.0",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/limner-mcp/src/version.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// GENERATED by scripts/sync-version.mjs — do not edit by hand.
// Run `pnpm sync-version` after bumping the root package.json version.
export const VERSION = '1.0.0' as const;
export const VERSION = '1.0.1' as const;