Skip to main content
Glama
notion.rs7.35 kB
use crate::util::{ CREATE_DATABASE_URL, CREATE_PAGE_URL, ReqMethod, SEARCH_BY_FILTER_URL, send_request, }; use anyhow::Result; use reqwest::StatusCode; use serde_json::Value; use serde_json::json; use std::time::Duration; use tokio::time::sleep; #[derive(Debug, Clone, serde::Deserialize)] pub struct Notion { token: String, } impl Notion { pub fn new(token: &str) -> Self { Self { token: token.to_owned(), } } pub async fn search_ref(&self, title: &str, ref_type: &str) -> Result<(StatusCode, Value)> { let body = json!({ "query":title, "filter": { "value": ref_type, "property": "object" }, "sort":{ "direction":"ascending", "timestamp":"last_edited_time" } }); send_request( SEARCH_BY_FILTER_URL, ReqMethod::Post, Some(body), self.token.as_str(), ) .await } pub async fn create_database(&self, page_id: &str) -> Result<(StatusCode, Value)> { let body = json!({ "parent": { "type": "page_id", "page_id": page_id }, "icon": { "type": "emoji", "emoji": "📝" }, "title": [ { "type": "text", "text": { "content": "Jot It Down McpServer Database" } } ], "properties": { "Name": { "title": {} }, "Content": { "rich_text": {} } } }); send_request( CREATE_DATABASE_URL, ReqMethod::Post, Some(body), self.token.as_str(), ) .await } /// Creates a page using formatted blocks /// /// # Arguments /// /// * `database_id` - ID of the Notion database /// * `title` - Title of the page /// * `blocks` - Formatted content blocks /// /// # Returns /// /// * `Result<(StatusCode, Value)>` - API status and response pub async fn create_page_with_blocks( &self, database_id: &str, title: &str, blocks: &[Value], ) -> Result<(StatusCode, Value)> { // Take the first 100 blocks (Notion API limit) let first_batch = if blocks.len() > 100 { &blocks[..100] } else { blocks }; let body = json!({ "parent": { "database_id": database_id }, "icon": { "emoji": "🥬" }, "properties": { "Name": { "title": [ { "text": { "content": title } } ] }, "Content": { "rich_text": [ { "text": { "content": "Content noted by Jotdown MCP server" } } ] } }, "children": first_batch }); // Create the page with the first batch of blocks let (status, response) = send_request( CREATE_PAGE_URL, ReqMethod::Post, Some(body), self.token.as_str(), ).await?; // If there are more blocks and the page was created successfully if blocks.len() > 100 && status.is_success() { if let Some(page_id) = response.get("id").and_then(|v| v.as_str()) { // Add remaining blocks in batches of 100 for chunk_start in (100..blocks.len()).step_by(100) { let chunk_end = (chunk_start + 100).min(blocks.len()); let chunk = &blocks[chunk_start..chunk_end]; let _ = self.append_blocks(page_id, chunk).await?; // Add a small delay to avoid rate limits sleep(Duration::from_millis(100)).await; } } } Ok((status, response)) } /// Adds blocks to an existing page /// /// # Arguments /// /// * `page_id` - ID of the Notion page /// * `blocks` - Content blocks to add /// /// # Returns /// /// * `Result<(StatusCode, Value)>` - API status and response pub async fn append_blocks( &self, page_id: &str, blocks: &[Value], ) -> Result<(StatusCode, Value)> { let url = format!("https://api.notion.com/v1/blocks/{}/children", page_id); let body = json!({ "children": blocks }); send_request( &url, ReqMethod::Patch, Some(body), self.token.as_str(), ).await } pub async fn fetch_page_content(&self, page_id: &str) -> Result<(StatusCode, Value)> { let page_content_url = format!( "https://api.notion.com/v1/blocks/{}/children?page_size=100", page_id ); send_request( page_content_url.as_str(), ReqMethod::Get, None, self.token.as_str(), ) .await } /// Updates a page with new formatted blocks /// /// # Arguments /// /// * `page_id` - ID of the Notion page /// * `blocks` - Formatted content blocks /// /// # Returns /// /// * `Result<(StatusCode, Value)>` - API status and response pub async fn update_page_with_blocks( &self, page_id: &str, blocks: &[Value], ) -> Result<(StatusCode, Value)> { // The Notion API doesn't allow replacing all blocks at once // So we need to add the new blocks // Take the first 100 blocks (Notion API limit) let first_batch = if blocks.len() > 100 { &blocks[..100] } else { blocks }; let url = format!("https://api.notion.com/v1/blocks/{}/children", page_id); let body = json!({ "children": first_batch }); let (status, response) = send_request( &url, ReqMethod::Patch, Some(body), self.token.as_str(), ).await?; // If there are more blocks and the update was successful if blocks.len() > 100 && status.is_success() { // Add remaining blocks in batches of 100 for chunk_start in (100..blocks.len()).step_by(100) { let chunk_end = (chunk_start + 100).min(blocks.len()); let chunk = &blocks[chunk_start..chunk_end]; let _ = self.append_blocks(page_id, chunk).await?; // Add a small delay to avoid rate limits sleep(Duration::from_millis(100)).await; } } Ok((status, response)) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Harry-027/JotDown'

If you have feedback or need assistance with the MCP directory API, please join our Discord server