nkitan/instructions

Python

0

9 commits

updated Feb 4, 2026

See the code

README

Instructions

Instructions is a comprehensive documentation and skills management system designed to provide AI agents with a reliable, locally-hosted "source of truth" for technical libraries, coding skills, and best practices. It ensures AI responses are based on up-to-date and accurate information through a powerful Retrieval-Augmented Generation (RAG) pipeline.

Features

🚀 Core Capabilities

  • Semantic Search: Vector-based search using sentence transformers for natural language queries
  • Semantic Highlighting: Uses zilliz/semantic-highlight-bilingual-v1 to identify the most relevant sentences in documents
  • Hybrid Retrieval: Combines file-level and chunk-level search with cross-encoder reranking
  • Skills Management: Search, generate, and validate coding skills for multiple AI platforms
  • WAF-like Security: Request validation and filtering with configurable exception rules

🔌 MCP (Model Context Protocol) Support

Specialized endpoints designed for LLM agents:

  1. Documentation Search (/mcp/search-docs) - Semantic search with highlighting
  2. llms.txt Access (/mcp/llms-txt/{library}) - Direct access to llms.txt files
  3. Skills Documentation (/mcp/skill-doc) - Platform-specific skill creation guides
  4. Skills Repository (/mcp/search-skills) - Search existing skill implementations

📚 Data Sources

The system provides access to three main repositories:

  1. llm-docs: Library documentation (txt, html, md, rst)

    • 50+ libraries indexed
    • Follows llms.txt specification
    • Semantic embeddings for fast retrieval
  2. skills-docs: Platform guidelines

    • claude-code (Claude Code Editor)
    • antigravity (Google Antigravity)
    • copilot (GitHub Copilot)
    • gemini-cli (Gemini CLI)
  3. skills-repos: Skill implementations

    • Searchable database of real-world skills
    • Platform-specific filtering
    • Example code and scripts

Architecture

The project consists of two main components:

  1. Documentation Synchronization Pipeline (fetch_docs.py): A Python script that fetches documentation from various sources (websites and GitHub repositories) as configured in libraries.json. The content is processed and stored locally in the llm-docs/ directory.

  2. RAG Server (mcp_server/): A FastAPI web server that provides a semantic search API over the downloaded documentation. It uses sentence-transformers to generate embeddings for the text and lancedb as a vector store for efficient searching. The server builds the vector store for a library on-demand when it's first queried.

Getting Started

Follow these steps to set up and run the instructions system.

Prerequisites

  • Python 3.13+
  • uv: This project uses uv for Python environment and package management. Ensure it is installed on your system.

1. Clone the Repository

git clone <repository-url>
cd instructions

2. Synchronize Documentation

Before running the server, you need to download the documentation for the libraries defined in libraries.json.

# This script reads libraries.json and populates the llm-docs/ directory
uv run fetch_docs.py

3. Install Server Dependencies

The RAG server has its own set of Python dependencies.

# Navigate to the server directory
cd mcp_server

# Install dependencies using uv
uv pip install -r requirements.txt

4. Run the RAG Server

The server must be run from the project's root directory (instructions) for the Python module paths to resolve correctly.

# Return to the project root directory
cd ..

# Run the server using uvicorn
uvicorn mcp_server.main:app --reload --host 0.0.0.0 --port 8000

The API will be available at http://0.0.0.0:8000. You can access the interactive API documentation (Swagger UI) at http://0.0.0.0:8000/docs.


Containerization with Podman (✅)

You can build and run the MCP server as a Podman container. Two options are provided: a direct podman workflow or using podman-compose.

Build the image (Podman)

# From project root (where the Containerfile lives)
podman build -t instructions-mcp-server .

Run the container (Podman)

# Mount local folders to preserve docs, vector store and DB
podman run -p 8000:8000 \
  -v "$(pwd)/llm-docs:/app/llm-docs:Z" \
  -v "$(pwd)/mcp_server/.vector_store:/app/mcp_server/.vector_store:Z" \
  -v "$(pwd)/mcp_server/libraries.db:/app/mcp_server/libraries.db:Z" \
  -e FETCH_DOCS=false \
  --name instructions-mcp instructions-mcp-server

Set FETCH_DOCS=true to fetch documentation during startup (may take a long time and is not recommended for production containers).

Run with Podman Compose

# Start services defined in podman-compose.yml
podman-compose -f podman-compose.yml up --build -d

This will build the images, create volumes to persist llm-docs, .vector_store and libraries.db, and expose the API on port 8000.


Init container (one-time sync)

An init service is provided that runs merge_sources.py and fetch_docs.py to populate libraries.json and the llm-docs/ folder. The init service writes directly to the project folder, so its artifacts (updated libraries.json and llm-docs/) are available to the mcp_server service.

To run the init step manually (recommended):

# One-off: run init to populate llm-docs and libraries.json (writes to host-mounted files)
podman-compose -f podman-compose.yml run --rm init

Security & unprivileged init container

  • The init container runs as an unprivileged user (UID 10001) to reduce risk during network fetches and writes. To minimize required host permissions, the init service mounts only ./llm-docs and ./libraries.json (not the full project root), so only those two paths must be writable by the init user.

  • On the host, ensure llm-docs and libraries.json are writable by UID 10001 (one of the following):

    • chown the folders/files: sudo chown -R 10001:10001 ./llm-docs && sudo chown 10001:10001 ./libraries.json
    • grant ACL write for UID 10001: sudo setfacl -R -m u:10001:rwx ./llm-docs && sudo setfacl -m u:10001:rw ./libraries.json
  • The init image will refuse to run if it cannot write to /work/llm-docs or /work/libraries.json to avoid silent failures and accidental root-owned files.

If the init container fails with a permissions error, apply one of the above host fixes and re-run the init job (e.g., ./run.sh init). Security note: mount llm-docs with noexec on the host

  • For safety, it's recommended to bind-mount llm-docs with noexec so files written there cannot be executed directly on the host. The provided podman-compose.yml uses bind options to request noexec on the llm-docs and the server enforces non-executable permissions on files at startup.
  • Example long-syntax bind in Compose (already applied in podman-compose.yml):
volumes:
  - type: bind
    source: ./llm-docs
    target: /app/llm-docs
    bind:
      options: ["noexec", "rw", "Z"]

If your host filesystem or environment doesn't support noexec bind flags, you can manually ensure safety by running:

# On the host
chmod -R a-x llm-docs
mount -o remount,noexec $(pwd)/llm-docs

If mount -o remount,noexec fails due to your filesystem, keep the chmod -R a-x protection in place and consider using a separate filesystem/volume for llm-docs that supports strict mount options.

If you start podman-compose up without running the init first, the compose file specifies depends_on: init for mcp_server, which will ensure the init container is created. However, a recommended approach is to run the init container explicitly to observe logs and progress.

GPU / Embedding (optional)

If you have an NVIDIA GPU and a compatible runtime, an optional mcp_server_gpu service is provided that uses a CUDA-enabled PyTorch runtime for faster embedding and model inference.

Notes & usage:

  • Podman GPU support must be configured on the host (nvidia-container-toolkit or equivalent). Consult Podman and NVIDIA docs for your distro.
  • The mcp_server_gpu image is built from a PyTorch CUDA runtime (see Containerfile.gpu). It exposes the API on port 8001 by default to keep it separate from the CPU service.

GTX 1050Ti (compute capability 6.1)

  • The GTX 1050Ti (Pascal, compute capability 6.1) is supported by CUDA 11.x runtimes. The provided Containerfile.gpu uses a PyTorch image built with CUDA 11.7 (pytorch/pytorch:2.1.0-cuda11.7-cudnn8-runtime), which is compatible with that GPU.
  • Ensure your host has an appropriate NVIDIA driver installed that supports CUDA 11.7 and that Podman is configured to expose GPU devices (tooling varies by distro).

Run the GPU variant (example):

# Build GPU image and start the GPU-enabled service
podman-compose -f podman-compose.yml up --build mcp_server_gpu -d

# Note: You may need to pass --device or configure hooks to expose the GPU devices depending on your Podman setup.

Tip: For production environments, consider running indexing/embedding as a dedicated worker using a GPU-enabled image and keeping the API server separate for better reliability and scale.

How to Query

The server provides multiple APIs for different use cases.

Standard Search API

curl -X POST "http://0.0.0.0:8000/search" \
-H "Content-Type: application/json" \
-d '{
  "library_name": "nextjs",
  "search_term": "how to handle client side rendering",
  "limit": 5,
  "highlight": true
}'

MCP Endpoints (for LLM Agents)

Search Documentation with Highlighting

curl -X POST "http://0.0.0.0:8000/mcp/search-docs" \
-H "Content-Type: application/json" \
-d '{
  "library_name": "fastapi",
  "query": "How to implement dependency injection?",
  "limit": 3,
  "highlight": true
}'

Get llms.txt File

curl "http://0.0.0.0:8000/mcp/llms-txt/nextjs"

Get Skill Documentation

curl -X POST "http://0.0.0.0:8000/mcp/skill-doc" \
-H "Content-Type: application/json" \
-d '{
  "platform": "claude-code"
}'

Search Skills Repository

curl -X POST "http://0.0.0.0:8000/mcp/search-skills" \
-H "Content-Type: application/json" \
-d '{
  "query": "API testing with authentication",
  "platform": "copilot",
  "limit": 10
}'

Admin Endpoints

WAF Rules Management

# List all WAF rules
curl "http://0.0.0.0:8000/admin/waf/rules"

# Add custom rule
curl -X POST "http://0.0.0.0:8000/admin/waf/rules" \
-H "Content-Type: application/json" \
-d '{
  "rule_id": "custom_block",
  "rule_type": "PATTERN",
  "action": "DENY",
  "target": "query",
  "pattern": "sensitive_pattern",
  "priority": 50,
  "description": "Block sensitive patterns"
}'

# Disable a rule
curl -X POST "http://0.0.0.0:8000/admin/waf/rules/custom_block/disable"

# Get WAF statistics
curl "http://0.0.0.0:8000/admin/waf/stats"

Library Management

# Rebuild library index
curl -X POST "http://0.0.0.0:8000/admin/resync" \
-H "Content-Type: application/json" \
-d '{
  "library_name": "nextjs",
  "rebuild_chunks": true,
  "wait": true
}'

# Sync filesystem
curl -X POST "http://0.0.0.0:8000/admin/sync_fs" \
-H "Content-Type: application/json" \
-d '{"wait": false}'

Interactive API Documentation

Visit http://0.0.0.0:8000/docs for the full Swagger UI with all endpoints, schemas, and try-it-out functionality.

Documentation

Development Conventions

  • Tooling: The project standardizes on uv for all Python-related tasks (execution, package management).
  • Modular Code: The application is split into logical components:
    • fetch_docs.py: Handles all data ingestion.
    • mcp_server/: Contains the API and RAG logic.
      • main.py: Defines API routes and the server.
      • rag.py: Encapsulates all logic for document processing, embedding, and searching.
  • Type Safety: The Python code uses type hints for clarity and robustness.
  • On-Demand Indexing: The RAG server creates a library's vector store only when it's first queried, making it efficient to start and manage.

Acknowledgments

Special thanks to the following sources for providing public lists of llms.txt documentation endpoints:

These resources make it possible to discover and aggregate LLM-friendly documentation across the web.

nkitan/instructions

Python

0

9 commits

updated Feb 4, 2026

See the code

README

Instructions

Instructions is a comprehensive documentation and skills management system designed to provide AI agents with a reliable, locally-hosted "source of truth" for technical libraries, coding skills, and best practices. It ensures AI responses are based on up-to-date and accurate information through a powerful Retrieval-Augmented Generation (RAG) pipeline.

Features

🚀 Core Capabilities

  • Semantic Search: Vector-based search using sentence transformers for natural language queries
  • Semantic Highlighting: Uses zilliz/semantic-highlight-bilingual-v1 to identify the most relevant sentences in documents
  • Hybrid Retrieval: Combines file-level and chunk-level search with cross-encoder reranking
  • Skills Management: Search, generate, and validate coding skills for multiple AI platforms
  • WAF-like Security: Request validation and filtering with configurable exception rules

🔌 MCP (Model Context Protocol) Support

Specialized endpoints designed for LLM agents:

  1. Documentation Search (/mcp/search-docs) - Semantic search with highlighting
  2. llms.txt Access (/mcp/llms-txt/{library}) - Direct access to llms.txt files
  3. Skills Documentation (/mcp/skill-doc) - Platform-specific skill creation guides
  4. Skills Repository (/mcp/search-skills) - Search existing skill implementations

📚 Data Sources

The system provides access to three main repositories:

  1. llm-docs: Library documentation (txt, html, md, rst)

    • 50+ libraries indexed
    • Follows llms.txt specification
    • Semantic embeddings for fast retrieval
  2. skills-docs: Platform guidelines

    • claude-code (Claude Code Editor)
    • antigravity (Google Antigravity)
    • copilot (GitHub Copilot)
    • gemini-cli (Gemini CLI)
  3. skills-repos: Skill implementations

    • Searchable database of real-world skills
    • Platform-specific filtering
    • Example code and scripts

Architecture

The project consists of two main components:

  1. Documentation Synchronization Pipeline (fetch_docs.py): A Python script that fetches documentation from various sources (websites and GitHub repositories) as configured in libraries.json. The content is processed and stored locally in the llm-docs/ directory.

  2. RAG Server (mcp_server/): A FastAPI web server that provides a semantic search API over the downloaded documentation. It uses sentence-transformers to generate embeddings for the text and lancedb as a vector store for efficient searching. The server builds the vector store for a library on-demand when it's first queried.

Getting Started

Follow these steps to set up and run the instructions system.

Prerequisites

  • Python 3.13+
  • uv: This project uses uv for Python environment and package management. Ensure it is installed on your system.

1. Clone the Repository

git clone <repository-url>
cd instructions

2. Synchronize Documentation

Before running the server, you need to download the documentation for the libraries defined in libraries.json.

# This script reads libraries.json and populates the llm-docs/ directory
uv run fetch_docs.py

3. Install Server Dependencies

The RAG server has its own set of Python dependencies.

# Navigate to the server directory
cd mcp_server

# Install dependencies using uv
uv pip install -r requirements.txt

4. Run the RAG Server

The server must be run from the project's root directory (instructions) for the Python module paths to resolve correctly.

# Return to the project root directory
cd ..

# Run the server using uvicorn
uvicorn mcp_server.main:app --reload --host 0.0.0.0 --port 8000

The API will be available at http://0.0.0.0:8000. You can access the interactive API documentation (Swagger UI) at http://0.0.0.0:8000/docs.


Containerization with Podman (✅)

You can build and run the MCP server as a Podman container. Two options are provided: a direct podman workflow or using podman-compose.

Build the image (Podman)

# From project root (where the Containerfile lives)
podman build -t instructions-mcp-server .

Run the container (Podman)

# Mount local folders to preserve docs, vector store and DB
podman run -p 8000:8000 \
  -v "$(pwd)/llm-docs:/app/llm-docs:Z" \
  -v "$(pwd)/mcp_server/.vector_store:/app/mcp_server/.vector_store:Z" \
  -v "$(pwd)/mcp_server/libraries.db:/app/mcp_server/libraries.db:Z" \
  -e FETCH_DOCS=false \
  --name instructions-mcp instructions-mcp-server

Set FETCH_DOCS=true to fetch documentation during startup (may take a long time and is not recommended for production containers).

Run with Podman Compose

# Start services defined in podman-compose.yml
podman-compose -f podman-compose.yml up --build -d

This will build the images, create volumes to persist llm-docs, .vector_store and libraries.db, and expose the API on port 8000.


Init container (one-time sync)

An init service is provided that runs merge_sources.py and fetch_docs.py to populate libraries.json and the llm-docs/ folder. The init service writes directly to the project folder, so its artifacts (updated libraries.json and llm-docs/) are available to the mcp_server service.

To run the init step manually (recommended):

# One-off: run init to populate llm-docs and libraries.json (writes to host-mounted files)
podman-compose -f podman-compose.yml run --rm init

Security & unprivileged init container

  • The init container runs as an unprivileged user (UID 10001) to reduce risk during network fetches and writes. To minimize required host permissions, the init service mounts only ./llm-docs and ./libraries.json (not the full project root), so only those two paths must be writable by the init user.

  • On the host, ensure llm-docs and libraries.json are writable by UID 10001 (one of the following):

    • chown the folders/files: sudo chown -R 10001:10001 ./llm-docs && sudo chown 10001:10001 ./libraries.json
    • grant ACL write for UID 10001: sudo setfacl -R -m u:10001:rwx ./llm-docs && sudo setfacl -m u:10001:rw ./libraries.json
  • The init image will refuse to run if it cannot write to /work/llm-docs or /work/libraries.json to avoid silent failures and accidental root-owned files.

If the init container fails with a permissions error, apply one of the above host fixes and re-run the init job (e.g., ./run.sh init). Security note: mount llm-docs with noexec on the host

  • For safety, it's recommended to bind-mount llm-docs with noexec so files written there cannot be executed directly on the host. The provided podman-compose.yml uses bind options to request noexec on the llm-docs and the server enforces non-executable permissions on files at startup.
  • Example long-syntax bind in Compose (already applied in podman-compose.yml):
volumes:
  - type: bind
    source: ./llm-docs
    target: /app/llm-docs
    bind:
      options: ["noexec", "rw", "Z"]

If your host filesystem or environment doesn't support noexec bind flags, you can manually ensure safety by running:

# On the host
chmod -R a-x llm-docs
mount -o remount,noexec $(pwd)/llm-docs

If mount -o remount,noexec fails due to your filesystem, keep the chmod -R a-x protection in place and consider using a separate filesystem/volume for llm-docs that supports strict mount options.

If you start podman-compose up without running the init first, the compose file specifies depends_on: init for mcp_server, which will ensure the init container is created. However, a recommended approach is to run the init container explicitly to observe logs and progress.

GPU / Embedding (optional)

If you have an NVIDIA GPU and a compatible runtime, an optional mcp_server_gpu service is provided that uses a CUDA-enabled PyTorch runtime for faster embedding and model inference.

Notes & usage:

  • Podman GPU support must be configured on the host (nvidia-container-toolkit or equivalent). Consult Podman and NVIDIA docs for your distro.
  • The mcp_server_gpu image is built from a PyTorch CUDA runtime (see Containerfile.gpu). It exposes the API on port 8001 by default to keep it separate from the CPU service.

GTX 1050Ti (compute capability 6.1)

  • The GTX 1050Ti (Pascal, compute capability 6.1) is supported by CUDA 11.x runtimes. The provided Containerfile.gpu uses a PyTorch image built with CUDA 11.7 (pytorch/pytorch:2.1.0-cuda11.7-cudnn8-runtime), which is compatible with that GPU.
  • Ensure your host has an appropriate NVIDIA driver installed that supports CUDA 11.7 and that Podman is configured to expose GPU devices (tooling varies by distro).

Run the GPU variant (example):

# Build GPU image and start the GPU-enabled service
podman-compose -f podman-compose.yml up --build mcp_server_gpu -d

# Note: You may need to pass --device or configure hooks to expose the GPU devices depending on your Podman setup.

Tip: For production environments, consider running indexing/embedding as a dedicated worker using a GPU-enabled image and keeping the API server separate for better reliability and scale.

How to Query

The server provides multiple APIs for different use cases.

Standard Search API

curl -X POST "http://0.0.0.0:8000/search" \
-H "Content-Type: application/json" \
-d '{
  "library_name": "nextjs",
  "search_term": "how to handle client side rendering",
  "limit": 5,
  "highlight": true
}'

MCP Endpoints (for LLM Agents)

Search Documentation with Highlighting

curl -X POST "http://0.0.0.0:8000/mcp/search-docs" \
-H "Content-Type: application/json" \
-d '{
  "library_name": "fastapi",
  "query": "How to implement dependency injection?",
  "limit": 3,
  "highlight": true
}'

Get llms.txt File

curl "http://0.0.0.0:8000/mcp/llms-txt/nextjs"

Get Skill Documentation

curl -X POST "http://0.0.0.0:8000/mcp/skill-doc" \
-H "Content-Type: application/json" \
-d '{
  "platform": "claude-code"
}'

Search Skills Repository

curl -X POST "http://0.0.0.0:8000/mcp/search-skills" \
-H "Content-Type: application/json" \
-d '{
  "query": "API testing with authentication",
  "platform": "copilot",
  "limit": 10
}'

Admin Endpoints

WAF Rules Management

# List all WAF rules
curl "http://0.0.0.0:8000/admin/waf/rules"

# Add custom rule
curl -X POST "http://0.0.0.0:8000/admin/waf/rules" \
-H "Content-Type: application/json" \
-d '{
  "rule_id": "custom_block",
  "rule_type": "PATTERN",
  "action": "DENY",
  "target": "query",
  "pattern": "sensitive_pattern",
  "priority": 50,
  "description": "Block sensitive patterns"
}'

# Disable a rule
curl -X POST "http://0.0.0.0:8000/admin/waf/rules/custom_block/disable"

# Get WAF statistics
curl "http://0.0.0.0:8000/admin/waf/stats"

Library Management

# Rebuild library index
curl -X POST "http://0.0.0.0:8000/admin/resync" \
-H "Content-Type: application/json" \
-d '{
  "library_name": "nextjs",
  "rebuild_chunks": true,
  "wait": true
}'

# Sync filesystem
curl -X POST "http://0.0.0.0:8000/admin/sync_fs" \
-H "Content-Type: application/json" \
-d '{"wait": false}'

Interactive API Documentation

Visit http://0.0.0.0:8000/docs for the full Swagger UI with all endpoints, schemas, and try-it-out functionality.

Documentation

Development Conventions

  • Tooling: The project standardizes on uv for all Python-related tasks (execution, package management).
  • Modular Code: The application is split into logical components:
    • fetch_docs.py: Handles all data ingestion.
    • mcp_server/: Contains the API and RAG logic.
      • main.py: Defines API routes and the server.
      • rag.py: Encapsulates all logic for document processing, embedding, and searching.
  • Type Safety: The Python code uses type hints for clarity and robustness.
  • On-Demand Indexing: The RAG server creates a library's vector store only when it's first queried, making it efficient to start and manage.

Acknowledgments

Special thanks to the following sources for providing public lists of llms.txt documentation endpoints:

These resources make it possible to discover and aggregate LLM-friendly documentation across the web.