Sign inSign up

mekayelanik/narsil-mcp

By mekayelanik

•Updated about 1 month ago

Image
Integration & delivery
Machine learning & AI
Developer tools
0

5.3K

mekayelanik/narsil-mcp repository overview

⁠Narsil MCP Server - Docker Image

Unofficial Multi-Architecture Docker Image for Narsil MCP Server

Docker Pulls Docker Stars GHCR License: GPL-3.0 Platforms GitHub Stars GitHub Forks GitHub Issues Last Commit

⁠Overview

This is an unofficial, community-maintained Docker image that packages the Narsil MCP Server⁠ for containerized deployment. It enables AI agents (Claude Code, VS Code Copilot, Cursor, Windsurf, etc.) to perform deep code intelligence via the Model Context Protocol (MCP).

Upstream: github.com/postrv/narsil-mcp⁠ (MIT OR Apache-2.0)

⁠Key Features
  • Multi-Architecture Support - Native support for x86-64 and ARM64
  • Modern MCP Bridge - mcp-proxy⁠ stdio↔StreamableHTTP/SSE; stateful, one shared child per session (no spawn-per-request leak)
  • 90 Code Intelligence Tools - Symbol search, call graphs, security analysis, SBOM, and more
  • 32 Language Support - Rust, Python, TypeScript, Go, Java, C#, and 26 more via Tree-sitter
  • Secure by Design - API key auth (case-insensitive Bearer), CORS, TLS termination, security headers
  • High Performance - HAProxy with QUIC/HTTP3 support, ZSTD compression
⁠Available Narsil MCP Tool Categories
CategoryExamples
Repository & File Managementlist_repos, get_project_structure, get_file, reindex
Symbol Search & Navigationfind_symbols, get_symbol_definition, find_references
Code Searchsearch_code, semantic_search, hybrid_search, find_similar_code
Call Graph Analysisget_call_graph, get_callers, get_callees, get_complexity
Security Analysisfind_injection_vulnerabilities, scan_security, check_owasp_top10
Supply Chain Securitygenerate_sbom, check_dependencies, check_licenses
Git Integrationget_blame, get_file_history, get_hotspots, get_contributors
Neural Semantic Searchneural_search, find_semantic_clones
Type Inferenceinfer_types, check_type_errors
Data Flow Analysisget_data_flow, find_dead_code, find_dead_stores
SPARQL / Knowledge Graphsparql_query, get_ccg_manifest, export_ccg

⁠Buy Me a Coffee

Your support encourages me to keep creating/supporting my open-source projects. If you found value in this project, you can buy me a coffee to keep me inspired.

Buy Me A Coffee ⁠

⁠Quick Start

⁠Prerequisites
  • Docker Engine: 23.0+

CRITICAL: Do NOT expose this container directly to the internet without proper security measures (reverse proxy, SSL/TLS, authentication, firewall rules).


services:
  narsil-mcp:
    image: mekayelanik/narsil-mcp:latest
    container_name: narsil-mcp
    restart: unless-stopped
    ports:
      - "8010:8010"
      # Optional: HTTP visualization frontend (requires NARSIL_HTTP=true)
      # - "3000:3000"
    volumes:
      - /path/to/your/repos:/data:ro
      - narsil-cache:/home/narsil/.cache         # Persist embedding model cache
    environment:
      - PORT=8010
      - INTERNAL_PORT=38011
      - PUID=1000
      - PGID=1000
      - TZ=UTC
      - NODE_ENV=production
      - PROTOCOL=SHTTP
      - ENABLE_HTTPS=false
      - HTTP_VERSION_MODE=auto
      - DATA_DIR=/data
      - NARSIL_GIT=true
      - NARSIL_CALL_GRAPH=true
      - NARSIL_PERSIST=true
      - NARSIL_STREAMING=true
      # Optional: Neural semantic search
      # - NARSIL_NEURAL=true
      # - VOYAGE_API_KEY=your-voyage-key
      # Optional: HTTP visualization frontend
      # - NARSIL_HTTP=true
      # - NARSIL_HTTP_PORT=3000
      # Optional: require Bearer token auth at HAProxy layer
      # - API_KEY=replace-with-strong-secret
      # Optional: CORS origins
      # - CORS=*

volumes:
  narsil-cache:
    driver: local
⁠Docker Run
docker volume create narsil-cache
docker run -d \
  --name=narsil-mcp \
  --restart=unless-stopped \
  -p 8010:8010 \
  -v /path/to/your/repos:/data:ro \
  -v narsil-cache:/home/narsil/.cache \
  -e PORT=8010 \
  -e PROTOCOL=SHTTP \
  -e NARSIL_GIT=true \
  -e NARSIL_CALL_GRAPH=true \
  -e NARSIL_PERSIST=true \
  mekayelanik/narsil-mcp:latest

# With HTTP visualization frontend enabled:
docker volume create narsil-cache
docker run -d \
  --name=narsil-mcp \
  --restart=unless-stopped \
  -p 8010:8010 \
  -p 3000:3000 \
  -v /path/to/your/repos:/data:ro \
  -v narsil-cache:/home/narsil/.cache \
  -e PORT=8010 \
  -e PROTOCOL=SHTTP \
  -e NARSIL_GIT=true \
  -e NARSIL_CALL_GRAPH=true \
  -e NARSIL_PERSIST=true \
  -e NARSIL_HTTP=true \
  mekayelanik/narsil-mcp:latest
⁠Access Endpoints
ServiceEndpointDescription
MCP (SHTTP)http://host-ip:8010/mcpStreamable HTTP MCP endpoint (recommended)
MCP (SSE)http://host-ip:8010/sseServer-Sent Events MCP endpoint
HTTP Frontendhttp://host-ip:3000Visualization frontend (requires NARSIL_HTTP=true)
Healthhttp://host-ip:8010/healthzHealth check endpoint

When HTTPS is enabled (ENABLE_HTTPS=true), use TLS endpoints:

ServiceEndpoint
MCP (SHTTP)https://host-ip:8010/mcp
MCP (SSE)https://host-ip:8010/sse
MCP (WS)wss://host-ip:8010/message

Security Warning: The container defaults to HTTP (ENABLE_HTTPS=false) for easier local setup. Use ENABLE_HTTPS=true with your own certificates for production. See CERTIFICATE_SETUP_GUIDE.md⁠ for instructions.


⁠Configuration

⁠Complete Environment Variables Reference
⁠Core Settings
VariableDefaultPossible ValuesDescription
PORT80101-65535External HAProxy listening port
INTERNAL_PORT380111-65535Internal mcp-proxy port (do not expose)
PROTOCOLSHTTPSHTTP, SSEMCP transport. mcp-proxy exposes both /mcp and /sse simultaneously; this flag chooses the default routed path. WS removed (unsupported by mcp-proxy)
MCP_PROXY_STATELESSfalsetrue, falsemcp-proxy mode. false=stateful (shared stdio child, no TTL — required for narsil's index-ready gate); true=per-request isolation (memory-hostile, breaks indexing)
NARSIL_MAX_MEM_MB00-Nprlimit --as MiB cap per narsil stdio child (0=off)
HAPROXY_FRONTEND_MAXCONN00-NHAProxy frontend max concurrent client conns (0=off)
HAPROXY_SERVER_MAXCONN00-NHAProxy→mcp-proxy max concurrent conns (0=off)
PUID1000Any valid UIDProcess user ID
PGID1000Any valid GIDProcess group ID
TZUTCAny timezoneContainer timezone
NODE_ENV(empty)production, etc.Deployment mode flag (triggers HTTPS-off security warning when set to production)
DATA_DIR/dataAny pathDirectory for mounted repositories
⁠Narsil MCP Feature Flags
VariableDefaultPossible ValuesDescription
NARSIL_GITfalsetrue, falseEnable git blame, history, contributors
NARSIL_CALL_GRAPHfalsetrue, falseEnable function call graph analysis
NARSIL_PERSISTfalsetrue, falseSave index to disk for fast startup
NARSIL_WATCHfalsetrue, falseAuto-reindex on file changes
NARSIL_LSPfalsetrue, falseEnable LSP for hover, go-to-definition
NARSIL_STREAMINGfalsetrue, falseStream large result sets
NARSIL_REMOTEfalsetrue, falseEnable GitHub remote repo support
NARSIL_NEURALfalsetrue, falseEnable neural semantic embeddings
NARSIL_GRAPHfalsetrue, falseEnable SPARQL/RDF knowledge graph and CCG tools
NARSIL_VERBOSEfalsetrue, falseEnable verbose logging
NARSIL_REINDEXfalsetrue, falseForce re-index on startup (once per container lifecycle)
NARSIL_HTTPfalsetrue, falseEnable visualization frontend HTTP server
⁠Narsil MCP String Settings
VariableDefaultPossible ValuesDescription
NARSIL_INDEX_PATH~/.cache/narsil-mcpAny pathCustom persistent index storage path
NARSIL_DISCOVER(empty)Directory pathAuto-discover repositories in a directory path
NARSIL_REPOS_MODEautoauto, single, subdirsHow DATA_DIR is interpreted. auto=single if DATA_DIR/.git exists else subdirs; subdirs=each immediate subdir is a separate --repos
NARSIL_HTTP_PORT30001-65535HTTP visualization frontend port
NARSIL_NO_CACHEfalsetrue, falseDisable analysis caching
NARSIL_CACHE_TTL1800Integer (seconds)Cache TTL in seconds
NARSIL_GRAPH_PATH<index_path>/graphAny pathCustom knowledge graph storage path
NARSIL_NEURAL_BACKENDapiapi, onnxNeural embedding backend
NARSIL_NEURAL_MODELvoyage-code-2voyage-code-2, text-embedding-3-large, etc.Embedding model name
NARSIL_NEURAL_DIMENSION(auto)Integer (e.g. 3072)Override embedding dimensions
NARSIL_PRESET(empty)minimal, balanced, full, security-focusedTool preset profile
NARSIL_ENABLED_CATEGORIES(empty)Comma-separatedEnable specific tool categories
NARSIL_DISABLED_TOOLS(empty)Comma-separatedDisable specific tools
⁠Neural Embedding API Keys
VariableDefaultDescription
EMBEDDING_API_KEY(empty)Generic API key for any embedding provider
VOYAGE_API_KEY(empty)Voyage AI specific API key
OPENAI_API_KEY(empty)OpenAI specific API key
EMBEDDING_SERVER_ENDPOINT(empty)Custom embedding API endpoint URL
GITHUB_TOKEN(empty)PAT for NARSIL_REMOTE=true. repo scope enables private repos; raises GitHub API rate limit from 60/h to 5000/h
⁠Neural Embedding Notes

Neural embeddings are optional. Without NARSIL_NEURAL=true, all 80+ core tools work (symbol search, call graphs, security scanning, SBOM, git analysis, type inference, data flow, SPARQL, etc.). Only neural_search and find_semantic_clones require embeddings.

  • API backend (default): Set NARSIL_NEURAL=true + NARSIL_NEURAL_BACKEND=api + an API key. Default model is voyage-code-2 (1024 dims).
  • ONNX backend (local, no API key): Set NARSIL_NEURAL_BACKEND=onnx. Requires manually downloading the model via optimum-cli export onnx. Does not auto-download.
  • Cache persistence: The narsil-cache volume at /home/narsil/.cache persists model files and ONNX caches across restarts.

API backend examples:

# Voyage AI
- NARSIL_NEURAL=true
- NARSIL_NEURAL_BACKEND=api
- NARSIL_NEURAL_MODEL=voyage-code-2
- VOYAGE_API_KEY=your-voyage-key

# OpenAI
- NARSIL_NEURAL=true
- NARSIL_NEURAL_BACKEND=api
- NARSIL_NEURAL_MODEL=text-embedding-3-small
- OPENAI_API_KEY=sk-your-key

# Custom OpenAI-compatible endpoint (e.g., self-hosted embedding server)
- NARSIL_NEURAL=true
- NARSIL_NEURAL_BACKEND=api
- NARSIL_NEURAL_MODEL=Snowflake/snowflake-arctic-embed-xs
- EMBEDDING_SERVER_ENDPOINT=http://your-embedder-host:port/v1
- EMBEDDING_API_KEY=your-key-or-unused
- NARSIL_NEURAL_DIMENSION=384
⁠Narsil MCP Presets
PresetToolsDescription
minimal26Fast, lightweight (Zed, Cursor)
balanced51Good defaults (VS Code, IntelliJ)
full75+All features (Claude Desktop, comprehensive analysis)
security-focusedvariesSecurity and supply chain tools
⁠Security Settings
VariableDefaultPossible ValuesDescription
API_KEY(empty)5-256 printable charsBearer token for HAProxy authentication
CORS(empty)Origins (comma-separated) or *Allowed CORS origins
ENABLE_HTTPSfalsetrue, falseEnable TLS termination
TLS_CERT_PATH/etc/haproxy/certs/server.crtFile pathTLS certificate path
TLS_KEY_PATH/etc/haproxy/certs/server.keyFile pathTLS private key path
TLS_MIN_VERSIONTLSv1.3TLSv1.2, TLSv1.3Minimum TLS version
HTTP_VERSION_MODEautoauto, h1, h2, h3, h1+h2, allHTTP version negotiation
RATE_LIMIT00-NMax requests per RATE_LIMIT_PERIOD per IP (0 = disabled)
RATE_LIMIT_PERIOD10s10s, 1m, 1h, etc.Sliding window for rate limiting
MAX_CONNECTIONS_PER_IP00-NMax concurrent connections per IP (0 = disabled)
IP_ALLOWLIST(empty)Comma-separated IPs/CIDRsIPs/CIDRs to allow (all others blocked)
IP_BLOCKLIST(empty)Comma-separated IPs/CIDRsIPs/CIDRs to block

Boolean values: true, 1, yes, on are all accepted as truthy. Everything else is falsy.

Once per container lifecycle: NARSIL_REINDEX runs only once after the container is created. It is skipped on subsequent restarts (e.g., crash recovery, docker restart). To re-trigger, recreate the container (docker compose down && docker compose up -d).

Healthcheck: The container's healthcheck has a 450-second start period to accommodate the index-ready gate (see WAIT_FOR_INDEX below) plus initial indexing/model loading.

⁠Gateway & Startup Lifecycle
VariableDefaultDescription
WAIT_FOR_INDEXtrueBlock HAProxy startup until narsil finishes initial indexing. Set false for empty-repo dev setups
INDEX_READY_TIMEOUT300Seconds to wait for indexing before giving up and starting HAProxy anyway
NARSIL_KEEPALIVEtruePeriodic tools/list ping to keep the embedded narsil web UI HTTP server reachable. Insurance only — mcp-proxy stateful has no server-side TTL
KEEPALIVE_INTERVAL240Seconds between keepalive pings
⁠API Key Authentication Notes
  • Set API_KEY to enforce auth at the reverse proxy level.
  • Header: Authorization: Bearer <API_KEY>.
  • /healthz and CORS preflight (OPTIONS) bypass authentication.
⁠Rate Limiting and IP Access Control
  • Rate limiting: Set RATE_LIMIT=100 to allow 100 requests per RATE_LIMIT_PERIOD (default 10s) per IP. Exceeding the limit returns HTTP 429 with a Retry-After header.
  • Connection limiting: Set MAX_CONNECTIONS_PER_IP=50 to cap concurrent connections per IP. Exceeding returns HTTP 429.
  • IP blocklist: Set IP_BLOCKLIST=192.0.2.0/24,198.51.100.5 to block specific IPs/CIDRs. Blocked IPs receive HTTP 403.
  • IP allowlist: Set IP_ALLOWLIST=10.0.0.0/8,192.168.1.0/24 to allow only listed IPs/CIDRs. All others receive HTTP 403. Localhost is always allowed.
  • All features default to disabled. Combine as needed — blocklist is checked before allowlist.
⁠One-Shot Operations

For ad-hoc operations without setting env vars, use docker exec:

docker exec narsil-mcp narsil-mcp --repos /data --reindex   # Force full re-index

⁠Mounting Repositories for Analysis

Mount your repository directories to /data (or the path specified by DATA_DIR). Each subdirectory becomes an indexable repository.

volumes:
  # Mount entire projects directory
  - /home/user/projects:/data:ro
  # Or mount individual repositories
  - /home/user/my-rust-app:/data/my-rust-app:ro
  - /home/user/my-node-app:/data/my-node-app:ro

Then tell your AI agent to analyze using the mounted path:

  • "Search for symbols in /data/my-rust-app"
  • "Find injection vulnerabilities in /data/my-node-app"
  • "Generate an SBOM for /data/my-rust-app"
  • "Get the call graph for main in /data/my-node-app"

⁠MCP Client Configuration

⁠Claude Code

Add to ~/.claude.json under mcpServers:

{
  "mcpServers": {
    "narsil": {
      "type": "sse",
      "url": "http://host-ip:8010/sse"
    }
  }
}

Or for Streamable HTTP:

{
  "mcpServers": {
    "narsil": {
      "type": "http",
      "url": "http://host-ip:8010/mcp"
    }
  }
}
⁠VS Code / Codex / Cursor / Windsurf

All use the same JSON format. Configure in the respective config file:

  • VS Code: .vscode/settings.json (key: mcp.servers)
  • Codex: ~/.codex/config.json (key: mcpServers)
  • Cursor: ~/.cursor/mcp.json (key: mcpServers)
  • Windsurf: .codeium/mcp_settings.json (key: mcpServers)
{
  "mcpServers": {
    "narsil": {
      "transport": "http",
      "url": "http://host-ip:8010/mcp"
    }
  }
}

⁠Available Tags

TagPlatformDescription
latestamd64, arm64Latest stable release
1.7.0amd64, arm64Specific version

⁠License

This Docker image packaging is licensed under the GNU General Public License v3.0⁠.

⁠Upstream Licenses

This is an unofficial community packaging. It is NOT affiliated with, endorsed by, or supported by the narsil-mcp authors. See NOTICE⁠ for full attribution.


⁠Buy Me a Coffee

Your support encourages me to keep creating/supporting my open-source projects. If you found value in this project, you can buy me a coffee to keep me inspired.

Buy Me A Coffee ⁠


⁠Maintainer

Mohammad Mekayel Anik

Tag summary

Content type

Image

Digest

sha256:4a10b87ee…

Size

102.5 MB

Last updated

about 1 month ago

docker pull mekayelanik/narsil-mcp