This is a submission for the Notion MCP Challenge
What I Built
Valkyrie is an AI-powered crisis response and logistics command center that uses the Model Context Protocol (MCP) to turn Notion into a real-time operations hub.
In modern logistics, "latency kills." When a natural disaster or geopolitical event occurs, operators lose precious minutes switching between news feeds, weather maps, and internal databases. Valkyrie solves this by:
- Bridging external threat data with internal asset data via MCP
- Autonomously staging incident responses in Notion for human approval
- Maintaining relational integrity between incidents and affected assets
Key Features
| Feature | Description |
|---|---|
| 🔍 Autonomous Threat Monitoring | Scans simulated global feeds for risks near tracked assets |
| 📋 Instant Incident Staging | Creates Notion pages with threat analysis and mitigation steps |
| 🔗 Relational Asset Resolver | Maps coordinates to Notion Page IDs for data integrity |
| 👤 Human-in-the-Loop | AI proposes solutions; humans approve and execute |
MCP Tools Exposed
analyze_global_threats → Check asset for threats, stage incident if detected
scan_all_assets → Batch scan all tracked assets
get_asset_details → Retrieve full asset information
list_all_assets → List assets with risk levels (🔴🟡🟢)
find_nearest_safe_asset → Find rerouting destination during crisis
Video Demo
[Demo video - showing threat detection, incident staging, and human approval workflow]
Demo Workflow:
- Ask AI: "Valkyrie, scan all assets for threats"
- AI detects tropical storm near Singapore Hub
- Incident page created in Notion with status "Awaiting Approval"
- Operator reviews, changes status to "In Progress"
- Crisis Response Playbook triggered
[Data Flow & Human-in-the-Loop Sequence - From threat detection to human approval]
Show us the code
GitHub Repository:
kanyingidickson
/
valkyrie-mcp-server
AI-Powered Crisis Logistics
🛰️ Project Valkyrie: AI-Powered Crisis Logistics
The Model Context Protocol (MCP) Command Center for Global Infrastructure
Demo Video: Youtube.com/Project Valkyrie : AI-Powered Crisis Logistics (Notion Workspace)
🌪️ The Problem
In modern logistics, "latency kills." When a natural disaster or geopolitical event occurs, information is scattered across news feeds, weather maps, and internal databases. Operators lose precious minutes switching between tabs, trying to piece together a complete picture of the crisis.
Context-switching fatigue costs millions in delayed response times.
🛡️ The Valkyrie Solution
Valkyrie uses the Model Context Protocol (MCP) to turn Notion into a living, breathing Command Center. It bridges real-time external "Threat Data" with internal "Asset Data," allowing an AI Agent to autonomously stage response plans for human approval.
Key Features
Feature
Description
Autonomous Threat Monitoring
Periodically scans global feeds for risks near assets listed in Notion
Instant Incident Staging
Automatically generates Notion pages with threat analysis and proposed
Tech Stack
-
MCP Server: TypeScript with
@modelcontextprotocol/sdk - Notion API: v2022-06-28 with direct HTTP queries for database operations
- Threat Simulator: Python FastAPI generating realistic crisis scenarios
- Deployment: Docker Compose + GitHub Actions CI/CD
Project Structure
valkyrie-mcp-server/
├── src/ # MCP server source code
│ ├── index.ts # MCP server entry point
│ ├── config.ts # Configuration management
│ ├── lib/ # Core libraries
│ │ ├── assets.ts # Asset data utilities
│ │ └── assets.d.ts # Type definitions
│ ├── tools/ # MCP tool implementations
│ │ ├── index.ts # Tool exports
│ │ ├── analyze-threats.ts # analyze_global_threats tool
│ │ ├── scan-assets.ts # scan_all_assets tool
│ │ ├── get-asset-details.ts # get_asset_details tool
│ │ ├── list-assets.ts # list_all_assets tool
│ │ └── find-nearest-safe.ts # find_nearest_safe_asset tool
│ └── types/ # Type definitions
├── mock-api/ # Threat simulator API
│ ├── valkyrie_mock_api.py # FastAPI threat simulator
│ ├── requirements.txt
│ └── Dockerfile
├── scripts/ # Orchestration & utility scripts
│ ├── seed_assets.py # Populate Notion logistics DB
│ ├── clean_duplicates.py # Remove duplicate assets
│ ├── scan_and_stage.js # Scan assets and stage incidents
│ ├── trigger_and_stage.js # Trigger threats and stage incidents
│ ├── notion_watcher.js # Poll Notion for status changes
│ ├── webhook_server.js # Handle Slack actions
│ ├── scheduler.js # Periodic scan scheduler
│ ├── notify.js # Notification utilities
│ └── requirements.txt
├── tests/ # Test files
├── docs/ # Documentation assets
│ ├── logical-overview.png
│ ├── deployment-overview.png
│ └── demo-workflow.png
├── .github/ # CI/CD workflows
│ └── workflows/
│ └── valkyrie-deploy.yml
├── .data/ # Local data storage
├── .husky/ # Git hooks
├── dist/ # Compiled output
├── package.json # Dependencies & scripts
├── tsconfig.json # TypeScript config
├── jest.config.cjs # Jest test config
├── .eslintrc.json # ESLint config
├── .prettierrc # Prettier config
├── docker-compose.yml # Docker orchestration
├── Dockerfile # MCP server container
├── .env.example # Environment template
├── MCP_INSTRUCTIONS.md # MCP usage guide
├── LICENSE
└── README.md
Key Code: Relational Asset Resolver
From src/lib/assets.ts:
// Maps external telemetry coordinates to Notion Page IDs
export async function queryNotionDatabase(
databaseId: string,
filter?: Record<string, unknown>
): Promise<NotionPageObject[]> {
const res = await fetch(`https://api.notion.com/v1/databases/${databaseId}/query`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NOTION_TOKEN}`,
'Content-Type': 'application/json',
'Notion-Version': '2022-06-28',
},
body: JSON.stringify(filter ? { filter } : {}),
});
const data = await res.json();
return data.results || [];
}
Incident Staging with Human-in-the-Loop
From src/tools/analyze-threats.ts:
// Creates Notion page with "Awaiting Approval" status
async function createIncidentPage(params: {
assetName: string;
assetPageId: string | null;
category: string;
summary: string;
threatLevel: number;
}): Promise<string> {
const threatLevelText = params.threatLevel >= 8 ? 'Critical (Red)' : 'Elevated (Yellow)';
const incidentPage = await notion.pages.create({
parent: { database_id: DASHBOARD_DB_ID },
properties: {
'Incident Name': {
title: [{ text: { content: `🚨 ALERT: ${params.category} - ${params.assetName}` } }],
},
Status: { status: { name: 'Awaiting Approval' } },
'Threat Level': { select: { name: threatLevelText } },
'Affected Assets': { relation: params.assetPageId ? [{ id: params.assetPageId }] : [] },
},
});
return incidentPage.id;
}
How I Used Notion MCP
The Integration
Valkyrie uses the Model Context Protocol to give AI assistants (like Windsurf's Cascade) direct access to Notion databases as tools. This unlocks:
- Autonomous Database Queries - AI can query assets without manual API calls
- Intelligent Incident Creation - AI stages responses with proper relations
- Contextual Awareness - AI understands asset locations and risk profiles
Notion Database Schema
Operations Dashboard (Incidents DB)
| Property | Type | Description |
|---|---|---|
| Incident Name | Title | Auto-generated: 🚨 ALERT: {Category} - {Asset}
|
| Status | Status |
Draft → Awaiting Approval → In Progress → Resolved
|
| Threat Level | Select |
Critical (Red) / Elevated (Yellow) / Stable (Green)
|
| Affected Assets | Relation | Links to Logistics DB for relational integrity |
| AI Assessments | Rich Text | Threat summary from simulation engine |
Global Assets & Logistics DB
| Property | Type | Description |
|---|---|---|
| Asset Name | Title | Unique facility identifier |
| Coordinates | Text | Latitude, Longitude (e.g., 1.2902, 103.8519) |
| Risk Sensitivity | Number | 1-10 scale for prioritization |
| Status | Select |
Active / Inactive / Maintenance
|
| Facility Type | Select |
Distribution Hub / Transport Node / Data Center
|
| Primary Contact | Text | On-site lead name |
| Primary Phone | Phone | Emergency contact number |
| Primary Email | Escalation contact | |
| Facility Manager | Text | Responsible party |
| Last Audit | Date | Compliance tracking |
What This Unlocks
- Zero-context-switching: Operators see threats and assets in one Notion workspace
- AI-assisted decisions: AI proposes actions, humans approve
- Relational data integrity: Incidents automatically link to affected assets
- Real-time monitoring: Continuous scanning with instant notification
[Technical Component Stack - Docker containers for MCP Server and Mock API]
Try It Yourself
# Clone and setup
git clone https://github.com/kanyingidickson/valkyrie-mcp-server.git
cd valkyrie-mcp-server
npm install
# Configure Notion
cp .env.example .env
# Add your NOTION_TOKEN and database IDs
# Seed assets
pip install -r scripts/requirements.txt
python scripts/seed_assets.py
# Run mock API
python mock-api/valkyrie_mock_api.py
# Build and run MCP server
npm run build
npm start
# Run a one-off scan:
node scripts/scan_and_stage.js
# Optional scheduler:
node scripts/scheduler.js
Add to your MCP client config:
{
"mcpServers": {
"valkyrie": {
"command": "node",
"args": ["/path/to/valkyrie-mcp-server/dist/index.js"],
"env": {
"NOTION_TOKEN": "your-token",
"DASHBOARD_DB_ID": "your-dashboard-id",
"LOGISTICS_DB_ID": "your-logistics-id"
}
}
}
}
Files of interest
-
src/index.ts— MCP server entry point and tool orchestration -
src/lib/assets.ts— Relational Asset Resolver implementation -
src/tools/analyze-threats.ts— Threat detection and incident staging -
mock-api/valkyrie_mock_api.py— FastAPI threat simulator -
scripts/seed_assets.py— Populate Notion databases with sample assets -
scripts/scan_and_stage.js— Batch scan + incident staging -
scripts/trigger_and_stage.js— Single-target trigger + staging -
scripts/scheduler.js— Periodic scan runner -
scripts/notion_watcher.js— Notion status change listener -
scripts/notify.js— Slack and email notifications -
scripts/webhook_server.js— Action link handler for approvals
Notes
- The system is intentionally conservative: AI stages incidents as
Awaiting Approvalfor human review. - The repo includes seeding and demo scripts to make the submission easy to reproduce.
Acknowledgments
- Notion for the MCP SDK and API
- Model Context Protocol for the integration framework
- DEV Community for the challenge platform
Built for the Notion MCP Challenge 2026 🚀
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.