DEV Community

Cover image for One sentence in VS Code. My entire Notion workspace becomes a live interactive briefing and the AI handles the rest.
Natnael Getenew
Natnael Getenew Subscriber

Posted on

One sentence in VS Code. My entire Notion workspace becomes a live interactive briefing and the AI handles the rest.

Notion MCP Challenge Submission 🧠

This is a submission for the Notion MCP Challenge


I maintain an open source AI agent SDK. I'm building a startup. I do both alone, from Addis Ababa, at 24, no team.

Every morning I open Notion and spend 15 minutes manually figuring out what's actually on fire. What's overdue. What's tied to which goal. I piece it together across five databases, hold it in working memory, then try to work.

That 15 minutes compounds. Every day. It's not a productivity problem - it's a tax on building alone.

People who have a chief of staff don't pay that tax. I can't afford one. So I built one.


The Thing Nobody Had Done Before

Before this, "AI + Notion" meant: AI reads your data and writes a text summary back at you. You still had to act on it yourself. You still had to go to Notion and change things.

Chief of Staff breaks both of those constraints at once.

First: the UI lives inside the chat. When you ask for your briefing, a full rendered dashboard appears inside the conversation — task rows, progress bars, overdue indicators, action buttons. It's not a screenshot. It's not a link. It's a live React app running inside an iframe inside VS Code Copilot or Claude. You can interact with it. Check off a task and it's gone from the list and marked done in Notion in the same click.

Checking a checkbox on a visual task — inside VS Code, without opening Notion, without leaving your editor — that had never been built before.

Second: the agent doesn't hand you a report. It executes. The action buttons in the dashboard don't navigate you somewhere. They tell the AI to go do the work. The AI calls the right MCP tool, reasons through the changes, and writes them back to Notion. You direct. It executes. The loop closes inside a single conversation.

This is what a chief of staff actually does. Not informing you. Acting on your behalf.


What I Built

Chief of Staff is an MCP App that reads your Notion workspace every morning and briefs you — then handles the work you tell it to.

You type: "Give me my morning briefing."

A live, interactive dashboard renders directly inside VS Code Copilot Chat — or Claude. Not a link to an external tool. Not a text summary. A real UI with real data, living inside your editor. You can click a checkbox and the task is marked done in Notion. You can click a button and the agent reschedules your entire overdue pile. You never leave your editor.

That's new. Nobody had shipped this before.

  • âš¡ Plan my week → the AI generates a task breakdown and creates every task directly in your Notion database
  • 📅 Reschedule overdue tasks → the AI looks at everything overdue, picks sensible new dates based on priority, patches them all in Notion. The guilt pile disappears.
  • 📋 Write weekly review → the AI pulls your completed tasks, synthesizes what happened, writes a full structured page into your workspace
  • 🎯 Break down stalled goal → the AI takes a goal sitting at 5% and creates 4-6 concrete sub-tasks with due dates in Notion

The briefing is the interface. Notion is where the work lands.

GitHub: https://github.com/Garinmckayl/chief-of-staff


How I Used Notion MCP

Notion MCP is the reason the write path exists. Without it I'd need custom integrations per action. With it, the AI can read and write across the entire workspace through one protocol, and every agent tool is just a description of what needs to happen.

The 8 MCP tools

Tool What it does
chief_of_staff_briefing Renders the live interactive dashboard as an MCP App
get_notion_briefing_data Reads your workspace — discovers databases dynamically, no hardcoded IDs
complete_notion_task Marks a task done — detects whether Status is a select, native status, or checkbox
create_notion_tasks Writes an AI-generated task plan straight into your Notion database
reschedule_overdue_tasks Updates due dates — the AI picks the dates and explains each one
write_weekly_review Creates a structured weekly review page in your workspace
break_down_goal Generates sub-tasks for a stalled goal and creates them in Notion
get_completed_tasks Fetches done tasks from the past N days for the weekly review

The generative UI layer

The interactive dashboard is a live React app that renders inside the chat - compiled to a single self-contained HTML string and returned as a tool response. When the AI calls chief_of_staff_briefing, the entire UI materialises: task rows, progress bars, overdue indicators, action buttons. All driven by your real Notion data.

The component catalog defines everything the AI can compose:

FocusCard      — the single most important thing right now
TaskList       — grouped task rows with heading and count
TaskRow        — individual task with completion checkbox that writes to Notion
GoalProgress   — progress bar with live percentage
InsightBadge   — win / tip / warning / pattern pill
AgentAction    — the button that triggers real Notion writes
SectionHeader  — section divider
Enter fullscreen mode Exit fullscreen mode

The AI fills this catalog from your actual Notion data. Every task row is real. Every progress bar reflects a real goal. The AgentAction component fires an event that the AI receives and routes to the right MCP tool. Visual layer and execution layer are the same system.

The agentic loop

The dashboard and the agent tools are two halves of the same system. The briefing shows the situation. The AgentAction buttons close the loop.

When you click "Reschedule overdue tasks," the AI gets a run_agent event, calls get_notion_briefing_data to see what's actually overdue, reasons about dates based on priority, and calls reschedule_overdue_tasks with the full update list. Notion gets patched. You touched nothing.

mcpServer.tool(
  "reschedule_overdue_tasks",
  `Reschedule overdue tasks by updating their due dates in Notion.
  First call get_notion_briefing_data to get current overdue tasks.
  Decide sensible new due dates based on priority and today's date.
  Spread them out — don't dump everything on one day.`,
  {
    updates: z.array(z.object({
      taskId: z.string(),
      newDueDate: z.string(),
      reason: z.string(),
    })),
  },
  async ({ updates }) => {
    const results = await rescheduleTasks(updates);
    return { content: [{ type: "text", text: JSON.stringify(results) }] };
  }
);
Enter fullscreen mode Exit fullscreen mode

The reason field is intentional. The AI isn't just moving dates — it's explaining why. You can see the reasoning in the tool call output. That's what makes it feel like delegation rather than automation.

Dynamic workspace discovery

No hardcoded database IDs. The system discovers your workspace by reading property shapes — it inspects what fields each database has, not what it's named. Databases with progress or percent fields are classified as goal trackers. Databases with status or due date fields are classified as task lists. This means it adapts to however you've structured your workspace — different column names, different layouts, different numbers of databases.

// Goals have progress fields — exclude them from task DBs
if (hasProgress) {
  goalDbs.push({ id: db.id, name: title });
} else if (hasStatus || hasDue) {
  taskDbs.push({ id: db.id, name: title });
}
Enter fullscreen mode Exit fullscreen mode

Works on any Notion workspace structure, out of the box.

The parts that were actually hard

completeTask silently did nothing for weeks. It was calling the Notion native status type, but most databases use a select field for Status. The silent fallback was to archive the page instead. Fixed it by reading the page schema first and detecting the actual property type before writing.

Goal databases kept appearing as task databases. Any database with a Status column and a date field got classified as tasks. My Goals DB has both. Fixed by checking for a progress/percent field first — if it exists, it's a goal DB.

Neither was hard to fix. Both would silently break the demo if I hadn't caught them.


Technical Stack

Layer What
MCP server @modelcontextprotocol/sdk — stdio + StreamableHTTP transports
Generative UI React app compiled to a single HTML string, served as a tool response, rendered live inside the chat
Notion writes Direct REST API with dynamic schema detection
Bundler Vite + vite-plugin-singlefile (entire React app as one inlined HTML string)
Runtime Node.js + tsx

Run it in 60 seconds with GitHub Codespaces — the repo includes devcontainer.json with everything pre-configured, port 3333 forwarded, NOTION_API_KEY as the only required secret.

git clone https://github.com/Garinmckayl/chief-of-staff
cd chief-of-staff && npm install && npm run build
NOTION_API_KEY=your_key npm run start:stdio
Enter fullscreen mode Exit fullscreen mode

Why This Matters

Before Chief of Staff, "AI + your data" meant a smarter search or a better summary. You still had to act on the output yourself. The AI was a reader. You were still the writer.

Chief of Staff makes the AI the writer too. It reads your workspace, shows you the situation visually, and when you point it at a problem — it fixes it. All in Notion. None of it requiring you to open a single Notion page.

I built this because I needed it. I'm a solo founder in Addis Ababa, maintaining open source infrastructure, building a startup, without a team, in a city where many of the tools the rest of the world assumes you have aren't available to you. Claude Desktop doesn't work here. I demo this in VS Code Copilot because that's what I actually have access to.

That constraint shaped everything. It works with what you have. One workspace, one API key, one command.

Three weeks ago, building an interactive visual app that lives inside VS Code wasn't possible. Now it is. And the first thing I built with it was a chief of staff — because that's what I needed most.

This isn't productivity software. It's what happens when the person who builds infrastructure finally gets some infrastructure of their own.


Built for the Notion MCP Challenge
GitHub: https://github.com/Garinmckayl/chief-of-staff

Top comments (0)