npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nullproof-studio/en-quire

v0.1.5

Published

Structured document management for agent systems, with governance. An MCP server.

Readme

en-quire

Structured document management for agent systems, with governance.

An MCP server that treats markdown and YAML files as structured, section-addressable documents with built-in RBAC, approval workflows via git, and semantic search. Designed for operational use cases where agents need to read, propose edits to, and maintain documents — SOPs, skill files, memory, runbooks, config files — under governance.

A Nullproof Studio open-source project.


The Problem

Agent systems increasingly depend on markdown files as operational infrastructure. But existing tooling falls short:

  • Filesystem MCP — no document awareness, no governance, no search. Agents can clobber files freely.
  • Knowledge-graph MCPs — impose opinionated schemas, designed for conversational memory rather than operational documents.
  • Search-only MCPs — read-only. No write or edit capability.
  • None of them have RBAC or approval flows. Every caller is fully trusted.

en-quire fills this gap: a server that understands document structure, supports surgical section-level editing, and treats governance as a first-class concern.

Key Features

  • Multi-format support — pluggable parser architecture handles markdown (.md, .mdx) and YAML (.yaml, .yml). Both produce the same section tree; all tools work uniformly across formats.
  • Section-addressable editing — read and write at the heading/key level, not the file level. Address sections by heading text (## Checks), breadcrumb path (Procedures > Checks > Daily), positional index ([0, 1]), or YAML dot-path (services.api.environment.PORT).
  • Multi-root document management — configure multiple named document roots with independent git repos, permissions, and search indices. Paths are prefixed by root name (docs/sops/runbook.md, config/docker-compose.yaml).
  • Git-native governance — edits from unprivileged callers land on branches, not main. Approval is a merge. Rejection is branch deletion. The audit trail is commit history.
  • RBAC inside the MCP — caller identity and permissions are resolved at the MCP layer. Different agents get different capabilities on different document sets.
  • Full-text search — SQLite FTS5 out of the box, with structural ranking (heading match boost, depth penalty, breadcrumb relevance).
  • Semantic search (optional) — local embeddings via sqlite-vec. No external API keys required.
  • Git-optional mode — full functionality without git for evaluation and local setups; governance features require git.
  • Write validation — output is validated before writing. Invalid YAML syntax is blocked; warnings are surfaced to the calling agent.
  • Language-agnostic — section addressing and search operate on document structure, not language. SOPs in Japanese, skill files in German, runbooks in Portuguese — en-quire works with any language that markdown supports.

MCP Tools

Document Reading

doc_outline · doc_read_section · doc_read · doc_list

Document Editing

doc_replace_section · doc_insert_section · doc_append_section · doc_delete_section · doc_set_value · doc_create · doc_find_replace · doc_rename · doc_generate_toc · doc_status

Search

doc_search · doc_list

Governance

doc_proposals_list · doc_proposal_diff · doc_proposal_approve · doc_proposal_reject

Admin

doc_exec — escape hatch for feature discovery, with full audit logging.

Quick Start

Docker (recommended)

docker run -i --rm \
  -v /path/to/your/docs:/data/docs:rw \
  -v /path/to/config:/app/config:ro \
  ghcr.io/nullproof-studio/en-quire:latest

MCP Client Configuration

Add en-quire to your MCP client (Claude Desktop, Cursor, etc.):

{
  "mcpServers": {
    "en-quire": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "/home/user/docs:/data/docs:rw",
        "-v", "/home/user/.config/en-quire:/app/config:ro",
        "ghcr.io/nullproof-studio/en-quire:latest"
      ]
    }
  }
}

Usage

Once connected, an agent (or you through an MCP client) can use en-quire's tools to navigate, search, and edit markdown documents. Here's a typical workflow.

1. Discover documents

doc_list({ scope: "sops/" })
→ { files: [{ path: "sops/deployment.md", size: 4820, modified: "2026-03-17T..." }] }

2. Explore structure

doc_outline({ file: "sops/deployment.md", max_depth: 2 })
→ { headings: [
    { level: 1, text: "Deployment Procedures", has_children: true, char_count: 4200 },
    { level: 2, text: "1. Pre-deployment", has_children: true, char_count: 980 },
    { level: 2, text: "2. Deployment Steps", has_children: true, char_count: 1640 },
    { level: 2, text: "3. Post-deployment", has_children: true, char_count: 720 }
  ]}

3. Read a specific section

doc_read_section({ file: "sops/deployment.md", section: "2. Deployment Steps" })
→ { content: "## 2. Deployment Steps\n\n...", heading: "2. Deployment Steps",
    path: "Deployment Procedures > 2. Deployment Steps",
    prev_sibling: "1. Pre-deployment", next_sibling: "3. Post-deployment" }

Sections can be addressed in multiple ways:

| Style | Example | Use when | |-------|---------|----------| | Heading text | "2. Deployment Steps" | You know the exact heading | | Breadcrumb path | "Procedures > Checks > Daily" | Disambiguating duplicates | | Positional index | "[0, 1]" | Navigating programmatically | | Glob pattern | "2.*" | Matching multiple sections | | Dot-path (YAML) | "services.api.environment.PORT" | YAML key hierarchies | | Bracket notation (YAML) | "services['my.dotted.key']" | YAML keys containing dots |

4. Search across documents

doc_search({ query: "rollback", section_filter: "Post-deployment*" })
→ { results: [
    { file: "sops/deployment.md", section_heading: "3.2 Rollback Plan",
      breadcrumb: ["Deployment Procedures", "3. Post-deployment", "3.2 Rollback Plan"],
      snippet: "...follow the >>>rollback<<< procedure described in..." }
  ]}

Search results include structural context — breadcrumbs, section paths, and heading-match boosting — so agents can triage results by where they sit in the document hierarchy, not just by text relevance.

5. Edit a section

doc_replace_section({
  file: "sops/deployment.md",
  section: "3.2 Rollback Plan",
  content: "\nUpdated rollback steps:\n\n1. Revert the deployment\n2. Notify on-call\n3. Open incident ticket\n",
  message: "Updated rollback procedure to include incident ticket step"
})
→ { success: true, mode: "write", commit: "a1b2c3d",
    diff: "--- a/sops/deployment.md\n+++ b/sops/deployment.md\n@@ -42,3 +42,5 @@..." }

Every write operation returns a unified diff and auto-commits with a structured message.

6. Propose changes (governance)

Callers without write permission can propose edits that land on a branch:

doc_replace_section({
  file: "sops/deployment.md",
  section: "1. Pre-deployment",
  content: "\nAdded new environment check for API keys.\n",
  mode: "propose"
})
→ { success: true, mode: "propose", branch: "propose/michelle/sops/deployment/20260317T1423Z" }

An approver can then review and merge:

doc_proposal_diff({ branch: "propose/michelle/sops/deployment/20260317T1423Z" })
doc_proposal_approve({ branch: "propose/michelle/sops/deployment/20260317T1423Z" })

7. Work with YAML files

YAML files are first-class citizens. The same tools work with dot-path addressing:

doc_outline({ file: "config/docker-compose.yaml" })
→ { headings: [
    { level: 1, text: "version", has_children: false },
    { level: 1, text: "services", has_children: true },
    ...
  ]}

doc_read_section({ file: "config/docker-compose.yaml", section: "services.api.environment" })
→ { content: "      NODE_ENV: production\n      PORT: 3100\n", heading: "environment" }

doc_set_value({ file: "config/docker-compose.yaml", path: "services.api.environment.PORT", value: "8080" })
→ { success: true, mode: "write", commit: "d4e5f6a" }

doc_set_value preserves the original YAML quote style — if the value was "quoted", the replacement stays quoted.

8. Append, insert, and find-replace

doc_append_section({
  file: "sops/deployment.md",
  section: "3.1 Monitoring",
  content: "- Check error rate dashboard after each deploy"
})

doc_insert_section({
  file: "sops/deployment.md",
  anchor: "2. Deployment Steps",
  position: "child_end",
  heading: "2.4 Canary Check",
  content: "Run canary checks before full rollout."
})

doc_find_replace({
  file: "sops/deployment.md",
  find: "staging",
  replace: "pre-production",
  expected_count: 3
})

Configuration

# en-quire.config.yaml

# Document roots (multiple supported)
document_roots:
  docs:
    path: /data/docs                # Must be a git repository for governance
  config:
    path: /data/config              # YAML configs, docker-compose, etc.

# Server
transport: stdio                    # stdio | streamable-http
port: 3100                          # For streamable-http

# Search
search:
  fulltext: true                    # Always on
  sync_on_start: blocking           # "blocking" or "background" (use background for 100k+ docs)
  batch_size: 500                   # Files per index transaction batch
  semantic:
    enabled: false                  # Opt-in
    endpoint: "http://localhost:11434/api/embeddings"
    model: "nomic-embed-text"
    dimensions: 768

# Logging
logging:
  level: info                       # error | warn | info | debug
  dir: null                         # null = stderr only; path = file logging
  # dir: /app/logs                  # Docker: writes combined.log + error.log

# Git
git:
  auto_commit: true                 # Commit on every write operation
  remote: null                      # Optional: push proposals to remote
  pr_hook: null                     # Optional: webhook/script to open PRs

# Callers (see RBAC section in spec)
callers:
  # ...

Technology Stack

| Component | Choice | |-----------|--------| | Language | TypeScript | | Runtime | Node.js 22 (LTS) | | Markdown AST | unified / remark | | YAML parser | yaml (with source token preservation) | | Git operations | simple-git | | Full-text search | better-sqlite3 + FTS5 | | Vector search | sqlite-vec (optional) | | Schema validation | Zod | | Logging | Winston | | MCP SDK | @modelcontextprotocol/sdk |

Development

Prerequisites

  • Node.js 22+
  • npm

Build from source

git clone https://github.com/nullproof-studio/en-quire.git
cd en-quire
npm install
npm run build

Run locally

# stdio transport (default)
npm start -- --config path/to/en-quire.config.yaml

# Development mode (no build step)
npm run dev -- --config path/to/en-quire.config.yaml

Run tests

npm test              # Single run
npm run test:watch    # Watch mode

Publish npm package

npm run build
npm run lint
npm test
npm publish --access public

The package is published as @nullproof-studio/en-quire. Ensure version in package.json is updated before publishing.

Build and publish Docker image

# Build
npm run build
docker build -t ghcr.io/nullproof-studio/en-quire:latest .

# Test locally
docker run -i --rm \
  -v /path/to/docs:/data/docs:rw \
  -v /path/to/config:/app/config:ro \
  -v /path/to/logs:/app/logs:rw \
  ghcr.io/nullproof-studio/en-quire:latest

# Publish to GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
docker push ghcr.io/nullproof-studio/en-quire:latest
docker tag ghcr.io/nullproof-studio/en-quire:latest ghcr.io/nullproof-studio/en-quire:0.1.0
docker push ghcr.io/nullproof-studio/en-quire:0.1.0

When using streamable-http transport, the Docker image includes a health check at GET /health:

docker run -d --name en-quire \
  -p 3100:3100 \
  -v /path/to/docs:/data/docs:rw \
  -v /path/to/config:/app/config:ro \
  -v /path/to/logs:/app/logs:rw \
  ghcr.io/nullproof-studio/en-quire:latest

curl http://localhost:3100/health
# → {"status":"ok","sessions":0}

Roadmap

  • v0.1 — Core: Document parsing, section addressing, read/write tools, git integration, full-text search, basic RBAC, Docker image, stdio transport, streamable-http transport.
  • v0.2 — Governance: Proposal workflows, remote push, PR hooks, audit log queries, conflict detection.
  • v0.3 — Search & Intelligence: Semantic vector search, cross-document reference tracking, inverse lookups, context bundle builder.
  • v0.4 — Scale & Polish: Bulk operations, watch mode, plugin hooks.

Contributing

Contributions welcome. See CONTRIBUTING.md for guidelines.

License

MIT — see LICENSE for details.


© 2026 Nullproof Studio. Released under the MIT License.