This is a submission for the Notion MCP Challenge
What I Built
Risk Radar reads your Notion project databases, builds a dependency graph in memory, and writes risk reports back to Notion. It finds critical paths, single points of failure, and cascade risks that project managers usually track in their heads (or don't track at all).
The part I'm most proud of: when a task is overdue, the agent walks the dependency graph and pushes every downstream deadline forward through notion-update-page. Mark one task late, run the scan, and watch 8 dates shift in Notion automatically.
Everything goes through Notion's MCP server. No direct API calls. Notion is the entire data layer.
Video Demo
Show us the code
π― Risk Radar β Dependency & Risk Intelligence for Notion
Built for the Notion MCP Hackathon β zero direct API calls, 100% MCP.
The Problem
Project managers track risks mentally but never systematically. When a task slips, nobody knows which 8 downstream tasks just broke their deadlines. Single points of failure hide in plain sight β one person quietly blocking an entire workstream. By the time anyone notices, the cascade has already happened.
The Solution
Risk Radar reads your Notion project databases, builds a dependency graph, and surfaces risks that humans miss. It writes actionable risk reports back to Notion and automatically propagates deadline changes through the dependency chain.
Mark one task late β watch 8 downstream dates shift automatically.
Everything runs through the Model Context Protocol (MCP) β zero direct Notion API calls.
How It Works
- Read β Fetches all projects and tasks from Notion via MCP, including dependencyβ¦
How I Used Notion MCP
Reading a dependency graph through MCP
The Tasks database has a self-referencing "Depends On" relation. Reading this through MCP takes three steps per task: fetch the database to get the data source URL, search to get page IDs, then fetch each page individually to get its properties.
The properties come back inside a <properties> XML block as JSON. Relation fields like "Depends On" and "Project" are arrays of Notion page URLs. So building the graph means parsing URLs like https://www.notion.so/abc123def456, stripping the prefix and dashes, and using the normalized ID as the graph node key. Without that normalization step, every dependency lookup fails silently and you get an empty graph. That bug cost me an hour.
The graph algorithms
Once the tasks are in memory with their dependencies resolved to names, the risk engine runs four analyses:
Critical path uses DFS with memoization from root tasks (tasks with no upstream dependencies). It finds the longest chain through the dependency graph. This tells you which sequence of tasks has zero slack β if any of them slip, the project end date moves.
Single point of failure detection does a recursive downstream traversal per task owner. If one person's incomplete tasks collectively block two or more downstream tasks, they're flagged. This catches the scenario where one engineer is quietly blocking an entire workstream.
At-risk detection is simpler: compare each task's deadline to today. Overdue tasks, tasks due within 3 days that haven't started, and tasks due tomorrow that are still in progress all get flagged.
Cascade impact runs BFS from each at-risk task to enumerate every downstream task that would be affected by a slip.
The risk score combines these: overdue_ratio Γ 40 + spof_penalty (capped at 30) + cascade_penalty (capped at 30). It's a rough heuristic, but it produces scores that feel right. A project with one overdue task and no dependencies scores low. A project with an overdue task that blocks 5 others through a single owner scores high.
Writing reports and cascading deadlines
The risk report is a Markdown page created with notion-create-pages. It includes the risk score with an emoji indicator (π΄/π‘/π’), the critical path, at-risk tasks with reasons, SPOFs with the tasks they're blocking, and cascade impact chains. A separate Health History entry logs the score with a date for trend tracking.
The cascade feature is the most interesting MCP interaction. When the scan finds an overdue task, it calculates the slip in days, then does a BFS through the dependency graph. For each downstream task that isn't done, it calls notion-update-page with the new deadline using the "date:Deadline:start" property format. A 5-task cascade means 5 sequential MCP update calls. Each one shifts a real deadline in Notion.
What surprised me about Notion MCP
The notion-search results don't include full properties. You get page IDs and titles, but to read "Depends On" or "Deadline" you need a separate notion-fetch per page. For 8 tasks across 3 projects, that's about 25 MCP calls just to read the data. It works, but it means the agent is I/O bound rather than compute bound. The graph algorithms themselves run in microseconds. The MCP calls take seconds.
The other surprise was date properties. Setting a date requires two properties: "date:Deadline:start" for the value and "date:Deadline:is_datetime": 0 to indicate it's a date-only field. Missing the second one doesn't error, but the date renders differently in Notion.
Top comments (0)