Skip to main content
Glama
amr05008

personal-context

by amr05008

Personal Context

A minimal system for giving LLMs your writing voice, opinions, and style. Curated markdown files served via MCP using FastMCP.

Inspired by Karpathy's LLM Wiki and nlwhittemore's Personal Context Portfolio.

More background on the why behind this project here.

How It Works

context/*.md  →  FastMCP server  →  MCP  →  Claude Code (or any MCP client)

You maintain 6 markdown files about yourself. A FastMCP server exposes them as tools. When you ask an LLM to write something, it can pull your context and match your voice.

The 6 Context Files

File

What It Captures

identity.md

Background, career arc, personal details

writing-style.md

Voice, tone, sentence patterns, vocabulary, annotated examples

opinions.md

Stances on topics you write about

expertise.md

Domains of deep knowledge

projects.md

Current and notable past projects

communication.md

How you communicate in different contexts (Slack, email, docs)

Each file has YAML frontmatter tracking last_updated and source_refs (which source materials informed the content).

Related MCP server: MCP Docs Provider

Getting Started

Use this as a template

  1. Fork or clone this repo

  2. Delete everything in context/ — those are my files, not yours

  3. Install dependencies and start filling in your own context

Setup

git clone <this-repo> personal-context
cd personal-context
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"

Bootstrap from existing writing (optional)

If you have a folder of markdown blog posts or writing samples, the ingest script can generate draft context files:

# Copy or symlink your markdown files
ln -s /path/to/your/blog/posts sources/blogs

# Generate drafts (--cutoff filters by date in frontmatter)
python scripts/ingest.py sources/blogs/ --cutoff 2024-01-01 --output drafts

This creates draft files in drafts/ with excerpts grouped by category. Review them, extract what's useful, and write your curated versions into context/.

The ingest script expects markdown files with YAML frontmatter containing title, pubDate, and optionally categories. If your files don't have frontmatter, you can skip this step and write context files manually.

Write your context files manually

If you don't have existing writing to ingest, just create the 6 files in context/ yourself. Use this template:

---
last_updated: 2026-05-30
source_refs: []
---

# Writing Style

## Voice
[How do you write? Conversational? Formal? Technical? Direct?]

## Patterns
[Recurring structures, transitions, vocabulary choices]

## Examples
[2-3 representative excerpts from your actual writing, with annotations]

A good approach: start a Claude Code session and ask it to interview you. Share writing samples and let it draft context files for you to review and edit.

Connect to Claude Code

The MCP server runs entirely locally — Claude Code spawns it as a subprocess on your machine, and it just reads markdown files from disk. No data is sent to external services beyond the normal Claude API calls.

Register the server as a user-scoped MCP so it's available in every Claude Code session, regardless of which project you're working in:

claude mcp add --scope user personal-context -- /absolute/path/to/personal-context/.venv/bin/python /absolute/path/to/personal-context/server.py

Restart Claude Code. The MCP tools will be available in every session.

Setting up on another machine

To use the same context on a work machine or second computer:

  1. Clone the repo: git clone <your-fork> personal-context

  2. Install: cd personal-context && uv venv && source .venv/bin/activate && uv pip install -e .

  3. Register the MCP server (update paths to match where you cloned it):

    claude mcp add --scope user personal-context -- /absolute/path/to/personal-context/.venv/bin/python /absolute/path/to/personal-context/server.py
  4. Restart Claude Code

That's it — same context files, same tools, works in any repo you open. If you keep your context files committed, git pull on either machine keeps them in sync.

Make it automatic

By default, Claude Code won't call MCP tools unless you ask. To have it pull your context automatically when drafting written content, add a rule to your global ~/.claude/CLAUDE.md:

## Personal Context (MCP)

When drafting any written content (emails, messages, docs, social posts, bios, etc.), call `get_writing_style` from the `personal-context` MCP server first to match my voice and tone. For tasks that benefit from broader context (introductions, project summaries, etc.), use `get_all_context` instead.

Test it

In a new Claude Code session:

  • Ask Claude to use your writing style to draft something

  • It should automatically call get_writing_style or get_all_context

  • Compare the output to how you actually write and iterate on your context files

Adding Context Over Time

This system is manually curated, you update the files, this is not an automated pipeline.

When to update

  • After publishing new writing — review if it reveals patterns not yet captured in writing-style.md

  • After changing jobs/projects — update projects.md and identity.md

  • After noticing the LLM gets your voice wrong — the gap between output and expectation tells you what's missing

  • After adding new source material — drop files in sources/private/ or sources/blogs/ (both gitignored), re-run ingest if helpful

How to update

  1. Edit the relevant context/*.md file directly

  2. Update the last_updated date in frontmatter

  3. Add any new source refs to source_refs

  4. Re-read the whole file, not just your changes — see Security. Context files accumulate, so the risk is usually something added long ago and never re-read. When you find something, paraphrase rather than delete: the point being illustrated almost always survives, and the specifics are what create the exposure.

  5. Check sibling files for contradictions. get_all_context() returns them together, so removing a claim from one file while another still asserts it produces an inconsistent picture.

  6. Commit

Private sources

Work emails, Slack exports, or other private writing go in sources/private/ which is gitignored. You can reference them in source_refs for provenance without committing the content.

Since sources/private/ is gitignored, these files are device-specific — they won't sync when you git pull on another machine. If you need the same private sources on multiple machines, copy them manually or sync via something outside git (e.g., iCloud, Dropbox).

Private served context

sources/private/ holds raw source material for ingest — it is not read by the MCP at runtime. If you have curated context that the MCP should serve but that must stay out of a public repo, put it in context/private.md, which is gitignored.

The server globs context/*.md, so any gitignored file you add there (e.g. context/private.md, context/travel.md) is returned by get_all_context() and served locally, but git never commits it. Like sources/private/, these are device-specific — copy them manually (or symlink them from a private repo) if you run the MCP on another machine.

Two things to know about this pattern:

  • Never put example/placeholder versions of private files in context/ — the glob would serve them to the model as if they were real. Public examples belong elsewhere, e.g. docs/.

  • A symlink works. If you keep the real file in a private repo (for backup/sync), symlink it into context/ — the server follows symlinks, and .gitignore keeps the link out of the public repo.

Travel profile

An example of the private-served-context pattern: a durable travel profile (home airport, airline status, hard rules, output contract) so an agent planning a trip never starts cold. See docs/travel.example.md for the shape with placeholder values. The real one lives at context/travel.md (gitignored); loyalty account numbers stay in a password manager — the file points at where they live, it never stores digits.

Re-running ingest

If you add new blog posts or writing samples to sources/blogs/:

python scripts/ingest.py sources/blogs/ --cutoff 2024-01-01 --output drafts

This regenerates drafts (in drafts/, also gitignored). Review the new excerpts and fold anything useful into your context files.

MCP Tools

The server exposes:

Tool/Resource

What It Does

get_writing_style()

Returns your writing-style.md — the most commonly needed file

get_all_context()

Returns all context files as a dict (includes a local private.md if present)

context://{filename}

Resource access to any individual file by name

Project Structure

personal-context/
├── context/           # Your curated context files (the product)
│   ├── private.md     # Optional private served context (GITIGNORED)
│   └── travel.md      # Optional travel profile, may be a symlink (GITIGNORED)
├── docs/
│   └── travel.example.md  # Public placeholder example (kept OUT of context/)
├── sources/
│   ├── blogs/         # Writing samples for ingest (GITIGNORED — symlink or copy)
│   └── private/       # Private writing samples (GITIGNORED)
├── scripts/
│   └── ingest.py      # Bootstrap drafts from existing writing
├── drafts/            # Generated drafts from ingest (GITIGNORED)
├── tests/             # Tests for ingest script and server
├── server.py          # FastMCP MCP server
├── pyproject.toml
└── README.md

Running Tests

pytest is an optional dev dependency, so install it before the first run:

uv sync --extra dev      # or: pip install -e ".[dev]"
python -m pytest -v

Security

This repo is designed to be public, but remember you are putting personal information in it. A few things to know:

  • Path traversal protection. The get_context resource handler validates that requested filenames resolve inside the context/ directory. Traversal attempts like ../../etc/passwd are rejected.

  • Private sources are gitignored. sources/private/ is in .gitignore so work emails, Slack exports, etc. stay local. But be careful with source_refs in frontmatter — the filenames are committed even if the files aren't. Use opaque names like work-email-1.md instead of descriptive titles.

  • Private served context is gitignored. context/private.md and context/travel.md are in .gitignore for curated context the MCP should serve locally but never commit (e.g. work-sensitive notes, travel preferences). They're the runtime-served counterpart to sources/private/. Keep placeholder examples of these files out of context/ entirely — the server would serve them as real context.

  • Account numbers never go in served context. Loyalty programs, traveler numbers, and similar identifiers stay in a password manager; context files may point at where they live but never contain the digits. An agent doesn't need them to plan, and you do the booking yourself.

  • Review your context files before committing. These files are meant to be public, but watch for details you didn't intend to share: financial specifics, internal company information, health details, or anything useful for phishing. If in doubt, leave it out.

  • .env is gitignored. If you extend this with API keys, they won't be committed accidentally.

Philosophy

  • Start minimal. 6 files was enough for me as a starting point. Add complexity only when you outgrow it.

  • Curate manually. You know your voice better than any automated pipeline. The LLM can help draft, but you decide what stays.

  • Iterate from use. The best edits come from noticing when the LLM gets something wrong about your writing.

  • Keep private things private. The sources/private/ directory exists so you can reference work writing without committing it.

Available Tools

2 tools
get_all_contextA

Get all personal context files at once.

Returns a dictionary mapping filename to file contents for all context markdown files (identity, writing-style, opinions, expertise, projects, communication).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden. It explicitly states the return format ('a dictionary mapping filename to file contents') and enumerates the files, which goes beyond the basic 'get' action. No side effects or limitations are mentioned, but none are expected for a read-only retrieval.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the main purpose, and then provides necessary detail about the return structure and file list. No fluff or redundant content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter, self-contained retrieval tool, the description is complete. It specifies the exact output format and scope, making it fully actionable for an agent without further elaboration.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has no parameters, so with 0 parameters the baseline is 4. The description correctly doesn't add parameter semantics since none exist, and the empty schema is fully sufficient.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Get all personal context files at once' with a specific verb and resource. It lists the exact files included (identity, writing-style, opinions, expertise, projects, communication), which distinguishes it from the sibling get_writing_style.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'at once' implies this tool is for retrieving the full set of context files, but it does not explicitly contrast with the sibling tool get_writing_style or specify when not to use it. Usage context is implied rather than explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_writing_styleA

Get Aaron's writing style context.

Returns the full writing-style.md file which describes voice, tone, patterns, vocabulary, and annotated examples of how Aaron writes. This is the most commonly needed context file.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It clearly states the tool returns the full file and describes its content (voice, tone, patterns, etc.), making the read-only nature evident. No side effects or caveats are mentioned, but for a simple retrieval tool this is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences, front-loaded with the primary purpose and then providing specific details about the returned content. Every sentence earns its place with no waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (no parameters, simple retrieval), the description is adequate. It explains what is returned and why it is useful, though it does not position the tool relative to get_all_context, which would add completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and the description confirms no input is required. This aligns with the baseline of 4 for zero-parameter tools, and the description adds no unnecessary parameter detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves Aaron's writing style context and specifically returns the full writing-style.md file. This is a specific verb+resource combo, but it does not explicitly distinguish from the sibling tool get_all_context, though the name and content make the distinction implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is a usage hint ('This is the most commonly needed context file') but no explicit when-to-use or when-not-to-use guidance relative to get_all_context. The context is implied rather than directly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv0.1.0
    • First observedget_all_context
    • First observedget_writing_style

TDQS

A3.8/5.0
Disambiguation4/5

The two tools are distinct: one retrieves all context files, the other retrieves a specific file. While get_all_context includes the writing style, the descriptions clarify the appropriate use case for each, so there is little confusion.

Naming Consistency5/5

Both tool names follow a consistent 'get_' prefix followed by a noun, making them predictable and easy to understand. The naming pattern is uniform.

Tool Count2/5

With only two tools, the set feels thin. The server's purpose is to provide personal context, but it only offers bulk retrieval and a single specific file. This is on the low end of the expected range and may be insufficient for flexible access.

Completeness2/5

The tools cover retrieval but lack any way to fetch individual context files other than writing style, forcing agents to fetch everything and parse. There is also no update or creation capability, so the surface is incomplete for a context management domain.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables personal project documentation management through local markdown files stored in nested directories. Supports organizing context by project and layer (backend/frontend/fullstack) with search functionality across all documentation files.
    4
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Personal RAG database and semantic search built from inside your AI chat. Store knowledge, voice, and skills; Claude and ChatGPT create work that sounds like you.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables Claude to write in your personal style by learning from your local documents. It provides statistical style context for natural language rewriting, all without any data leaving your machine.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/amr05008/personal-context'

If you have feedback or need assistance with the MCP directory API, please join our Discord server