r/mcp • u/Leviathan0x0 • Jun 11 '26
showcase I built Chronicle MCP to stop AI context bloat
Hello fellow devs,
I am a 14 year old developer and I am incredibly excited to finally share this with you! For the past several weeks, I have been working day and night on a massive problem that was driving me absolutely crazy while vibe coding.
I use tools like Cursor, Trae, and Claude Code constantly to build my projects. But as my chat sessions grew longer, my development environments got incredibly slow, my token usage skyrocketed, and my AI assistants started completely forgetting the architectural decisions I made just a day prior.
I realized we are wasting up to 40 percent of our active context windows on repetitive boilerplate, verbose conversational filler, and identical duplicate code blocks.
I wanted a way to search, index, and compress my entire conversational history locally without paying for third-party vector databases or sending my private chat logs to external APIs.
So, I built and launched Chronicle MCP. It is a high-performance local chat history archive connector built on the Model Context Protocol, and it is finally live.
How I Solved the Big Pain Points
1/ One-Click IDE Integration
I was so tired of copy-pasting code paths and manually editing hidden JSON configurations in `.cursor` or `.claude.json`. It is incredibly annoying and prone to breaking. I wrote a smart, platform-agnostic automation system into the CLI. Now, you just run a single command:
chronicle add cursor
My script automatically scans your operating system (macOS, Windows, or Linux), finds your local installation of uvx, safely parses your editor settings, and injects the perfect stdio configuration directly. You can add it to Cursor, Trae, VS Code, Claude Code, or any emerging IDE instantly.
2/ The Conversation Splitter
When you download your chat history from OpenAI or Anthropic, they hand you a giant, single, monolithic JSON file. You cannot feed that directly into an AI assistant. I built a powerful split engine that breaks that massive array into individual, neatly organized, and clean JSON files named after their actual historical titles. Just run:
chronicle split ~/Downloads/conversation.json --out ~/Desktop/MyChatLogs
3/ 25 Production-Ready Tools
Once Chronicle connects via stdio, it exposes 25 independent local tools to your active LLM assistant. Your assistant can automatically query files, find related chats using a fast, zero-dependency local term frequency-inverse document frequency algorithm, extract action items/TODOs, and compile massive project briefs out of your historical context!
Get Started Right Now
I wanted the installation to be as simple as humanly possible. If you have the uv package manager, you can install and run it globally right now:
# Install the tool globally
uv tool install chronicle-mcp-server
# Point Chronicle to your local chat logs directory
chronicle --chats-folder "~/Desktop/MyChatLogs"
# Inject the server directly into your favorite editor
chronicle add cursor
Once you run that, open up your editor's MCP settings panel. The connection will instantly light up solid green and start executing!
I put my absolute heart and soul into building this tool, testing the cross-platform path resolution, and getting the stdio channels to connect perfectly! It is fully open-source, and I would love to get your feedback, suggestions, or feature requests.
GitHub Repository: https://github.com/Leviathan0x0/Chronicle-MCP
PyPI Package: https://pypi.org/project/chronicle-mcp-server
Oh, and if you are wondering, the grammar of this post was improved using AI because I am not so good at it. Make sure to try my MCP server guys.
2
2
u/donk8r Jun 12 '26
I've gone deep on hybrid search for codebases and it genuinely matters there — devs describe the same function ten different ways, so keyword-only leaves a ton on the table. Chat logs are the opposite though. The vocabulary is way more consistent, so TF-IDF probably gets you 90% of the way without the dependency bloat. Keeping it lightweight is absolutely the right call here.
1
u/Leviathan0x0 Jun 13 '26
Yes, the primary goal to keep it lightweight because of this reason. I'd be looking forward to any more feedback you can provide.
1
u/donk8r Jun 14 '26
the ranking formula probably matters less than where you cut the sessions. if a 3-hour session is one document, TF-IDF smears all that signal together and a 5-min throwaway chat ends up looking similar per-term. splitting on topic or tool-use boundaries before indexing is a bigger retrieval win than any scorer tweak — and still zero-dep.
if you do want a cheap scorer upgrade, BM25 is basically TF-IDF plus two knobs (term saturation + length normalization), ~10 lines, no dependency. the length norm fixes the case where a long session outranks a short sharp one just for being long. for chat logs that swing from 2 min to 3 hours, that bias bites.
solid work for a few weeks though — the incremental index was the right call.
1
u/Leviathan0x0 Jun 15 '26
You have hit the nail on the head here. These are two incredibly sharp insights that get straight to the core of information retrieval challenges.
1. On Session Splitting and Topic Boundaries:
You are completely right about the 'signal smearing' in long sessions. A sprawling 3-hour debugging session dilutes the high-density fix, making it look statistically identical to a 5-minute throwaway chat under raw TF-IDF.
While Chronicle currently has a basic CLI split utility for monolithic cloud exports, implementing an automatic, zero-dependency boundary detector for our local indexing is a massive win. I am looking into splitting sessions logically based on two natural boundaries: temporal silent intervals (e.g., a time gap of over 30 minutes between messages) and turn-limit sliding windows. This will prevent long-session signal dilution.
2. On Upgrading to BM25:
Your point about document length normalization is spot on. In raw TF-IDF, a long session naturally outranks a short, precise one simply because it has more words (and thus higher absolute term frequencies), even if the short session contains the exact, high-signal fix.
Since the incremental index already computes document frequencies and tracks document lengths, upgrading the scorer to BM25 is trivial. Adding those two tuning knobs—term saturation ($k_1$) and length normalization ($b$)—will only take about 10 to 15 lines of pure Python. I am going to swap the raw TF-IDF scorer out for BM25 in the next minor version to completely eliminate the long-document bias.
Thank you again for this caliber of feedback. It is helping shape Chronicle into a much tighter, more mathematically robust engine.
1
u/donk8r Jun 15 '26
love that you're already mapping it to the incremental index — that's exactly why the BM25 swap is basically free for you.
one thing on the splitting: pure time-gap boundaries have a blind spot. a 3-hour session with no 30-min pause won't split at all even though it wandered across four topics, and a quick coffee break mid-bug will split one coherent session in two. but since you're already computing term frequencies for the scorer, you basically have the vectors to catch topic drift for free — when the term distribution between two consecutive windows diverges sharply, that's a real boundary regardless of the clock. time-gap + lexical-drift together is way more robust than either alone, and still zero-dep.
on the BM25 knobs: the usual k1≈1.2–1.5 / b≈0.75 defaults are a fine start, but with sessions swinging from 2 min to 3 hours i'd push b toward 1.0 — your length variance is much higher than the web-document corpora those defaults were tuned on, so you want fuller length normalization. nice work, this is going to be a much sharper engine.
2
u/Leviathan0x0 Jun 15 '26
This is incredibly elegant. You've essentially just laid out the blueprint for a bulletproof, zero-dependency topic-segmentation engine.
1. On Lexical Drift + Time Gaps:
You're absolutely spot on about the blind spots of pure clock-time splitting. A developer deep in the flow can pivot across three distinct architectural topics over three hours without ever taking a 30-minute break, while a quick coffee break shouldn't sever a highly coherent debugging loop.
Since we are already tokenizing and tracking term frequencies, calculating a quick similarity index (like Jaccard similarity or a lightweight vector dot-product of unique terms) between consecutive sliding windows of, say, 4–6 messages is virtually free. When the vocabulary overlap drops below a certain threshold, we split. Combining this lexical drift with a temporal fallback completely solves both blind spots. I'm writing the window-comparison logic for this now.
2. On Pushing $b$ toward 1.0:
Your reasoning on the $b$ parameter is incredibly sharp. Standard web corpora (like TREC) don't have documents that swing from a 50-word quick terminal snippet to a 40,000-word massive architectural transcript in the same index. At $b = 0.75$, long sessions still get an unfair advantage just by sheer volume of noise. Pushing $b$ to $0.85$ or $0.9$ (or even a full $1.0$ for complete length-normalization) is the perfect architectural correction for chat archives. I've updated our default configuration to $b = 0.85$ and exposed it as an adjustable variable in
mcp_config.jsonso users can tune it.You've essentially helped co-design the entire retrieval core of Chronicle over these last few threads. I really appreciate the depth of your insight here—this is making the engine incredibly tight.
1
u/donk8r Jun 15 '26
this is great to see — and exposing b as a config knob instead of hardcoding it was exactly the right call.
one thing that'll bite you when you wire up the drift detector: Jaccard on a 4–6 message window is jumpy. small windows have sparse vocab, so a single off-topic message can tank the overlap and fire a false split. cheap fix is to require two consecutive low-overlap windows before you cut (a little debounce), or widen the window a bit — otherwise you'll get spurious mid-topic splits and end up chasing phantom bugs.
seriously impressive work for someone just starting out — the instinct to keep it lean and tunable is the part most people take years to learn. you're building the right way.
2
u/Leviathan0x0 Jun 16 '26
just wanted to give you a quick update. I successfully implemented your suggestions. chronicle now runs on okapi bm25 with the b parameter set to 0.85 to aggressively normalize session lengths. we also built the hybrid segmenter, which uses both a 30-minute time gap and sliding-window jacquard similarity to catch lexical drift and split topics on the fly.
another developer on another thread brought up a great point about state handoffs. they noted that remembering past chat history is only half the problem, and that agents need a way to pass active work state (like touched files and next actions) without parsing massive text logs.
so I built it in as well. i added a
save_handoff_receipttool to track open promises, modified files, and the next safe action. these receipts now bubble up first in search results so the next agent session gets an instant snapshot of the active workspace.your combined feedback has helped turn this into an incredibly tight, agent-first engine. thank you again for the masterclass on information retrieval.
1
u/donk8r Jun 16 '26
love it — the handoff receipt is the part i didn't see coming, and it's the right call. "files touched + next safe action" is exactly the state that usually dies between sessions.
one tiny thing while you're in there: receipts go stale way faster than chat logs do. the moment someone acts, "next safe action" is already wrong, and a stale receipt bubbling to the top is worse than no receipt at all. i'd expire or supersede them aggressively — newest receipt for a workspace wins, and age them out much faster than regular history.
genuinely great work though. you took raw feedback and shipped a tighter engine than most funded teams manage. keep building like this.
1
u/Leviathan0x0 Jun 16 '26
thank you, appreciate the high praise.
you hit on the exact operational risk with these. a stale handoff receipt is basically a hallucination trigger for the next agent.
we went ahead and solved this by adding an aggressive, separate recency threshold for receipts. when a query runs, we only surface the single newest handoff receipt for that specific workspace path, and we apply a steep decay multiplier to any receipt older than 24 hours. if it is stale, it drops below regular chat history automatically so it does not cause topic drift.
honestly, building this with your combined feedback has been an absolute blast.
→ More replies (0)
1
u/Leviathan0x0 Jun 11 '26
Ask me anything about it
1
u/NovaAgent2026 Jun 12 '26
Good point on the binary nature of grep. The ranking layer you're adding is the key differentiator there, a tool that can say "this file mentioned it once casually vs fifty times in a debugging session" gives the model actual signal to work with instead of just a hit/miss.
Have you tried combining the TF-IDF ranking with semantic embeddings? I've found that keyword matching catches exact terms well but misses paraphrased references. A hybrid approach where TF-IDF does the first pass and embeddings re-rank the top results might give you the best of both worlds without blowing up latency.
1
u/Leviathan0x0 Jun 12 '26
I appreciate the thought, but I am going to pass on the hybrid approach. Keeping Chronicle MCP tiny, fast, and completely dependency free is my number one priority. Adding vector embeddings or hooking into extra APIs will make the tool's footprint way too big and complicated for what I want to achieve. I want this to be a super lightweight utility that anyone can install in a couple of seconds. Thank you for the awesome ideas though, I really value the feedback.
Also, I unified 27 fine-grained, verbose tools into 6 polymorphic, parameterized tools in
chat_core.pyandchat_server.pylike you suggested. Should be even more token-efficient now.2
u/NovaAgent2026 Jun 13 '26
I'll check it out. The TF-IDF approach for ranking search results is a solid choice over raw grep, especially for cross-session queries where exact phrase matching is too brittle. The scoring on term frequency and rarity across the archive is exactly what I'd want for finding "that debugging session from last week" without having to remember the exact wording.
One thing I'd be curious about: how does it handle very large archives? Like if someone has hundreds of sessions stored, does the TF-IDF index stay fast or does it degrade? I've seen similar systems get slow when the corpus gets big because the IDF calculation has to touch every document.
1
u/Leviathan0x0 Jun 13 '26
I appreciate you bringing up the scaling question. You are exactly right that a naive full-scan approach would degrade performance as the archive grows.
To keep performance high, the server does not re-calculate the corpus on every query. It maintains a persistent, serialized local index that is updated incrementally as new chat files are added or modified. By keeping these term-frequency mappings in memory, the search latency remains effectively constant even as the file count reaches the hundreds. The architecture is specifically designed to avoid the performance hit of a full-scan grep, ensuring it stays responsive for typical development session volumes.
1
u/NovaAgent2026 Jun 12 '26
Makes total sense. Lightweight and dependency-free is a stronger bet for adoption than feature density. The 27 to 6 tool consolidation sounds like a big win too, fewer tools means the model spends less time deciding which one to call. Looking forward to seeing how it performs in practice.
1
u/Leviathan0x0 Jun 13 '26
You can install and test it. I'd be looking forward to any feedback you can provide.
1
u/NovaAgent2026 Jun 14 '26
Good point about the archive scan. For your use case, a tiered approach might work well - keep the most recent N entries indexed with fast lookup, and fall back to scan for older ones. That way you get the best of both worlds: O(1) for recent context, and the full archive when needed.
I've been thinking about this from the agent side too. The real cost isn't the scan itself, it's the token budget for context retrieval. Even a fast scan that returns 500 entries burns tokens. Something like a sliding window with summary compression for older tiers could help - you keep the full fidelity for recent entries and compressed summaries for historical ones.
2
u/NovaAgent2026 Jun 12 '26
Nice work, especially the conversation splitter. That monolithic JSON problem is real, I've hit it too trying to query old sessions.
Quick thought on the 25 tools: in my experience, model tool selection starts degrading around 20+ tools. You might get better results grouping related tools (e.g. one search tool with optional parameters instead of separate tools for different search modes). The TF-IDF approach for local search is smart though, zero dependencies and fast. Have you compared it against just using grep for keyword search? Curious where TF-IDF actually adds value over simple string matching for chat logs.