MCP Hub
Back to servers

@nullproof-studio/en-quire

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

npm127/wk
Updated
Mar 20, 2026

Quick Install

npx -y @nullproof-studio/en-quire

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:

StyleExampleUse 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

ComponentChoice
LanguageTypeScript
RuntimeNode.js 22 (LTS)
Markdown ASTunified / remark
YAML parseryaml (with source token preservation)
Git operationssimple-git
Full-text searchbetter-sqlite3 + FTS5
Vector searchsqlite-vec (optional)
Schema validationZod
LoggingWinston
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.

Reviews

No reviews yet

Sign in to write a review