DEV Community

Dang Tran
Dang Tran

Posted on

Notion Bookmarks Manager

Notion MCP Challenge Submission 🧠

This is a submission for the Notion MCP Challenge

What I Built

The web content I browse every day is part of my personal knowledge base — but finding something I read weeks ago is frustratingly hard. I built this Chrome extension to solve that: it saves any page I bookmark directly to Notion, uses AI to generate a summary of the page content, and lets me search across everything I've saved using natural language.

Video Demo

Show us the code

Notion Bookmark Manager

A Chrome extension that saves browser tabs to your Notion workspace, with folder organization, notes, AI-generated summaries, and AI-powered search.

Features

  • Save bookmarks — Save the current tab to a Notion database with a title, URL, and optional notes
  • Folder tree — Organize bookmarks into nested folders synced from Notion
  • AI summaries — Optionally generate a page summary using Gemini AI based on a custom prompt
  • Browse bookmarks — View all your bookmarks grouped by folder in a collapsible tree
  • Search — Search your Notion bookmarks using natural language via Gemini AI and the Notion MCP

Architecture

Chrome Extension (Manifest V3)
├── popup/          UI for saving, browsing, and searching bookmarks
├── background/     Service worker — routes messages between popup and server
├── shared/         Shared types, constants, and chrome.storage helpers
└── dist/           Built output (load this directory in Chrome)
Local Server (Express)
└── server/         Handles all Notion API
…

How I Used Notion MCP

MCP (Model Context Protocol) is used only in the searchBookmark function in server/notion-api.ts. It is not used anywhere else — all other Notion operations (create bookmark, fetch folders, etc.) go through the @notionhq/client SDK directly.

How it works

User presses Enter in search
→ popup sends SEARCH_BOOKMARKS message
→ service worker calls POST /call { tool: "search_bookmarks" }
→ server calls searchBookmark()
→ searchBookmark() connects to Notion MCP via npx mcp-remote
→ Gemini AI uses the MCP tools to query Notion
→ AI response text returned to popup

The three components involved (MCP Client, mcpToTool adapter, Gemini)

1.MCP Client (@modelcontextprotocol/sdk)

const notionClient = new McpClient({ name: "notion-client", version: "1.0.0" });
const transport = new StdioClientTransport({
  command: "npx",
  args: ["-y", "mcp-remote", "https://mcp.notion.com/mcp"],
  env: { NOTION_TOKEN: process.env.NOTION_API_KEY },
});
await notionClient.connect(transport);
Enter fullscreen mode Exit fullscreen mode

The MCP client spawns npx mcp-remote as a child process (stdio transport), which acts as a proxy connecting to Notion's official MCP server at https://mcp.notion.com/mcp. This exposes Notion's capabilities (search pages, read content, etc.) as MCP tools.

2.mcpToTool adapter (@google/genai)

config: {
  tools: [mcpToTool(notionClient)],
}
Enter fullscreen mode Exit fullscreen mode

mcpToTool wraps the MCP client so that Gemini can discover and call Notion's MCP tools automatically — Gemini decides which Notion tools to invoke based on the prompt.

3.Gemini as the orchestrator

const prompt = `Search for pages under the database with the ID ${databaseId} mentioning '${keyword}'`;
const response = await ai.models.generateContent({
  model: process.env.GEMINI_MODEL ?? "gemini-2.5-flash",
  contents: prompt,
  config: { tools: [mcpToTool(notionClient)] },
});

Enter fullscreen mode Exit fullscreen mode

Gemini receives the natural language prompt and autonomously calls Notion MCP tools to find relevant pages, then summarizes the results into a text response.

Why MCP for search vs. the SDK for everything else?
The Notion SDK's search() API only matches page titles — it cannot search page body content. Notion's MCP server exposes richer capabilities including content-level search. By routing the query through Gemini + MCP, the search can find bookmarks by their AI-generated summary text, not just the title.

Top comments (0)