databasedmcp gives your AI assistant databases it keeps between conversations, so everything in this article works from the day you connect it. Free to start, no card.
Get started freeWhy build it yourself
Release notes are hard to write at the end, because by then nobody remembers what changed. Beamer and LaunchNotes give you a place to publish announcements and a widget to show them in. A small team's struggle comes earlier: noticing the change while it's fresh.
opencode is in the code when the change lands. Ask it to log a line about what changed and who it's for, in words a customer would follow. When you cut a release, it pulls the unreleased entries together and drafts the notes. You edit a draft instead of starting from nothing.
Connect opencode to databasedmcp
databasedmcp is a remote MCP server that gives AI assistants private SQLite databases, with nothing to install.
Create an API key on the API keys page. Keep it in an environment variable, with export DATABASED_API_KEY=… in your shell profile. The config below names the variable, never the key.
{
"mcp": {
"databased": {
"type": "remote",
"url": "https://databasedmcp.com/mcp",
"oauth": false,
"headers": {
"Authorization": "Bearer {env:DATABASED_API_KEY}"
}
}
}
}
"oauth": false makes opencode use the key instead of asking you to sign in.
Any other MCP client works the same way; the docs have the details.
Copy this prompt to build it
Paste this into opencode to set up the database, its tables and its guide in one go. The rest of this article walks through what it makes and how you use it.
Set up a changelog for me in databasedmcp, in one go. 1. Create a database called changelog, described as "Changelog: user-facing changes logged as they land, grouped into releases with drafted notes". 2. Create two tables: - releases: id, version (required, unique), released_on (date, defaults to today), status (draft or published, defaults to draft), notes (the drafted release notes in markdown). - entries: id, kind (added, changed, fixed or removed), summary (required, one sentence a customer understands, no internal names), area, pr (the pull request number), release_id (references releases, NULL until the change ships), created_at (defaults to now). 3. Write the database a guide that says what each table is for, to log an entry when a change users would notice is merged, and to skip refactors and internal tooling. Include the query for "unreleased": entries with no release yet, grouped by kind. And say how to cut a release: insert it, attach the unreleased entries, read them back grouped by kind, and write the notes to releases.notes with added first, then changed, fixed and removed. From then on: when we finish something users would notice, log an entry with its kind, a customer-facing summary and the PR. When I cut a release, draft the notes from its entries, and set it to published once I've approved them. Show me the tables when you're finished.
Ask for the database
You don't write the schema. Describe what you want:
Keep a changelog in databasedmcp: entries for each change (added, changed, fixed or removed) with a one-line summary for customers and the PR, and releases that group them. Log an entry whenever we finish something users would notice. When I cut a release, draft the notes from its entries.
opencode creates a database called changelog and its tables:
CREATE TABLE releases (
id INTEGER PRIMARY KEY,
version TEXT NOT NULL UNIQUE,
released_on TEXT NOT NULL DEFAULT (date('now')),
status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'published')),
notes TEXT
);
CREATE TABLE entries (
id INTEGER PRIMARY KEY,
kind TEXT NOT NULL CHECK (kind IN ('added', 'changed', 'fixed', 'removed')),
summary TEXT NOT NULL,
area TEXT,
pr INTEGER,
release_id INTEGER REFERENCES releases(id),
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
It also writes the database a guide on how the tables are meant to be used. The guide comes back with the schema whenever an assistant looks the database up. opencode files things the same way next week as today, and so does any other assistant you connect.
# changelog: entries and releases - **entries**: one per user-facing change. kind: added, changed, fixed, removed. `summary` is one sentence a customer understands, no internal names. `pr` is the pull request number. `release_id` stays NULL until the change ships. - **releases**: one per version. `notes` is the drafted release notes in markdown; status: draft, published. Log an entry when a change users would notice is merged. Skip refactors and internal tooling. Unreleased: `SELECT id, kind, summary, pr FROM entries WHERE release_id IS NULL ORDER BY kind, id` To cut a release: insert it, attach the unreleased entries, read them back grouped by kind, and write the notes to `releases.notes`. Added first, then changed, fixed, removed.
Use it
From here on you talk, and opencode writes the rows. Each request below is one statement:
That's the CSV export merged in #212. Log it for the changelog.
INSERT INTO entries (kind, summary, area, pr) VALUES (?, ?, ?, ?) -- params: ["added","Export any report as a CSV file from the report's menu.","reports",212]
And the date picker fix from #215.
INSERT INTO entries (kind, summary, area, pr) VALUES (?, ?, ?, ?) -- params: ["fixed","The date picker no longer jumps to January when you change the year.","forms",215]
We're shipping 2.4.0 today. Cut the release.
INSERT INTO releases (version) VALUES (?) RETURNING id -- params: ["2.4.0"]
opencode attaches the unreleased entries to it.
UPDATE entries SET release_id = ? WHERE release_id IS NULL -- params: [1]
Draft the notes. Looks good, publish them.
UPDATE releases SET notes = ?, status = 'published' WHERE id = ? -- params: ["## 2.4.0\n\n**Added**\n- Export any report as a CSV file from the report's menu.\n\n**Fixed**\n- The date picker no longer jumps to January when you change the year.",1]
opencode reads the release's entries, writes the markdown, and saves it once you've approved it. You paste it wherever your customers read updates.
Ask it questions
Once there's data, each report you'd pay for is a single query:
What's merged but not released yet?
SELECT id, kind, summary, pr FROM entries WHERE release_id IS NULL ORDER BY kind, id
What did each release this year contain?
SELECT r.version, r.released_on, sum(e.kind = 'added') AS added, sum(e.kind = 'changed') AS changed, sum(e.kind = 'fixed') AS fixed, sum(e.kind = 'removed') AS removed FROM releases r LEFT JOIN entries e ON e.release_id = r.id WHERE r.released_on >= date('now', 'start of year') GROUP BY r.id ORDER BY r.released_on DESC
When did we change anything about exports?
SELECT r.version, r.released_on, e.kind, e.summary FROM entries e JOIN releases r ON r.id = e.release_id WHERE e.summary LIKE ? OR e.area LIKE ? ORDER BY r.released_on DESC -- params: ["%export%","%export%"]
You can also open the database on the website, page through its rows and run read-only SQL yourself.
What you give up
There's no public changelog page and no in-app widget. Beamer and LaunchNotes host your announcements, show a badge in your product when something's new, and let customers subscribe or react. Here the notes are markdown in a database, and you paste them into your blog, docs or release email yourself.
You also get no audience targeting, no analytics on who read what and no email to subscribers. Anyone on your account can browse the entries on the website, so the team sees what's going out. If announcing changes inside your product is how you reach users, pay for the widget and write your announcements from this.
Try it
databasedmcp is free to start, with no card. Free has 100 tool calls a week, enough to set this up and try it for a week. Starter has 1,000 for everyday use.