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);
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)],
}
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)] },
});
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)