Hister Indexes Everything You Read and Hands It to Your Agent. Its Own Docs Explain Why That Is a Problem.
A self-hosted personal search engine with an MCP endpoint, and the most candid prompt-injection warning I have read in any MCP server's documentation.
Most MCP servers describe what they can do. Hister's MCP page spends its second section describing what it cannot promise.
"Every indexed title, URL, metadata value, document body, and history field is untrusted source data. A page can contain instructions aimed at the assistant that reads it." Then, four paragraphs later, after listing the mitigations: "These controls reduce risk but cannot guarantee that every consuming model will resist prompt injection."
That is a vendor documenting the limits of its own defense, on the integration page, before the tool reference. It is rare enough to be the reason to write about this project, and it points at something structural that the rest of the MCP ecosystem has been avoiding.
Hister is a self-hosted search engine for the pages you visit and the files you keep. A browser extension for Firefox or Chrome sends the full text of pages you view to a local server, which indexes them alongside whatever local directories you point it at. You search from a web UI, a terminal client, or an AI assistant connected through MCP. It hit the front page of Hacker News on September 17 and is sitting around 4,900 stars, AGPL-3.0, written in Go.
It is a genuinely useful thing. It is also a category of MCP server nobody has thought hard enough about.
The corpus is adversarial by construction
Think about what an MCP server usually exposes. A database you own. An issue tracker your team writes. A filesystem you control. The content has a trust story, even a sloppy one: somebody you can name put it there.
Hister inverts that. Its entire index is text written by strangers. Every blog post, every documentation page, every forum thread, every PDF, every marketing page you happened to open in a tab. You did not author any of it. You did not review any of it. The extension indexed it because it rendered in your browser.
Now attach that to an agent. Ask Claude Code "search my history for anything about Rust error handling," and the search tool returns full stored article text from pages you read weeks ago and have forgotten. If any one of those pages contains a line addressed to a model rather than a human, it is now inside your agent's context, delivered by a tool you installed and trust, about a query you initiated.
The attack does not need to target you. It needs to be on a page you might read. That is a materially different threat model from "an attacker compromises your MCP server," and it is one where the ordinary advice, run the server locally and keep it off the network, does nothing at all. Hister running entirely on your laptop with no telemetry is exactly as exposed as Hister running on a VPS. Local does not mean trusted when the data came from outside.
What Hister actually does about it
The mitigations are more thoughtful than most, and worth stealing whether or not you ever install this.
Tool responses place source-controlled values under structuredContent.untrusted_content. Every record carries trust: "untrusted" and trust_scope: "all values in fields". A security instruction names the exact untrusted path so a client can find it programmatically rather than guessing. The same structured JSON also appears in the required text content block, behind a security notice. Invisible control characters get stripped. HTML is returned only when a caller explicitly asks for it through the search tool's fields parameter or as a rendered preview from get_preview, and even then it stays inside the untrusted structured record.
The tool surface is three calls. search takes a query, a limit capped at 50, optional date bounds, an optional semantic flag, and a fields array that can escalate a result from a snippet to full stored text, raw HTML, language, label, domain, score, or type. get_preview takes an exact URL and returns complete stored plain text plus rendered HTML and metadata. get_history returns recently indexed pages or your opened-result history.
Then the docs say the quiet part: "MCP clients must sanitize HTML before rendering it and should require user confirmation before any action outside read only retrieval, especially before using file, shell, browser, email, or network tools."
That sentence is where the design hands the problem off. Hister labels. Your client is supposed to enforce. And the number of MCP clients that read trust_scope and gate their shell tool accordingly is, as far as I can tell, zero.
This is not a criticism of Hister so much as a description of where MCP currently sits. The protocol gives a server a way to say "this is untrusted." It gives the server no way to make that stick. Labeling without enforcement is a seatbelt that asks the passenger to hold it.
The default that will bite people
One more thing from the same page, and it is the part I would change before shipping this to anyone non-technical.
"The default Hister configuration does not require authentication. Authentication is required only when Hister is configured with app.access_token or app.user_handling."
So out of the box you get an unauthenticated HTTP endpoint at http://127.0.0.1:4433/mcp serving the full text of everything you have read. On a single-user laptop with a loopback bind that is defensible, and it makes the quickstart genuinely frictionless, which is presumably the point. It stops being defensible the moment anyone follows the docs' own instructions for a remote or self-hosted server and changes base_url without also setting app.access_token. The docs tell you how to put it behind a reverse proxy under a subpath in the same section where they tell you auth is optional.
Any local process can also reach a loopback port. A malicious npm postinstall script does not need your filesystem if it can just ask your search index what you have been reading.
Put this into practice
If you want to try it, the setup is a binary and about four minutes.
Download the release for your platform, chmod +x hister, run ./hister listen, open http://127.0.0.1:4433, install the extension. Homebrew (brew install hister), Docker, and Nix all work too. Then browse normally for a day and search for a phrase you remember reading.
Before you point an agent at it, do four things.
Set app.access_token immediately, even locally. It is one config line and it closes the loopback hole. Then use the Authorization: Bearer header in your client config rather than running open.
Decide what gets indexed before you index it. The extension captures whatever renders with it enabled. Your banking session, your company's internal wiki, a shared doc with somebody's salary in it. Hister's configuration supports choosing what it indexes, and the default of "everything" is the wrong starting point for a corpus you are going to expose to a model. Turn the extension off for the tabs you would not paste into a chat window.
Leave semantic search off unless you have read where the text goes. It is optional and it works by sending document text to an embeddings endpoint you configure. That is disclosed clearly in the README, and it is the one feature that takes a local-only tool and makes it a data-egress path. If you enable it, know which endpoint and under what retention.
Treat the results as untrusted in your own prompts. Until clients enforce trust_scope, you are the enforcement layer. If you are going to hand search output to an agent that also has shell or file tools, put the retrieval in a separate turn from the action, and read what came back. A single-turn "search my history and then fix the build" is the exact pattern the docs warn about.
What I would not claim about it
I have not audited the code, and nothing here is a security review. The mitigations are described in documentation dated April 20, 2026; I have verified the docs say what I quote them as saying and have not verified the implementation matches.
Some other honest gaps. The newest thing in the releases feed is a rolling automatic dev build, and the latest versioned release is v0.19.0 from September 3, which is a normal pattern for an active project but means "latest" and "stable" point at different artifacts. The default branch is master, not main, which will trip you up if you script against it. The LICENSE file contains only the Free Software Foundation's own 2007 boilerplate with no project copyright line, so AGPL-3.0 comes from the README's assertion rather than a filled-in notice. The README carries a sponsor credit for Uruky, which is disclosure, not a problem, but you should know it is there.
And the broader claim in this piece, that labeling without client enforcement does not hold, is my read rather than a measured finding. I have not tested a real injection through the MCP path, and a sufficiently careful model may well ignore instructions sitting inside a field marked untrusted. The point is that you would be relying on the model's judgment, which is precisely what the protocol layer was supposed to stop doing.
The part worth keeping
Install Hister or do not. The thing to take from it is the question its docs force you to ask about every MCP server you have connected: who wrote the data this thing returns?
For most of them the answer is comfortable. For any server that reaches the open web, a browser tool, a scraper, a documentation fetcher, a news reader, a search index, the answer is "anyone," and the protocol has no way to make that matter yet. Hister is honest enough to say so on the integration page. Go look at whether the others are.
Sources: asciimoo/hister on GitHub (README fetched from master, 2026-09-18) · Hister MCP Integration docs · Hister documentation index
Medium metadata
Title: Hister Indexes Everything You Read and Hands It to Your Agent. Its Own Docs Explain Why That Is a Problem. Subtitle: A self-hosted personal search engine with an MCP endpoint, and the most candid prompt-injection warning I have read in any MCP server's documentation. Tags: MCP, AI Agents, Security, Self Hosted, Prompt Injection Canonical: publish on fervorai.dev first, import to Medium from the canonical URL.