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
A content calendar is a list of posts with a channel, a date and a status. CoSchedule or a Notion template gives you that as a board, and you spend a fair part of planning time dragging cards and filling in fields.
If you brainstorm posts with Grok, it can write them into the calendar as you go. Say "a LinkedIn post about the launch next Tuesday" and it's planned. Later you ask what's coming up this week, or which days have nothing, and get a straight answer.
Connect Grok to databasedmcp
databasedmcp is a remote MCP server that gives AI assistants private SQLite databases, with nothing to install.
Open grok.com/connectors, add a new connector, choose Custom and enter https://databasedmcp.com/mcp. When Grok opens the databasedmcp page, sign in and select Allow. Then turn the connector on in a chat.
Any other MCP client works the same way; the docs have the details.
Copy this prompt to build it
Paste this into Grok 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 content calendar for me in databasedmcp, in one go. 1. Create a database called content_calendar, described as "Content calendar: planned and published posts by channel and date, kept by Grok." 2. Create two tables: - campaigns: id, name (required), starts_on (date), ends_on (date), goal. - posts: id, title (required), channel (blog, newsletter, linkedin, x, instagram or youtube, required), status (idea, drafting, ready or published, defaults to idea), publish_on (the planned date, can be empty for ideas), campaign_id (references campaigns), notes, url (set once it's live), created_at (defaults to now). 3. Write the database a guide that says what each table is for, that a post is one channel so a blog post and the LinkedIn post about it are two rows, that ideas may have no date, that nothing here publishes anything and a post is marked published only when I say it's out, and the queries for "what's planned in the next 14 days" and "ideas without a date". From then on: when we come up with a post, add it with its channel, a date if we have one and its campaign if it belongs to one. When I start a launch or theme, add it as a campaign. When I say a post is live, mark it published and save its link. Show me the tables when you're finished.
Ask for the database
You don't write the schema. Describe what you want:
Set up a content calendar in databasedmcp: posts with a channel, a publish date, a status from idea to published, and the campaign they belong to. When we come up with a post, add it; when I say it's out, mark it published with its link.
Grok creates a database called content_calendar and its tables:
CREATE TABLE campaigns (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
starts_on TEXT,
ends_on TEXT,
goal TEXT
);
CREATE TABLE posts (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
channel TEXT NOT NULL CHECK (channel IN ('blog', 'newsletter', 'linkedin', 'x', 'instagram', 'youtube')),
status TEXT NOT NULL DEFAULT 'idea' CHECK (status IN ('idea', 'drafting', 'ready', 'published')),
publish_on TEXT,
campaign_id INTEGER REFERENCES campaigns(id),
notes TEXT,
url TEXT,
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. Grok files things the same way next week as today, and so does any other assistant you connect.
# content_calendar: posts and campaigns
- **campaigns**: a launch or theme that several posts belong to, with start and end dates.
- **posts**: one row per post on one channel. A blog post and the LinkedIn post about it are two rows. status: idea, drafting, ready, published. `publish_on` is the planned date; ideas may have none. `url` is set once it's live.
Next 14 days: `SELECT publish_on, channel, title, status FROM posts WHERE publish_on BETWEEN date('now') AND date('now', '+14 days') ORDER BY publish_on`
Ideas without a date: `SELECT id, title, channel FROM posts WHERE status = 'idea' AND publish_on IS NULL`
Nothing here publishes anything. The human posts; mark it published when they say so.
Use it
From here on you talk, and Grok writes the rows. Each request below is one statement:
We're launching the spring collection over the next three weeks. Make that a campaign.
INSERT INTO campaigns (name, starts_on, ends_on, goal) VALUES (?, date('now'), date('now', '+21 days'), ?) RETURNING id
-- params: ["Spring collection","Newsletter sign-ups from the launch"]
Plan a blog post on how the collection was made for next Tuesday, and a LinkedIn post pointing to it the day after.
INSERT INTO posts (title, channel, status, publish_on, campaign_id) VALUES (?, 'blog', 'drafting', date('now', 'weekday 2'), ?), (?, 'linkedin', 'idea', date('now', 'weekday 2', '+1 day'), ?)
-- params: ["How the spring collection was made",1,"Behind the spring collection, link to the blog",1]
One statement can add several rows. weekday 2 is the coming Tuesday.
Idea for later: a reader Q&A in the newsletter. No date yet.
INSERT INTO posts (title, channel) VALUES (?, ?) -- params: ["Reader Q&A","newsletter"]
The blog post is live.
UPDATE posts SET status = 'published', url = ? WHERE id = ? -- params: ["https://example.com/blog/spring-collection",1]
Ask it questions
Once there's data, each report you'd pay for is a single query:
What's coming up in the next two weeks?
SELECT publish_on, channel, title, status FROM posts WHERE publish_on BETWEEN date('now') AND date('now', '+14 days') ORDER BY publish_on, channel
Which weekdays in the next two weeks have nothing planned?
WITH RECURSIVE days(d) AS (SELECT date('now') UNION ALL SELECT date(d, '+1 day') FROM days WHERE d < date('now', '+13 days')) SELECT d AS free_day FROM days WHERE strftime('%w', d) NOT IN ('0', '6') AND d NOT IN (SELECT publish_on FROM posts WHERE publish_on IS NOT NULL) ORDER BY d
A recursive query builds the list of days, so the gaps show up without a calendar view.
How is the spring campaign going?
SELECT p.status, count(*) AS posts, group_concat(p.channel, ', ') AS channels FROM posts p JOIN campaigns c ON c.id = p.campaign_id WHERE c.name LIKE ? GROUP BY p.status -- params: ["%spring%"]
You can also open the database on the website, page through its rows and run read-only SQL yourself.
What you give up
It plans but doesn't publish. CoSchedule connects to your social accounts, schedules posts and sends them at the right time. Here nothing goes out on its own: you post, then tell Grok it's live. There's no reminder on the morning a post is due either, so ask what's coming up when you start the week.
There's no drag-and-drop calendar and nowhere to keep images or drafts as files. The website shows rows, not a month grid, so a team that plans visually will miss the Notion board. You also won't get engagement numbers from the networks, or approval steps for the people you invite.
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.