Skip to content

tinyalg/notion-mcp-challenge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zero-Friction Publishing: A Human-in-the-Loop Agentic CMS powered by Notion MCP

This is the exact repository where I, @lwgena, approved my own submission for the Notion MCP Challenge, triggering a GitHub Actions workflow that automatically published it to dev.to. (You may notice another contributor named @talgina here, which is my dedicated machine account.)

Before hitting merge, the workflow started with this simple conversation:

Me: Fetch and convert to markdown the draft with the filename "posts/notion-mcp-challenge.md" from the Notion database. Open a PR in tinyalg/notion-mcp-challenge repo, targeting main, using the branch name specified in its github_branch property.

You MUST properly escape all newlines with \n, double quotes with \", and formatting when constructing the JSON payload for the tool. DO NOT pass raw markdown, and DO NOT use \t for newlines.

Before executing the tool, you must decode the escaped string in your head back to Markdown and strictly verify that it is a 100% perfect match with the original draft. If you fail to escape it properly, the GitHub action will break. Do it perfectly.

Claude: Got it. Let me read the properties via Notion MCP. I'll format the content with YAML frontmatter, create the branch you specified, and open a Pull Request for you.

⏱️ The 18-Minute "Stringification Hell" Log

Curious how the AI reacted to the strict "Zero-Error" prompt above?

It took Claude exactly 18 minutes of internal reasoning and mental round-trip verification to perfectly escape the Notion draft into a JSON payload without breaking the GitHub Action.

You can read the raw, unedited thought process of the AI agent here: 👉 Read the 18_MINUTES_LOG_FOR_GOLIVE.md

🏗 Workflow Overview

This diagram shows the overview of the workflow I presented. It defines the interaction between the AI Orchestrator (Claude), the Human Director, and the external systems.

graph TD
 subgraph Legend_Box["Legend"]
        L1["🟧 Thick Orange Line: External System Operation via MCP"]
  end
 subgraph CMS_Phase["CMS & Human Edit"]
        Author(("You: Editor"))
        Notion[("Notion: Structured CMS")]
  end
 subgraph Notion_Structure["Notion Database Schema"]
    direction LR
        Prop1["title"]
        Prop2["Content"]
        Prop3["filename"]
  end
    Input(("You: Director")) == "1. Convey Intent (Natural Language)" ==> Claude["Claude Sonnet 4.5: Orchestrator"]
    Claude == "2. Save Initial Draft" ==> Notion
    Notion == "4. Fetch Edited Content" ==> Claude
    Claude == "6. Create PR" ==> GitHub{{"GitHub: Version Control"}}
    Author -- "3. Refine & Polish Draft" --> Notion
    Claude -- "5. Transform to MD + YAML" --> Claude
    User(("You: Final Approver")) -- "8. Merge (The 'Publish' Signal)" --> GitHub
    GitHub -- "7. Review PR (Diff Check)" --> User
    GitHub -- "9. Actions (Triggered by Merge)" --> devto(("dev.to: Live"))
    Prop1 --- Prop2
    Prop2 --- Prop3
    Notion -.-> Notion_Structure

     Claude:::claudeStyle
    classDef claudeStyle fill:#e6e6fa,stroke:#7b68ee,stroke-width:2px,color:#333
    style L1 fill:#ffffff,stroke:none,color:#333,rx:5,ry:5
    linkStyle 1 stroke:#ff964f,stroke-width:6px,fill:none
    linkStyle 2 stroke:#ff964f,stroke-width:6px,fill:none
    linkStyle 3 stroke:#ff964f,stroke-width:6px,fill:none
Loading

🛠 Setup & Configuration

Getting started with Zero-Friction CMS is simple. Just set up your Notion schema, configure MCP on Claude Desktop, and add a GitHub Actions workflow. Here is the breakdown:

1. Notion Schema

The AI orchestrator relies on this specific schema to manage the publishing lifecycle.

Notion Database Schema

To make the AI orchestrator act predictably, I defined a strict schema in the Notion Database:

  • title: The main headline of your post.
  • published: A boolean to control visibility.
  • description: Used for SEO and dev.to's summary.
  • tags: Automates categorization.
  • organization_username: Allows publishing under a specific dev.to organization when GitHub workflow uses the Publish to Dev.to Organization action.
  • canonical_url: Maintains SEO integrity for cross-posted content.
  • cover_image: Managed via URL to handle article headers.
  • filename: The exact ID for the .md file in the GitHub repo.
  • github_branch: Tells the AI which branch to target for the PR.

Duplicate this Notion Template to instantly get the exact database schema required for the AI to generate perfect YAML frontmatter.

2. MCP Integration

The workflow relies on two core MCP servers:

3. Publish to dev.to

To automate posting to dev.to, you can use a GitHub Actions workflow. You can set up the workflow to automatically publish your articles to dev.to whenever a PR is merged into your main branch.

The easiest way to achieve this is by using the Publish to Dev.to Organization action. Please refer to the GitHub Marketplace for detailed setup instructions.

Security Tips: Limiting the Blast Radius

Don't want Claude to accidentally mess things up? Create a machine user account, as permitted in Types of GitHub Accounts.

When creating a Fine-grained PAT (Personal Access Token) to paste into your claude_desktop_config.json file, be sure to restrict its scope strictly to the target repository with only the following permissions:

  • Contents: Read and Write
  • Pull requests: Read and Write

Created for the Notion MCP Challenge.

About

Zero-Friction Publishing - Repository for Notion MCP Challenge Submission by lwgena

Topics

Resources

License

Stars

Watchers

Forks

Contributors