Skip to main content
Glama
mcp-context-window

mcp-context-window

mcp-context-window

An MCP server that gives a local model an external context buffer: durable session memory it can write notes into, and large documents it can page through without ever loading them whole.

Built on the MCP TypeScript SDK v2 against the 2026-07-28 protocol revision. Runs over stdio (LM Studio, Claude Desktop, anything that spawns a local process) or Streamable HTTP.


Read this first: what an MCP server can and cannot do

No MCP server can see or modify your context window. MCP is strictly request/response — the host calls a tool, the tool answers. The server never sees the conversation, cannot intercept messages before they reach the model, and cannot trim anything. LM Studio does its own truncation internally and does not consult any server about it.

So this is not an automatic sliding window, and anything advertising itself as one is misleading you. What it is: a store the model deliberately pages against, keeping the bulk of the material outside the window and pulling back only what it needs. That is genuinely powerful with an 8k-token local model — but it works because the model calls it, not because it intercepts anything.

The practical consequence: the model has to cooperate. Tool descriptions here are written to be prescriptive, and context_guide returns the intended workflow. If your model ignores them, say so in your system prompt.

One related note: MCP Sampling — the mechanism letting a server ask the client's LLM to generate text — was deprecated in the 2026-07-28 spec, with the official advice to "integrate directly with LLM provider APIs instead". So this server calls an OpenAI-compatible endpoint itself. That is also what keeps it harness-agnostic: the same code works against LM Studio, Ollama, llama.cpp, or vLLM.


Related MCP server: membot

The two halves

Sessions — working memory across a long task

Tool

Purpose

context_open

Start or resume a named session; shows what is already stored

context_append

Record a fact, decision, or dead end. Pin what must never be lost

context_recall

Pull back the most relevant entries, packed into a token budget

context_compact

Fold old entries into a summary to free budget

context_status

How full the session is, and whether to compact

context_update

Pin, unpin, or delete one entry

context_list_sessions

Find a session id from earlier work

Documents — material too large to read at once

Tool

Purpose

doc_ingest

Load text or a file; chunked and stored, almost nothing enters context

doc_outline

Structure map: chunk indices, headings, sizes, optional summaries

doc_search

Find the relevant chunks by keyword and return them verbatim

doc_window

Read chunk ranges in order; the cursor advances by itself

doc_summarize

Summarize a range, or the whole thing

doc_list / doc_forget

Manage what is stored

Plus context_guide, which explains the workflow to the model.


Quick start

npm install
npm run build
npm test
node dist/index.js --ingest-root ./sources

Or explore it interactively:

npx @modelcontextprotocol/inspector node dist/index.js

LM Studio

Edit ~/.lmstudio/mcp.json (on Windows, C:\Users\<you>\.lmstudio\mcp.json) via Program → Install → Edit mcp.json, then reload LM Studio.

{
  "mcpServers": {
    "context": {
      "command": "node",
      "args": [
        "/absolute/path/to/mcp-context-sliding/dist/index.js",
        "--ingest-root", "/absolute/path/to/your/project",
        "--budget", "4000"
      ]
    }
  }
}

These two paths must be absolute. The host spawns the server as a child process with an unpredictable working directory, so a relative path will not resolve. On the command line, where you control the working directory, relative paths like --ingest-root ./sources are fine.

On Windows either write forward slashes (C:/Users/you/projects) or double the backslashes, since a single \ is an escape character inside a JSON string.

Set --budget to roughly half your model's context length. It is the target this server packs recalls into, not a limit LM Studio enforces.

--ingest-root is what lets doc_ingest read files. Leave it out and the server accepts inline text only — which is the safe default, since a server that opens arbitrary paths on a model's say-so is a liability.

Docker

docker build -t mcp-context-window:latest .
{
  "mcpServers": {
    "context": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm", "--init",
        "-v", "mcp-context-data:/data",
        "-v", "/absolute/path/to/your/project:/ingest:ro",
        "-e", "CTX_INGEST_ROOTS=/ingest",
        "--add-host", "host.docker.internal:host-gateway",
        "mcp-context-window:latest", "--stdio"
      ]
    }
  }
}

Two things that bite here: -i is mandatory or the JSON-RPC handshake never happens, and the named volume is mandatory or every restart silently discards all stored sessions. From inside a container localhost is the container, so the LLM base URL defaults to host.docker.internal. Docker also requires the host side of a -v bind mount to be an absolute path.


How a session actually goes

context_open        session_id "refactor-auth"
context_append      "Goal: replace session cookies with JWT" (pinned)
context_append      "auth/middleware.ts:42 assumes a cookie is present"
context_append      "Decision: keep cookie support behind a flag for one release"
...
context_status      → 3200/4000 tokens — approaching budget
context_compact     → folds 14 old entries into one 380-token summary
context_recall      "cookie flag decision" → returns the pinned goal + the decision

And a document:

doc_ingest      file_path "logs/build-failure.log"  → doc_kx91, 240 chunks
doc_search      "OutOfMemory"                       → 3 chunks, 1400 tokens
doc_window      from 118 to 121                     → the surrounding context

The log never entered the model's context. Three targeted reads did.


Configuration

Flag

Env

Default

Meaning

--data-dir <dir>

CTX_DATA_DIR

platform data dir

Where state lives

--ingest-root <dir>

CTX_INGEST_ROOTS

(none)

Allow doc_ingest to read files here. Repeatable.

--llm-base-url <url>

CTX_LLM_BASE_URL

http://localhost:1234/v1

OpenAI-compatible endpoint

--llm-model <id>

CTX_LLM_MODEL

(loaded model)

Leave empty to use whatever is loaded

--llm-timeout <ms>

CTX_LLM_TIMEOUT_MS

120000

Local models can be slow

--no-llm

CTX_LLM_ENABLED=false

enabled

Extractive summaries only

--budget <n>

CTX_BUDGET

4000

Default recall/window budget

--chunk-tokens <n>

CTX_CHUNK_TOKENS

800

Target chunk size

--chunk-overlap <n>

CTX_CHUNK_OVERLAP

80

Overlap between chunks

--token-ratio <n>

CTX_TOKEN_RATIO

0.27

Cold-start tokens-per-character guess

--stdio / --http

CTX_TRANSPORT

stdio

Transport

--host / --port

CTX_HTTP_HOST / CTX_HTTP_PORT

127.0.0.1 / 3001

HTTP bind

--audit / --no-audit

CTX_AUDIT

on

JSON log per call on stderr


Design notes

Token counting is calibrated against your actual model. There is no universal tokenizer — Llama, Qwen and GPT all split differently — and bundling one would be large and wrong for whatever you loaded. Instead the server estimates cheaply, then measures the truth: it sends two samples of different lengths to your endpoint with max_tokens: 1 and takes the slope of the reported usage.prompt_tokens between them. The slope cancels out the chat template's fixed overhead and yields the real marginal cost per character. The result is cached, so only the very first run is uncalibrated, and it runs in the background so startup never blocks on a model that may not be loaded yet.

Estimates deliberately lean high. Undercounting overflows the window and truncates the very context this server exists to protect.

Summarization degrades instead of failing. If your endpoint is unreachable or no model is loaded, it falls back to extractive summarization — TF-ISF sentence scoring — which is instant, deterministic, and structurally incapable of hallucinating, since it can only select sentences that were really there. Losing access to your stored context is a worse outcome than a cruder summary of it. After a failure the client backs off briefly, so a 200-chunk document does not wait out 200 separate TCP timeouts.

Storage is append-only JSONL. A crash can corrupt at most the final line, which is skipped on load rather than being fatal. tail the file to watch memory accumulate. Compaction marks originals superseded rather than deleting them, so a compaction that dropped something important is still recoverable from the log.

Chunking follows document structure, not fixed offsets — headings, paragraphs, and fenced code blocks stay intact, and each chunk carries the heading trail it sits under. Only a block genuinely larger than a whole chunk gets hard-split.

Retrieval is BM25 plus recency, with no embedding model. That needs nothing loaded, costs no VRAM alongside your main model, and is deterministic — which matters when the entire point is predictability about what the model sees. Identifiers are indexed whole and split, so getUserName is findable as "user name".

Limits

  • The model must actually call these tools. Nothing is automatic.

  • Keyword search misses paraphrases that an embedding model would catch.

  • Token counts are estimates until the first calibration succeeds.

  • Neither transport authenticates; HTTP binds to loopback for that reason.

  • doc_ingest reads UTF-8 text. It is not a PDF or DOCX extractor.

License

MIT

Available Tools

15 tools
context_appendA

Record something worth remembering into the session. Use this as you go — after discovering a fact, making a decision, or hitting a dead end — rather than trying to hold it all in your reply. Keep each entry self-contained: it may be read back much later without the surrounding conversation. Set pinned for facts that must never be dropped during compaction, such as the goal or a hard constraint.

Inputs: text (required), session_id (required), role, tags, +1 more.

context_compactA

Fold older entries into a single summary to free budget, keeping the most recent entries verbatim. Call this when context_status or context_append warns that the session is over budget. Pinned entries are never compacted. The originals are kept on disk and can be recovered, so this is safe to run. Use dry_run first to see what would happen.

Inputs: session_id (required), dry_run, keep_recent, target_tokens.

context_guideA

Explain how to use this server effectively — the intended workflow for sessions and documents. Call this once if you have not used these tools before.

Inputs: no named parameters.

context_list_sessionsA

List stored sessions, newest first. Use this to find a session id from earlier work when you do not remember it.

Inputs: no named parameters.

context_openA

Start or resume a named memory session. Call this ONCE at the beginning of any task that will run long enough to risk losing earlier details, then reuse the same session_id for every later call. Returns what is already stored, so resuming a session after a restart tells you what you previously knew.

Inputs: title, session_id.

context_recallA

Retrieve the most relevant stored entries for a query, packed to fit a token budget. This is the main way to get memory back into your working context: ask for what you need rather than reading the whole session. Pinned entries are always included. Omit the query to get the most recent entries instead.

Inputs: session_id (required), limit, query, budget_tokens.

context_statusA

Report how full a session is, what is pinned, and whether compaction is advisable. Cheap to call — use it to decide whether you need to compact before adding more.

Inputs: session_id (required).

context_updateA

Pin, unpin, or delete a single entry by its id. Pin what must survive compaction; delete what turned out to be wrong, so it stops polluting recall.

Inputs: entry_id (required), session_id (required), delete, pinned.

doc_forgetA

Permanently delete an ingested document and everything derived from it. Use when a document is stale or was ingested by mistake.

Inputs: doc_id (required).

doc_ingestA

Load a large text into the store and split it into addressable chunks. Use this INSTEAD OF reading a big file into your context: the content stays on disk and you page through it with doc_outline, doc_search and doc_window. Accepts inline text, or a file path if the server was started with an ingest root. Returns a document id.

Inputs: text, title, doc_id, file_path.

doc_listA

List ingested documents with their ids, sizes and read positions.

Inputs: no named parameters.

doc_outlineA

Show the structure of an ingested document: every chunk with its index, heading and size. Call this right after doc_ingest to decide what is worth reading. Set summarize to also generate a one-line summary per chunk — more useful, but it runs the summarizer once per chunk, so it is slow on large documents.

Inputs: doc_id (required), summarize, max_chunks.

doc_summarizeA

Summarize a whole document or a range of its chunks. Use this to get the gist of something too large to read, before deciding which parts to pull verbatim. The whole-document summary is cached, so asking again is free.

Inputs: doc_id (required), to, from, refresh, +1 more.

doc_windowA

Read a range of chunks verbatim. This is the sliding window: ask for chunks 0-2, then 3-5, and so on, keeping each read inside your budget. Omit from/to to continue from where the last window left off — the read cursor is stored server-side, so sequential paging works without you tracking position.

Inputs: doc_id (required), to, from, reset, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.3/5.0

    Scored across 15 tools

    Disambiguation5/5

    The tools are cleanly divided into context/session memory tools and document ingestion tools, with each serving a distinct operation: append, recall, compact, status, update, ingest, outline, window, search, summarize, list, and forget. Even the two retrieval-style tools, context_recall and doc_search, are clearly scoped to different stores by their descriptions.

    Naming Consistency4/5

    All names are lowercase snake_case and consistently grouped with context_ and doc_ prefixes, mostly following a verb-action pattern. Minor deviations exist: context_status and doc_window use nouns as commands, but the overall convention is readable and predictable.

    Tool Count5/5

    At 15 tools, the server is at the upper edge of a well-scoped set, but every tool maps to a distinct and useful operation across two related subdomains. There are no redundant utilities, and the count feels justified for the stated context-window and document-management purpose.

    Completeness4/5

    The server covers the core session lifecycle (open/resume, append, recall, compact, status, update, list) and the document lifecycle (ingest, outline, read, search, summarize, list, forget). The main gap is the absence of an explicit session deletion or close tool, though agents can still work around this by leaving sessions unused.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Provides persistent session memory for AI assistants, enabling them to store, search, and retrieve conversation summaries across sessions via the Model Context Protocol.
      10
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Provides a persistent, versioned, and searchable context store for AI agents with local embedding and hybrid search.
      55 npm
      3
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Provides a unified context layer for Cursor's agent with lossless token savings and verifiable memory, enabling efficient code exploration and cross-session continuity.
      11 npm
      1
      MIT