> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blursec.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How it works

# How it all works

A plain-language tour of the Blursec ecosystem: what the SDK does, what the
Replit and MCP packages add on top, and exactly what to do to connect each
one. No prior security knowledge required.

## The problem in one paragraph

Most account takeovers don't involve anyone "hacking" your platform.
**Infostealer malware** infects a user's device and silently harvests every
credential it can find — saved browser passwords and session cookies for
*your* app, their SaaS tools, email, banking, and every other provider they
use. Those credentials are packaged into **stealer-log databases** sold on
the dark web, and an attacker simply logs into your platform with the
user's genuinely valid email + password (or replays a stolen session
token). Your code never sees anything wrong — the credentials are correct.
Blursec's job is to answer one question before you accept a login:
**"Is this credential already in the wild?"**

## How a check works (step by step)

When your server calls `blursec.checkCredential(email, password)`:

```text theme={null}
your server                                   Blursec API
-----------                                   -----------
1. hash  email:password  with SHA-256
   → e.g. 6f1ed002ab5595859014ebf0951522d9...
2. cut off the FIRST 10 characters
   → "6f1ed002ab"
3. send ONLY those 10 characters  ───────────►  4. return every known-leaked
                                                   hash that starts with
   ◄───────────────────────────────────────────    "6f1ed002ab" (a few dozen)
5. compare the REST of the hash locally
   → exact match found?  leaked : clean
6. map severity → recommended action
   → block / force_reset / monitor / allow
```

This is called **k-anonymity**. The password — and even its full hash —
never leaves your server. Blursec only ever sees a 10-character prefix that
matches thousands of unrelated hashes, so it learns nothing about the
actual credential. The same model is used for session tokens via
`blursec.verifySession(req)`.

Two more guarantees you get for free:

* **Fail-open** — if the Blursec API is slow, down, or unreachable, checks
  return `{ leaked: false, recommendedAction: "allow", failedOpen: true }`
  instead of throwing. An outage on our side never locks your users out.
* **Fast** — checks are budgeted at 1500 ms worst-case and typically answer
  in under 50 ms.

## The three pieces

| Package           | What it is                                                                                                                            | Use it when                                                                                        |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `@blursec/sdk`    | The core library. Runs anywhere JavaScript runs (Node 18+, browsers, Cloudflare Workers, Deno, Bun). Zero dependencies.               | Always — the other two packages sit on top of it.                                                  |
| `@blursec/replit` | A Replit adapter: reads your API key from Replit Secrets and gives you ready-made Express middlewares for login and session checks.   | Your app is hosted on Replit and/or uses Express.                                                  |
| `@blursec/mcp`    | An [MCP](https://modelcontextprotocol.io) server that exposes Blursec checks as **tools for AI agents** (Claude, Copilot, Cursor...). | You want to ask an AI assistant "is this account compromised?" during triage or incident response. |

Rule of thumb: the **SDK** protects your `/login` endpoint in production
code; the **MCP server** is for humans-with-AI-assistants investigating
things. Never put an LLM in the login hot path.

## Using the SDK (2 minutes)

```bash theme={null}
npm i @blursec/sdk
```

```ts theme={null}
import { Blursec } from "@blursec/sdk";

const blursec = new Blursec({ apiKey: process.env.BLURSEC_API_KEY! });

// In your login handler, BEFORE verifying the password:
const result = await blursec.checkCredential(email, password);

if (result.recommendedAction === "block") {
  return res.status(403).json({ error: "credential_compromised" });
}
if (result.recommendedAction === "force_reset") {
  return res.redirect("/auth/reset");
}
// "monitor" and "allow" → continue with your normal password check
```

That's the whole integration. Details: [configuration](/docs/configuration),
[error model & fail-open](/docs/errors), [advanced usage](/docs/advanced).

## Using the Replit adapter (3 minutes)

If your app lives on Replit, the adapter removes the remaining boilerplate:

1. Open your Repl's **Secrets** pane (lock icon) and add `BLURSEC_API_KEY`.
2. `npm i @blursec/sdk @blursec/replit`
3. Wire the middlewares:

```ts theme={null}
import express from "express";
import { createBlursecFromReplit } from "@blursec/replit";
import { blursecLogin, blursecSession } from "@blursec/replit/express";

const app = express();
app.use(express.json());

const blursec = createBlursecFromReplit();   // key comes from Secrets

app.use(blursecSession(blursec));            // checks every session
app.post("/login", blursecLogin(blursec), yourLoginHandler);
```

The middlewares apply the block / reset / monitor decisions for you. Full
option reference: [Replit integration](/docs/replit).

## Connecting the MCP server (5 minutes)

The MCP server lets an AI assistant call Blursec as tools:
`blursec_check_credential`, `blursec_check_token`, `blursec_check_hash`,
`blursec_verify_session`, and `blursec_whoami`.

You need two things: your **Blursec API key** and a one-block config in
your AI client. The key is passed as an environment variable only — it
never appears in prompts or chat history.

### Claude Desktop / Claude Code

Add to `claude_desktop_config.json` (Claude Desktop → Settings →
Developer → Edit Config), or `.mcp.json` for Claude Code:

```json theme={null}
{
  "mcpServers": {
    "blursec": {
      "command": "npx",
      "args": ["-y", "@blursec/mcp"],
      "env": { "BLURSEC_API_KEY": "bsk_live_..." }
    }
  }
}
```

Restart the app. You should see **blursec** listed under available tools.

### VS Code (GitHub Copilot agent mode)

Create `.vscode/mcp.json` in your workspace:

```json theme={null}
{
  "servers": {
    "blursec": {
      "command": "npx",
      "args": ["-y", "@blursec/mcp"],
      "env": { "BLURSEC_API_KEY": "${input:blursec-key}" },
      "inputs": [
        { "id": "blursec-key", "type": "promptString", "password": true,
          "description": "Blursec API key" }
      ]
    }
  }
}
```

VS Code prompts for the key once and stores it securely.

### Cursor and other MCP clients

Any client that speaks MCP over stdio works with the same shape: command
`npx`, args `["-y", "@blursec/mcp"]`, and `BLURSEC_API_KEY` in `env`.

### Try it

Ask your assistant:

> Is the credential `demo@example.com` / `hunter2` in any stealer log?

The agent calls `blursec_check_credential`, and you get back `leaked`,
`severity`, and a `recommendedAction` — with the same k-anonymity guarantee
as the SDK (only the 10-character hash prefix leaves your machine).

Full tool reference and troubleshooting: [AI agents & MCP](/docs/mcp).

## What goes over the wire (summary)

| Action                         | What Blursec receives                                     | What never leaves your machine                    |
| ------------------------------ | --------------------------------------------------------- | ------------------------------------------------- |
| `checkCredential`              | 10-char SHA-256 prefix, optional context (IP, user agent) | password, email:password string, full hash        |
| `verifySession` / `checkToken` | 10-char hash prefix of the token                          | the token itself                                  |
| MCP tool calls                 | same as above                                             | same as above — and the API key stays in env vars |
