惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
IT之家
IT之家
Last Week in AI
Last Week in AI
J
Java Code Geeks
L
LangChain Blog
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Google DeepMind News
Google DeepMind News
博客园 - Franky
博客园 - 司徒正美
月光博客
月光博客
博客园 - 叶小钗
Vercel News
Vercel News
腾讯CDC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
B
Blog RSS Feed
人人都是产品经理
人人都是产品经理
H
Help Net Security
G
Google Developers Blog
D
DataBreaches.Net

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I gave Claude a memory of everything I browse — here's th...
Kiell Tampubolon · 2026-06-15 · via DEV Community

Claude can read my files, my terminal, even my screen. But it had no idea what I read in my browser yesterday.

That gap bugged me enough to build BraveMCP: a local-first "second brain" that gives Claude Desktop access to my browsing history, bookmarks, highlights, and notes through the Model Context Protocol (MCP). Everything stays on my machine. No cloud, no tracking.

This is the technical write-up: the architecture, the one constraint that shaped the whole design, and the bugs that cost me the most time.

The constraint that shaped everything

MCP servers talk to Claude Desktop over stdio, a JSON-RPC stream on stdin/stdout. A browser extension lives in a sandbox and cannot speak stdio. It can only make outbound HTTP requests.

So the two halves of the system physically cannot talk to each other directly. That single fact drove the entire design.

BraveMCP architecture

The fix is a small HTTP bridge: an Express server running on port 3747, inside the same process as the MCP server. The extension POSTs browsing events to it; the MCP server reads from the shared database when Claude calls a tool.

The storage layer: hybrid search

Keyword search and semantic search each miss things the other catches. So BraveMCP runs both and merges them.

  • SQLite with FTS5 for fast BM25 keyword ranking over titles, summaries, notes, and highlights.
  • ChromaDB for cosine vector similarity, so "MCP security" still finds a page titled "Claude agent hardening."
// Merge keyword + vector hits; boost items that appear in both
const merged = new Map();
for (const m of chromaMatches) merged.set(m.id, { ...m, source: "semantic" });
for (const m of ftsMatches) {
  const existing = merged.get(m.id);
  if (existing) existing.relevance *= 1.1; // appears in both -> boost
  else merged.set(m.id, { ...m, source: "keyword" });
}

If ChromaDB is not running, the server degrades to FTS5-only instead of failing. Local-first means it has to work with whatever services you actually have up.

The AI pipeline, and why the fallback matters

When a page is captured, BraveMCP generates a summary and an embedding. It tries Ollama first (fully local: llama3.2 for summaries, nomic-embed-text for embeddings), then falls back to the Anthropic API.

But here is the trap I walked into. The first version, when no LLM was available, returned canned strings:

// before: this ignores the actual data entirely
return `Synthesis on "${topic}": Relies on the gathered browser research database.`;

That is useless. It says the same thing no matter what you searched. So I rewrote every fallback to be extractive: to build a real summary from the actual data, grouping matching pages by domain with real snippets pulled from SQLite. With no LLM at all, asking for a topic synthesis now returns the genuine sources. Different input produces different output. The "AI" tools stay useful even when there is no AI running.

Recovering forgotten pages

The tool I use most is find_forgotten_content. You give it a vague description and it does hybrid search, then re-ranks with time decay and a visit-count boost:

const timeDecay  = Math.max(0.5, Math.exp(-0.01 * daysElapsed));
const visitBoost = 1 + 0.2 * Math.log(visitCount);
const adjusted   = Math.min(0.99, relevance * timeDecay * visitBoost);

A page you opened three times last week beats one you glanced at once today. That matches how memory actually feels.

Before and after BraveMCP

Two bugs that cost me hours

1. dotenv v17 broke the entire protocol. MCP communicates over stdout. dotenv v17 prints a status line to stdout by default. That one line corrupted the JSON-RPC channel and Claude Desktop refused to connect with a cryptic Unexpected token error. The fix was pinning dotenv@16. Two hours on a single log line.

2. The dual-process state problem. Claude Desktop and my dev client each spawn their own copy of the MCP server. Only the instance that grabs port 3747 receives extension data. The other had empty in-memory state, so tab tools returned nothing. The fix: stop treating in-memory state as the source of truth and fall back to SQLite, which both processes share.

What's in the box

  • A Manifest V3 extension (tab sync, bookmarks, context-menu highlights)
  • An MCP server exposing 13 tools (search_memory, find_forgotten_content, summarize_research_topic, generate_weekly_digest, suggest_tab_cleanup, and more)
  • SQLite + ChromaDB hybrid search
  • A test suite on Node's built-in runner, wired into CI

It is open source, MIT licensed: https://github.com/glatinone/BraveMCP

If you are building on MCP, the stdio-vs-HTTP bridge pattern is the part worth stealing. What would you want your AI to remember?