Repository navigation
v0.2.0 — external MCP servers, package apps, one private-host allowlist
33 commits since v0.1.1. Two breaking configuration changes. Read "Before you upgrade" first. The node refuses to start while a removed setting or provider name is still set, and the error points at the notice to follow.
If you run
ghcr.io/kentcdodds/kody-celld:latest, you already have these changes::latestfollows main. Pin:0.2/:0.2.0for versioned upgrades.
Before you upgrade (breaking)
1. One private-host allowlist: KODY_PRIVATE_HOSTS (#66, notice #62). Four settings are removed:
KODY_MCP_ALLOW_PRIVATE_HOSTS;KODY_BROWSER_ALLOW_PRIVATE_HOSTS;KODY_PACKAGE_SOURCE_HOSTS;KODY_ALLOW_INSECURE_SECRET_HOSTS.
To migrate:
- Merge their entries into one comma-separated
KODY_PRIVATE_HOSTS. It accepts hosts,*.suffix, IPs and CIDRs. - Delete the old variables.
- Replace a bare
loopbackentry with explicitlocalhost,127.0.0.1,::1(or127.0.0.0/8).
Plain http: secret fetches are now allowed only to hosts on this list. Private package sources (Gitea, host.docker.internal, …) must be listed too.
2. Generic adapters only (#67, notice #63).
| Removed | Use instead |
|---|---|
Outbound email resend, postmark, mailgun, sendgrid |
KODY_EMAIL_OUTBOUND_PROVIDER=bridge with the mail-bridge sidecar relaying over SMTP (compose.mail.yaml). Resend, for example, becomes MAIL_BRIDGE_SMTP_URL=smtps://resend:<key>@smtp.resend.com:465 |
Inbound email postmark, mailgun, sendgrid, cloudflare |
/email/inbound/bridge (mail-bridge, or the Cloudflare Email Worker in examples/cloudflare-email-forwarder) or /email/inbound/generic |
KODY_AI_PROVIDER=anthropic |
openai with any OpenAI-compatible KODY_AI_BASE_URL |
KODY_BROWSER_PROVIDER=cloudflare |
browserless (compose.browser.yaml) |
| Separate R2 blob lane | KODY_BLOB_PROVIDER=s3 (S3-compatible). A bound BLOBS bucket still works |
The provider-only knobs go with them, e.g. KODY_EMAIL_MAILGUN_* and KODY_BROWSER_CF_ACCOUNT_ID.
Highlights
External MCP servers (#44).
mcpServerAdd({ name, url })adds remote MCP servers. Call their tools from execute askody.mcp[name].tool(input)(#46).- OAuth for MCP servers (#48):
- three ways for Kody to identify itself: a pre-registered client, a Client ID Metadata Document (served at
/oauth/client-metadata.json), or Dynamic Client Registration; - a consent page, then a callback;
- host-side refresh;
mcpServerReconnect.
- three ways for Kody to identify itself: a pre-registered client, a Client ID Metadata Document (served at
- Hardening: OAuth attempts are bound to their server and client (#57, #65); cross-origin authorization endpoints are refused, and the 401 challenge is used (#60); the CSP allows an
http:LAN authorization server (#56); DNS answers are reused per host within one call (#74). - Hosts are checked against
KODY_PRIVATE_HOSTSat each hop. The DNS lookup used for that check goes throughKODY_DNS_RESOLVER_URL.
Package apps (#42).
- Packages that declare
kody.appare served as server-rendered browser apps on a separate app origin set by the newKODY_APP_BASE_URL. It supports path mode (https://apps.example) and subdomain mode (https://*.apps.example) (#79). - The Open app link and
packageAppUrl()go through a one-minute, single-use handoff bound to the browser that started it. - Owner-only. Kody credentials never reach app code.
kody.app.assetsis served under/_assets/*(#80). For now that means text files only, andkody.app.clientis not built yet.- Off unless configured. See
docs/package-apps.md; use a different registrable domain fromKODY_PUBLIC_URL.
Packages.
- TypeScript, TSX and JSX packages and ad hoc TypeScript run (#38).
- Git packs are inflated with a pinned pako (#35).
- Each package file is stored in its own row (#35).
- Only real imports are rewritten (and unresolvable ones are named).
- The package files explorer arrives, with its follow-ups (#30, #31).
- The preview page shows the package description (#32).
- Fixes for URL-cache freshness, SHA pinning before tarball download, and
.dev.varshost merging (#43). packageStorageClearskips celld's litestream tables (#40).
Runs.
- Run triage with
runSummary,runUpdateandrunUpdateBulk, plus auto-resolve and triage on the Activity page (#33). - Package apps record failures as
appruns.
Search and docs.
guide:provisionmatches what this build ships (#76).- The docs cover
KODY_PRIVATE_HOSTSand the generic adapters throughout (#75, #78). - Imported principles (#61), a faithful self-host architecture decision (#70), and the contributor PR bar and steward checklist (#71).
- Files copied from kody are pinned and checked in CI (#68, #72).
New settings
KODY_PRIVATE_HOSTS: the one private-host allowlist (replaces four, see above).KODY_APP_BASE_URL: the package-app origin (optional; unset means apps are off).KODY_DNS_RESOLVER_URL: the DNS-over-HTTPS resolver for MCP host checks.KODY_MCP_CALL_TIMEOUT_MS.KODY_QUOTA_MCP_SERVERS.
The Docker entrypoint now forwards KODY_DNS_*, KODY_PRIVATE_* and KODY_APP_* to the Worker.
Upgrade
- Back up the data volume (
/data). - Apply the two migrations above to your
.env/ compose. - Set the image to
ghcr.io/kentcdodds/kody-celld:0.2.0, thendocker compose pull && docker compose up -d. - Check that
/healthreports"version":"0.2.0".
Full changelog: v0.1.1...v0.2.0