Compare commits

..

63 Commits

Author SHA1 Message Date
Charles N Wyble
616085e0cf docs: update production status to 79% (33/42 servers)
Updated STATUS.md and PRODUCTION-READY.md:
- MCP servers: 29/38 (76%) production ready
- LSP servers: 4/4 (100%) production ready
- Total: 33/42 (79%)

Fixed servers moved to working:
- mcp-ansible: local source entrypoint fix
- postizz-mcp: stdio transport default

Blocked servers documented:
- discourse-mcp: upstream SDK incompatibility

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-27 11:22:29 -05:00
Charles N Wyble
e886950c40 fix(reverse-engineering-assistant): update Ghidra to 12.0.3
Updated Ghidra download URL from 11.2.1 to 12.0.3:
- Old URL returned 404
- New URL: Ghidra_12.0.3_build with date 20260210

Status: IN PROGRESS - gradlew not found issue remains

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-27 11:22:19 -05:00
Charles N Wyble
ad9c4c450e fix(discourse-mcp): attempt SDK version pinning (still blocked)
Attempted to fix TypeScript TS2345 error by:
- Switching to node:24-alpine with pnpm
- Pinning @modelcontextprotocol/sdk@^1.23.0

Status: BLOCKED - upstream code incompatibility in src/tools/remote/tool_exec_api.ts:58
The code uses incompatible SDK types. Cannot fix without upstream changes.

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-27 11:22:07 -05:00
Charles N Wyble
afa88abda4 fix(mcp-ansible): use local source install instead of uvx
The mcp-ansible package is not published to PyPI, causing uvx to fail.
Changed entrypoint to run directly from local source installation:
- Uses `uv pip install -e .` for local editable install
- Entrypoint: `python src/ansible_mcp/server.py`
- MCP handshake validated: ansible-mcp v1.26.0

Status: WORKING (29/38 MCP servers production ready)

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-27 11:21:55 -05:00
Charles N Wyble
fedd591b75 docs: add production readiness documentation
- Created PRODUCTION-READY.md with 31 deployable servers
- Updated README.md with production status badges and markers
  -  Production Ready (no config needed)
  - ⚠️ Config Required (works with backend)
  -  Not Production Ready (blocked)
- Updated STATUS.md with production summary table
- Added legend for status indicators

Production status: 31/42 servers (74%) ready for deployment

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-27 10:46:24 -05:00
Charles N Wyble
855b6e1f22 feat: add firefly-iii-mcp and paperless-mcp MCP servers
- Added firefly-iii-mcp (v1.3.0) for personal finance management
  - Uses npm package @firefly-iii-mcp/local instead of source build
  - Requires FIREFLY_III_BASE_URL and FIREFLY_III_PAT env vars
- Added paperless-mcp (v1.0.0) for document management
  - Requires PAPERLESS_URL and PAPERLESS_TOKEN CLI args
- Created wrapper scripts for Crush integration
- Updated docker-compose.yml with new services
- Updated .env.example with required environment variables
- Added Financial & Budgeting category to README.md

Both servers validated with MCP protocol handshake.

Working MCP servers count: 27

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-27 10:10:35 -05:00
Charles N Wyble
1526af86d8 fix(agents): add mandatory task completion checklist and tracked git hooks
Root cause fix for AI agent failing to commit/push automatically:

1. Added Task Completion Checklist to AGENTS.md with mandatory items:
   - All requested work implemented
   - Changes staged (git add)
   - Changes committed (conventional format)
   - Changes pushed (git push)
   - STATUS.md updated (if applicable)
   - JOURNAL.md updated (if applicable)

2. Added pre-push hook in .githooks/ (tracked, not .git/hooks/):
   - Blocks push if uncommitted changes exist
   - Safety net if checklist is skipped

3. Fixed .gitignore: changed "vendor/" to "vendor" to also ignore symlink

After cloning, run: git config core.hooksPath .githooks

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-20 12:08:43 -05:00
Charles N Wyble
a73699ad8b fix(agents): add mandatory task completion checklist and pre-push hook
Root cause fix for AI agent failing to commit/push automatically:
- Added explicit Task Completion Checklist section to AGENTS.md
- Added pre-push git hook to block push if uncommitted changes exist

The checklist forces verification of commit/push before declaring work done.
The git hook provides safety net if checklist is skipped.

Checklist items:
- All requested work implemented
- Changes staged (git add)
- Changes committed (conventional format)
- Changes pushed (git push)
- STATUS.md updated (if applicable)
- JOURNAL.md updated (if applicable)

DO NOT STOP until all applicable items complete.

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-20 12:04:54 -05:00
Charles N Wyble
787fe1f702 docs(audit): add comprehensive security audit report
External security audit of KNEL-AIMiddleware before release:

- FINAL-REPORT.md: Executive summary, risk assessment, remediation roadmap
- 01-dockerfile-security.md: 38/40 containers run as root (HIGH)
- 02-shell-script-security.md: 83 missing set -e/u directives (HIGH)
- 03-docker-compose-security.md: 3 privileged services documented (MEDIUM)
- 04-secrets-audit.md: PASS - no hardcoded secrets found
- 05-vulnerability-scan.md: 14+ CVEs, 1 CRITICAL OpenSSL (golang:1.23-alpine)

Assessment: CONDITIONAL PASS for release

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-20 11:59:09 -05:00
Charles N Wyble
d97fb09a9d fix(mcp): resolve proxmox-mcp fastmcp import, mark snipeit-mcp blocked
- proxmox-mcp: Fixed by patching pyproject.toml to use fastmcp from PyPI
  and updating imports from mcp.server.fastmcp to fastmcp. Container now
  builds and runs (requires PROXMOX_MCP_CONFIG env var).
- snipeit-mcp: Created stub Dockerfile that exits with error message.
  Upstream depends on private snipeit-api package never published to PyPI.
- STATUS.md: Updated to reflect 25 working MCP servers including proxmox-mcp.
- .env: Added template with placeholders for required credentials.

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-20 11:08:53 -05:00
Charles N Wyble
d80eff6df6 feat(mcp): add 8 new validated MCP servers
Add actual-mcp, beszel-mcp, gitea-mcp, ha-mcp, limesurvey-mcp,
linkwarden-mcp, mcp-grafana, and superset-mcp with full validation.

Key fixes applied:
- linkwarden-mcp: Added 'stdio' subcommand to ENTRYPOINT
- mcp-grafana: Fixed build path (./cmd/mcp-grafana) and added '--transport stdio' flag

All 8 servers validated with MCP protocol handshake.
Working MCP server count: 24 (up from 16)

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-20 10:41:56 -05:00
Charles N Wyble
cde8838133 docs: refactor AGENTS.md and README.md for proper separation of concerns
AGENTS.md now contains only AI agent rules/guidelines:
- Commit Policy, SDLC Compliance, Status Tracking, Journal Maintenance
- Project Conventions, Crush Configuration, Validation Checklist
- MCP Handshake Command example
- References to other documentation files instead of duplicating content

README.md now contains comprehensive project documentation:
- Full MCP/LSP server inventory tables (30+ servers organized by category)
- Server technologies by language (TypeScript, Python, Go, Rust, Prebuilt)
- Environment variables reference table for all services
- Installation, usage, troubleshooting guides
- Crush integration configuration examples

This refactoring ensures:
- AGENTS.md is a concise reference for AI agent behavior (~107 lines)
- README.md is the comprehensive project documentation (~424 lines)
- No duplication between files
- Each file has a single responsibility

💔 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-20 09:52:02 -05:00
Charles N Wyble
b1965c8161 feat(scripts): add 8 new MCP server vendor repositories
Added vendor clone entries for:

- actual-mcp: Actual budget MCP integration
  https://github.com/s-stefanov/actual-mcp
- superset-mcp: Apache Superset MCP server
  https://github.com/aptro/superset-mcp
- beszel-mcp: Beszel monitoring MCP
  https://github.com/Red5d/beszel-mcp
- mcp-grafana: Official Grafana MCP server
  https://github.com/grafana/mcp-grafana
- ha-mcp: Home Assistant MCP integration
  https://github.com/homeassistant-ai/ha-mcp
- gitea-mcp: Gitea MCP server
  https://gitea.com/gitea/gitea-mcp
- limesurvey-mcp: LimeSurvey MCP integration
  https://github.com/TonisOrmisson/limesurvey-mcp
- linkwarden-mcp-server: Linkwarden bookmark manager MCP
  https://github.com/irfansofyana/linkwarden-mcp-server

Total vendor repositories now at 40+.
2026-02-20 09:26:32 -05:00
Charles N Wyble
bdadb891f2 docs(readme): update script paths and remove Makefile references
Changes:
- Updated all script references to use scripts/ prefix
- Updated vendor repository count from 32+ to 40+
- Removed Makefile targets section (Makefile no longer primary interface)

This aligns documentation with current project structure where all
utility scripts are organized under the scripts/ directory.
2026-02-20 09:26:19 -05:00
Charles N Wyble
ea3b0907ae feat(scripts): add comprehensive validation script for all MCP/LSP servers
Created scripts/validate-all.sh to validate ALL servers with actual
protocol handshake messages:

Coverage:
- 29 MCP servers (Design, Infrastructure, Content, Communication,
  Analytics, Productivity, Reverse Engineering)
- 4 LSP servers (bash, docker, marksman, terraform-ls)

Features:
- Sends actual MCP initialize handshake to each container
- Sends actual LSP initialize handshake to LSP containers
- Categorizes results: PASSED, FAILED, SKIPPED, NEEDS_ENV,
  NEEDS_SERVICE, TRANSPORT_MISMATCH
- Provides detailed summary with server names and versions
- Color-coded output for easy scanning

Usage:
  ./scripts/validate-all.sh           # Test all servers
  ./scripts/validate-all.sh mcp       # MCP servers only
  ./scripts/validate-all.sh lsp       # LSP servers only
  ./scripts/validate-all.sh <service> # Specific service

This script implements the SDLC requirement for protocol validation.
Every server must pass build + start + protocol handshake to be
considered "working".
2026-02-20 09:24:59 -05:00
Charles N Wyble
32c003d2d9 docs(agents): enforce automatic commits and SDLC compliance
Added mandatory callout at top of AGENTS.md:

- AI agents MUST commit and push changes automatically WITHOUT prompting
- Use atomic commits (one logical change per commit)
- Use conventional format (feat:, fix:, docs:, build:, refactor:, test:)
- Verbose commit messages required

Updated Development Notes section:
- Added "SDLC Compliance (REQUIRED)" section with link to docs/SDLC.md
- Documented mandatory MCP handshake command
- Updated Validation Checklist to emphasize protocol handshake is MANDATORY

This ensures AI agents understand that committing is automatic,
not something to ask permission for.
2026-02-20 09:24:45 -05:00
Charles N Wyble
5fd45d48c9 docs: add SDLC.md with MCP/LSP validation requirements and commit policy
Defines the software development lifecycle for KNEL-AIMiddleware:

- Protocol validation is NON-NEGOTIABLE: build + start + protocol handshake
  ALL required before marking a server as "working"
- MCP initialize handshake: {"jsonrpc":"2.0","method":"initialize"...}
- STATUS.md is the single source of truth for server status
- Status categories: Working, Runtime Connection Required, Host-Only,
  Transport Mismatch, Build Failed, Runtime Issue
- Step-by-step process for adding new MCP/LSP servers
- Common Dockerfile patterns for Python/uv, Node/npx, Go
- Wrapper script pattern for Crush integration

Commit Policy (MANDATORY):
- AI agents MUST commit automatically WITHOUT prompting
- Atomic commits: one logical change per commit
- Conventional format: feat:, fix:, docs:, build:, refactor:, test:
- Verbose messages explaining what, why, and how validated
- Automatic push after each commit

Version: 1.0
2026-02-20 09:24:32 -05:00
Charles N Wyble
72d5058659 docs: add Docker registry push session to JOURNAL.md
Recorded the completion of pushing all 32 container images to
git.knownelement.com/knel/knel-aimiddleware/ registry.

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-19 13:19:36 -05:00
Charles N Wyble
671b9f57d1 feat: add run.sh for Docker registry management
Adds utility script for pushing container images to Gitea Docker registry
at git.knownelement.com/knel/knel-aimiddleware. Commands: list, tag, tag-all,
push, push-all. Includes shellcheck compliance fixes.

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-19 13:13:37 -05:00
Charles N Wyble
ff5c73de7c docs: validate all MCP servers with protocol handshake
- Added matomo-mcp, mcp-redmine, paperless-mcp to working servers list
- Documented runtime failures (nextcloud, imap, webserial, kicad)
- Documented transport mismatches (postizz, penpot)
- Updated README.md vendor count and date
- Added JOURNAL entry for mock credential validation

💔 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-19 12:35:31 -05:00
Charles N Wyble
ff897aec58 fix: complete MCP server validation and documentation
- Fixed penpot-mcp Dockerfile for monorepo build (added data/ copy)
- Fixed snipeit-mcp Dockerfile COPY path and entrypoint
- Completed validation of all pending MCP servers
- Updated STATUS.md with comprehensive validation results
- Added JOURNAL.md entry documenting session work

Validation summary:
- terraform-mcp: Working (MCP handshake validates)
- 6 servers require config/env vars (matomo, nextcloud, paperless, postizz, redmine)
- 6 servers have build/runtime issues (discourse, revas, snipeit, proxmox, penpot, mcp-ansible)
2026-02-19 11:33:10 -05:00
Charles N Wyble
bc89169265 fix: correct crush.json paths and add missing MCP wrapper scripts
- Fixed incorrect path /KNEL/KNEL-AIMiddleware/ to /KNEL-AIMiddleware/
- Added discourse and penpot MCP configurations to crush.json
- Tracked 10 new wrapper scripts for pending MCP servers
- Added paperless-mcp and postizz-mcp Dockerfiles
- Updated JOURNAL.md with today's work entry

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-19 10:59:32 -05:00
Charles N Wyble
55166db065 feat: update Dockerfiles, add new MCP configurations, and sync documentation
- Add Dockerfiles for bitwarden-mcp, mcp-ansible, reverse-engineering-assistant
- Update CloneVendorRepos.sh with official repository URLs (migrate from ahujasid mirrors)
- Update docker-compose.yml with new services and reorganization
- Update STATUS.md with current operational status of all MCP servers
- Update AGENTS.md with webserial-mcp and terraform-ls documentation
- Add journal entries for recent work (ADRs, insights, patterns)

💔 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-19 09:06:35 -05:00
Charles N Wyble
30cb9a8829 docs: update AGENTS.md with webserial-mcp and terraform-ls
- Add LSP Servers section (4 servers)
- Add webserial-mcp to Additional Tools section
- Reorganize Development Tools (remove LSP entries)
- Update language counts (Python 11, add HashiCorp Binary)
2026-02-17 11:44:10 -05:00
Charles N Wyble
0972556b38 docs: add terraform-ls and wordpress-mcp status to STATUS.md
- Add terraform-ls to detailed status table (Built, v0.38.4)
- Document wordpress-mcp as Blocked (requires WordPress instance)
- Add Known Issues section for WordPress MCP Adapter architecture
- Update MCP Servers with Configuration Issues section

🧡 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-17 11:38:57 -05:00
Charles N Wyble
e7df499874 feat: integrate terraform-ls LSP for Terraform development
- Add terraform-ls Dockerfile (Alpine-based, v0.38.4)
- Add terraform-ls service to docker-compose.yml
- Create LSP wrapper script for Crush integration
- Add terraform entry to crush.json under lsp section
- Update STATUS.md with terraform-ls working status

🧡 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-17 11:33:05 -05:00
Charles N Wyble
0c20861103 feat: integrate webserial-mcp for ESP32 MicroPython development
- Add webserial-mcp service to docker-compose.yml
- Create wrapper script and add to crush.json
- Update STATUS.md with build status and requirements
- Note: requires bridge server + browser + ESP32 hardware

deps: generated with Crush
Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-17 11:10:38 -05:00
Charles N Wyble
af1a823683 feat: integrate silenceper/mcp-k8s for kubernetes-mcp
- Switch from empty ahujasid/kubernetes-mcp-server to silenceper/mcp-k8s
- Build multi-stage Go container (golang:1.24.1 -> alpine:3.18.4)
- Add wrapper script with kubeconfig mount
- Configure in crush.json for Crush integration
- Update STATUS.md with working status

Supports K8s resources (get/list/create/update/delete) and Helm operations.

💔 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-17 11:03:56 -05:00
Charles N Wyble
7304d1e4a8 docs: document empty ahujasid vendor repositories
Investigation revealed that 9 additional ahujasid MCP repositories are
empty (contain only .git folder, no actual code):
- kubernetes-mcp-server
- ProxmoxMCP
- terraform-mcp-server
- nextcloud-mcp-server
- snipeit-mcp
- mcp-redmine
- mcp-ansible
- penpot-mcp
- postizz-MCP

These cannot be used to build MCP containers. Added detailed entries to:
- Missing/Empty Vendor Repositories section
- Detailed Status table
- Known Issues section with alternative for kubernetes-mcp (silenceper/mcp-k8s)

This brings the total blocked MCPs to 11:
- 1 missing repo (matomo-mcp - 404)
- 10 empty repos (discourse + 9 documented here)

Related: ADR-007 Sequential MCP validation
2026-02-17 10:54:31 -05:00
Charles N Wyble
60f317e92c feat: integrate ONLYOFFICE docspace-mcp v3.1.0
- Updated CloneVendorRepos.sh to use official ONLYOFFICE/docspace-mcp
  repository instead of ahujasid/docspace-mcp (which was outdated)
- Successfully built and validated docspace-mcp Docker container (236MB)
- Created wrapper script mcp-docspace-wrapper.sh with environment
  variables for DOCSPACE_HOST and DOCSPACE_TOKEN
- Added docspace MCP configuration to crush.json
- Updated STATUS.md with working status for docspace-mcp

MCP handshake test confirmed server responds correctly:
- Protocol version: 2024-11-05
- Server: @onlyoffice/docspace-mcp v3.1.0
- Capabilities: tools

Also documented blocked MCPs in STATUS.md:
- matomo-mcp: vendor repo does not exist (404)
- discourse-mcp: vendor repo exists but is empty (no commits)

Related: ADR-007 Sequential MCP validation
2026-02-17 10:44:10 -05:00
Charles N Wyble
3bdf281a4a docs: document discourse-mcp empty vendor repository
discourse-mcp repository at https://github.com/ahujasid/discourse-mcp.git
exists but contains no commits - completely empty repository.

Added to:
- Missing Vendor Repositories section
- Known Issues section
- Detailed Status table (status: Blocked)

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-17 10:19:37 -05:00
Charles N Wyble
04e9d80025 docs: document matomo-mcp missing vendor repository
matomo-mcp-client repository referenced in CloneVendorRepos.sh
does not exist on GitHub (404). Verified via GitHub API that
ahujasid has 46 repos but none named matomo-mcp-client.

Unable to build this MCP until a valid source repository is identified.

Added to:
- Missing Vendor Repositories section
- Known Issues section
- Detailed Status table (status: Blocked)

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-17 10:14:08 -05:00
Charles N Wyble
feea0945c1 docs: document kicad-mcp as host-only MCP
kicad-mcp requires the pcbnew Python module which is only
available with a KiCAD installation. The container builds
successfully but fails validation because pcbnew cannot be
pip-installed or included in the container.

- Added "Host-Only MCP Servers" section to STATUS.md
- Updated detailed status table with kicad-mcp entry
- Added JOURNAL.md entry documenting the finding
- Updated docker-compose.yml to use custom Dockerfile

This MCP can only be used on a host machine with KiCAD
installed. It cannot be integrated into Crush via Docker.

Build details:
- Container size: 463MB
- Base: node:22-alpine with Python 3 + pip
- Dependencies: kicad-skip, Pillow, cairosvg, colorlog, pydantic

Validation error:
[ERROR] pcbnew validation failed: ModuleNotFoundError: No module named 'pcbnew'

Root cause:
- KiCAD's pcbnew is a C++ Python binding bundled with KiCAD
- Cannot be installed via pip or any package manager
- Server validates pcbnew at startup and exits if missing

Pattern identified:
Some MCPs integrate with desktop applications and cannot
be containerized. These should be documented as host-only
and excluded from Docker-based Crush integration.

Next MCP to process: matomo-mcp

💘 Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-17 09:43:14 -05:00
b211d36bd2 docs: add session summary for MCP integration work
Document current state of MCP integration work before system reboot.

Summary:
- 11 MCPs successfully integrated and working
- 1 MCP integrated with known issue (imap-mcp)
- 5 MCPs added this session (context7, freecad, ghost, gimp, imap)
- All changes committed and pushed
- Working tree clean

Next MCP to process: kicad-mcp (special case: host-only)

Remaining MCPs to process:
- kicad-mcp (special case: host-only, requires KiCAD running)
- mcp-ansible (ansibe-mcp)
- mcp-redmine (redmine-mcp)
- matomo-mcp
- nextcloud-mcp (special case: HTTP-based)
- discourse-mcp
- docspace-mcp
- penpot-mcp
- postizz-mcp
- proxmox-mcp
- snipeit-mcp
- terraform-mcp
- wordpress-mcp
- kubernetes-mcp (special case: requires kube config)

Patterns established:
- Build container
- Fix Dockerfile if needed
- Create wrapper script
- Test MCP protocol
- Add to crush.json
- Update STATUS.md and JOURNAL.md
- Commit and push
- Docker cleanup
2026-01-23 15:40:42 -05:00
d067f195c2 feat: add imap-mcp to Crush integration (known issue)
Build and integrate IMAP MCP Server.

Changes:
- mcp-imap-wrapper.sh: Created wrapper script with container cleanup
- crush.json: Added imap-mcp entry with type: stdio and timeout: 60
- STATUS.md: Updated to mark imap-mcp as having configuration issues
- JOURNAL.md: Documented integration with full analysis of known issue

Known Issue:
- Server crashes on startup if IMAP connection fails
- Server does not respond to JSON-RPC initialize before crashing
- Requires working IMAP server to function in Crush
- Root cause: server attempts IMAP connection during lifespan context entry
- If connection fails, exception propagates and causes server exit
- Bug in imap-mcp: should handle connection gracefully

Validation:
- Container builds successfully (317MB, Python + uv)
- Wrapper script tested and working
- MCP protocol handshake: FAILED (server crashes before initialize)
- Cannot test protocol version or server capabilities due to crash

Environment Variables Required:
- PYTHONUNBUFFERED=1
- IMAP_HOST: IMAP server hostname
- IMAP_PORT: IMAP server port (default: 993)
- IMAP_USER: IMAP username
- IMAP_PASSWORD: IMAP password

Workaround:
User must have a working IMAP server running for imap-mcp
to initialize in Crush. If IMAP is unavailable, MCP will fail.

This is fifth MCP added in alphabetical order after filtering
out already working MCPs (audiobook, bitwarden, blender, cloudron,
context7, docker, drawio, elasticsearch, freecad, ghost, gimp).

Following ADR-007: Sequential Server Validation - one MCP at a time,
noting issues as they are encountered.
2026-01-23 15:31:59 -05:00
2596cc42e0 feat: add gimp-mcp to Crush integration
Build and validate GIMP MCP Server (GimpMCP v1.10.1).

Changes:
- dockerfiles/gimp-mcp/Dockerfile: Fixed ENTRYPOINT to use python -m instead of uvx
- mcp-gimp-wrapper.sh: Created wrapper script with container cleanup
- crush.json: Added gimp-mcp entry with type: stdio and timeout: 180
- STATUS.md: Updated working MCP list and detailed status table
- JOURNAL.md: Documented integration with full validation results

Validation:
- Container builds successfully (418MB, Python + uv)
- Dockerfile fix: Changed from uvx (slow, rebuilds packages) to python -m (fast, uses .venv)
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: GimpMCP, version 1.10.1
- Wrapper script tested and working
- Environment variable: PYTHONUNBUFFERED=1
- External dependency: GIMP 3.0 with server

Dockerfile Fix:
- Before: ENTRYPOINT ["uvx", "gimp-mcp-server"] (slow, rebuilds on every run)
- After: ENTRYPOINT ["python", "-m", "gimp_mcp_server"] (fast, uses built .venv)
- Entry point: gimp-mcp-server = "gimp_mcp_server:main" (from pyproject.toml)

This is fourth MCP added in alphabetical order after filtering
out already working MCPs (audiobook, bitwarden, blender, cloudron,
context7, docker, drawio, elasticsearch, freecad, ghost).

Following ADR-007: Sequential Server Validation - one MCP at a time.
2026-01-23 15:20:48 -05:00
2b79f5dd95 feat: add ghost-mcp to Crush integration
Build and validate Ghost CMS MCP Server (ghost-mcp-ts v1.0.0).

Changes:
- mcp-ghost-wrapper.sh: Created wrapper script with container cleanup
- crush.json: Added ghost-mcp entry with type: stdio and timeout: 60
- STATUS.md: Updated working MCP list and detailed status table
- JOURNAL.md: Documented integration with full validation results

Validation:
- Container builds successfully (284MB, Node.js + TypeScript)
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: ghost-mcp-ts, version 1.0.0
- Wrapper script tested and working
- Environment variables: GHOST_API_URL, GHOST_ADMIN_API_KEY
- Capabilities: resources, tools, prompts (all listChanged: true)

This is third MCP added in alphabetical order after filtering
out already working MCPs (audiobook, bitwarden, blender, cloudron,
context7, docker, drawio, elasticsearch, freecad).

Following ADR-007: Sequential Server Validation - one MCP at a time,
awaiting user validation before proceeding to next MCP.
2026-01-23 15:05:09 -05:00
fcfb6f486a feat: add freecad-mcp to Crush integration
Build and validate FreeCAD MCP Server (v1.25.0).

Changes:
- mcp-freecad-wrapper.sh: Created wrapper script with container cleanup
- crush.json: Added freecad-mcp entry with type: stdio and timeout: 180
- STATUS.md: Updated working MCP list and detailed status table
- JOURNAL.md: Documented integration with full validation results

Validation:
- Container builds successfully (317MB, Python + uv)
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: FreeCADMCP, version 1.25.0
- Wrapper script tested and working
- Environment variable: PYTHONUNBUFFERED=1
- External dependency: FreeCAD with MCP addon (warning if not running)

Similar to blender-mcp:
- Both Python-based with uv package manager
- Both require CAD application with addon running
- Both show warning on startup when CAD app not connected
- Both still initialize properly for MCP protocol handshake

This is second MCP added in alphabetical order after filtering
out already working MCPs (audiobook, bitwarden, blender, cloudron,
context7, docker, drawio, elasticsearch).

Following ADR-007: Sequential Server Validation - one MCP at a time,
awaiting user validation before proceeding to next MCP.
2026-01-23 14:52:34 -05:00
834d3524a0 chore: add previously created MCP wrapper scripts
Add MCP wrapper scripts that were created during earlier troubleshooting
but were not committed yet. All wrappers follow same pattern:

- Container cleanup before starting new instance
- Explicit naming with -crush suffix
- Environment variable passing from host .env file
- Special cases handled (docker-mcp socket mount)

Scripts added:
- mcp-audiobook-wrapper.sh
- mcp-bitwarden-wrapper.sh
- mcp-blender-wrapper.sh
- mcp-cloudron-wrapper.sh
- mcp-docker-wrapper.sh (with Docker socket mount)
- mcp-drawio-wrapper.sh
- mcp-elasticsearch-wrapper.sh

All scripts are executable and tested.
2026-01-23 14:24:55 -05:00
475bc39111 feat: add context7-mcp to Crush integration
Build and validate Context7 Documentation MCP Server (v2.1.0).

Changes:
- mcp-context7-wrapper.sh: Created wrapper script with container cleanup
- crush.json: Added context7-mcp entry with type: stdio and timeout: 60
- STATUS.md: Updated working MCP list and detailed status table
- JOURNAL.md: Documented integration with full validation results

Validation:
- Container builds successfully (224MB, Node.js + TypeScript)
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: Context7, version 2.1.0
- Wrapper script tested and working
- Environment variables: UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN

This is the first MCP added in alphabetical order after filtering
out already working MCPs (audiobook, bitwarden, blender, cloudron,
docker, drawio, elasticsearch).

Following ADR-007: Sequential Server Validation - one MCP at a time,
awaiting user validation before proceeding to next MCP.
2026-01-23 14:24:18 -05:00
2cb5f29683 manual git sync by human 2026-01-23 12:24:06 -05:00
c5393f9b5e feat: add elasticsearch-mcp validation
Build and validate Elasticsearch MCP server for search/indexing.

Changes:
- docker-compose.yml: Updated elasticsearch-mcp to use custom Dockerfile
  and ES_URL env var (not ELASTICSEARCH_URL)
- dockerfiles/elasticsearch-mcp/Dockerfile: Added custom Dockerfile with
  fix to pass "stdio" subcommand to ENTRYPOINT
- STATUS.md: Added elasticsearch-mcp as validated MCP (v0.2.1, 22MB)

Validation:
- Container builds successfully from Rust source (22MB)
- Fixed Dockerfile to pass "stdio" subcommand to entry point
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: rmcp, version 0.2.1
- Requires ES_URL environment variable (not ELASTICSEARCH_URL)
- NOTE: Server is deprecated, superseded by Elastic Agent Builder
- Tested with proper --name flag for container
2026-01-23 00:40:09 -05:00
5398e4b7e6 feat: add drawio-mcp validation
Build and validate Draw.io MCP server for diagram management.

Changes:
- STATUS.md: Added drawio-mcp as validated MCP (v1.4.0, 302MB)
- STATUS.md: Updated counts and status sections

Validation:
- Container builds successfully from TypeScript source (302MB)
- Uses pnpm package manager for fast dependency installation
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: drawio-mcp-server, version 1.4.0
- Requires DRAWIO_URL environment variable
- WebSocket extension runs on port 3333
- Tested with proper --name flag for container
2026-01-23 00:22:17 -05:00
fa0b2b95c5 feat: add docker-mcp validation
Build and validate Docker MCP server for container management.

Changes:
- STATUS.md: Added docker-mcp as validated MCP (v0.1.0, 188MB)
- STATUS.md: Updated counts and status sections

Validation:
- Container builds successfully from Python source (188MB)
- Uses uv package manager for fast dependency installation
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: docker-mcp, version 0.1.0
- Requires Docker socket mount (/var/run/docker.sock)
- Tested with proper --name flag for container
2026-01-23 00:16:19 -05:00
6017d996fe feat: add cloudron-mcp validation
Build and validate Cloudron MCP server for self-hosted app management.

Changes:
- docker-compose.yml: Updated to use custom Dockerfile for cloudron-mcp
- dockerfiles/cloudron-mcp/Dockerfile: Added custom Dockerfile with fix
  for CMD entry point (dist/server.js instead of dist/index.js)
- STATUS.md: Added cloudron-mcp as validated MCP (v0.1.0, 374MB)

Validation:
- Container builds successfully from TypeScript source (374MB)
- Fixed Dockerfile CMD to use correct entry point (dist/server.js)
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: cloudron-mcp, version 0.1.0
- Requires CLOUDRON_URL environment variable
- Tested with proper --name flag for container
2026-01-23 00:13:28 -05:00
8c67bbcf77 feat: add blender-mcp validation
Build and validate Blender MCP server for 3D modeling.

Changes:
- STATUS.md: Added blender-mcp as validated MCP (v1.25.0, 321MB)
- STATUS.md: Updated counts and status sections

Validation:
- Container builds successfully from Python source (321MB)
- Uses uv package manager for fast dependency installation
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: BlenderMCP, version 1.25.0
- Requires Blender application running with addon for full functionality
- Tested with proper --name flag for container
2026-01-23 00:05:33 -05:00
15c5cd8446 feat: add bitwarden-mcp validation
Build and validate Bitwarden MCP server for password management.

Changes:
- STATUS.md: Added bitwarden-mcp as validated MCP (v2026.1.0, 377MB)
- STATUS.md: Updated counts and status sections

Validation:
- Container builds successfully from source (multi-stage distroless build)
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: Bitwarden MCP Server, version 2026.1.0
- Requires BITWARDEN_CLIENT_ID, BITWARDEN_CLIENT_SECRET,
  BITWARDEN_PASSWORD, BITWARDEN_SERVER_URL env vars
- Tested with proper --name flag for container
2026-01-23 00:00:40 -05:00
2c0e19ab2b feat: add audiobook-mcp validation and fix Dockerfile
Build and validate audiobook-mcp server for audiobook management.

Changes:
- dockerfiles/audiobook-mcp/Dockerfile: Fixed esbuild ETXTBSY error
  by using 'npm install --ignore-scripts' instead of 'npm ci'
- STATUS.md: Added audiobook-mcp as validated MCP (v1.1.0, 361MB)
- AGENTS.md: Added audiobook-mcp to Productivity & Automation section

Validation:
- Container builds successfully from source
- MCP protocol handshake verified with initialize request
- Protocol version 2024-11-05 confirmed
- Server name: audiobook-library, version 1.1.0
- Requires AUDIOBOOK_ROOT environment variable
2026-01-22 23:50:58 -05:00
a024b4c353 docs: add marksman LSP validation and update documentation
Document marksman Markdown LSP build and validation success.

Changes:
- STATUS.md: Added marksman as validated LSP (2025-12-13, 144MB)
- AGENTS.md: Added marksman to Development Tools section
- AGENTS.md: Updated server counts (Development Tools: 3→4)

Validation:
- Container builds successfully from custom Dockerfile
- Version 2025-12-13 verified with --version flag
- Crush wrapper script functional
- All three LSP servers (bash, docker, marksman) now working
2026-01-22 23:43:29 -05:00
a08204920d docs: add docker-language-server validation and update documentation
Document docker-language-server LSP build and validation success.

Changes:
- STATUS.md: Added docker-language-server as validated LSP (v0.0.0, 49.2MB)
- AGENTS.md: Moved docker-language-server to Development Tools section
- AGENTS.md: Updated server counts (Development Tools: 2→3, Additional Tools: 3→2)
- AGENTS.md: Added No Language/Prebuilt category for LSP servers

Validation:
- Container builds successfully from custom multi-stage Dockerfile
- Version 0.0.0 verified with --version flag
- Crush wrapper script functional
- User acceptance testing completed in fresh Crush session
2026-01-22 23:35:58 -05:00
1638fffbdb docs: reset STATUS.md and add bash-language-server validation
Reset STATUS.md to clean slate and document bash-language-server LSP
build and validation success.

Changes:
- Cleaned all previous MCP/LSP server status entries
- Added bash-language-server as validated LSP (v5.6.0, 190MB)
- Updated crush.json configuration reference
- Cleared all known issues and build progress sections

Validation:
- Container builds successfully from custom Dockerfile
- Version 5.6.0 verified with --version flag
- Crush wrapper script functional
- User acceptance testing completed
2026-01-22 23:23:48 -05:00
b6e4499bec clean: remove all MCP servers except elasticsearch-mcp
- Clear crush.json MCP section for focused UAT
- Keep only elasticsearch-mcp for testing
- Retain all LSP server configurations
2026-01-22 18:26:19 -05:00
2c26012c01 docs: update STATUS.md with build progress
- Mark 6 services as Built (cloudron, docspace, freecad, gimp, kicad, blender)
- Update 5 services as Building (elasticsearch, kubernetes, matomo, postizz, wordpress)
- Document 3 build failures with action items (ansible, snipeit, terraform)
- Update detailed status table with latest build information
2026-01-22 18:18:03 -05:00
c023d939bd feat: add additional MCP servers to crush.json
Add the following built MCP servers to crush.json configuration:
- blender-mcp
- cloudron-mcp
- docspace-mcp
- freecad-mcp
- gimp-mcp
- kicad-mcp

All servers configured with appropriate environment variables.
2026-01-22 18:07:39 -05:00
ea1c90d53e refactor: replace Makefile with maintenance.sh
Remove Makefile in favor of more flexible shell-based maintenance script.
The new maintenance.sh provides all the same functionality with
easier maintenance and better shell script integration.
2026-01-22 18:02:57 -05:00
7c583e2821 refactor: organize scripts into scripts/ directory
Move utility scripts to dedicated scripts/ directory for better project
organization:
- BuildAll.sh
- CleanVendor.sh
- CloneVendorRepos.sh
- StatusCheck.sh
- validate-mcp.sh

Remove temporary build-nextcloud-mcp.sh as nextcloud-mcp is now built.
2026-01-22 18:02:56 -05:00
3c0565d0e9 chore: add .env.example template
Add .env.example with dummy values for all required environment
variables. Users can copy this to .env and fill in actual values.
2026-01-22 18:02:54 -05:00
8f0c366686 chore: add .env to gitignore
Add .env file to gitignore to prevent committing sensitive
environment variables.
2026-01-22 18:02:53 -05:00
34844512a8 fix: update LSP configurations to use wrapper scripts
Update crush.json LSP configurations to use newly created
wrapper scripts instead of direct Docker commands. This ensures
LSP server containers have consistent names matching their
images, allowing multiple Crush sessions to share containers
and enabling clean restart capability.
2026-01-22 17:43:45 -05:00
a7e5c61e6a feat: add LSP wrapper scripts for named containers
Add wrapper scripts for bash, docker, and marksman LSP servers
to ensure containers use explicit names matching image names.
Enables multiple Crush sessions to share LSP server containers
with clean restart capability.

- lsp-bash-wrapper.sh: Wrapper for bash-language-server
- lsp-docker-wrapper.sh: Wrapper for docker-language-server
- lsp-marksman-wrapper.sh: Wrapper for marksman markdown LSP

Each wrapper cleans up existing containers and starts new container
with --name flag to ensure consistent naming.
2026-01-22 17:43:37 -05:00
982f6afd6d docs: update STATUS.md with accurate validation results
- Add validation summary section with working MCP servers list
- Document ProxmoxMCP config incompatibility with Crush
- Note slow initialization for context7, drawio, redmine
- Update bitwarden-mcp and audiobook-mcp status to Working
- Add known issues section for documentation
- Document validation script fixes and Docker config warning
2026-01-22 16:51:09 -05:00
c3f216e6bd fix: MCP validation script stdin handling and timeouts
- Fix bash script to use 'echo |' instead of '<<<' for Docker stdin
- Increase default timeout from 5s to 10s
- Add explicit timeout parameter to all test function calls
- Fix Ghost MCP env variables to use correct names and format
- Script was giving false negatives due to incorrect bash syntax
2026-01-22 16:50:57 -05:00
fea9473d83 fix: remove context7 from LSP section and add Ghost env vars
- Remove context7 from LSP section in crush.json (it's an MCP server)
- Add GHOST_API_URL and GHOST_ADMIN_API_KEY to ghost-mcp config
- Context7 was incorrectly configured as both LSP and MCP
2026-01-22 16:50:46 -05:00
98 changed files with 6917 additions and 740 deletions

96
.env
View File

@@ -1,86 +1,14 @@
# Dummy environment variables for MCP servers
# Replace with actual values as needed
# Nextcloud MCP
NEXTCLOUD_HOST=
NEXTCLOUD_USERNAME=
NEXTCLOUD_APP_PASSWORD=
# KiCAD
KICAD_HOST=host.docker.internal
KICAD_PORT=5555
# IMAP MCP
IMAP_SERVER=
IMAP_PORT=
IMAP_USERNAME=
IMAP_PASSWORD=
# Proxmox
PROXMOX_HOST=https://proxmox.example.com:8006
PROXMOX_USER=root@pam
PROXMOX_TOKEN=dummy-token-replace-with-real-token
PROXMOX_NODE=pve
# Cloudron
CLOUDRON_URL=https://cloudron.example.com
CLOUDRON_TOKEN=dummy-cloudron-token-replace-with-real
# Context7 (Upstash Redis)
UPSTASH_REDIS_REST_URL=https://dummy-redis-url.upstash.io
UPSTASH_REDIS_REST_TOKEN=dummy-redis-token-replace-with-real
# Nextcloud
NEXTCLOUD_HOST=https://nextcloud.example.com
NEXTCLOUD_USERNAME=admin
NEXTCLOUD_APP_PASSWORD=dummy-app-password-replace-with-real
# Ghost (defaults already set in docker-compose)
GHOST_API_URL=http://localhost:2368
GHOST_ADMIN_API_KEY=012345678901234567890123:0123456789012345678901234567890123456789012345678901234567890123
# DocSpace
DOCSPACE_HOST=https://docspace.example.com
DOCSPACE_TOKEN=dummy-docspace-token-replace-with-real
# WordPress
WORDPRESS_URL=https://wordpress.example.com
WORDPRESS_USERNAME=admin
WORDPRESS_APPLICATION_PASSWORD=dummy-app-password-replace-with-real
# Discourse
DISCOURSE_URL=https://discourse.example.com
DISCOURSE_API_KEY=dummy-api-key-replace-with-real
DISCOURSE_API_USERNAME=admin
# IMAP
IMAP_HOST=imap.example.com
IMAP_PORT=993
IMAP_USERNAME=user@example.com
IMAP_PASSWORD=dummy-password-replace-with-real
# Postiz
POSTIZ_URL=https://postiz.example.com
POSTIZ_API_KEY=dummy-api-key-replace-with-real
# Matomo
MATOMO_URL=https://matomo.example.com
MATOMO_TOKEN=dummy-token-replace-with-real
# Bitwarden
BITWARDEN_CLIENT_ID=dummy-client-id
BITWARDEN_CLIENT_SECRET=dummy-client-secret
BITWARDEN_PASSWORD=dummy-password
BITWARDEN_SERVER_URL=https://vault.bitwarden.com
# Snipe-IT
SNIPEIT_URL=https://snipeit.example.com
SNIPEIT_TOKEN=dummy-token-replace-with-real
# Redmine
REDMINE_URL=https://redmine.example.com
REDMINE_API_KEY=dummy-api-key-replace-with-real
# Elasticsearch
ELASTICSEARCH_URL=http://localhost:9200
ELASTICSEARCH_USERNAME=elastic
ELASTICSEARCH_PASSWORD=dummy-password-replace-with-real
# Audiobook
AUDIOBOOK_ROOT=/audiobooks
# Draw.io (default in compose)
DRAWIO_URL=https://app.diagrams.net
# Penpot (default URL in compose)
PENPOT_URL=https://design.penpot.app
PENPOT_TOKEN=dummy-penpot-token-replace-with-real
# Home Assistant (if needed)
HOMEASSISTANT_URL=
HOMEASSISTANT_TOKEN=

100
.env.example Normal file
View File

@@ -0,0 +1,100 @@
# Dummy environment variables for MCP servers
# Replace with actual values as needed
# KiCAD
KICAD_HOST=host.docker.internal
KICAD_PORT=5555
# Proxmox
PROXMOX_HOST=https://proxmox.example.com:8006
PROXMOX_USER=root@pam
PROXMOX_TOKEN=dummy-token-replace-with-real-token
PROXMOX_NODE=pve
# Cloudron
CLOUDRON_URL=https://cloudron.example.com
CLOUDRON_TOKEN=dummy-cloudron-token-replace-with-real
# Context7 (Upstash Redis)
UPSTASH_REDIS_REST_URL=https://dummy-redis-url.upstash.io
UPSTASH_REDIS_REST_TOKEN=dummy-redis-token-replace-with-real
# Nextcloud
NEXTCLOUD_HOST=https://nextcloud.example.com
NEXTCLOUD_USERNAME=admin
NEXTCLOUD_APP_PASSWORD=dummy-app-password-replace-with-real
# Ghost (defaults already set in docker-compose)
GHOST_API_URL=http://localhost:2368
GHOST_ADMIN_API_KEY=012345678901234567890123:0123456789012345678901234567890123456789012345678901234567890123
# DocSpace
DOCSPACE_HOST=https://docspace.example.com
DOCSPACE_TOKEN=dummy-docspace-token-replace-with-real
# WordPress
WORDPRESS_URL=https://wordpress.example.com
WORDPRESS_USERNAME=admin
WORDPRESS_APPLICATION_PASSWORD=dummy-app-password-replace-with-real
# Discourse
DISCOURSE_URL=https://discourse.example.com
DISCOURSE_API_KEY=dummy-api-key-replace-with-real
DISCOURSE_API_USERNAME=admin
# IMAP
IMAP_HOST=imap.example.com
IMAP_PORT=993
IMAP_USERNAME=user@example.com
IMAP_PASSWORD=dummy-password-replace-with-real
# Postiz
POSTIZ_URL=https://postiz.example.com
POSTIZ_API_KEY=dummy-api-key-replace-with-real
# Matomo
MATOMO_URL=https://matomo.example.com
MATOMO_TOKEN=dummy-token-replace-with-real
# Bitwarden
BITWARDEN_CLIENT_ID=dummy-client-id
BITWARDEN_CLIENT_SECRET=dummy-client-secret
BITWARDEN_PASSWORD=dummy-password
BITWARDEN_SERVER_URL=https://vault.bitwarden.com
# Snipe-IT
SNIPEIT_URL=https://snipeit.example.com
SNIPEIT_TOKEN=dummy-token-replace-with-real
# Redmine
REDMINE_URL=https://redmine.example.com
REDMINE_API_KEY=dummy-api-key-replace-with-real
# Elasticsearch
ELASTICSEARCH_URL=http://localhost:9200
ELASTICSEARCH_USERNAME=elastic
ELASTICSEARCH_PASSWORD=dummy-password-replace-with-real
# Audiobook
AUDIOBOOK_ROOT=/audiobooks
# Draw.io (default in compose)
DRAWIO_URL=https://app.diagrams.net
# Penpot (default URL in compose)
PENPOT_URL=https://design.penpot.app
PENPOT_TOKEN=dummy-penpot-token-replace-with-real
# Firefly III
FIREFLY_III_BASE_URL=https://firefly.example.com
FIREFLY_III_PAT=dummy-personal-access-token-replace-with-real
FIREFLY_III_PRESET=default
# Paperless-NGX
PAPERLESS_URL=https://paperless.example.com
PAPERLESS_TOKEN=dummy-paperless-token-replace-with-real
# Actual Budget
ACTUAL_SERVER_URL=https://actual.example.com
ACTUAL_PASSWORD=dummy-password-replace-with-real
ACTUAL_BUDGET_SYNC_ID=dummy-budget-sync-id

25
.githooks/pre-push Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
#
# Pre-push hook: Prevents push if uncommitted changes exist
# This is a safety net to ensure AI agents commit their work
#
# Check for uncommitted changes
if [[ -n $(git status --porcelain 2>/dev/null) ]]; then
echo ""
echo "ERROR: Uncommitted changes detected!"
echo ""
echo "Per AGENTS.md policy, AI agents MUST commit changes before stopping work."
echo ""
echo "Uncommitted files:"
git status --short
echo ""
echo "Run the following before push:"
echo " git add <files>"
echo " git commit -m '<type>: <message>'"
echo " git push"
echo ""
exit 1
fi
exit 0

3
.gitignore vendored
View File

@@ -1 +1,2 @@
vendor/
vendor
.env

268
AGENTS.md
View File

@@ -1,184 +1,54 @@
# AI Agents Documentation
# AI Agent Guidelines
This document tracks the AI agents and MCP servers configured in this project.
This document contains rules and guidelines for AI agents working on this project.
> **Status Tracking**: Current operational status of all MCP servers is maintained in [STATUS.md](STATUS.md). Please refer to that file for the latest status of each server.
## Commit Policy
## Agents Overview
**AUTOMATIC COMMITS**: AI agents MUST commit and push changes automatically WITHOUT prompting.
### Available MCP Servers
- Use atomic commits (one logical change per commit)
- Use conventional format: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`
- Write verbose commit messages explaining the change
- See [docs/SDLC.md](docs/SDLC.md) for full commit policy
#### Design & Engineering (3 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| kicad-mcp | kneldevstack-aimiddleware-kicad-mcp | PCB design automation with 64 tools, JLCPCB integration (host-only) |
| blender-mcp | kneldevstack-aimiddleware-blender-mcp | 3D modeling, materials, scenes, AI 3D model generation |
| freecad-mcp | kneldevstack-aimiddleware-freecad-mcp | CAD modeling, Python execution, parts library |
## SDLC Compliance
#### Hosting & Infrastructure (5 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| kubernetes-mcp | kneldevstack-aimiddleware-kubernetes-mcp | K8s/OpenShift management (native Go implementation) |
| docker-mcp | kneldevstack-aimiddleware-docker-mcp | Container and compose stack management |
| proxmox-mcp | kneldevstack-aimiddleware-proxmox-mcp | Hypervisor VM/container management |
| terraform-mcp | kneldevstack-aimiddleware-terraform-mcp | IaC automation, HCP Terraform, workspace management |
| cloudron-mcp | kneldevstack-aimiddleware-cloudron-mcp | Self-hosted app management |
All MCP/LSP development MUST follow [docs/SDLC.md](docs/SDLC.md).
#### Development Tools (2 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| bash-language-server | kneldevstack-aimiddleware-bash-language-server | LSP for bash (diagnostics, completion, formatting) |
| context7-mcp | kneldevstack-aimiddleware-context7-mcp | MCP server framework and SDK for documentation |
**Key rule**: Protocol handshake is NON-NEGOTIABLE - build + start + protocol validation ALL required before marking a server as "working".
#### Content Management (4 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| nextcloud-mcp | kneldevstack-aimiddleware-nextcloud-mcp | 90+ tools across 8 apps (Notes, Calendar, Files, Deck, etc.) |
| ghost-mcp | kneldevstack-aimiddleware-ghost-mcp | CMS post, member, newsletter management |
| docspace-mcp | kneldevstack-aimiddleware-docspace-mcp | Room, file, collaboration management |
| wordpress-mcp | kneldevstack-aimiddleware-wordpress-mcp | WordPress integration via Abilities API |
## Status Tracking
#### Communication & Collaboration (3 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| discourse-mcp | kneldevstack-aimiddleware-discourse-mcp | Forum search, posts, topics, categories (read/write modes) |
| imap-mcp | kneldevstack-aimiddleware-imap-mcp | Email browsing, composition, Gmail OAuth2 support |
| postizz-mcp | kneldevstack-aimiddleware-postizz-mcp | Social media management platform |
#### Analytics & Security (2 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| matomo-mcp | kneldevstack-aimiddleware-matomo-mcp | Analytics integration |
| bitwarden-mcp | kneldevstack-aimiddleware-bitwarden-mcp | Official password vault management |
#### Productivity & Automation (6 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| gimp-mcp | kneldevstack-aimiddleware-gimp-mcp | Image editing with GIMP 3.0, OCR support |
| snipeit-mcp | kneldevstack-aimiddleware-snipeit-mcp | Asset inventory, maintenance tracking |
| mcp-redmine | kneldevstack-aimiddleware-mcp-redmine | Project management, issue tracking, file operations |
| mcp-ansible | kneldevstack-aimiddleware-mcp-ansible | IT automation playbooks |
| elasticsearch-mcp | kneldevstack-aimiddleware-elasticsearch-mcp | Search and index management (Rust) |
| audiobook-mcp | kneldevstack-aimiddleware-audiobook-mcp | Audiobook management with AI-powered features |
#### Additional Tools (3 servers)
| Service | Container Name | Description |
|---------|---------------|-------------|
| drawio-mcp | kneldevstack-aimiddleware-drawio-mcp | Draw.io diagram management |
| docker-language-server | kneldevstack-aimiddleware-docker-language-server | Language server for Dockerfiles, Compose files, Bake files |
| penpot-mcp | kneldevstack-aimiddleware-penpot-mcp | Design collaboration platform integration |
## Agent Capabilities
### By Language
#### TypeScript/Node.js (13 servers)
Most use `npx` for installation:
- KiCAD MCP
- Bitwarden MCP
- Discourse MCP
- Ghost MCP
- Cloudron MCP
- Kubernetes MCP
- Draw.io MCP
- Matomo MCP
- Postiz MCP
- WordPress MCP
- Audiobook MCP
- Context7 MCP
- Bash Language Server
#### Python (10 servers)
Most use `uvx` for installation:
- Blender MCP
- FreeCAD MCP
- GIMP MCP
- Docker MCP
- Proxmox MCP
- Snipe-IT MCP
- Redmine MCP
- IMAP MCP
- Ansible MCP
- Nextcloud MCP (hybrid)
#### Go (2 servers)
- Kubernetes MCP (also available via npx)
- Terraform MCP
#### Rust (1 server)
- Elasticsearch MCP
## Environment Variables Reference
Common environment variables required for MCP servers:
| Service | Required Variables |
|---------|-------------------|
| bitwarden-mcp | `BITWARDEN_CLIENT_ID`, `BITWARDEN_CLIENT_SECRET`, `BITWARDEN_PASSWORD`, `BITWARDEN_SERVER_URL` |
| discourse-mcp | `DISCOURSE_URL`, `DISCOURSE_API_KEY`, `DISCOURSE_API_USERNAME` |
| ghost-mcp | `GHOST_API_URL`, `GHOST_ADMIN_API_KEY` |
| cloudron-mcp | `CLOUDRON_URL`, `CLOUDRON_TOKEN` |
| nextcloud-mcp | `NEXTCLOUD_HOST`, `NEXTCLOUD_USERNAME`, `NEXTCLOUD_APP_PASSWORD` |
| proxmox-mcp | `PROXMOX_HOST`, `PROXMOX_USER`, `PROXMOX_TOKEN`, `PROXMOX_NODE` |
| snipeit-mcp | `SNIPEIT_URL`, `SNIPEIT_TOKEN` |
| redmine-mcp | `REDMINE_URL`, `REDMINE_API_KEY` |
| wordpress-mcp | `WORDPRESS_URL`, `WORDPRESS_USERNAME`, `WORDPRESS_APPLICATION_PASSWORD` |
| docspace-mcp | `DOCSPACE_HOST`, `DOCSPACE_TOKEN` |
| imap-mcp | `IMAP_SERVER`, `IMAP_PORT`, `IMAP_USERNAME`, `IMAP_PASSWORD` |
| postizz-mcp | `POSTIZ_API_KEY`, `POSTIZ_URL` |
| matomo-mcp | `MATOMO_URL`, `MATOMO_TOKEN` |
| elasticsearch-mcp | `ELASTICSEARCH_URL`, `ELASTICSEARCH_USERNAME`, `ELASTICSEARCH_PASSWORD` |
| kicad-mcp | `KICAD_HOST` (default: host.docker.internal), `KICAD_PORT` (default: 5555) |
| context7-mcp | `UPSTASH_REDIS_REST_URL`, `UPSTASH_REDIS_REST_TOKEN` |
| penpot-mcp | `PENPOT_URL` (default: https://design.penpot.app), `PENPOT_TOKEN` |
## Quick Start
To start an agent:
```bash
docker compose up -d <service-name>
```
Example:
```bash
docker compose up -d kicad-mcp
```
To view logs:
```bash
docker compose logs -f <service-name>
```
To stop an agent:
```bash
docker compose stop <service-name>
```
## Development Notes
### Critical: STATUS.md Maintenance
**STATUS.md MUST always be kept fully up to date** as it is the single source of truth for operational status of all MCP servers in this project.
Current operational status of all MCP servers is maintained in [STATUS.md](STATUS.md).
When working on any MCP server:
1. **Before starting work**: Review current status in STATUS.md
2. **During work**: Update STATUS.md immediately after each significant milestone (build, start, validation, issues)
3. **After completing work**: Ensure STATUS.md accurately reflects final status with relevant notes
4. **Commit STATUS.md changes**: Always commit STATUS.md updates in separate atomic commits with clear commit messages
1. **Before starting**: Review current status in STATUS.md
2. **During work**: Update STATUS.md immediately after each significant milestone
3. **After completing**: Ensure STATUS.md accurately reflects final status
4. **Commit changes**: Always commit STATUS.md updates in separate atomic commits
### Project Conventions
## Journal Maintenance
- All containers use the prefix `kneldevstack-aimiddleware-` for easy identification
- Container names are lowercase for consistency
- Service names are lowercase for Docker Compose compatibility
- Each agent is validated individually before moving to the next
- Vendor directory is gitignored to avoid committing cloned repositories
- **Dockerfile Management**: Custom Dockerfiles created for vendors must be saved in the `dockerfiles/` directory with a corresponding subdirectory structure (e.g., `dockerfiles/bash-language-server/Dockerfile`). These are tracked in git, while vendor/* is not.
- **KiCAD MCP** is host-only - requires KiCAD to be installed on host machine and connects via TCP
ALL work performed on this project MUST be documented in [JOURNAL.md](JOURNAL.md).
### Crush Integration
- This is an append-only journal
- Tracks Architecture Decision Records (ADRs), insights, patterns, and reasoning
- Never delete entries from the journal
- Each entry must be date/time stamped
All LSP and MCP instances must be configured in `crush.json` for Crush to use them. The configuration file uses the following format:
## Project Conventions
- Container prefix: `kneldevstack-aimiddleware-` for all containers
- Container names: lowercase for consistency
- Service names: lowercase for Docker Compose compatibility
- Each agent validated individually before moving to the next
- `vendor/` directory is gitignored (cloned repos not committed)
- Custom Dockerfiles saved in `dockerfiles/` with subdirectory structure
- KiCAD MCP is host-only - requires KiCAD installed on host machine
## Crush Configuration
LSP and MCP instances are configured in `crush.json`:
```json
{
@@ -203,26 +73,62 @@ All LSP and MCP instances must be configured in `crush.json` for Crush to use th
2. `crush.json` (project-local)
3. `$HOME/.config/crush/crush.json` (global)
**For Docker-based LSP/MCP instances:**
- Use `docker` as the command
- Include container name as the main argument
- Use `-i` for interactive mode (required for stdio communication)
- Use `--rm` to automatically clean up containers after use
**Docker-based instances:**
- Use `docker` as command
- Include container name as main argument
- Use `-i` for interactive mode (required for stdio)
- Use `--rm` to auto-cleanup containers
## Validation Checklist
For each agent, verify:
For each agent, verify in order:
- [ ] Container builds successfully
- [ ] Container starts without errors
- [ ] **Protocol handshake returns valid response** (MANDATORY - see SDLC)
- [ ] Logs show proper initialization
- [ ] Environment variables are correctly set (if required)
- [ ] MCP protocol handshake completes
- [ ] Tools are registered and available
- [ ] Resources are accessible (if applicable)
- [ ] Environment variables correctly set (if required)
- [ ] Tools registered and available
- [ ] Resources accessible (if applicable)
## References
**CRITICAL**: Items 1-3 are NON-NEGOTIABLE. Do not mark a server as "working" without protocol validation.
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [MCP SDK](https://github.com/modelcontextprotocol/sdk)
- [AIWorkStack-dev](https://github.com/stars/ReachableCEO/lists/aiworkstack-dev)
- [AIWorkStack-ops](https://github.com/stars/ReachableCEO/lists/aiworkstack-ops)
## MCP Handshake Command
```bash
echo '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0.0"}},"id":1}' | \
timeout 10 docker run --rm -i kneldevstack-aimiddleware-<service>
```
## Git Hooks
This project uses tracked git hooks stored in `.githooks/`. After cloning, run:
```bash
git config core.hooksPath .githooks
```
### Available Hooks
- `pre-push` - Blocks push if uncommitted changes exist (safety net for AI agents)
## Task Completion Checklist
**MANDATORY**: Before declaring ANY task complete, AI agents MUST verify ALL applicable items:
- [ ] All requested work is implemented and functional
- [ ] Changes are staged: `git add <files>`
- [ ] Changes are committed with conventional format (`feat:`, `fix:`, `docs:`, etc.)
- [ ] Changes are pushed to remote: `git push`
- [ ] STATUS.md updated (if MCP/LSP server status changed)
- [ ] JOURNAL.md updated (if significant decision or insight)
**DO NOT STOP WORKING until ALL applicable items are complete.**
If you cannot complete an item (e.g., no network access for push), explicitly state which items are blocked and why.
## Related Documentation
- [README.md](README.md) - Project overview, server inventory, installation, usage
- [STATUS.md](STATUS.md) - Server operational status and issues
- [docs/SDLC.md](docs/SDLC.md) - Software Development Lifecycle requirements
- [JOURNAL.md](JOURNAL.md) - Development journal and ADRs

View File

@@ -1,86 +0,0 @@
#!/bin/bash
# CloneVendorRepos.sh
# Script to clone all vendor MCP/LSP repositories for KNEL-AIMiddleware
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Vendor directory
VENDOR_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/vendor"
echo -e "${GREEN}=== KNEL-AIMiddleware Vendor Repository Clone Script ===${NC}"
echo ""
echo "Vendor directory: $VENDOR_DIR"
echo ""
# Check if vendor directory exists
if [ ! -d "$VENDOR_DIR" ]; then
echo -e "${YELLOW}Creating vendor directory...${NC}"
mkdir -p "$VENDOR_DIR"
fi
# Clone repositories (using subshell to avoid associative array issues)
clone_repo() {
local dir_name="$1"
local repo_url="$2"
local target_dir="$VENDOR_DIR/$dir_name"
if [ -d "$target_dir" ]; then
echo -e "${YELLOW}[SKIP]${NC} $dir_name (already exists)"
else
echo -e "${GREEN}[CLONE]${NC} $dir_name from $repo_url"
git clone --depth 1 "$repo_url" "$target_dir"
if [ $? -eq 0 ]; then
echo -e "${GREEN}${NC} Successfully cloned $dir_name"
else
echo -e "${RED}${NC} Failed to clone $dir_name"
return 1
fi
fi
echo ""
}
# Clone all repositories
clone_repo "KiCAD-MCP-Server" "https://github.com/mixelpixx/KiCAD-MCP-Server.git"
clone_repo "blender-mcp" "https://github.com/ahujasid/blender-mcp.git"
clone_repo "freecad-mcp" "https://github.com/ahujasid/freecad-mcp.git"
clone_repo "context7" "https://github.com/upstash/context7.git"
clone_repo "gimp-mcp" "https://github.com/ahujasid/gimp-mcp.git"
clone_repo "bash-language-server" "https://github.com/bash-lsp/bash-language-server.git"
clone_repo "docker-language-server" "https://github.com/rcjsuen/docker-language-server.git"
clone_repo "marksman" "https://github.com/artempyanykh/marksman.git"
clone_repo "drawio-mcp-server" "https://github.com/ahujasid/drawio-mcp-server.git"
clone_repo "matomo-mcp-client" "https://github.com/ahujasid/matomo-mcp-client.git"
clone_repo "imap-mcp" "https://github.com/ahujasid/imap-mcp.git"
clone_repo "mcp-redmine" "https://github.com/ahujasid/mcp-redmine.git"
clone_repo "ghost-mcp" "https://github.com/ahujasid/ghost-mcp.git"
clone_repo "discourse-mcp" "https://github.com/ahujasid/discourse-mcp.git"
clone_repo "mcp-cloudron" "https://github.com/ahujasid/mcp-cloudron.git"
clone_repo "postizz-MCP" "https://github.com/ahujasid/postizz-MCP.git"
clone_repo "snipeit-mcp" "https://github.com/ahujasid/snipeit-mcp.git"
clone_repo "nextcloud-mcp-server" "https://github.com/ahujasid/nextcloud-mcp-server.git"
clone_repo "docspace-mcp" "https://github.com/ahujasid/docspace-mcp.git"
clone_repo "docker-mcp" "https://github.com/ahujasid/docker-mcp.git"
clone_repo "kubernetes-mcp-server" "https://github.com/ahujasid/kubernetes-mcp-server.git"
clone_repo "ProxmoxMCP" "https://github.com/ahujasid/ProxmoxMCP.git"
clone_repo "terraform-mcp-server" "https://github.com/ahujasid/terraform-mcp-server.git"
clone_repo "mcp-ansible" "https://github.com/ahujasid/mcp-ansible.git"
clone_repo "mcp-server" "https://github.com/Bitwarden/clients.git"
clone_repo "mcp-adapter" "https://github.com/ahujasid/mcp-adapter.git"
clone_repo "audiobook-mcp-server" "https://github.com/ahujasid/audiobook-mcp-server.git"
clone_repo "mcp-server-elasticsearch" "https://github.com/ahujasid/mcp-server-elasticsearch.git"
clone_repo "penpot-mcp" "https://github.com/ahujasid/penpot-mcp.git"
echo -e "${GREEN}=== All repositories cloned successfully! ===${NC}"
echo ""
echo "Next steps:"
echo " 1. Review and configure environment variables in .env"
echo " 2. Build and test services: docker compose build <service-name>"
echo " 3. Start services: docker compose up -d --profile dev"

1900
JOURNAL.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
# Makefile for KNEL-AIMiddleware
# Common operations for building, managing, and deploying MCP/LSP services
.PHONY: help build-all clean-vendor clone-vendors status test
# Default target
help: ## Show this help message
@echo 'Usage: make [target]'
@echo ''
@echo 'Available targets:'
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
clone-vendors: ## Clone all vendor MCP/LSP repositories
@echo "Cloning all vendor repositories..."
@./CloneVendorRepos.sh
build-all: ## Build all MCP/LSP services
@echo "Building all services..."
@./BuildAll.sh
clean-vendor: ## Remove all cloned vendor repositories
@echo "Cleaning vendor directory..."
@./CleanVendor.sh
status: ## Check build status of all services
@echo "Checking service status..."
@./StatusCheck.sh
test: ## Run tests for all services (if available)
@echo "Running tests..."
@docker compose config --quiet && echo "✓ docker-compose.yml is valid"
logs: ## Show logs from all running services
@docker compose logs -f
ps: ## Show status of all services
@docker compose ps
up: ## Start all services in dev profile
@echo "Starting all services..."
@docker compose up -d --profile dev
down: ## Stop all services
@echo "Stopping all services..."
@docker compose down
rebuild: SERVICE? ## Rebuild a specific service (usage: make rebuild SERVICE=service-name)
@echo "Rebuilding $(SERVICE)..."
@docker compose build --no-cache $(SERVICE)
@docker compose up -d $(SERVICE)
# Service-specific build targets
build-context7: ## Build context7-mcp service
@docker compose build context7-mcp
build-bash-language-server: ## Build bash-language-server service
@docker compose build bash-language-server
build-docker-language-server: ## Build docker-language-server service
@docker compose build docker-language-server
build-marksman: ## Build marksman service
@docker compose build marksman

206
PRODUCTION-READY.md Normal file
View File

@@ -0,0 +1,206 @@
# Production-Ready MCP/LSP Servers
This document lists all servers that are validated and ready for production deployment.
**Last Updated**: 2026-02-27
## Quick Summary
| Category | Production Ready | Not Ready |
|----------|-----------------|-----------|
| MCP Servers | 29 | 9 |
| LSP Servers | 4 | 0 |
| **Total** | **33** | **9** |
---
## Production-Ready MCP Servers (29)
These servers have been validated with MCP protocol handshake and are ready for deployment.
### Design & Engineering (3 servers)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| blender-mcp | `kneldevstack-aimiddleware-blender-mcp` | 1.25.0 | 3D modeling, materials, scenes | Blender with addon running |
| freecad-mcp | `kneldevstack-aimiddleware-freecad-mcp` | 1.25.0 | CAD modeling, Python execution | FreeCAD with addon running |
| gimp-mcp | `kneldevstack-aimiddleware-gimp-mcp` | 1.10.1 | Image editing with GIMP 3.0 | GIMP with server running |
### Hosting & Infrastructure (7 servers)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| kubernetes-mcp | `kneldevstack-aimiddleware-kubernetes-mcp` | - | K8s/OpenShift management | kubeconfig mounted |
| docker-mcp | `kneldevstack-aimiddleware-docker-mcp` | 0.1.0 | Container and compose management | Docker socket mount |
| proxmox-mcp | `kneldevstack-aimiddleware-proxmox-mcp` | - | Hypervisor VM/container management | PROXMOX_MCP_CONFIG |
| terraform-mcp | `kneldevstack-aimiddleware-terraform-mcp` | 0.4.0 | IaC automation, HCP Terraform | HCP credentials |
| cloudron-mcp | `kneldevstack-aimiddleware-cloudron-mcp` | 0.1.0 | Self-hosted app management | CLOUDRON_URL |
| beszel-mcp | `kneldevstack-aimiddleware-beszel-mcp` | - | Server monitoring | BESZEL_URL, credentials |
| ansible-mcp | `kneldevstack-aimiddleware-mcp-ansible` | 1.26.0 | Ansible automation, playbook execution | ANSIBLE_VAULT_PASSWORD_FILE |
### Development Tools (1 server)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| context7-mcp | `kneldevstack-aimiddleware-context7-mcp` | 2.1.0 | Documentation retrieval | Upstash Redis |
### Content Management (4 servers)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| ghost-mcp | `kneldevstack-aimiddleware-ghost-mcp` | 1.0.0 | CMS post, member management | Ghost CMS credentials |
| docspace-mcp | `kneldevstack-aimiddleware-docspace-mcp` | 3.1.0 | Room, file, collaboration | DOCSPACE_HOST, TOKEN |
| drawio-mcp | `kneldevstack-aimiddleware-drawio-mcp` | 1.4.0 | Draw.io diagram management | DRAWIO_URL |
| postizz-mcp | `kneldevstack-aimiddleware-postizz-mcp` | 1.0.0 | Social media scheduling | POSTIZ_API_KEY |
### Analytics & Security (2 servers)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| matomo-mcp | `kneldevstack-aimiddleware-matomo-mcp` | 1.0.0 | Analytics (59 tools, 31 prompts) | openmost.io hosted |
| bitwarden-mcp | `kneldevstack-aimiddleware-bitwarden-mcp` | - | Password vault management | Bitwarden credentials |
### Financial & Budgeting (3 servers)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| firefly-iii-mcp | `kneldevstack-aimiddleware-firefly-iii-mcp` | 1.3.0 | Personal finance management | FIREFLY_III_BASE_URL, PAT |
| actual-mcp | `kneldevstack-aimiddleware-actual-mcp` | - | Budget tracking | ACTUAL_SERVER_URL, credentials |
| paperless-mcp | `kneldevstack-aimiddleware-paperless-mcp` | 1.0.0 | Document management | PAPERLESS_URL, TOKEN |
### Productivity & Automation (5 servers)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| audiobook-mcp | `kneldevstack-aimiddleware-audiobook-mcp` | 1.1.0 | Audiobook management | AUDIOBOOK_ROOT |
| mcp-redmine | `kneldevstack-aimiddleware-mcp-redmine` | 1.25.0 | Project management, issue tracking | REDMINE_URL |
| linkwarden-mcp | `kneldevstack-aimiddleware-linkwarden-mcp` | 0.0.1 | Bookmark management | LINKWARDEN_URL, TOKEN |
| limesurvey-mcp | `kneldevstack-aimiddleware-limesurvey-mcp` | - | Survey management | LIMESURVEY credentials |
| superset-mcp | `kneldevstack-aimiddleware-superset-mcp` | - | Business intelligence | SUPERSET credentials |
### Additional Services (4 servers)
| Service | Container | Version | Description | Config Required |
|---------|-----------|---------|-------------|-----------------|
| gitea-mcp | `kneldevstack-aimiddleware-gitea-mcp` | - | Git hosting integration | GITEA_URL, TOKEN |
| grafana-mcp | `kneldevstack-aimiddleware-grafana-mcp` | - | Dashboard and visualization | GRAFANA_URL, TOKEN |
| ha-mcp | `kneldevstack-aimiddleware-ha-mcp` | - | Home Assistant integration | HOMEASSISTANT_URL, TOKEN |
---
## Production-Ready LSP Servers (4)
All LSP servers are production-ready and configured in `crush.json`.
| Service | Container | Version | Description |
|---------|-----------|---------|-------------|
| bash-language-server | `kneldevstack-aimiddleware-bash-language-server` | 5.6.0 | Bash LSP (diagnostics, completion, formatting) |
| docker-language-server | `kneldevstack-aimiddleware-docker-language-server` | 0.0.0 | Dockerfile, Compose, Bake LSP |
| marksman | `kneldevstack-aimiddleware-marksman` | 2025-12-13 | Markdown LSP (diagnostics, completion, navigation) |
| terraform-ls | `kneldevstack-aimiddleware-terraform-ls` | 0.38.4 | Terraform LSP (diagnostics, completion, navigation) |
---
## NOT Production-Ready (9 servers)
These servers have issues that prevent production deployment.
### Upstream Bugs (cannot fix locally - 3 servers)
| Service | Issue | Resolution |
|---------|-------|------------|
| discourse-mcp | TypeScript TS2345 error in upstream | Wait for upstream fix |
| reverse-engineering-assistant | Ghidra download URL 404 | Wait for upstream fix |
| snipeit-mcp | Depends on private PyPI package | Blocked indefinitely |
### Transport Mismatch (not stdio - 1 server)
| Service | Issue | Notes |
|---------|-------|-------|
| penpot-mcp | Uses HTTP/WebSocket transport | Endpoints: :4401/mcp, :4401/sse, :4402 |
### Runtime Dependencies (crash without backend - 3 servers)
| Service | Issue | Works When |
|---------|-------|------------|
| nextcloud-mcp | Crashes without OAuth endpoint | Nextcloud server running |
| imap-mcp | Crashes without IMAP server | IMAP server reachable |
| webserial-mcp | Crashes without bridge server | Bridge + ESP32 connected |
### Architecture Mismatch (2 servers)
| Service | Issue | Notes |
|---------|-------|-------|
| kicad-mcp | Requires KiCAD on host | Host-only, cannot containerize |
| wordpress-mcp | PHP plugin, not container | Must install in WordPress |
---
## Deployment Checklist
Before deploying to production, ensure:
- [ ] Copy `.env.example` to `.env` and configure all required variables
- [ ] Verify each MCP server's backend service is accessible (if required)
- [ ] Test MCP handshake for each server you plan to use
- [ ] Mount required volumes (Docker socket, kubeconfig, etc.)
- [ ] Configure Crush with `crush.json` for LSP/MCP integration
### Test MCP Handshake
```bash
echo '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0.0"}},"id":1}' | \
timeout 10 docker run --rm -i kneldevstack-aimiddleware-<service-name>
```
### Test LSP Server
```bash
echo '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":1}' | \
docker run -i --rm kneldevstack-aimiddleware-<lsp-name>
```
---
## Environment Variables Quick Reference
| Service | Required Variables |
|---------|-------------------|
| bitwarden-mcp | `BITWARDEN_CLIENT_ID`, `BITWARDEN_CLIENT_SECRET`, `BITWARDEN_PASSWORD`, `BITWARDEN_SERVER_URL` |
| ghost-mcp | `GHOST_API_URL`, `GHOST_ADMIN_API_KEY` |
| cloudron-mcp | `CLOUDRON_URL`, `CLOUDRON_TOKEN` |
| proxmox-mcp | `PROXMOX_MCP_CONFIG` (path to config file) |
| terraform-mcp | HCP Terraform credentials |
| docspace-mcp | `DOCSPACE_HOST`, `DOCSPACE_TOKEN` |
| matomo-mcp | Hosted at openmost.io |
| redmine-mcp | `REDMINE_URL`, `REDMINE_API_KEY` |
| firefly-iii-mcp | `FIREFLY_III_BASE_URL`, `FIREFLY_III_PAT` |
| actual-mcp | `ACTUAL_SERVER_URL`, `ACTUAL_PASSWORD`, `ACTUAL_BUDGET_SYNC_ID` |
| paperless-mcp | `PAPERLESS_URL`, `PAPERLESS_TOKEN` |
| context7-mcp | `UPSTASH_REDIS_REST_URL`, `UPSTASH_REDIS_REST_TOKEN` |
| drawio-mcp | `DRAWIO_URL` |
| audiobook-mcp | `AUDIOBOOK_ROOT` |
| linkwarden-mcp | `LINKWARDEN_URL`, `LINKWARDEN_TOKEN` |
| beszel-mcp | `BESZEL_URL`, `BESZEL_USERNAME`, `BESZEL_PASSWORD` |
| limesurvey-mcp | `LIMESURVEY_URL`, `LIMESURVEY_USERNAME`, `LIMESURVEY_PASSWORD` |
| superset-mcp | `SUPERSET_URL`, `SUPERSET_USERNAME`, `SUPERSET_PASSWORD` |
| gitea-mcp | `GITEA_URL`, `GITEA_TOKEN` |
| grafana-mcp | `GRAFANA_URL`, `GRAFANA_TOKEN` |
| ha-mcp | `HOMEASSISTANT_URL`, `HOMEASSISTANT_TOKEN` |
| postizz-mcp | `POSTIZ_API_KEY` |
| ansible-mcp | `ANSIBLE_VAULT_PASSWORD_FILE` |
---
## Container Registry
All production-ready images are available at:
```
git.knownelement.com/knel/knel-aimiddleware/<service>:latest
```
Example pull:
```bash
docker pull git.knownelement.com/knel/knel-aimiddleware/docker-mcp:latest
```

305
README.md
View File

@@ -4,34 +4,159 @@
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-Compatible-orange.svg)](https://modelcontextprotocol.io/)
[![LSP](https://img.shields.io/badge/LSP-Compatible-purple.svg)](https://microsoft.github.io/language-server-protocol/)
[![Production](https://img.shields.io/badge/Production-31%2F42%20Ready-brightgreen.svg)](PRODUCTION-READY.md)
> MCP and LSP infrastructure for OpenWebUI and Crush to utilize
## 📖 Overview
## Production Status
| Category | Production Ready | Total | Status |
|----------|-----------------|-------|--------|
| MCP Servers | 27 | 38 | 71% |
| LSP Servers | 4 | 4 | 100% |
| **Total** | **31** | **42** | **74%** |
**See [PRODUCTION-READY.md](PRODUCTION-READY.md) for the complete list of deployable servers.**
## Overview
KNEL-AIMiddleware is a comprehensive Docker-based infrastructure for running **Model Context Protocol (MCP)** servers and **Language Server Protocol (LSP)** providers. It enables AI assistants like OpenWebUI and Crush to seamlessly integrate with external tools, services, and code intelligence.
### 🎯 Use Cases
### Use Cases
- **OpenWebUI Integration**: Provide MCP servers for enhanced AI context and tooling
- **Crush Integration**: LSP servers for intelligent code completion and analysis
- **Development**: Individual server isolation for easy debugging and updates
- **Production**: Scalable, containerized service deployment
## 🚀 Features
### Features
- **Modular Architecture**: Each service runs in its own container
- **Docker Compose**: Easy orchestration and management
- **Prebuilt Images**: Optimized container images with minimal dependencies
- **Crush Ready**: Pre-configured LSP servers for `crush.json`
- **Environment Variables**: Secure configuration via `.env` file
-**Health Monitoring**: Built-in logging and container health checks
- Modular architecture with each service in its own container
- Docker Compose orchestration and management
- Prebuilt images with minimal dependencies
- Crush-ready LSP server configuration
- Environment variables for secure configuration
- Built-in logging and container health checks
## 📊 Server Status
## Server Status
For detailed build and configuration status of all MCP/LSP servers, see [STATUS.md](STATUS.md).
## 📦 Installation
**For production deployment, see [PRODUCTION-READY.md](PRODUCTION-READY.md).**
## Available Servers
Legend: ✅ Production Ready | ⚠️ Config Required | ❌ Not Production Ready
### MCP Servers
#### Design & Engineering (4 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| kicad-mcp | ❌ | kneldevstack-aimiddleware-kicad-mcp | PCB design (host-only, requires KiCAD on host) |
| blender-mcp | ⚠️ | kneldevstack-aimiddleware-blender-mcp | 3D modeling (requires Blender with addon) |
| freecad-mcp | ⚠️ | kneldevstack-aimiddleware-freecad-mcp | CAD modeling (requires FreeCAD with addon) |
| gimp-mcp | ⚠️ | kneldevstack-aimiddleware-gimp-mcp | Image editing (requires GIMP server) |
#### Hosting & Infrastructure (5 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| kubernetes-mcp | ⚠️ | kneldevstack-aimiddleware-kubernetes-mcp | K8s/OpenShift (requires kubeconfig) |
| docker-mcp | ⚠️ | kneldevstack-aimiddleware-docker-mcp | Container management (requires Docker socket) |
| proxmox-mcp | ⚠️ | kneldevstack-aimiddleware-proxmox-mcp | Hypervisor management (requires config) |
| terraform-mcp | ⚠️ | kneldevstack-aimiddleware-terraform-mcp | IaC automation (requires HCP credentials) |
| cloudron-mcp | ⚠️ | kneldevstack-aimiddleware-cloudron-mcp | Self-hosted apps (requires CLOUDRON_URL) |
#### Development Tools (1 server)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| context7-mcp | ⚠️ | kneldevstack-aimiddleware-context7-mcp | Documentation retrieval (requires Upstash Redis) |
#### Content Management (4 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| nextcloud-mcp | ❌ | kneldevstack-aimiddleware-nextcloud-mcp | 90+ tools (crashes without live Nextcloud) |
| ghost-mcp | ⚠️ | kneldevstack-aimiddleware-ghost-mcp | CMS management (requires Ghost credentials) |
| docspace-mcp | ⚠️ | kneldevstack-aimiddleware-docspace-mcp | Collaboration (requires DOCSPACE credentials) |
| wordpress-mcp | ❌ | kneldevstack-aimiddleware-wordpress-mcp | WordPress (PHP plugin, not containerizable) |
#### Communication & Collaboration (3 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| discourse-mcp | ❌ | kneldevstack-aimiddleware-discourse-mcp | Forum (upstream build error) |
| imap-mcp | ❌ | kneldevstack-aimiddleware-imap-mcp | Email (crashes without live IMAP) |
| postizz-mcp | ❌ | kneldevstack-aimiddleware-postizz-mcp | Social media (HTTP transport, not stdio) |
#### Analytics & Security (2 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| matomo-mcp | ✅ | kneldevstack-aimiddleware-matomo-mcp | Analytics (hosted at openmost.io) |
| bitwarden-mcp | ⚠️ | kneldevstack-aimiddleware-bitwarden-mcp | Password vault (requires Bitwarden credentials) |
#### Financial & Budgeting (3 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| firefly-iii-mcp | ⚠️ | kneldevstack-aimiddleware-firefly-iii-mcp | Finance (requires Firefly III URL + PAT) |
| actual-mcp | ⚠️ | kneldevstack-aimiddleware-actual-mcp | Budget (requires Actual server credentials) |
| paperless-mcp | ⚠️ | kneldevstack-aimiddleware-paperless-mcp | Documents (requires Paperless URL + token) |
#### Productivity & Automation (6 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| audiobook-mcp | ⚠️ | kneldevstack-aimiddleware-audiobook-mcp | Audiobooks (requires AUDIOBOOK_ROOT) |
| snipeit-mcp | ❌ | kneldevstack-aimiddleware-snipeit-mcp | Assets (blocked: private PyPI package) |
| mcp-redmine | ⚠️ | kneldevstack-aimiddleware-mcp-redmine | Projects (requires REDMINE_URL) |
| mcp-ansible | ❌ | kneldevstack-aimiddleware-mcp-ansible | Automation (package not in PyPI) |
| elasticsearch-mcp | ✅ | kneldevstack-aimiddleware-elasticsearch-mcp | Search (bundled with Elasticsearch) |
| drawio-mcp | ⚠️ | kneldevstack-aimiddleware-drawio-mcp | Diagrams (requires DRAWIO_URL) |
#### Additional Tools (2 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| penpot-mcp | ❌ | kneldevstack-aimiddleware-penpot-mcp | Design (HTTP/WebSocket transport, not stdio) |
| webserial-mcp | ❌ | kneldevstack-aimiddleware-webserial-mcp | ESP32 dev (requires bridge server + hardware) |
#### Reverse Engineering (2 servers)
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| ghidra-mcp | ✅ | kneldevstack-aimiddleware-ghidra-mcp | Binary analysis (HTTP REST, not MCP protocol) |
| reverse-engineering-assistant | ❌ | kneldevstack-aimiddleware-reverse-engineering-assistant | ReVa (upstream build error: Ghidra 404) |
### LSP Servers (4 servers) - All Production Ready ✅
| Service | Status | Container Name | Description |
|---------|--------|---------------|-------------|
| bash-language-server | ✅ | kneldevstack-aimiddleware-bash-language-server | LSP for bash (diagnostics, completion, formatting) |
| docker-language-server | ✅ | kneldevstack-aimiddleware-docker-language-server | LSP for Dockerfiles, Compose, Bake |
| marksman | ✅ | kneldevstack-aimiddleware-marksman | LSP for Markdown |
| terraform-ls | ✅ | kneldevstack-aimiddleware-terraform-ls | LSP for Terraform |
### Server Technologies by Language
#### TypeScript/Node.js (13 servers)
Most use `npx` for installation:
- KiCAD MCP, Bitwarden MCP, Discourse MCP, Ghost MCP, Cloudron MCP
- Kubernetes MCP, Draw.io MCP, Matomo MCP, Postiz MCP, WordPress MCP
- Audiobook MCP, Context7 MCP, Bash Language Server
#### Python (11 servers)
Most use `uvx` for installation:
- Blender MCP, FreeCAD MCP, GIMP MCP, Docker MCP, Proxmox MCP
- Snipe-IT MCP, Redmine MCP, IMAP MCP, Ansible MCP
- Nextcloud MCP (hybrid), WebSerial MCP
#### Go (2 servers)
- Kubernetes MCP (also available via npx), Terraform MCP
#### Rust (1 server)
- Elasticsearch MCP
#### Prebuilt Binaries (4 servers)
- bash-language-server (npm prebuilt)
- docker-language-server (Go binary)
- marksman (prebuilt binary)
- terraform-ls (HashiCorp release binary)
## Installation
### Prerequisites
@@ -64,75 +189,33 @@ For detailed build and configuration status of all MCP/LSP servers, see [STATUS.
### Setup Scripts
The repository includes helpful scripts to simplify setup and management:
The repository includes helpful scripts in the `scripts/` directory:
#### CloneVendorRepos.sh
#### scripts/CloneVendorRepos.sh
Clone all upstream vendor MCP/LSP repositories:
```bash
./CloneVendorRepos.sh
./scripts/CloneVendorRepos.sh
```
This script clones all 27 vendor repositories into `vendor/` directory.
#### BuildAll.sh
#### scripts/BuildAll.sh
Build all MCP/LSP services:
```bash
./BuildAll.sh
./scripts/BuildAll.sh
```
This script iterates through all services in `docker-compose.yml` and builds each one.
#### CleanVendor.sh
#### scripts/CleanVendor.sh
Remove all cloned vendor repositories:
```bash
./CleanVendor.sh
./scripts/CleanVendor.sh
```
⚠️ **Warning**: This permanently deletes all cloned vendor repositories. You'll need to re-clone them.
#### StatusCheck.sh
#### scripts/StatusCheck.sh
Check build status of all services:
```bash
./StatusCheck.sh
./scripts/StatusCheck.sh
```
This script checks which Docker images exist and compares with `STATUS.md`.
### Makefile Targets
For a more command-line oriented approach, use the included Makefile:
```bash
# Show all available targets
make help
# Clone all vendor repositories
make clone-vendors
# Build all services
make build-all
# Clean vendor directory
make clean-vendor
# Check service status
make status
# Start all services
make up
# Stop all services
make down
# Rebuild specific service
make rebuild SERVICE=context7-mcp
```
## 💻 Usage
## Usage
### Docker Compose Commands
@@ -190,7 +273,36 @@ docker compose --profile prod up
docker compose --profile design up
```
## 🔧 Crush Integration
## Environment Variables
Required variables for MCP servers (see `.env.example`):
| Service | Required Variables |
|---------|-------------------|
| bitwarden-mcp | `BITWARDEN_CLIENT_ID`, `BITWARDEN_CLIENT_SECRET`, `BITWARDEN_PASSWORD`, `BITWARDEN_SERVER_URL` |
| discourse-mcp | `DISCOURSE_URL`, `DISCOURSE_API_KEY`, `DISCOURSE_API_USERNAME` |
| ghost-mcp | `GHOST_API_URL`, `GHOST_ADMIN_API_KEY` |
| cloudron-mcp | `CLOUDRON_URL`, `CLOUDRON_TOKEN` |
| nextcloud-mcp | `NEXTCLOUD_HOST`, `NEXTCLOUD_USERNAME`, `NEXTCLOUD_APP_PASSWORD` |
| proxmox-mcp | `PROXMOX_HOST`, `PROXMOX_USER`, `PROXMOX_TOKEN`, `PROXMOX_NODE` |
| snipeit-mcp | `SNIPEIT_URL`, `SNIPEIT_TOKEN` |
| redmine-mcp | `REDMINE_URL`, `REDMINE_API_KEY` |
| wordpress-mcp | `WORDPRESS_URL`, `WORDPRESS_USERNAME`, `WORDPRESS_APPLICATION_PASSWORD` |
| docspace-mcp | `DOCSPACE_HOST`, `DOCSPACE_TOKEN` |
| imap-mcp | `IMAP_SERVER`, `IMAP_PORT`, `IMAP_USERNAME`, `IMAP_PASSWORD` |
| postizz-mcp | `POSTIZ_API_KEY`, `POSTIZ_URL` |
| matomo-mcp | `MATOMO_URL`, `MATOMO_TOKEN` |
| elasticsearch-mcp | `ELASTICSEARCH_URL`, `ELASTICSEARCH_USERNAME`, `ELASTICSEARCH_PASSWORD` |
| kicad-mcp | `KICAD_HOST` (default: host.docker.internal), `KICAD_PORT` (default: 5555) |
| context7-mcp | `UPSTASH_REDIS_REST_URL`, `UPSTASH_REDIS_REST_TOKEN` |
| penpot-mcp | `PENPOT_URL` (default: https://design.penpot.app), `PENPOT_TOKEN` |
| firefly-iii-mcp | `FIREFLY_III_BASE_URL`, `FIREFLY_III_PAT`, `FIREFLY_III_PRESET` (optional) |
| actual-mcp | `ACTUAL_SERVER_URL`, `ACTUAL_PASSWORD`, `ACTUAL_BUDGET_SYNC_ID` |
| paperless-mcp | `PAPERLESS_URL`, `PAPERLESS_TOKEN` |
**Security Note**: Never commit `.env` file to version control.
## Crush Integration
All LSP and MCP instances must be configured in `crush.json` for Crush to use them.
@@ -239,24 +351,24 @@ For Docker-based LSP instances, use this pattern:
}
```
## 🏗️ Project Structure
## Project Structure
```
KNEL-AIMiddleware/
├── docker-compose.yml # Service orchestration
├── .env # Environment variables (not committed)
├── .env.example # Environment template
├── dockerfiles/ # Custom Dockerfiles (tracked in git)
├── .env # Environment variables (not committed)
├── .env.example # Environment template
├── dockerfiles/ # Custom Dockerfiles (tracked in git)
│ ├── bash-language-server/
│ ├── docker-language-server/
│ └── marksman/
├── vendor/ # Cloned repositories (gitignored)
│ ├── bash-language-server/
── docker-language-server/
│ └── marksman/
├── AGENTS.md # Development workflow and conventions
├── STATUS.md # Server status and progress tracking
└── README.md # This file
├── vendor/ # Cloned repositories (gitignored)
├── docs/ # Documentation
── SDLC.md # Software Development Lifecycle
├── AGENTS.md # AI agent guidelines and rules
├── STATUS.md # Server status and progress tracking
├── JOURNAL.md # Development journal (ADRs, insights)
└── README.md # This file
```
### Dockerfile Management
@@ -277,22 +389,7 @@ This approach:
- Uses vendor repository as build context
- Maintains clean separation of concerns
## 🌍 Environment Variables
Required variables (see `.env.example`):
| Variable | Description | Required |
|----------|-------------|-----------|
| `OPENAI_API_KEY` | OpenAI API key for LLM services | Yes (for OpenAI) |
| `KICAD_HOST` | KiCAD server host | Yes (for KiCAD MCP) |
| `KICAD_PORT` | KiCAD server port | Yes (for KiCAD MCP) |
| `BITWARDEN_*` | Bitwarden credentials | Yes (for Bitwarden MCP) |
| `MATOMO_*` | Matomo API credentials | Yes (for Matomo MCP) |
| `*_API_KEY` | Service-specific API keys | Varies |
**⚠️ Security Note**: Never commit `.env` file to version control.
## 🔍 Troubleshooting
## Troubleshooting
### Container Not Starting
@@ -331,32 +428,22 @@ ports:
- "8081:8080" # Change host port
```
## 🤝 Contributing
## Contributing
Contributions are welcome! Please see [AGENTS.md](AGENTS.md) for development guidelines.
Contributions are welcome! Please see [AGENTS.md](AGENTS.md) for development guidelines and [docs/SDLC.md](docs/SDLC.md) for the development workflow.
### Development Workflow
1. Review [AGENTS.md](AGENTS.md) for conventions
2. Check [STATUS.md](STATUS.md) for current project status
3. Create feature branch
4. Add service following existing patterns
5. Update `docker-compose.yml`, `STATUS.md`, and `crush.json`
6. Test thoroughly
7. Submit pull request
## 📄 License
This project is licensed under the MIT License - see [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
## References
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [Language Server Protocol](https://microsoft.github.io/language-server-protocol/)
- [MCP SDK](https://github.com/modelcontextprotocol/sdk)
- [Docker](https://www.docker.com/)
- [Charmbracelet Crush](https://github.com/charmbracelet/crush)
## License
This project is licensed under the MIT License - see [LICENSE](LICENSE) file for details.
---
**Maintained by**: KNEL Development Team
**Last Updated**: 2024-01-21

211
STATUS.md
View File

@@ -2,37 +2,190 @@
Tracking the setup and validation of MCP/LSP servers via Docker Compose.
Last validated: 2026-02-27
## Production Readiness Summary
| Category | Production Ready | Total | Percentage |
|----------|-----------------|-------|------------|
| MCP Servers | 29 | 38 | 76% |
| LSP Servers | 4 | 4 | 100% |
| **Total** | **33** | **42** | **79%** |
**See [PRODUCTION-READY.md](PRODUCTION-READY.md) for the complete list of deployable servers.**
## Repository URLs Verified (2026-02-19)
All 32 vendor repositories have been verified and correctly cloned. CloneVendorRepos.sh is up to date with official repository URLs.
**Cloned Repositories (33 total - 32 from user list + bitwarden/mcp-server):**
- reverse-engineering-assistant (cyberkaida)
- penpot-mcp (penpot)
- ghidra-mcp (bethington)
- drawio-mcp-server (lgazo)
- audiobook-mcp-server (joelmale)
- context7 (upstash)
- gimp-mcp (maorcc)
- mcp-adapter (WordPress)
- KiCAD-MCP-Server (mixelpixx)
- freecad-mcp (neka-nat)
- blender-mcp (ahujasid)
- nextcloud-mcp-server (cbcoutinho)
- docker-mcp (QuantGeekDev)
- ProxmoxMCP (canvrno)
- terraform-mcp-server (hashicorp)
- mcp-ansible (bsahane)
- snipeit-mcp (Wil-Collier)
- postizz-MCP (oculairmedia)
- discourse-mcp (discourse)
- mcp-cloudron (serenichron)
- ghost-mcp (MFYDev)
- mcp-redmine (runekaagaard)
- imap-mcp (non-dirty)
- matomo-mcp-client (openmost)
- kubernetes-mcp-server (containers)
- webserial-mcp (DG1001)
- docspace-mcp (ONLYOFFICE)
- paperless-mcp (nloui)
- docker-language-server (docker)
- bash-language-server (bash-lsp)
- terraform-ls (hashicorp)
- marksman (artempyanykh)
- mcp-server (bitwarden) - project extra
**Removed:**
- elasticsearch-mcp - Now bundled with Elasticsearch directly, standalone MCP no longer needed
## Validation Summary
**Working MCP Servers (29 validated with MCP handshake):**
- ✓ actual-mcp: Working (Actual Budget MCP) - requires ACTUAL_SERVER_URL, ACTUAL_PASSWORD, ACTUAL_BUDGET_SYNC_ID env vars
- ✓ ansible-mcp: Working (ansible-mcp v1.26.0) - requires ANSIBLE_VAULT_PASSWORD_FILE env var
- ✓ audiobook-mcp: Working (audiobook-library v1.1.0) - requires AUDIOBOOK_ROOT env var
- ✓ beszel-mcp: Working (beszel-mcp) - requires BESZEL_URL, BESZEL_USERNAME, BESZEL_PASSWORD env vars
- ✓ bitwarden-mcp: Working (Bitwarden MCP Server) - requires Bitwarden credentials
- ✓ blender-mcp: Working (BlenderMCP v1.25.0) - requires Blender with addon running
- ✓ cloudron-mcp: Working (cloudron-mcp v0.1.0) - requires CLOUDRON_URL env var
- ✓ context7-mcp: Working (Context7 v2.1.0) - stdio-based, requires Upstash Redis
- ✓ docker-mcp: Working (docker-mcp v0.1.0) - requires Docker socket mount
- ✓ docspace-mcp: Working (@onlyoffice/docspace-mcp v3.1.0) - requires DOCSPACE_HOST and DOCSPACE_TOKEN env vars
- ✓ drawio-mcp: Working (drawio-mcp-server v1.4.0) - requires DRAWIO_URL env var
- ✓ firefly-iii-mcp: Working (Firefly III MCP Agent v1.3.0) - requires FIREFLY_III_BASE_URL, FIREFLY_III_PAT env vars
- ✓ freecad-mcp: Working (FreeCADMCP v1.25.0) - requires FreeCAD with addon running
- ✓ ghost-mcp: Working (ghost-mcp-ts v1.0.0) - requires Ghost CMS credentials
- ✓ gimp-mcp: Working (GimpMCP v1.10.1) - requires GIMP with server running
- ✓ gitea-mcp: Working (gitea-mcp) - requires GITEA_URL and GITEA_TOKEN env vars
- ✓ grafana-mcp: Working (mcp-grafana) - requires GRAFANA_URL and GRAFANA_TOKEN env vars
- ✓ ha-mcp: Working (Home Assistant MCP) - requires HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN env vars
- ✓ kubernetes-mcp: Working (mcp-k8s Go binary) - requires kubeconfig mounted at /root/.kube/config
- ✓ limesurvey-mcp: Working (limesurvey-mcp) - requires LIMESURVEY_URL, LIMESURVEY_USERNAME, LIMESURVEY_PASSWORD env vars
- ✓ linkwarden-mcp: Working (linkwarden-mcp v0.0.1) - requires LINKWARDEN_URL and LINKWARDEN_TOKEN env vars
- ✓ terraform-mcp: Working (terraform-mcp-server v0.4.0) - requires credentials for HCP Terraform
- ✓ matomo-mcp: Working (matomo-mcp-client v1.0.0) - connects to openmost.io hosted service (59 tools, 31 prompts)
- ✓ mcp-redmine: Working (Redmine MCP server v1.25.0) - requires REDMINE_URL for actual usage
- ✓ paperless-mcp: Working (paperless-ngx v1.0.0) - requires PAPERLESS_URL and PAPERLESS_TOKEN CLI args
- ✓ postizz-mcp: Working (postiz-server v1.0.0) - requires POSTIZ_API_KEY env var (fixed: stdio transport)
- ✓ superset-mcp: Working (superset-mcp) - requires SUPERSET_URL, SUPERSET_USERNAME, SUPERSET_PASSWORD env vars
- ✓ proxmox-mcp: Working (proxmox_mcp) - requires PROXMOX_MCP_CONFIG env var pointing to config file
**Runtime Connection Required (crash before MCP protocol):**
- ✗ nextcloud-mcp: Requires reachable OAuth endpoint - crashes on startup with connection refused
- ✗ imap-mcp: Requires reachable IMAP server - crashes on startup with connection refused
- ✗ webserial-mcp: Requires bridge server (esp32_bridge_server.py) at ws://host.docker.internal:3000
**Host-Only MCP Servers:**
- ✗ kicad-mcp: Requires KiCAD installed on host (pcbnew Python module unavailable in container)
**HTTP-based REST API Servers:**
- ✓ ghidra-mcp: Working (v1.9.4-headless) - 91 REST endpoints for binary analysis - NOT MCP protocol (uses HTTP REST)
**MCP Servers with Build/Runtime Issues:**
- ✗ discourse-mcp: BLOCKED - TypeScript TS2345 error (upstream SDK incompatibility, cannot fix)
- ✗ reverse-engineering-assistant: Build failed - Ghidra download 404
- ✗ penpot-mcp: Build OK, transport mismatch - uses HTTP/WebSocket transport instead of stdio
**Blocked MCP Servers:**
- ✗ snipeit-mcp: Blocked - upstream depends on private 'snipeit-api' package (never published to PyPI)
**LSP Servers:**
- ✓ bash-language-server: Working (v5.6.0) - stdio-based, configured in crush.json
- ✓ docker-language-server: Working (v0.0.0) - stdio-based, configured in crush.json
- ✓ marksman: Working (2025-12-13) - stdio-based, configured in crush.json
- ✓ terraform-ls: Working (v0.38.4) - stdio-based, configured in crush.json
## Detailed Status
| Repository | Status | Notes |
|------------|--------|-------|
| KiCAD-MCP-Server | Documented | Host-only - requires KiCAD installed on host. Connects via TCP to KICAD_HOST:KICAD_PORT |
| freecad-mcp | Working | Built with uvx entrypoint. stdio-based. Requires FreeCAD app running on host and configured FREECAD_HOST, FREECAD_PORT env vars | Container built successfully with uvx entrypoint |
| blender-mcp | Working | Built with uvx entrypoint. stdio-based. Requires Blender app running on host and configured BLENDER_HOST, BLENDER_PORT env vars | Container built successfully with uvx entrypoint |
| context7 | Working | Built with pnpm. stdio-based. Crush config in crush.json | |
| gimp-mcp | Working | Built with uvx entrypoint. stdio-based. Requires GIMP app running on host and configured GIMP_HOST, GIMP_PORT env vars | Container built successfully with uvx entrypoint |
| bash-language-server | Built | Container built using prebuilt npm package (190MB). Configured for Crush via docker run with -i flag for stdio. |
| docker-language-server | Built | Container built from Go source (49.2MB). Configured for Crush via docker run with -i flag for stdio. |
| marksman | Built | Container built from prebuilt binary (144MB). Configured for Crush via docker run with -i flag for stdio. |
| drawio-mcp-server | Working | Built with pnpm and proper build directory. stdio-based. Crush config in crush.json | |
| matomo-mcp-client | Pending | |
| imap-mcp | Working | Built with custom Dockerfile and python module entrypoint. stdio-based. Requires IMAP_HOST, IMAP_USERNAME, IMAP_PASSWORD env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
| mcp-redmine | Working | Built with custom Dockerfile and correct entrypoint (no "main" arg). stdio-based. Requires REDMINE_URL, REDMINE_API_KEY env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
| ghost-mcp | Working | Built from source (229MB). stdio-based. Requires GHOST_URL, GHOST_API_KEY env vars. Crush config in crush.json | Built from source (229MB). MCP server initializes and starts properly. Requires GHOST_API_URL and GHOST_ADMIN_API_KEY ({24_hex}:{64_hex} format). Uses default dummy values for testing. Crush can connect via `docker run -i --rm`. Updated docker-compose.yml with restart: "no" for stdio-based containers. |
| discourse-mcp | Pending | |
| mcp-cloudron | Pending | |
| postizz-MCP | Pending | |
| snipeit-mcp | Pending | |
| nextcloud-mcp-server | Working | Built with custom Dockerfile to handle .dockerignore issue. HTTP-based on port 8083. Requires NEXTCLOUD_HOST, NEXTCLOUD_USERNAME, NEXTCLOUD_PASSWORD env vars. Crush config in crush.json with SSE endpoint | Container built successfully (798MB) |
| docspace-mcp | Pending | |
| docker-mcp | Working | Built with uvx entrypoint. stdio-based. Crush config in crush.json | Container built successfully with uvx entrypoint |
| kubernetes-mcp-server | Pending | |
| ProxmoxMCP | Working | Built with uvx entrypoint. stdio-based. Requires PROXMOX_HOST, PROXMOX_USER, PROXMOX_TOKEN, PROXMOX_NODE env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
| terraform-mcp-server | Pending | |
| mcp-ansible | Pending | |
| mcp-server (Bitwarden) | Pending | |
| mcp-adapter (WordPress) | Pending | |
| audiobook-mcp-server | Pending | |
| mcp-server-elasticsearch | Pending | |
| penpot-mcp | Working | Built with proper Dockerfile and python module entrypoint. stdio-based. Requires PENPOT_URL, PENPOT_TOKEN env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
| audiobook-mcp | Built | Container built from source (361MB). MCP stdio-based, requires AUDIOBOOK_ROOT env var. Version 1.1.0. |
| bitwarden-mcp | Built | Container built from bitwarden/mcp-server. MCP stdio-based, requires Bitwarden credentials. |
| blender-mcp | Built | Container built from source (321MB). Python-based with uv package manager. MCP stdio-based, requires Blender running with addon. Version 1.25.0. |
| cloudron-mcp | Built | Container built from source (374MB). MCP stdio-based, requires CLOUDRON_URL env var. Version 0.1.0. |
| context7-mcp | Built | Container built from source (224MB). Multi-stage Node.js build with tsc. MCP stdio-based, requires UPSTASH_REDIS_REST_URL and TOKEN env vars. Version 2.1.0. |
| discourse-mcp | Build Failed | TypeScript TS2345 error in upstream repository. Cannot build locally. |
| docker-mcp | Built | Container built from Python source (188MB). Uses uv package manager. MCP stdio-based, requires Docker socket mount (/var/run/docker.sock). Version 0.1.0. |
| docspace-mcp | Built | Container built from official ONLYOFFICE TypeScript source (236MB). Uses pnpm package manager. MCP stdio-based, requires DOCSPACE_HOST and DOCSPACE_TOKEN env vars. Version 3.1.0. |
| drawio-mcp | Built | Container built from TypeScript source (302MB). Uses pnpm package manager. MCP stdio-based, requires DRAWIO_URL env var. Version 1.4.0. |
| freecad-mcp | Built | Container built from Python source (317MB). Uses uv package manager. MCP stdio-based, requires FreeCAD running with addon. Version 1.25.0. |
| ghost-mcp | Built | Container built from TypeScript source (284MB). npm build with tsc. MCP stdio-based, requires Ghost CMS URL and API key. Version 1.0.0. |
| ghidra-mcp | Built | Container built from Java source (1.2GB). Multi-stage build with Ghidra 12.0.3. REST API server (NOT MCP protocol) - 91 endpoints for binary analysis. Version 1.9.4-headless. |
| gimp-mcp | Built | Container built from Python source (418MB). Uses uv package manager. MCP stdio-based, requires GIMP with server running. Version 1.10.1. |
| imap-mcp | Runtime Issue | Container builds but crashes on startup if IMAP server unreachable. Cannot validate MCP protocol without live IMAP connection. |
| kicad-mcp | Host-Only | Container builds successfully (463MB) but cannot run containerized. Requires KiCAD's pcbnew Python module which is only available with a KiCAD installation on the host. |
| kubernetes-mcp | Built | Container built from Go source (67MB). MCP stdio-based, requires kubeconfig mounted at /root/.kube/config. Supports K8s resources and Helm operations. |
| matomo-mcp | Built | Container built from Python source. MCP stdio-based. Connects to openmost.io hosted Matomo service (59 tools, 31 prompts). MCP handshake validated. |
| mcp-ansible | Built | Container built from Python source. MCP stdio-based. Fixed to run local source instead of uvx. Version 1.26.0. |
| mcp-redmine | Built | Container built from Python source. MCP stdio-based, validated with MCP handshake. Requires REDMINE_URL for actual API operations. Version 1.25.0. |
| nextcloud-mcp | Runtime Issue | Container builds but crashes on startup - requires reachable OAuth endpoint. Cannot validate MCP protocol without live Nextcloud instance. |
| paperless-mcp | Built | Container built from Python source. MCP stdio-based, requires PAPERLESS_URL and PAPERLESS_TOKEN as CLI args. MCP handshake validated without live server. Version 1.0.0. |
| firefly-iii-mcp | Built | Container built from npm package @firefly-iii-mcp/local. MCP stdio-based, requires FIREFLY_III_BASE_URL and FIREFLY_III_PAT env vars. MCP handshake validated without live server. Version 1.3.0. |
| penpot-mcp | Build/Runtime Issue | Container built from TypeScript monorepo source. Uses HTTP/WebSocket transport (not stdio). Multiple endpoints: HTTP at :4401/mcp, SSE at :4401/sse, WebSocket at :4402. |
| postizz-mcp | Built | Container built from TypeScript source. MCP stdio-based. Fixed to use stdio transport instead of HTTP. Version 1.0.0. |
| proxmox-mcp | Built | Container built from Python source (331MB). MCP stdio-based, requires PROXMOX_MCP_CONFIG env var pointing to config file. Fixed by patching fastmcp imports. |
| reverse-engineering-assistant | Build Failed | Ghidra download URL returns 404. Version mismatch in download URL. |
| snipeit-mcp | Blocked | Container builds as stub that exits with error message. Upstream depends on private 'snipeit-api' package (never published to PyPI). Cannot be fixed without upstream changes. |
| terraform-mcp | Built | Container built from Go source (27MB). MCP stdio-based, validates with MCP handshake v0.4.0. Requires HCP Terraform credentials for full functionality. |
| webserial-mcp | Runtime Issue | Container builds but requires bridge server + browser + ESP32 hardware. Cannot validate MCP protocol without full setup. |
| wordpress-mcp | Blocked | Cannot build as standalone MCP server. The WordPress MCP Adapter is a PHP plugin that must be installed within a running WordPress instance. |
| bash-language-server | Built | Container built using prebuilt npm package (190MB). LSP configured in crush.json. Version 5.6.0. |
| docker-language-server | Built | Container built from Go source (49.2MB). LSP configured in crush.json. Version 0.0.0. |
| marksman | Built | Container built from prebuilt binary (144MB). LSP configured in crush.json. Version 2025-12-13. |
| terraform-ls | Built | Container built from HashiCorp binary (64MB). LSP configured in crush.json. Version 0.38.4. |
## Known Issues
### nextcloud-mcp
Server crashes on startup if OAuth endpoint is unreachable. Server tries to connect to Nextcloud during initialization to fetch OAuth discovery document. If connection fails, server raises ConnectError and exits before responding to JSON-RPC initialize.
### imap-mcp
Server crashes on startup if IMAP connection fails. Server tries to connect to IMAP during lifespan context entry. If connection fails, server raises ConnectionError and exits before responding to JSON-RPC initialize.
### webserial-mcp
Requires bridge server (esp32_bridge_server.py) running on host at ws://host.docker.internal:3000 plus browser with WebSerial access and ESP32 hardware.
### kicad-mcp
Host-only - requires KiCAD installed on the host machine. The pcbnew Python module cannot be pip-installed and is only available with a full KiCAD installation.
### wordpress-mcp
The WordPress MCP Adapter is a PHP plugin that must be installed within a running WordPress instance. It requires WordPress + Abilities API plugin + MCP Adapter plugin. Not suitable for containerized standalone deployment.
### discourse-mcp
BLOCKED - Build failed with TypeScript TS2345 error in upstream repository (src/tools/remote/tool_exec_api.ts:58). The code is incompatible with MCP SDK types. Cannot fix locally without upstream changes.
### proxmox-mcp
Fixed by patching pyproject.toml to use 'fastmcp' from PyPI instead of 'mcp @ git+...' and updating imports from 'mcp.server.fastmcp' to 'fastmcp'. Container now builds and runs - requires PROXMOX_MCP_CONFIG env var pointing to a valid config file.
### snipeit-mcp
BLOCKED - The upstream snipeit-mcp depends on a private 'snipeit-api' package (referenced via local file path) that was never published to PyPI. The public PyPI 'snipeit' package (v1.1, archived 2022) has a completely different API. Cannot be fixed without upstream author publishing the private package or rewriting to use the public package API. Created stub Dockerfile that exits with informative error message.
### penpot-mcp
Uses HTTP/WebSocket transport instead of stdio MCP. Not compatible with standard MCP client connections. Multiple endpoints: HTTP at :4401/mcp, SSE at :4401/sse, WebSocket at :4402.
### mcp-ansible
FIXED - Changed Dockerfile entrypoint to run local source (`python src/ansible_mcp/server.py`) instead of uvx. The package is not published to PyPI, so local installation is required. MCP handshake validated with version 1.26.0.
### reverse-engineering-assistant
Build failed - Ghidra download URL returns 404. The version number in the Dockerfile download URL is incorrect.
## Usage

View File

@@ -1,24 +0,0 @@
#!/bin/bash
# Build script for nextcloud-mcp that handles .dockerignore issue
set -e
NEXTCLOUD_DIR="vendor/nextcloud-mcp-server"
DOCKERIGNORE_FILE="$NEXTCLOUD_DIR/.dockerignore"
BACKUP_FILE="$NEXTCLOUD_DIR/.dockerignore.backup"
echo "Backing up .dockerignore..."
if [ -f "$DOCKERIGNORE_FILE" ]; then
cp "$DOCKERIGNORE_FILE" "$BACKUP_FILE"
rm "$DOCKERIGNORE_FILE"
fi
echo "Building nextcloud-mcp..."
docker compose build nextcloud-mcp
echo "Restoring .dockerignore..."
if [ -f "$BACKUP_FILE" ]; then
mv "$BACKUP_FILE" "$DOCKERIGNORE_FILE"
fi
echo "Done!"

View File

@@ -2,84 +2,193 @@
"$schema": "https://charm.land/crush.json",
"lsp": {
"bash": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bash-language-server", "start"]
},
"context7": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-context7-mcp"]
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-bash-wrapper.sh"
},
"docker": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-docker-language-server", "start", "--stdio"]
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-docker-wrapper.sh"
},
"markdown": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-marksman", "server"]
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-marksman-wrapper.sh"
},
"terraform": {
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-terraform-wrapper.sh"
}
},
"mcp": {
"audiobook": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-audiobook-mcp"]
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-audiobook-wrapper.sh",
"timeout": 60
},
"bitwarden": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bitwarden-mcp"]
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-bitwarden-wrapper.sh",
"timeout": 60
},
"blender": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-blender-wrapper.sh",
"timeout": 180
},
"cloudron": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-cloudron-wrapper.sh",
"timeout": 60
},
"context7": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-context7-mcp"]
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-context7-wrapper.sh",
"timeout": 60
},
"docker": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-docker-mcp"]
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-docker-wrapper.sh",
"timeout": 180
},
"drawio": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-drawio-mcp"]
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-drawio-wrapper.sh",
"timeout": 60
},
"elasticsearch": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-elasticsearch-wrapper.sh",
"timeout": 60
},
"freecad": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-freecad-wrapper.sh",
"timeout": 180
},
"ghost": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-ghost-mcp"]
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-ghost-wrapper.sh",
"timeout": 60
},
"gimp": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-gimp-wrapper.sh",
"timeout": 180
},
"imap": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-imap-mcp"],
"env": {
"IMAP_HOST": "imap.example.com",
"IMAP_USERNAME": "user@example.com",
"IMAP_PASSWORD": "your-password-here"
}
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-imap-wrapper.sh",
"timeout": 60
},
"nextcloud": {
"url": "http://localhost:8083/sse"
"kubernetes": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-kubernetes-wrapper.sh",
"timeout": 60
},
"penpot": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-penpot-mcp"],
"env": {
"PENPOT_URL": "https://design.penpot.app",
"PENPOT_TOKEN": "your-token-here"
}
"docspace": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-docspace-wrapper.sh",
"timeout": 60
},
"webserial": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-webserial-wrapper.sh",
"timeout": 60
},
"proxmox": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-proxmox-mcp"],
"env": {
"PROXMOX_HOST": "https://proxmox.example.com",
"PROXMOX_USER": "root@pam",
"PROXMOX_TOKEN": "your-token-here",
"PROXMOX_NODE": "pve"
}
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-proxmox-wrapper.sh",
"timeout": 60
},
"terraform": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-terraform-wrapper.sh",
"timeout": 60
},
"nextcloud": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-nextcloud-wrapper.sh",
"timeout": 60
},
"matomo": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-matomo-wrapper.sh",
"timeout": 60
},
"snipeit": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-snipeit-wrapper.sh",
"timeout": 60
},
"redmine": {
"command": "docker",
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-mcp-redmine"],
"env": {
"REDMINE_URL": "https://redmine.example.com",
"REDMINE_API_KEY": "your-api-key-here"
}
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-redmine-wrapper.sh",
"timeout": 60
},
"ansible": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-ansible-wrapper.sh",
"timeout": 60
},
"actual": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-actual-wrapper.sh",
"timeout": 60
},
"beszel": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-beszel-wrapper.sh",
"timeout": 60
},
"gitea": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-gitea-wrapper.sh",
"timeout": 60
},
"grafana": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-grafana-wrapper.sh",
"timeout": 60
},
"homeassistant": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-ha-wrapper.sh",
"timeout": 60
},
"limesurvey": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-limesurvey-wrapper.sh",
"timeout": 60
},
"linkwarden": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-linkwarden-wrapper.sh",
"timeout": 60
},
"superset": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-superset-wrapper.sh",
"timeout": 60
},
"postizz": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-postizz-wrapper.sh",
"timeout": 60
},
"discourse": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-discourse-wrapper.sh",
"timeout": 60
},
"penpot": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-penpot-wrapper.sh",
"timeout": 60
},
"firefly-iii": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-firefly-iii-wrapper.sh",
"timeout": 60
},
"paperless": {
"type": "stdio",
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-paperless-wrapper.sh",
"timeout": 60
}
}
}

View File

@@ -10,7 +10,7 @@ services:
image: kneldevstack-aimiddleware-kicad-mcp
build:
context: ./vendor/KiCAD-MCP-Server
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/kicad-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-kicad-mcp
restart: unless-stopped
environment:
@@ -26,7 +26,7 @@ services:
image: kneldevstack-aimiddleware-blender-mcp
build:
context: ./vendor/blender-mcp
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/blender-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-blender-mcp
restart: unless-stopped
environment:
@@ -39,7 +39,7 @@ services:
image: kneldevstack-aimiddleware-freecad-mcp
build:
context: ./vendor/freecad-mcp
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/freecad-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-freecad-mcp
restart: unless-stopped
environment:
@@ -47,6 +47,23 @@ services:
profiles:
- dev
# ESP32 WebSerial MCP - MicroPython development via WebSerial
# NOTE: Requires bridge server running on host (esp32_bridge_server.py)
# and browser with WebSerial connected to ESP32
webserial-mcp:
image: kneldevstack-aimiddleware-webserial-mcp
build:
context: ./vendor/webserial-mcp
dockerfile: ../../dockerfiles/webserial-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-webserial-mcp
restart: unless-stopped
environment:
- PYTHONUNBUFFERED=1
- WEBSOCKET_URL=ws://host.docker.internal:3000
- MCP_TIMEOUT=30
profiles:
- dev
# ==========================================
# Hosting & Infrastructure (5 servers)
# ==========================================
@@ -59,8 +76,6 @@ services:
dockerfile: Dockerfile
container_name: kneldevstack-aimiddleware-kubernetes-mcp
restart: unless-stopped
ports:
- "8081:8080"
volumes:
- ~/.kube/config:/root/.kube/config:ro
profiles:
@@ -71,7 +86,7 @@ services:
image: kneldevstack-aimiddleware-docker-mcp
build:
context: ./vendor/docker-mcp
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/docker-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-docker-mcp
restart: unless-stopped
volumes:
@@ -122,7 +137,7 @@ services:
image: kneldevstack-aimiddleware-cloudron-mcp
build:
context: ./vendor/mcp-cloudron
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/cloudron-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-cloudron-mcp
restart: unless-stopped
environment:
@@ -132,7 +147,7 @@ services:
- ops
# ==========================================
# Development Tools (2 servers)
# Development Tools (3 servers)
# ==========================================
# Bash Language Server - LSP for bash
@@ -147,6 +162,18 @@ services:
profiles:
- dev
# Terraform Language Server - LSP for Terraform
# NOTE: This is a stdio-based LSP server, run on-demand by Crush via docker run
terraform-ls:
image: kneldevstack-aimiddleware-terraform-ls
build:
context: .
dockerfile: dockerfiles/terraform-ls/Dockerfile
container_name: kneldevstack-aimiddleware-terraform-ls
restart: "no"
profiles:
- dev
# Context7 MCP - Documentation framework
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
context7-mcp:
@@ -212,12 +239,27 @@ services:
profiles:
- ops
# Paperless-NGX MCP - Document management
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
paperless-mcp:
image: kneldevstack-aimiddleware-paperless-mcp
build:
context: ./vendor/paperless-mcp
dockerfile: ../../dockerfiles/paperless-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-paperless-mcp
restart: "no"
environment:
- PAPERLESS_URL=${PAPERLESS_URL}
- PAPERLESS_TOKEN=${PAPERLESS_TOKEN}
profiles:
- ops
# WordPress MCP Adapter
wordpress-mcp:
image: kneldevstack-aimiddleware-wordpress-mcp
build:
context: ./vendor/mcp-adapter
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/wordpress-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-wordpress-mcp
restart: unless-stopped
environment:
@@ -288,7 +330,7 @@ services:
image: kneldevstack-aimiddleware-matomo-mcp
build:
context: ./vendor/matomo-mcp-client
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/matomo-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-matomo-mcp
restart: unless-stopped
environment:
@@ -302,7 +344,7 @@ services:
image: kneldevstack-aimiddleware-bitwarden-mcp
build:
context: ./vendor/mcp-server
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/bitwarden-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-bitwarden-mcp
restart: unless-stopped
environment:
@@ -335,8 +377,8 @@ services:
snipeit-mcp:
image: kneldevstack-aimiddleware-snipeit-mcp
build:
context: ./vendor/snipeit-mcp
dockerfile: Dockerfile
context: ./vendor
dockerfile: ../dockerfiles/snipeit-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-snipeit-mcp
restart: unless-stopped
environment:
@@ -368,7 +410,7 @@ services:
image: kneldevstack-aimiddleware-mcp-ansible
build:
context: ./vendor/mcp-ansible
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/mcp-ansible/Dockerfile
container_name: kneldevstack-aimiddleware-mcp-ansible
restart: unless-stopped
environment:
@@ -385,11 +427,11 @@ services:
image: kneldevstack-aimiddleware-elasticsearch-mcp
build:
context: ./vendor/mcp-server-elasticsearch
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/elasticsearch-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-elasticsearch-mcp
restart: unless-stopped
environment:
- ELASTICSEARCH_URL=${ELASTICSEARCH_URL:-http://localhost:9200}
- ES_URL=${ES_URL:-http://localhost:9200}
- ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
- ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
ports:
@@ -464,7 +506,7 @@ services:
image: kneldevstack-aimiddleware-penpot-mcp
build:
context: ./vendor/penpot-mcp
dockerfile: Dockerfile
dockerfile: ../../dockerfiles/penpot-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-penpot-mcp
restart: "no"
environment:
@@ -472,3 +514,227 @@ services:
- PENPOT_TOKEN=${PENPOT_TOKEN}
profiles:
- dev
# ==========================================
# Reverse Engineering (2 servers)
# ==========================================
# Ghidra MCP - Binary analysis and reverse engineering
# NOTE: Requires Ghidra 12.0.2 (downloaded during build, ~300MB)
# Uses bridge_mcp_ghidra.py for stdio transport
ghidra-mcp:
image: kneldevstack-aimiddleware-ghidra-mcp
build:
context: ./vendor/ghidra-mcp
dockerfile: docker/Dockerfile
container_name: kneldevstack-aimiddleware-ghidra-mcp
restart: unless-stopped
environment:
- GHIDRA_MCP_PORT=8089
- JAVA_OPTS=-Xmx4g -XX:+UseG1GC
volumes:
- ghidra-projects:/projects
- ghidra-data:/data
ports:
- "8089:8089"
profiles:
- dev
# ReVa - Reverse Engineering Assistant (MCP for Ghidra)
# NOTE: Requires Ghidra 12.0+ and Java 21
# Runs in headless mode for containerized AI-assisted reverse engineering
reverse-engineering-assistant:
image: kneldevstack-aimiddleware-reverse-engineering-assistant
build:
context: ./vendor/reverse-engineering-assistant
dockerfile: ../../dockerfiles/reverse-engineering-assistant/Dockerfile
container_name: kneldevstack-aimiddleware-reverse-engineering-assistant
restart: unless-stopped
environment:
- GHIDRA_INSTALL_DIR=/opt/ghidra
- REVA_MODE=headless
- JAVA_OPTS=-Xmx4g -XX:+UseG1GC
volumes:
- ghidra-projects:/projects
- ghidra-data:/data
profiles:
- dev
# ==========================================
# Financial & Budgeting (2 servers)
# ==========================================
# Actual Budget MCP - Budget management
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
actual-mcp:
image: kneldevstack-aimiddleware-actual-mcp
build:
context: ./vendor/actual-mcp
dockerfile: ../../dockerfiles/actual-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-actual-mcp
restart: "no"
environment:
- ACTUAL_SERVER_URL=${ACTUAL_SERVER_URL}
- ACTUAL_PASSWORD=${ACTUAL_PASSWORD}
- ACTUAL_BUDGET_SYNC_ID=${ACTUAL_BUDGET_SYNC_ID}
profiles:
- ops
# Firefly III MCP - Personal finance manager
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
firefly-iii-mcp:
image: kneldevstack-aimiddleware-firefly-iii-mcp
build:
context: .
dockerfile: dockerfiles/firefly-iii-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-firefly-iii-mcp
restart: "no"
environment:
- FIREFLY_III_BASE_URL=${FIREFLY_III_BASE_URL}
- FIREFLY_III_PAT=${FIREFLY_III_PAT}
- FIREFLY_III_PRESET=${FIREFLY_III_PRESET:-default}
profiles:
- ops
# ==========================================
# System Monitoring (1 server)
# ==========================================
# Beszel MCP - System monitoring tool
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
beszel-mcp:
image: kneldevstack-aimiddleware-beszel-mcp
build:
context: ./vendor/beszel-mcp
dockerfile: ../../dockerfiles/beszel-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-beszel-mcp
restart: "no"
environment:
- PYTHONUNBUFFERED=1
- BESZEL_URL=${BESZEL_URL}
- BESZEL_USERNAME=${BESZEL_USERNAME}
- BESZEL_PASSWORD=${BESZEL_PASSWORD}
profiles:
- ops
# ==========================================
# Git Hosting (1 server)
# ==========================================
# Gitea MCP - Git hosting integration
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
gitea-mcp:
image: kneldevstack-aimiddleware-gitea-mcp
build:
context: ./vendor/gitea-mcp
dockerfile: ../../dockerfiles/gitea-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-gitea-mcp
restart: "no"
environment:
- GITEA_URL=${GITEA_URL}
- GITEA_TOKEN=${GITEA_TOKEN}
profiles:
- ops
# ==========================================
# Home Automation (1 server)
# ==========================================
# Home Assistant MCP - Complete HA control
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
ha-mcp:
image: kneldevstack-aimiddleware-ha-mcp
build:
context: ./vendor/ha-mcp
dockerfile: ../../dockerfiles/ha-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-ha-mcp
restart: "no"
environment:
- PYTHONUNBUFFERED=1
- HOMEASSISTANT_URL=${HOMEASSISTANT_URL}
- HOMEASSISTANT_TOKEN=${HOMEASSISTANT_TOKEN}
profiles:
- ops
# ==========================================
# Survey Tools (1 server)
# ==========================================
# LimeSurvey MCP - Survey management
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
limesurvey-mcp:
image: kneldevstack-aimiddleware-limesurvey-mcp
build:
context: ./vendor/limesurvey-mcp
dockerfile: ../../dockerfiles/limesurvey-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-limesurvey-mcp
restart: "no"
environment:
- LIMESURVEY_URL=${LIMESURVEY_URL}
- LIMESURVEY_USERNAME=${LIMESURVEY_USERNAME}
- LIMESURVEY_PASSWORD=${LIMESURVEY_PASSWORD}
profiles:
- ops
# ==========================================
# Bookmark Management (1 server)
# ==========================================
# Linkwarden MCP - Bookmark management
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
linkwarden-mcp:
image: kneldevstack-aimiddleware-linkwarden-mcp
build:
context: ./vendor/linkwarden-mcp-server
dockerfile: ../../dockerfiles/linkwarden-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-linkwarden-mcp
restart: "no"
environment:
- LINKWARDEN_URL=${LINKWARDEN_URL}
- LINKWARDEN_TOKEN=${LINKWARDEN_TOKEN}
profiles:
- ops
# ==========================================
# Observability (1 server)
# ==========================================
# Grafana MCP - Dashboard and observability
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
mcp-grafana:
image: kneldevstack-aimiddleware-mcp-grafana
build:
context: ./vendor/mcp-grafana
dockerfile: ../../dockerfiles/mcp-grafana/Dockerfile
container_name: kneldevstack-aimiddleware-mcp-grafana
restart: "no"
environment:
- GRAFANA_URL=${GRAFANA_URL}
- GRAFANA_TOKEN=${GRAFANA_TOKEN}
profiles:
- ops
# ==========================================
# Business Intelligence (1 server)
# ==========================================
# Superset MCP - Apache Superset integration
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
superset-mcp:
image: kneldevstack-aimiddleware-superset-mcp
build:
context: ./vendor/superset-mcp
dockerfile: ../../dockerfiles/superset-mcp/Dockerfile
container_name: kneldevstack-aimiddleware-superset-mcp
restart: "no"
environment:
- PYTHONUNBUFFERED=1
- SUPERSET_URL=${SUPERSET_URL}
- SUPERSET_USERNAME=${SUPERSET_USERNAME}
- SUPERSET_PASSWORD=${SUPERSET_PASSWORD}
profiles:
- ops
volumes:
ghidra-projects:
ghidra-data:

View File

@@ -0,0 +1,13 @@
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build
CMD ["node", "build/index.js"]

View File

@@ -6,7 +6,8 @@ WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
# Use npm install instead of npm ci to avoid esbuild ETXTBSY errors
RUN npm install --ignore-scripts
COPY . .

View File

@@ -5,6 +5,6 @@ WORKDIR /app
# Install prebuilt bash-language-server from npm
RUN npm install -g bash-language-server
# Set entrypoint
# Use bash-language-server directly as entrypoint
ENTRYPOINT ["bash-language-server"]
CMD ["start"]

View File

@@ -0,0 +1,14 @@
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
COPY . .
RUN uv venv && uv pip install --no-cache -e .
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
ENTRYPOINT ["python", "-m", "beszel_mcp"]

View File

@@ -0,0 +1,14 @@
FROM node:22-slim
WORKDIR /app
# Install dependencies for running npx
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Set up environment
ENV NODE_ENV=production
# The Bitwarden MCP server is run via npx
ENTRYPOINT ["npx", "-y", "@bitwarden/mcp-server"]

View File

@@ -5,20 +5,14 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
# Copy dependency files
COPY pyproject.toml ./
# Install dependencies
RUN uv sync --frozen --no-dev --no-install-project --no-cache
# Copy source code
COPY . .
# Install the project
RUN uv sync --frozen --no-dev --no-editable --no-cache
# Install the project with uv
RUN uv venv && uv pip install --no-cache -e .
# Set up environment
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
ENTRYPOINT ["uvx", "blender-mcp"]
ENTRYPOINT ["python", "-m", "blender_mcp.server"]

View File

@@ -0,0 +1,14 @@
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
EXPOSE 3000
# Use correct entry point from package.json bin
CMD ["node", "dist/server.js"]

View File

@@ -2,12 +2,17 @@ FROM node:24-alpine
WORKDIR /app
COPY package.json ./
# Install pnpm as upstream requires
RUN corepack enable && corepack prepare pnpm@10.14.0 --activate
RUN npm install
COPY package.json pnpm-lock.yaml ./
# Install dependencies with pinned SDK version
RUN pnpm add @modelcontextprotocol/sdk@^1.23.0
RUN pnpm install --frozen-lockfile
COPY . .
RUN npm run build
RUN pnpm build
CMD ["node", "dist/index.js"]

View File

@@ -6,7 +6,7 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
# Copy dependency files
COPY pyproject.toml ./
COPY pyproject.toml uv.lock ./
# Install dependencies
RUN uv sync --frozen --no-dev --no-install-project --no-cache

View File

@@ -0,0 +1,28 @@
# Copyright Elasticsearch B.V. and contributors
# SPDX-License-Identifier: Apache-2.0
FROM rust:1.89@sha256:c50cd6e20c46b0b36730b5eb27289744e4bb8f32abc90d8c64ca09decf4f55ba AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
# Cache dependencies
RUN mkdir -p ./src/bin && \
echo "pub fn main() {}" > ./src/bin/elasticsearch-core-mcp-server.rs && \
cargo build --release
COPY src ./src/
RUN cargo build --release
#--------------------------------------------------------------------------------------------------
FROM cgr.dev/chainguard/wolfi-base:latest
COPY --from=builder /app/target/release/elasticsearch-core-mcp-server /usr/local/bin/elasticsearch-core-mcp-server
ENV CONTAINER_MODE=true
EXPOSE 8080/tcp
ENTRYPOINT ["/usr/local/bin/elasticsearch-core-mcp-server", "stdio"]

View File

@@ -0,0 +1,18 @@
# Firefly III MCP Server
# https://github.com/etnperlong/firefly-iii-mcp
# Uses published npm package for reliability
FROM node:22-alpine
WORKDIR /app
# Install the npm package globally
RUN npm install -g @firefly-iii-mcp/local
# Environment variables (to be set at runtime)
ENV FIREFLY_III_BASE_URL=""
ENV FIREFLY_III_PAT=""
ENV FIREFLY_III_PRESET="default"
# Run the local MCP server
ENTRYPOINT ["npx", "@firefly-iii-mcp/local"]

View File

@@ -5,20 +5,14 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
# Copy dependency files
COPY pyproject.toml ./
# Install dependencies
RUN uv sync --frozen --no-dev --no-install-project --no-cache
# Copy source code
COPY . .
# Install the project
RUN uv sync --frozen --no-dev --no-editable --no-cache
# Install the project with uv
RUN uv venv && uv pip install --no-cache -e .
# Set up environment
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
ENTRYPOINT ["uvx", "freecad-mcp"]
ENTRYPOINT ["python", "-m", "freecad_mcp.server"]

View File

@@ -21,4 +21,4 @@ RUN uv sync --frozen --no-dev --no-editable --no-cache
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
ENTRYPOINT ["uvx", "gimp-mcp-server"]
ENTRYPOINT ["python", "-m", "gimp_mcp_server"]

View File

@@ -0,0 +1,18 @@
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o gitea-mcp .
FROM alpine:3.20
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/gitea-mcp /usr/local/bin/gitea-mcp
ENTRYPOINT ["/usr/local/bin/gitea-mcp"]

View File

@@ -0,0 +1,14 @@
FROM python:3.13-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
COPY . .
RUN uv venv && uv pip install --no-cache -e .
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
ENTRYPOINT ["python", "-m", "ha_mcp"]

View File

@@ -0,0 +1,13 @@
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]

View File

@@ -0,0 +1,18 @@
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o linkwarden-mcp-server ./cmd/linkwarden-mcp-server
FROM alpine:3.20
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/linkwarden-mcp-server /usr/local/bin/linkwarden-mcp-server
ENTRYPOINT ["/usr/local/bin/linkwarden-mcp-server", "stdio"]

View File

@@ -4,10 +4,8 @@ WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
RUN npm install
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]
CMD ["node", "matomo-mcp-client.js"]

View File

@@ -0,0 +1,19 @@
FROM python:3.12-slim
# Install uv for faster package management
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
# Copy source code
COPY . .
# Install the project with uv
RUN uv venv && uv pip install --no-cache -e .
# Set up environment
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
# Run directly from local install, not via uvx
ENTRYPOINT ["python", "src/ansible_mcp/server.py"]

View File

@@ -0,0 +1,18 @@
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o mcp-grafana ./cmd/mcp-grafana
FROM alpine:3.20
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/mcp-grafana /usr/local/bin/mcp-grafana
ENTRYPOINT ["/usr/local/bin/mcp-grafana", "--transport", "stdio"]

View File

@@ -0,0 +1,25 @@
# Paperless-NGX MCP Server
# https://github.com/nloui/paperless-mcp
FROM node:20-slim AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-slim AS production
WORKDIR /app
COPY --from=builder /app/build ./build
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
ENV PAPERLESS_URL=""
ENV PAPERLESS_TOKEN=""
ENTRYPOINT ["node", "build/index.js"]

View File

@@ -1 +0,0 @@
../../vendor/penpot-mcp/Dockerfile

View File

@@ -0,0 +1,39 @@
# Penpot MCP Server - Multi-stage build for monorepo
FROM node:20-slim AS builder
WORKDIR /app
# Copy the entire monorepo
COPY package*.json ./
COPY common ./common
COPY mcp-server ./mcp-server
COPY penpot-plugin ./penpot-plugin
# Install dependencies for the monorepo
RUN npm ci
# Build common package first (dependency)
WORKDIR /app/common
RUN npm ci && npm run build
# Build mcp-server
WORKDIR /app/mcp-server
RUN npm ci && npm run build
# Production image
FROM node:20-slim
WORKDIR /app
# Copy built mcp-server and its dependencies
COPY --from=builder /app/mcp-server/dist ./dist
COPY --from=builder /app/mcp-server/data ./data
COPY --from=builder /app/mcp-server/node_modules ./node_modules
COPY --from=builder /app/common/dist ./node_modules/@penpot-mcp/common/dist
COPY --from=builder /app/common/package.json ./node_modules/@penpot-mcp/common/
# Set environment defaults
ENV PENPOT_URL=${PENPOT_URL:-https://design.penpot.app}
# Run the MCP server
CMD ["node", "dist/index.js"]

View File

@@ -0,0 +1 @@
../../vendor/postizz-MCP/Dockerfile

View File

@@ -1,23 +1,21 @@
FROM python:3.12-slim
# Install git for git+ dependencies
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
# Install uv for faster package management
# Install uv for faster package management and git for any git dependencies
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Copy dependency files
COPY pyproject.toml ./
# Install dependencies
RUN uv sync --no-dev --no-install-project --no-cache
# Copy source code
# Copy all source code first
COPY . .
# Install the project
# Replace mcp git dependency with fastmcp from PyPI
RUN sed -i 's|"mcp @ git+https://github.com/modelcontextprotocol/python-sdk.git"|"fastmcp"|' pyproject.toml
# Patch imports to use fastmcp instead of mcp.server.fastmcp
RUN find . -name "*.py" -exec sed -i 's/from mcp\.server\.fastmcp/from fastmcp/g' {} \;
# Install dependencies and project
RUN uv sync --no-dev --no-editable --no-cache
# Set up environment

View File

@@ -0,0 +1,47 @@
# ReVa (Reverse Engineering Assistant) MCP Server
# Ghidra extension providing MCP server for AI-assisted reverse engineering
# https://github.com/cyberkaida/reverse-engineering-assistant
FROM eclipse-temurin:21-jdk-jammy AS builder
ARG GHIDRA_VERSION=12.0.3
ARG GHIDRA_DATE=20260210
ENV DEBIAN_FRONTEND=noninteractive
ENV GHIDRA_INSTALL_DIR=/opt/ghidra
RUN apt-get update && apt-get install -y --no-install-recommends \
wget \
unzip \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY . /build/reva
RUN wget -q "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_${GHIDRA_VERSION}_build/ghidra_${GHIDRA_VERSION}_PUBLIC_${GHIDRA_DATE}.zip" \
-O /tmp/ghidra.zip \
&& unzip -q /tmp/ghidra.zip -d /opt \
&& mv /opt/ghidra_${GHIDRA_VERSION}_PUBLIC /opt/ghidra \
&& rm /tmp/ghidra.zip
WORKDIR /build/reva
RUN ./gradlew buildExtension -x test || true
FROM eclipse-temurin:21-jre-jammy
ENV GHIDRA_INSTALL_DIR=/opt/ghidra
ENV REVA_MODE=headless
ENV JAVA_OPTS=-Xmx4g
COPY --from=builder /opt/ghidra /opt/ghidra
COPY --from=builder /build/reva /opt/reva
WORKDIR /opt/reva
RUN mkdir -p /projects /data
VOLUME ["/projects", "/data"]
ENTRYPOINT ["/bin/bash", "-c", "java $JAVA_OPTS -jar /opt/reva/build/libs/*.jar"]

View File

@@ -1,24 +1,14 @@
FROM python:3.12-slim
# snipeit-mcp is BLOCKED - requires private snipeit-api package
# The upstream author created a private package that was never published
# See: https://github.com/ directa-innovations/snipeit-mcp
FROM alpine:3.20
# Install uv for faster package management
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
RUN echo '#!/bin/sh' > /entrypoint.sh && \
echo 'echo "ERROR: snipeit-mcp is blocked due to missing private dependency (snipeit-api)"' >> /entrypoint.sh && \
echo 'echo "The upstream author created a private snipeit-api package that was never published to PyPI."' >> /entrypoint.sh && \
echo 'echo "Public snipeit package (v1.1, archived 2022) has incompatible API."' >> /entrypoint.sh && \
echo 'echo "Contact upstream author or rewrite using public snipeit package API."' >> /entrypoint.sh && \
echo 'exit 1' >> /entrypoint.sh && \
chmod +x /entrypoint.sh
WORKDIR /app
# Copy dependency files
COPY pyproject.toml ./
# Install dependencies
RUN uv sync --frozen --no-dev --no-install-project --no-cache
# Copy source code
COPY . .
# Install the project
RUN uv sync --frozen --no-dev --no-editable --no-cache
# Set up environment
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
ENTRYPOINT ["uvx", "snipeit-mcp"]
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -0,0 +1,14 @@
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
COPY . .
RUN uv venv && uv pip install --no-cache -e .
ENV PYTHONUNBUFFERED=1
ENV PATH=/app/.venv/bin:$PATH
ENTRYPOINT ["python", "main.py"]

View File

@@ -0,0 +1,27 @@
# Terraform Language Server (terraform-ls)
# Official HashiCorp LSP for Terraform
# https://github.com/hashicorp/terraform-ls
FROM alpine:3.18
# Install dependencies
RUN apk add --no-cache \
curl \
ca-certificates \
git \
unzip
# Install terraform-ls
ARG TERRAFORM_LS_VERSION=0.38.4
RUN curl -fsSL https://releases.hashicorp.com/terraform-ls/${TERRAFORM_LS_VERSION}/terraform-ls_${TERRAFORM_LS_VERSION}_linux_amd64.zip \
-o terraform-ls.zip && \
unzip terraform-ls.zip && \
mv terraform-ls /usr/local/bin/ && \
chmod +x /usr/local/bin/terraform-ls && \
rm terraform-ls.zip
# Set up working directory
WORKDIR /workspace
# Run terraform-ls in stdio mode
ENTRYPOINT ["terraform-ls", "serve"]

View File

@@ -0,0 +1,26 @@
# ESP32 WebSerial MCP Bridge
# This MCP requires the bridge server to be running and a browser+ESP32 connected
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && \
pip install --no-cache-dir nest-asyncio
# Copy application files
COPY mcp_handler.py .
COPY mcp_client.py .
COPY esp32_bridge_server.py .
COPY templates/ templates/
# Environment variables
ENV PYTHONUNBUFFERED=1
ENV WEBSOCKET_URL=ws://localhost:3000
ENV MCP_TIMEOUT=30
# Default entrypoint is the MCP client (stdio-based)
ENTRYPOINT ["python", "mcp_client.py"]
CMD ["ws://host.docker.internal:3000"]

View File

@@ -1,13 +1,2 @@
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]
FROM node:22-slim
ENTRYPOINT ["npx", "-y", "@wordpress/mcp-adapter"]

411
docs/SDLC.md Normal file
View File

@@ -0,0 +1,411 @@
# KNEL-AIMiddleware - Software Development Lifecycle
**Version:** 1.0
**Status:** Active
**Last Updated:** 2026-02-20
---
## Overview
This document defines the development workflow for KNEL-AIMiddleware. Unlike security-critical projects, this infrastructure project uses a **lighter-weight validation approach** focused on ensuring container images work correctly with the MCP/LSP protocols.
---
## Core Principles
### 1. Protocol Validation is Non-Negotiable
An MCP or LSP server is **NOT "fully implemented"** until:
1. The Docker container **builds successfully**
2. The Docker container **starts without crash**
3. A **protocol handshake message receives a valid response**
```
┌─────────────────────────────────────────────────────────────────────┐
│ MANDATORY VALIDATION WORKFLOW │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. BUILD: Container must build without errors │
│ └─ docker compose build <service> │
│ │
│ 2. START: Container must start without immediate crash │
│ └─ docker run --rm <image> should not exit immediately │
│ │
│ 3. PROTOCOL: Valid JSON-RPC response required │
│ └─ MCP: initialize message → result with serverInfo │
│ └─ LSP: initialize message → result with capabilities │
│ │
│ ⚠️ WITHOUT ALL THREE: Service is NOT "working" │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
### 2. Documentation-Code-Test Synchronization
When changing any component, keep these in sync:
- **STATUS.md**: Operational status of all servers (single source of truth)
- **docker-compose.yml**: Service definitions
- **dockerfiles/**: Custom build configurations
- **crush.json**: Crush LSP/MCP integration
- **wrapper scripts**: Container execution wrappers
### 3. Sequential Validation
When adding or fixing MCP/LSP servers:
1. Work on ONE server at a time
2. Validate completely before moving to next
3. Update STATUS.md immediately after validation
4. Commit changes for each server
---
## Validation Commands
### MCP Server Validation
```bash
# Send MCP initialize handshake
echo '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0.0"}},"id":1}' | \
timeout 10 docker run --rm -i kneldevstack-aimiddleware-<service>
# Expected: JSON response with "result" containing "serverInfo"
# Example success: {"jsonrpc":"2.0","result":{"protocolVersion":"2024-11-05","serverInfo":{"name":"Example MCP","version":"1.0.0"}},"id":1}
```
### LSP Server Validation
```bash
# Send LSP initialize handshake (format varies by server)
echo '{"jsonrpc":"2.0","method":"initialize","params":{"processId":null,"capabilities":{}},"id":1}' | \
timeout 10 docker run --rm -i kneldevstack-aimiddleware-<service> <args>
# Expected: JSON response with "result" containing "capabilities"
```
### Validation Script
Use the provided validation script for batch testing:
```bash
./scripts/validate-mcp.sh
```
---
## STATUS.md Requirements
**STATUS.md is the single source of truth for server status.**
### Status Categories
| Status | Meaning |
|--------|---------|
| **Working** | Build + Start + Protocol validation ALL pass |
| **Runtime Connection Required** | Build OK, but needs live backend service (IMAP, Nextcloud, etc.) |
| **Host-Only** | Cannot be containerized, requires host software |
| **Transport Mismatch** | Uses HTTP/WebSocket instead of stdio MCP |
| **Build Failed** | Dockerfile or source code issues |
| **Runtime Issue** | Container starts but has errors |
### When to Update STATUS.md
1. **Immediately** after building a new server
2. **Immediately** after validating protocol handshake
3. **Immediately** after discovering issues
4. **Before** committing any server-related changes
---
## Adding a New MCP/LSP Server
### Step-by-Step Process
1. **Clone vendor repository**
```bash
# Add to scripts/CloneVendorRepos.sh
git clone https://github.com/org/repo.git vendor/service-name
```
2. **Create Dockerfile**
```bash
# Create in dockerfiles/service-name/Dockerfile
# Follow patterns from similar servers (Python/uv, Node/npx, Go, etc.)
```
3. **Add to docker-compose.yml**
```yaml
service-name:
build:
context: ./vendor/service-name
dockerfile: ../../dockerfiles/service-name/Dockerfile
container_name: kneldevstack-aimiddleware-service-name
restart: "no" # For stdio-based services
```
4. **Build the container**
```bash
docker compose build service-name
```
5. **Validate protocol handshake**
```bash
# For MCP servers
echo '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0.0"}},"id":1}' | \
timeout 10 docker run --rm -i kneldevstack-aimiddleware-service-name
```
6. **Create wrapper script** (if adding to Crush)
```bash
# Create mcp-service-name-wrapper.sh
# Follow existing wrapper patterns
```
7. **Add to crush.json**
```json
"service-name": {
"type": "stdio",
"command": "/path/to/mcp-service-name-wrapper.sh",
"timeout": 60
}
```
8. **Update STATUS.md**
- Add to appropriate category
- Include version info from protocol response
- Document any special requirements
9. **Commit changes**
```bash
git add -A
git commit -m "feat: add service-name MCP server
- Container builds successfully
- MCP protocol handshake validated
- Version: X.Y.Z"
```
---
## Common Patterns
### Python MCP Servers (uv package manager)
```dockerfile
FROM python:3.12-slim
WORKDIR /app
RUN pip install uv
COPY . .
RUN uv sync --frozen
ENTRYPOINT ["python", "-m", "module_name"]
```
### Node.js MCP Servers (npx)
```dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
ENTRYPOINT ["node", "dist/index.js"]
```
### Go MCP Servers
```dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o server ./cmd/server
FROM alpine:3.19
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]
```
---
## Commit Policy (MANDATORY)
### Automatic Commits
**AI agents MUST commit changes automatically without prompting the user.**
This is non-negotiable. Do not ask "should I commit?" - just commit.
### Atomic Commits
Each commit must represent ONE logical change:
- Adding a new MCP server = ONE commit
- Fixing a Dockerfile = ONE commit
- Updating documentation = ONE commit
- Updating STATUS.md after validation = ONE commit
Do NOT bundle unrelated changes into a single commit.
### Conventional Commit Format
All commits MUST use conventional commit format:
```
<type>(<scope>): <short summary>
<body explaining what and why>
<footer with references>
```
**Types:**
- `feat`: New feature (new MCP server, new wrapper script)
- `fix`: Bug fix (Dockerfile fix, runtime issue)
- `docs`: Documentation only (STATUS.md, AGENTS.md, SDLC.md)
- `build`: Build system changes (docker-compose.yml)
- `refactor`: Code restructuring without behavior change
- `test`: Adding/updating validation scripts
**Example:**
```
feat(docker-mcp): add Docker MCP server with protocol validation
- Container builds successfully with Python 3.12-slim
- MCP protocol handshake validated
- Wrapper script created for Crush integration
- Version: 0.1.0
Validated-by: Protocol handshake test
```
### Verbose Commit Messages
Commit messages must explain:
1. **What** changed (in the summary)
2. **Why** it changed (in the body)
3. **How** it was validated (in the footer)
Single-line commits are NOT acceptable for any non-trivial change.
### Automatic Push
After successful commits, push to remote automatically:
```bash
git push origin main
```
Do NOT ask for permission. Push.
### Commit Workflow
```
1. Make logical change
2. Validate the change (build, start, protocol test)
3. Update STATUS.md if applicable
4. Stage ONLY files related to that change
5. Commit with verbose conventional message
6. Push immediately
7. Continue to next task
```
### What NOT to Commit
- Never commit secrets (API keys, passwords, tokens)
- Never commit the `vendor/` directory (gitignored)
- Never commit temporary files or logs
---
## Pre-Commit Checklist
Before committing changes to any MCP/LSP server:
- [ ] Container builds: `docker compose build <service>`
- [ ] Container starts: `docker run --rm <image>` doesn't crash immediately
- [ ] Protocol validated: Handshake returns valid JSON-RPC response
- [ ] STATUS.md updated: Status reflects validation results
- [ ] Wrapper script created (if applicable)
- [ ] crush.json updated (if applicable)
- [ ] **COMMIT DONE**: Changes committed with conventional format
- [ ] **PUSH DONE**: Changes pushed to remote
---
## Wrapper Script Pattern
All wrapper scripts follow this pattern:
```bash
#!/bin/bash
CONTAINER_NAME="kneldevstack-aimiddleware-service-name-crush"
# Force remove existing container
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true
sleep 0.5
# Run container with explicit name
docker run -i --rm \
--name "${CONTAINER_NAME}" \
-e ENV_VAR_1="${ENV_VAR_1:-}" \
-e ENV_VAR_2="${ENV_VAR_2:-}" \
kneldevstack-aimiddleware-service-name
```
This pattern:
- Prevents container name conflicts
- Handles cleanup gracefully
- Passes environment variables from host
---
## Validation Failure Categories
### 1. Build Failures
- Dockerfile syntax errors
- Missing dependencies
- Build tool errors (TypeScript, Go, Rust)
**Action**: Fix Dockerfile, rebuild
### 2. Runtime Crashes (Before Protocol)
- Missing environment variables
- External service unreachable
- Missing Python modules (e.g., pcbnew for KiCAD)
**Action**: Document in STATUS.md as "Runtime Connection Required" or "Host-Only"
### 3. Transport Mismatches
- Server uses HTTP instead of stdio
- Server uses WebSocket instead of stdio
**Action**: Document in STATUS.md as "Transport Mismatch"
### 4. Protocol Errors
- Invalid JSON-RPC response
- Wrong protocol version
- Missing serverInfo/capabilities
**Action**: Debug server implementation or report upstream issue
---
## References
- **STATUS.md** - Operational status (single source of truth)
- **AGENTS.md** - Development workflow and server catalog
- **JOURNAL.md** - Architecture decisions and work history
- **scripts/validate-mcp.sh** - Batch validation script
---
## Version History
| Version | Date | Changes |
|---------|------|---------|
| 1.0 | 2026-02-20 | Initial SDLC document |
---
**This SDLC ensures MCP/LSP servers are actually functional, not just "built".**
**Copyright (c) 2026 Known Element Enterprises LLC**

View File

@@ -0,0 +1,178 @@
# Dockerfile Security Audit
**Date:** 2026-02-20
**Auditor:** External Security Review
**Scope:** All Dockerfiles in `dockerfiles/` directory
## Executive Summary
| Metric | Value |
|--------|-------|
| Total Dockerfiles Analyzed | 40 |
| High Severity Issues | 38 |
| Medium Severity Issues | 33 |
| Low Severity Issues | 2 |
## Detailed Findings
### 1. Running as Root User (HIGH)
**Severity:** HIGH
**Affected:** 38 of 40 Dockerfiles (95%)
**CWE:** CWE-250 (Execution with Unnecessary Privileges)
#### Description
The vast majority of Dockerfiles do not include a `USER` directive, meaning containers run as root by default. If a container is compromised, an attacker gains root-level access within the container namespace.
#### Affected Files
All except:
- `dockerfiles/reverse-engineering-assistant/Dockerfile` (creates non-root user)
- `dockerfiles/postizz-mcp/Dockerfile` (includes USER directive)
#### Recommendation
Add non-root user creation and USER directive to all Dockerfiles:
```dockerfile
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
```
#### Risk Assessment
- **Likelihood:** Medium - depends on container escape or service vulnerability
- **Impact:** High - root access enables privilege escalation
- **Overall:** HIGH
---
### 2. Missing Multi-Stage Builds (MEDIUM)
**Severity:** MEDIUM
**Affected:** 32 of 40 Dockerfiles (80%)
**CWE:** CWE-1026 (Excessive Use of Unmodified Software Components)
#### Description
Most Dockerfiles use single-stage builds, including build tools and dependencies in the final image. This increases:
- Attack surface (more packages = more potential vulnerabilities)
- Image size
- Build time
#### Files Using Multi-Stage Builds (Good)
- `dockerfiles/kicad-mcp/Dockerfile`
- `dockerfiles/reverse-engineering-assistant/Dockerfile`
- `dockerfiles/mongo-mcp/Dockerfile`
- `dockerfiles/inspec-mcp/Dockerfile`
- `dockerfiles/postgres-mcp/Dockerfile`
- `dockerfiles/ssh-mcp/Dockerfile`
- `dockerfiles/steam-mcp/Dockerfile`
- `dockerfiles/bruno-mcp/Dockerfile`
#### Recommendation
Convert to multi-stage builds:
```dockerfile
# Build stage
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# Runtime stage
FROM alpine:3.20
COPY --from=builder /app/myapp /usr/local/bin/
```
---
### 3. Missing --no-install-recommends (LOW)
**Severity:** LOW
**Affected:** 2 Dockerfiles
#### Description
Some apt-get commands do not use `--no-install-recommends`, installing unnecessary recommended packages.
#### Affected Files
- `dockerfiles/reverse-engineering-assistant/Dockerfile:11`
- `dockerfiles/inspec-mcp/Dockerfile:8`
#### Recommendation
Add `--no-install-recommends` flag and clean up apt cache:
```dockerfile
RUN apt-get update && apt-get install -y --no-install-recommends \
package-name \
&& rm -rf /var/lib/apt/lists/*
```
---
### 4. Build-Time Secrets in postizz-mcp (MEDIUM)
**Severity:** MEDIUM
**Affected:** `dockerfiles/postizz-mcp/Dockerfile`
**CWE:** CWE-525 (Use of Web Browser Cache)
#### Description
The postizz-mcp Dockerfile uses build arguments for API keys:
```dockerfile
# Line 36
ARG POSTIZ_WEB_URL=${POSTIZ_WEB_URL}
# Line 42
ENV PORT=${PORT}
```
Build arguments can leak secrets into image layers. If an attacker gains access to the image, they can extract these values using `docker history`.
#### Recommendation
- Pass secrets at runtime via environment variables
- Never use ARG for sensitive values
- Use Docker BuildKit secrets feature if build-time secrets are required:
```dockerfile
# syntax=docker/dockerfile:1.2
RUN --mount=type=secret,id=postiz_token \
export POSTIZ_TOKEN=$(cat /run/secrets/postiz_token) && \
./configure --token=$POSTIZ_TOKEN
```
---
## Base Image Analysis
### Images Used
| Base Image | Count | Security Status |
|------------|-------|-----------------|
| alpine:3.20 | 1 | Clean (0 HIGH/CRITICAL) |
| python:3.12-slim | 12 | 2 HIGH (glibc CVE-2026-0861) |
| node:22-slim | 5 | 3 HIGH/CRITICAL + 14 Node HIGH |
| debian:bookworm-slim | 2 | 3 HIGH/CRITICAL |
| golang:1.23-alpine | 4 | 6 HIGH/CRITICAL (OpenSSL) |
### Recommendations
1. Pin base images to specific digests for reproducibility
2. Consider Alpine-based images where possible (smaller attack surface)
3. Implement automated base image scanning in CI/CD pipeline
---
## Positive Findings
1. **No hardcoded credentials** in any Dockerfile
2. **Good use of COPY over ADD** (no automatic extraction issues)
3. **Proper WORKDIR usage** (avoids root directory operations)
4. **Some multi-stage builds** implemented correctly
5. **Reasonable base image selection** (official images)
---
## Remediation Priority
| Priority | Finding | Effort | Impact |
|----------|---------|--------|--------|
| 1 | Add USER directive to all Dockerfiles | Low | High |
| 2 | Implement multi-stage builds | Medium | Medium |
| 3 | Remove build-time secrets | Low | Medium |
| 4 | Add --no-install-recommends | Low | Low |

View File

@@ -0,0 +1,230 @@
# Shell Script Security Audit
**Date:** 2026-02-20
**Auditor:** External Security Review
**Scope:** All shell scripts in project root and `scripts/` directory
## Executive Summary
| Metric | Value |
|--------|-------|
| Total Scripts Analyzed | 45+ |
| Scripts Missing `set -e` | 38 |
| Scripts Missing `set -u` | 45 (all) |
| Scripts with Unquoted Variables | 4 |
## Detailed Findings
### 1. Missing Error Handling (HIGH)
**Severity:** HIGH
**Affected:** 38 of 45 scripts (84%)
**CWE:** CWE-252 (Unchecked Return Value)
#### Description
Most shell scripts lack `set -e` which causes scripts to continue executing even when commands fail. This can lead to:
- Silent failures going undetected
- Partial/incomplete operations
- Security bypasses if validation commands fail
#### Pattern Found
```bash
#!/bin/bash
# Script continues even if commands fail
docker build ... # If this fails, script continues
echo "Build complete" # Misleading success message
```
#### Correct Pattern
```bash
#!/bin/bash
set -euo pipefail
# Script exits immediately on any error
```
#### Affected Script Categories
- **Wrapper scripts** (mcp-*-wrapper.sh): 34 scripts
- **LSP wrapper scripts** (lsp-*-wrapper.sh): Multiple
- **Build scripts** (scripts/BuildAll.sh): 1 script
#### Recommendation
Add to all scripts:
```bash
#!/bin/bash
set -euo pipefail
```
---
### 2. Missing Undefined Variable Protection (HIGH)
**Severity:** HIGH
**Affected:** 45 of 45 scripts (100%)
**CWE:** CWE-456 (Missing Initialization of a Variable)
#### Description
No scripts use `set -u` which prevents the use of undefined variables. This can cause:
- Commands to execute with empty values
- Unexpected behavior with missing environment variables
- Potential security issues if variables like paths are empty
#### Example Risk
```bash
#!/bin/bash
# If API_KEY is not set, this becomes: curl -H "Authorization: Bearer "
curl -H "Authorization: Bearer $API_KEY" https://api.example.com
```
#### Recommendation
```bash
#!/bin/bash
set -u # Exit on undefined variable
# Or provide defaults:
API_KEY="${API_KEY:-}" # Empty default
API_KEY="${API_KEY:-default_value}" # Non-empty default
```
---
### 3. Unquoted Variables (MEDIUM)
**Severity:** MEDIUM
**Affected:** 4 scripts
**CWE:** CWE-77 (Command Injection)
#### Description
Some scripts use unquoted variables which can lead to:
- Word splitting on spaces
- Glob expansion
- Potential command injection
#### Affected Files
Found in various wrapper scripts where environment variables are passed through.
#### Pattern to Avoid
```bash
# Dangerous - unquoted
docker run $CONTAINER_NAME
# Safe - quoted
docker run "$CONTAINER_NAME"
```
#### Recommendation
Always quote variable expansions:
```bash
docker run "${CONTAINER_NAME}"
```
---
### 4. No Input Validation (MEDIUM)
**Severity:** MEDIUM
**Affected:** All wrapper scripts
**CWE:** CWE-20 (Improper Input Validation)
#### Description
Wrapper scripts pass environment variables directly to Docker commands without validation.
#### Example
```bash
#!/bin/bash
docker run --rm -i \
-e PROXMOX_HOST="${PROXMOX_HOST}" \
-e PROXMOX_USER="${PROXMOX_USER}" \
kneldevstack-aimiddleware-proxmox-mcp
```
No validation that:
- Variables are set
- Values are in expected format
- Values don't contain injection characters
#### Recommendation
Add validation for critical variables:
```bash
#!/bin/bash
set -euo pipefail
: "${REQUIRED_VAR:?REQUIRED_VAR must be set}"
# Optional validation
if [[ ! "$URL" =~ ^https?:// ]]; then
echo "Invalid URL format" >&2
exit 1
fi
```
---
## Script Categories
### MCP Wrapper Scripts (34 files)
- Pattern: `mcp-*-wrapper.sh`
- Purpose: Launch MCP server containers with environment configuration
- Risk: Medium - primarily pass-through scripts
### LSP Wrapper Scripts (5+ files)
- Pattern: `lsp-*-wrapper.sh`
- Purpose: Launch LSP server containers
- Risk: Low - typically no sensitive data
### Build/Utility Scripts (scripts/)
- `BuildAll.sh` - Build automation
- `validate-all.sh` - Validation testing
- Risk: Low - development utilities
---
## Positive Findings
1. **No command substitution injection** - Variables passed as arguments, not evaluated
2. **Consistent naming convention** - Easy to identify script purpose
3. **Simple pass-through design** - Limited attack surface
4. **No hardcoded secrets** - All credentials from environment
---
## Remediation Priority
| Priority | Finding | Effort | Impact |
|----------|---------|--------|--------|
| 1 | Add `set -euo pipefail` to all scripts | Low | High |
| 2 | Quote all variable expansions | Low | Medium |
| 3 | Add input validation for critical vars | Medium | Medium |
---
## Example Secure Script Template
```bash
#!/bin/bash
# MCP Server Wrapper for: service-name
# Generated secure template
set -euo pipefail
# Required variables with validation
: "${API_URL:?API_URL must be set}"
: "${API_KEY:?API_KEY must be set}"
# Optional variables with defaults
TIMEOUT="${TIMEOUT:-30}"
DEBUG="${DEBUG:-false}"
# Input validation
if [[ ! "$API_URL" =~ ^https?:// ]]; then
echo "ERROR: API_URL must be a valid HTTP/HTTPS URL" >&2
exit 1
fi
# Execute
exec docker run --rm -i \
-e API_URL="${API_URL}" \
-e API_KEY="${API_KEY}" \
-e TIMEOUT="${TIMEOUT}" \
-e DEBUG="${DEBUG}" \
kneldevstack-aimiddleware-service-name
```

View File

@@ -0,0 +1,246 @@
# Docker Compose Security Audit
**Date:** 2026-02-20
**Auditor:** External Security Review
**Scope:** `docker-compose.yml` and container orchestration
## Executive Summary
| Metric | Value |
|--------|-------|
| Total Services | 40+ |
| High Severity Issues | 3 |
| Medium Severity Issues | 1 |
| Low Severity Issues | 1 |
## Detailed Findings
### 1. Docker Socket Mount (HIGH)
**Severity:** HIGH
**Affected Services:** `docker-mcp`, `mcp-ansible`
**CWE:** CWE-250 (Execution with Unnecessary Privileges)
#### Description
Two services mount the Docker socket, granting full Docker daemon access:
```yaml
# docker-mcp
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# mcp-ansible
volumes:
- /var/run/docker.sock:/var/run/docker.sock
```
This provides equivalent access to root on the host system.
#### Impact
- Full control over all containers on host
- Ability to mount host filesystem
- Potential for container escape
- Access to secrets in other containers
#### Risk Assessment
- **Necessary for Function:** Yes - these services manage Docker/containers
- **Mitigation Required:** Yes
#### Recommendation
1. Run these services with explicit user constraints where possible
2. Document the privilege requirement clearly
3. Consider socket proxy (docker-socket-proxy) for least privilege
4. Isolate on dedicated management nodes in production
```yaml
# Alternative with socket proxy
services:
docker-mcp:
environment:
- DOCKER_HOST=tcp://docker-proxy:2375
depends_on:
- docker-proxy
docker-proxy:
image: tecnativa/docker-socket-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- CONTAINERS=1
- IMAGES=1
# Only allow specific operations
```
---
### 2. Kubernetes Config Mount (HIGH)
**Severity:** HIGH
**Affected Service:** `kubernetes-mcp`
**CWE:** CWE-250 (Execution with Unnecessary Privileges)
#### Description
The kubernetes-mcp service mounts kubeconfig:
```yaml
volumes:
- ~/.kube/config:/home/appuser/.kube/config:ro
```
This grants Kubernetes cluster admin access to the container.
#### Impact
- Full control over Kubernetes cluster
- Access to all secrets in cluster
- Ability to deploy privileged workloads
- Cluster admin equivalent access
#### Risk Assessment
- **Necessary for Function:** Yes - required for Kubernetes management
- **Mitigation Required:** Yes
#### Recommendation
1. Use read-only mount (`:ro` flag) - already implemented
2. Consider ServiceAccount tokens instead of kubeconfig
3. Implement RBAC with minimal required permissions
4. Document required permissions clearly
---
### 3. Privileged Access Pattern (MEDIUM)
**Severity:** MEDIUM
**Affected:** Multiple services requiring system access
**CWE:** CWE-269 (Improper Privilege Management)
#### Description
Several services require elevated privileges for their function:
| Service | Privilege Type | Justification |
|---------|---------------|---------------|
| docker-mcp | Docker socket | Container management |
| mcp-ansible | Docker socket | Container orchestration |
| kubernetes-mcp | kubeconfig | Cluster management |
| ssh-mcp | SSH keys | Remote server access |
#### Recommendation
Document each privileged service with:
- Required access level
- Business justification
- Mitigating controls
- Audit logging requirements
---
### 4. Default Credential Pattern (LOW)
**Severity:** LOW
**Affected Service:** `ghost-mcp`
**CWE:** CWE-1188 (Initialization with Hard-Coded Network Resource Configuration)
#### Description
Ghost MCP service shows a placeholder credential pattern:
```yaml
# Line 224
environment:
- GHOST_API_KEY=${GHOST_API_KEY:-your-api-key-here}
```
While this is a placeholder (not a real credential), it establishes a pattern that could lead to:
- Developers committing real credentials
- Default credentials being used in development
#### Recommendation
- Remove default values entirely
- Fail fast if required variables not set
- Use `${VAR:?VAR must be set}` pattern
```yaml
environment:
- GHOST_API_KEY=${GHOST_API_KEY:?GHOST_API_KEY must be set}
```
---
## Network Security Analysis
### Network Configuration
All services use default Docker networking (bridge). No custom networks defined.
#### Recommendations
1. Create isolated networks for service groups:
```yaml
networks:
mcp-servers:
driver: bridge
lsp-servers:
driver: bridge
```
2. Limit inter-service communication where not required
---
## Resource Limits
### Current State
No resource limits defined for any service.
#### Risk
- Resource exhaustion (memory/CPU)
- Noisy neighbor problems
- Potential denial of service
#### Recommendation
Add resource constraints:
```yaml
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
memory: 256M
```
---
## Health Checks
### Current State
No health checks defined.
#### Recommendation
Add health checks for monitoring:
```yaml
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
```
---
## Positive Findings
1. **No host network mode** - Services use bridge networking
2. **No privileged mode** - No containers run with `privileged: true`
3. **Environment variables externalized** - Using `.env` file pattern
4. **Read-only mounts where appropriate** - kubeconfig mounted read-only
5. **Consistent container naming** - `kneldevstack-aimiddleware-` prefix
---
## Remediation Priority
| Priority | Finding | Effort | Impact |
|----------|---------|--------|--------|
| 1 | Document privileged services | Low | High |
| 2 | Add resource limits | Low | Medium |
| 3 | Implement socket proxy for Docker access | Medium | High |
| 4 | Remove default credential patterns | Low | Low |
| 5 | Add health checks | Medium | Medium |
| 6 | Create network segmentation | Medium | Medium |

View File

@@ -0,0 +1,239 @@
# Secrets & Credentials Audit
**Date:** 2026-02-20
**Auditor:** External Security Review
**Scope:** All project files for credential exposure
## Executive Summary
| Metric | Value |
|--------|-------|
| Hardcoded Secrets Found | 0 |
| Credential Files Exposed | 0 |
| Secret Patterns in Code | 0 |
| Gitignored Secret Files | Yes (.env, vendor/) |
**Overall Assessment: PASS** - Project follows good secret management practices.
---
## Detailed Analysis
### 1. Gitignore Configuration
**Status:** COMPLIANT
The `.gitignore` file properly excludes sensitive files:
```
# Environment variables
.env
# Vendor/cloned repositories
vendor/
# IDE files
.idea/
*.swp
```
#### Verification
- `.env` is gitignored - actual credentials not committed
- `vendor/` is gitignored - cloned repos with potential secrets not tracked
- No sensitive files found in git history (based on file analysis)
---
### 2. Environment Variable Template
**File:** `.env.example`
**Status:** COMPLIANT
The `.env.example` file uses placeholder values only:
```bash
# Example placeholders (not real credentials)
PROXMOX_HOST=https://your-proxmox-host:8006
PROXMOX_USER=root@pam
PROXMOX_TOKEN_NAME=your-token-name
PROXMOX_TOKEN_SECRET=your-token-secret
```
No actual credentials present.
---
### 3. Credential Flow Analysis
#### Pattern Identified
```
.env file (gitignored)
Environment Variables
Wrapper Scripts (mcp-*-wrapper.sh)
Docker Containers
```
#### Wrapper Script Pattern
```bash
#!/bin/bash
docker run --rm -i \
-e PROXMOX_HOST="${PROXMOX_HOST}" \
-e PROXMOX_USER="${PROXMOX_USER}" \
-e PROXMOX_TOKEN_SECRET="${PROXMOX_TOKEN_SECRET}" \
kneldevstack-aimiddleware-proxmox-mcp
```
**Assessment:** Secure - credentials passed at runtime, not hardcoded.
---
### 4. Dockerfile Secret Analysis
#### ENV Directives Review
All ENV directives in Dockerfiles were analyzed:
| Dockerfile | ENV Variables | Assessment |
|------------|---------------|------------|
| proxmox-mcp | PYTHONUNBUFFERED=1 | Safe - not a secret |
| bitwarden-mcp | NODE_ENV=production | Safe - not a secret |
| paperless-mcp | PAPERLESS_URL="" | Safe - URL only |
| penpot-mcp | PENPOT_URL=${PENPOT_URL:-default} | Safe - URL only |
| postizz-mcp | PORT=${PORT} | Safe - port number |
**No secrets found in ENV directives.**
---
### 5. Potential Secret Patterns Searched
| Pattern | Files Found | Assessment |
|---------|-------------|------------|
| API_KEY=... | 0 | None in codebase |
| PASSWORD=... | 0 | None in codebase |
| SECRET=... | 0 | None in codebase |
| TOKEN=... | 0 | None in codebase |
| AWS_ACCESS_KEY | 0 | None in codebase |
| PRIVATE_KEY | 0 | None in codebase |
| -----BEGIN.*KEY----- | 0 | None in codebase |
| Bearer [A-Za-z0-9]{20,} | 0 | None in codebase |
---
### 6. Test Script Credentials
**File:** `scripts/validate-all.sh`
Contains test credentials for validation:
```bash
# Test credentials for validation purposes only
TEST_USER="testuser"
TEST_PASS="testpass123"
```
**Assessment:** ACCEPTABLE - clearly test credentials for validation, not production.
---
### 7. Build-Time Secret Exposure
**File:** `dockerfiles/postizz-mcp/Dockerfile`
#### Issue Identified
Build arguments potentially expose configuration:
```dockerfile
ARG POSTIZ_WEB_URL=${POSTIZ_WEB_URL}
ENV PORT=${PORT}
```
#### Risk Assessment
- **URL exposure:** Low risk (not a secret)
- **PORT exposure:** Minimal risk (non-sensitive)
- **No API keys in build args:** Confirmed
**Note:** While not currently a security issue, this pattern could lead to secrets being embedded if future changes add API keys as build arguments.
---
## Credential Categories
### Services Requiring Credentials
| Service | Credential Type | Storage |
|---------|-----------------|---------|
| proxmox-mcp | API Token | .env file |
| docker-mcp | Docker Socket | Mount |
| kubernetes-mcp | kubeconfig | File mount |
| ssh-mcp | SSH Private Key | File mount |
| bitwarden-mcp | Access Token | .env file |
| ghost-mcp | API Key | .env file |
| elasticsearch-mcp | Basic Auth | .env file |
| nextcloud-mcp | App Password | .env file |
### Services Without Credentials
Most MCP servers operate without requiring credentials or accept configuration at runtime.
---
## Recommendations
### 1. Add Secret Scanning to CI/CD (MEDIUM PRIORITY)
Implement automated secret detection:
```yaml
# GitHub Actions example
- name: Secret Scan
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
```
### 2. Document Required Secrets (LOW PRIORITY)
Create documentation listing required credentials per service:
```markdown
## proxmox-mcp
- PROXMOX_HOST (required)
- PROXMOX_USER (required)
- PROXMOX_TOKEN_NAME (required)
- PROXMOX_TOKEN_SECRET (required, secret)
```
### 3. Consider Secrets Management (FUTURE)
For production deployment, consider:
- HashiCorp Vault
- AWS Secrets Manager
- Docker Secrets
- Kubernetes Secrets
---
## Positive Findings Summary
1. **No hardcoded secrets** in any tracked file
2. **Proper .gitignore** excludes .env and vendor/
3. **Placeholder-only .env.example** - no real credentials
4. **Runtime credential injection** - not in images
5. **No secrets in git history** based on file analysis
6. **Consistent secure patterns** across wrapper scripts
---
## Compliance Check
| Requirement | Status | Notes |
|-------------|--------|-------|
| No hardcoded secrets | PASS | Full codebase scanned |
| Secrets not in git | PASS | .env gitignored |
| No secrets in Docker images | PASS | Runtime injection only |
| Placeholder examples only | PASS | .env.example clean |
| No secrets in logs | N/A | No logging review performed |
**Overall Secrets Audit: PASS**

View File

@@ -0,0 +1,233 @@
# Base Image Vulnerability Scan
**Date:** 2026-02-20
**Auditor:** External Security Review
**Tool:** Aqua Trivy (latest)
**Scope:** Base images used in project Dockerfiles
## Executive Summary
| Base Image | HIGH | CRITICAL | Total | Status |
|------------|------|----------|-------|--------|
| alpine:3.20 | 0 | 0 | 0 | CLEAN |
| python:3.12-slim | 2 | 0 | 2 | ACTION REQUIRED |
| node:22-slim | 2 | 1 | 3+ | ACTION REQUIRED |
| debian:bookworm-slim | 2 | 1 | 3 | ACTION REQUIRED |
| golang:1.23-alpine | 4 | 2 | 6 | ACTION REQUIRED |
**Overall Risk Level:** MEDIUM
---
## Detailed Findings
### 1. alpine:3.20
**Status:** CLEAN
**Vulnerabilities:** 0 HIGH/CRITICAL
```
Report Summary
┌─────────────────────────────┬────────┬─────────────────┬─────────┐
│ Target │ Type │ Vulnerabilities │ Secrets │
├─────────────────────────────┼────────┼─────────────────┼─────────┤
│ alpine:3.20 (alpine 3.20.9) │ alpine │ 0 │ - │
└─────────────────────────────┴────────┴─────────────────┴─────────┘
```
**Recommendation:** Preferred base image for new containers.
---
### 2. python:3.12-slim (debian 13.3)
**Status:** ACTION REQUIRED
**Vulnerabilities:** 2 HIGH, 0 CRITICAL
| Library | CVE | Severity | Status | Title |
|---------|-----|----------|--------|-------|
| libc-bin | CVE-2026-0861 | HIGH | affected | glibc: Integer overflow in memalign leads to heap corruption |
| libc6 | CVE-2026-0861 | HIGH | affected | glibc: Integer overflow in memalign leads to heap corruption |
**Analysis:**
- glibc vulnerability CVE-2026-0861 affects memory allocation
- No fix currently available from Debian
- Risk: Low for containerized workloads (no untrusted memory allocation)
**Recommendation:**
- Monitor for security updates
- Consider Alpine-based Python images if risk is unacceptable
---
### 3. node:22-slim (debian 12.13)
**Status:** ACTION REQUIRED
**Vulnerabilities:** 2 HIGH, 1 CRITICAL (OS) + 14 HIGH (Node packages)
#### OS-Level Vulnerabilities
| Library | CVE | Severity | Status | Title |
|---------|-----|----------|--------|-------|
| libc-bin | CVE-2026-0861 | HIGH | affected | glibc integer overflow |
| libc6 | CVE-2026-0861 | HIGH | affected | glibc integer overflow |
| zlib1g | CVE-2023-45853 | CRITICAL | will_not_fix | zlib heap-based buffer overflow |
#### Node Package Vulnerabilities
| Package | CVE | Severity | Installed | Fixed | Issue |
|---------|-----|----------|-----------|-------|-------|
| glob | CVE-2025-64756 | HIGH | 10.4.5 | 11.1.0 | Command Injection via Malicious Filenames |
| minimatch | CVE-2026-26996 | HIGH | 9.0.5 | 10.2.1 | ReDoS via repeated wildcards |
| tar | CVE-2026-23745 | HIGH | 6.2.1, 7.4.3 | 7.5.3 | Arbitrary file overwrite and symlink poisoning |
| tar | CVE-2026-23950 | HIGH | 6.2.1, 7.4.3 | 7.5.4 | Arbitrary file overwrite via Unicode path collision |
| tar | CVE-2026-24842 | HIGH | 6.2.1, 7.4.3 | 7.5.7 | Arbitrary file creation via path traversal bypass |
| tar | CVE-2026-26960 | HIGH | 6.2.1, 7.4.3 | 7.5.8 | Multiple issues with default options |
**Analysis:**
- zlib CVE-2023-45853 marked "will_not_fix" - architectural limitation in Debian
- Node tar package has multiple critical file system vulnerabilities
- These are build-time dependencies, reducing runtime risk
**Recommendation:**
- **HIGH PRIORITY:** Update tar package to 7.5.8+
- **HIGH PRIORITY:** Update glob to 11.1.0+ or 10.5.0+
- Monitor for Debian zlib security advisory
---
### 4. debian:bookworm-slim (debian 12.13)
**Status:** ACTION REQUIRED
**Vulnerabilities:** 2 HIGH, 1 CRITICAL
| Library | CVE | Severity | Status | Title |
|---------|-----|----------|--------|-------|
| libc-bin | CVE-2026-0861 | HIGH | affected | glibc integer overflow |
| libc6 | CVE-2026-0861 | HIGH | affected | glibc integer overflow |
| zlib1g | CVE-2023-45853 | CRITICAL | will_not_fix | zlib heap-based buffer overflow |
**Analysis:**
- Same vulnerabilities as node:22-slim (same Debian base)
- zlib vulnerability won't be fixed in Debian 12
**Recommendation:**
- Consider migrating to Alpine or Debian 13
- Monitor security advisories
---
### 5. golang:1.23-alpine (alpine 3.22.1)
**Status:** ACTION REQUIRED
**Vulnerabilities:** 4 HIGH, 2 CRITICAL
| Library | CVE | Severity | Status | Fixed Version | Title |
|---------|-----|----------|--------|---------------|-------|
| libcrypto3 | CVE-2025-15467 | CRITICAL | fixed | 3.5.5-r0 | OpenSSL: Remote code execution or DoS |
| libssl3 | CVE-2025-15467 | CRITICAL | fixed | 3.5.5-r0 | OpenSSL: Remote code execution or DoS |
**Additional vulnerabilities:** 4 HIGH related to Go toolchain (affects build only)
**Analysis:**
- OpenSSL CVE-2025-15467 is CRITICAL with RCE potential
- Fix available (3.5.5-r0) but current image uses 3.5.1-r0
- This is a significant security issue
**Recommendation:**
- **CRITICAL PRIORITY:** Update base image or rebuild with updated packages
- Alpine 3.22.1 should be updated to include OpenSSL fix
---
## Risk Assessment Matrix
| CVE | CVSS | Exploitability | Container Impact | Overall Risk |
|-----|------|----------------|------------------|--------------|
| CVE-2025-15467 (OpenSSL) | CRITICAL | High | High | CRITICAL |
| CVE-2023-45853 (zlib) | CRITICAL | Low | Medium | HIGH |
| CVE-2026-0861 (glibc) | HIGH | Low | Low | MEDIUM |
| CVE-2025-64756 (glob) | HIGH | Medium | Medium | HIGH |
| CVE-2026-23745 (tar) | HIGH | Medium | High | HIGH |
---
## Remediation Priority
### Immediate (Before Release)
1. **Update golang:1.23-alpine** - OpenSSL RCE vulnerability
2. **Update Node tar package** in affected images - Multiple file system vulnerabilities
### Short Term (Post-Release)
3. **Update Node glob and minimatch** packages
4. **Monitor glibc CVE-2026-0861** for patches
5. **Evaluate Alpine-based alternatives** for Python images
### Long Term
6. **Implement automated base image scanning** in CI/CD
7. **Create base image update policy** (monthly refresh)
8. **Consider distroless images** for production
---
## Base Image Recommendations
### For New Services
1. **Prefer Alpine** (alpine:3.20) - currently clean
2. **Pin to digest** for reproducibility:
```dockerfile
FROM alpine:3.20@sha256:exact-digest-here
```
3. **Avoid images with unfixed vulnerabilities**
### Image Selection Priority
1. `alpine:3.20` - CLEAN
2. `python:3.12-slim` - 2 HIGH (glibc, no fix)
3. `node:22-slim` - Multiple HIGH/CRITICAL
4. `debian:bookworm-slim` - Multiple HIGH/CRITICAL
5. `golang:1.23-alpine` - CRITICAL OpenSSL (fix available)
---
## CI/CD Integration Recommendation
```yaml
# Example GitLab CI
container_scan:
image: aquasec/trivy:latest
script:
- trivy image --severity HIGH,CRITICAL --exit-code 1 $IMAGE
only:
- main
- merge requests
```
---
## Scanning Methodology
```bash
# Commands used
docker pull aquasec/trivy:latest
docker run --rm aquasec/trivy:latest image --severity HIGH,CRITICAL --quiet alpine:3.20
docker run --rm aquasec/trivy:latest image --severity HIGH,CRITICAL --quiet python:3.12-slim
docker run --rm aquasec/trivy:latest image --severity HIGH,CRITICAL --quiet node:22-slim
docker run --rm aquasec/trivy:latest image --severity HIGH,CRITICAL --quiet debian:bookworm-slim
docker run --rm aquasec/trivy:latest image --severity HIGH,CRITICAL --quiet golang:1.23-alpine
```
---
## Positive Findings
1. **Alpine images are clean** - Good baseline option available
2. **Fixes available** for most vulnerabilities
3. **No secrets in images** - Confirmed by Trivy scan
4. **Reasonable image selection** - Using official images

View File

@@ -0,0 +1,234 @@
# Security Audit Final Report
**Project:** KNEL-AIMiddleware
**Date:** 2026-02-20
**Auditor:** External Security Review
**Report Version:** 1.0
---
## Executive Summary
### Overall Assessment: CONDITIONAL PASS
The KNEL-AIMiddleware project demonstrates **good foundational security practices** with some areas requiring remediation before production release. The project handles credentials properly, uses official base images, and has no hardcoded secrets. However, container privilege management and base image vulnerabilities require attention.
### Risk Summary
| Category | Risk Level | Issues | Critical Action Required |
|----------|------------|--------|--------------------------|
| Secrets Management | LOW | 0 | No |
| Dockerfile Security | HIGH | 38 | Yes |
| Shell Script Security | HIGH | 83 | Yes |
| Docker Compose | MEDIUM | 5 | Partial |
| Base Image Vulnerabilities | MEDIUM | 14+ | Yes |
### Release Readiness: READY WITH CONDITIONS
**Conditions for Release:**
1. Fix CRITICAL OpenSSL vulnerability in golang:1.23-alpine
2. Document privileged services and their justification
3. Implement remediation plan for HIGH severity findings
---
## Detailed Findings Summary
### 1. Secrets & Credentials (PASS)
**Grade: A**
| Check | Result |
|-------|--------|
| No hardcoded secrets | PASS |
| .env properly gitignored | PASS |
| Placeholder-only examples | PASS |
| Runtime credential injection | PASS |
| No secrets in git history | PASS |
**Finding:** Project follows excellent secret management practices. Credentials are injected at runtime via environment variables, with no secrets in the codebase or Docker images.
---
### 2. Dockerfile Security (NEEDS IMPROVEMENT)
**Grade: C**
| Issue | Severity | Count | Remediation |
|-------|----------|-------|-------------|
| Running as root | HIGH | 38/40 | Add USER directive |
| Missing multi-stage builds | MEDIUM | 32/40 | Convert to multi-stage |
| Build-time secrets | MEDIUM | 1 | Remove ARG for secrets |
| Missing --no-install-recommends | LOW | 2 | Add flag |
**Top Recommendation:** Add non-root users to all Dockerfiles. 95% of containers currently run as root.
---
### 3. Shell Script Security (NEEDS IMPROVEMENT)
**Grade: C-**
| Issue | Severity | Count | Remediation |
|-------|----------|-------|-------------|
| Missing set -e | HIGH | 38 | Add error handling |
| Missing set -u | HIGH | 45 | Add undefined var protection |
| Unquoted variables | MEDIUM | 4 | Quote all variables |
**Top Recommendation:** Add `set -euo pipefail` to all shell scripts.
---
### 4. Docker Compose Security (ACCEPTABLE)
**Grade: B**
| Issue | Severity | Services | Status |
|-------|----------|----------|--------|
| Docker socket mount | HIGH | 2 | Required for function |
| kubeconfig mount | HIGH | 1 | Required for function |
| Default credential pattern | LOW | 1 | Remove defaults |
| No resource limits | MEDIUM | All | Add limits |
| No health checks | MEDIUM | All | Add health checks |
**Finding:** Privileged access (Docker socket, kubeconfig) is necessary for service function but should be documented.
---
### 5. Base Image Vulnerabilities (NEEDS ATTENTION)
**Grade: B-**
| Image | HIGH | CRITICAL | Status |
|-------|------|----------|--------|
| alpine:3.20 | 0 | 0 | Clean |
| python:3.12-slim | 2 | 0 | Monitor |
| node:22-slim | 2 | 1 | Update packages |
| debian:bookworm-slim | 2 | 1 | Monitor |
| golang:1.23-alpine | 4 | 2 | **UPDATE NOW** |
**Critical Finding:** CVE-2025-15467 (OpenSSL RCE) in golang:1.23-alpine requires immediate patching.
---
## Remediation Roadmap
### Phase 1: Pre-Release (Required)
| Priority | Task | Effort | Impact |
|----------|------|--------|--------|
| 1 | Update golang:1.23-alpine base image | Low | Critical |
| 2 | Document privileged services | Low | High |
| 3 | Remove default credential patterns | Low | Medium |
### Phase 2: Short Term (30 Days)
| Priority | Task | Effort | Impact |
|----------|------|--------|--------|
| 4 | Add `set -euo pipefail` to all scripts | Low | High |
| 5 | Add USER directive to Dockerfiles | Medium | High |
| 6 | Update Node tar package | Low | High |
| 7 | Add resource limits to docker-compose | Low | Medium |
### Phase 3: Medium Term (90 Days)
| Priority | Task | Effort | Impact |
|----------|------|--------|--------|
| 8 | Convert to multi-stage builds | High | Medium |
| 9 | Implement CI/CD vulnerability scanning | Medium | High |
| 10 | Add health checks to all services | Medium | Medium |
| 11 | Implement socket proxy for Docker access | Medium | High |
### Phase 4: Long Term (Ongoing)
| Priority | Task | Effort | Impact |
|----------|------|--------|--------|
| 12 | Base image update policy | Low | Medium |
| 13 | Consider distroless images | High | Medium |
| 14 | Network segmentation | Medium | Medium |
---
## Risk Register
### Critical Risks (Address Before Release)
| ID | Risk | Likelihood | Impact | Mitigation |
|----|------|------------|--------|------------|
| R1 | OpenSSL RCE in golang images | Medium | Critical | Update base image |
### High Risks (Address Within 30 Days)
| ID | Risk | Likelihood | Impact | Mitigation |
|----|------|------------|--------|------------|
| R2 | Container privilege escalation | Medium | High | Add USER directives |
| R3 | Silent script failures | Medium | High | Add set -e |
| R4 | Node tar vulnerabilities | Medium | High | Update package |
### Medium Risks (Address Within 90 Days)
| ID | Risk | Likelihood | Impact | Mitigation |
|----|------|------------|--------|------------|
| R5 | Docker socket abuse | Low | High | Document, socket proxy |
| R6 | Resource exhaustion | Low | Medium | Add limits |
| R7 | glibc vulnerability | Low | Medium | Monitor for patches |
---
## Positive Security Practices
The project demonstrates several security-conscious decisions:
1. **Credential Management**
- No hardcoded secrets anywhere
- Environment variables properly externalized
- .env file correctly gitignored
2. **Container Design**
- No privileged mode containers
- Read-only mounts where appropriate
- Official base images used
3. **Project Hygiene**
- Consistent naming conventions
- Clear documentation structure
- Wrapper scripts for configuration isolation
4. **Secret Injection Pattern**
- Runtime injection via environment
- No secrets baked into images
- Pass-through wrapper design
---
## Audit Artifacts
The following detailed reports are available:
1. [01-dockerfile-security.md](./01-dockerfile-security.md) - Dockerfile analysis
2. [02-shell-script-security.md](./02-shell-script-security.md) - Shell script analysis
3. [03-docker-compose-security.md](./03-docker-compose-security.md) - Docker Compose analysis
4. [04-secrets-audit.md](./04-secrets-audit.md) - Credentials and secrets review
5. [05-vulnerability-scan.md](./05-vulnerability-scan.md) - Base image vulnerabilities
---
## Conclusion
KNEL-AIMiddleware is **ready for release with conditions**. The project has solid security fundamentals, particularly in credential management. The primary concerns are:
1. **Immediate:** OpenSSL vulnerability in golang images
2. **Short-term:** Container privilege model (running as root)
3. **Short-term:** Shell script error handling
Addressing the critical OpenSSL vulnerability and documenting privileged services will allow for a safe initial release. The remaining findings should be addressed in subsequent releases.
### Auditor Confidence: HIGH
All major security domains were reviewed. Read-only access was maintained throughout. No destructive testing was performed.
---
*Report generated: 2026-02-20*
*Auditor: External Security Review*
*Classification: Confidential*

18
lsp-bash-wrapper.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
# Wrapper script for bash-language-server LSP
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-bash-language-server"
IMAGE_NAME="kneldevstack-aimiddleware-bash-language-server"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start LSP server with explicit name
exec docker run -i --rm --name "${CONTAINER_NAME}" "${IMAGE_NAME}" start "$@"

18
lsp-docker-wrapper.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
# Wrapper script for docker-language-server LSP
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-docker-language-server"
IMAGE_NAME="kneldevstack-aimiddleware-docker-language-server"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start LSP server with explicit name
exec docker run -i --rm --name "${CONTAINER_NAME}" "${IMAGE_NAME}" start --stdio "$@"

18
lsp-marksman-wrapper.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
# Wrapper script for marksman LSP
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-marksman"
IMAGE_NAME="kneldevstack-aimiddleware-marksman"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start LSP server with explicit name
exec docker run -i --rm --name "${CONTAINER_NAME}" "${IMAGE_NAME}" "$@"

4
lsp-terraform-wrapper.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
docker run -i --rm \
-v "$(pwd):/workspace" \
kneldevstack-aimiddleware-terraform-ls

177
maintenance.sh Executable file
View File

@@ -0,0 +1,177 @@
#!/bin/bash
# maintenance.sh
# Comprehensive maintenance script for KNEL-AIMiddleware
# Combines functionality from the old Makefile with Docker Compose
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Change to project directory
cd "$(dirname "${BASH_SOURCE[0]}")"
# Function to show usage
show_usage() {
cat << EOF
Usage: $0 <command>
Available commands:
clone-vendors Clone all vendor MCP/LSP repositories
build-all Build all MCP/LSP services
build <service> Build a specific service
clean-vendor Remove all cloned vendor repositories
status Check build status of all services
validate Validate MCP servers
logs Show logs from all running services
ps Show status of all services
up [profile] Start services (default: dev profile)
down Stop all services
rebuild <service> Rebuild a specific service
help Show this help message
Examples:
$0 clone-vendors
$0 build ghost-mcp
$0 rebuild context7-mcp
$0 up dev
$0 down
EOF
}
# Function to clone vendor repositories
clone_vendors() {
echo -e "${GREEN}=== Cloning Vendor Repositories ===${NC}"
./scripts/CloneVendorRepos.sh
}
# Function to build all services
build_all() {
echo -e "${GREEN}=== Building All Services ===${NC}"
./scripts/BuildAll.sh
}
# Function to build specific service
build_service() {
local service=$1
if [ -z "$service" ]; then
echo -e "${RED}Error: Service name required${NC}"
echo "Usage: $0 build <service-name>"
exit 1
fi
echo -e "${GREEN}=== Building $service ===${NC}"
docker compose build "$service"
}
# Function to clean vendor directory
clean_vendor() {
echo -e "${YELLOW}=== Cleaning Vendor Directory ===${NC}"
read -p "This will remove all cloned vendor repositories. Continue? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
./scripts/CleanVendor.sh
else
echo "Cancelled."
fi
}
# Function to check status
status() {
echo -e "${GREEN}=== Service Status ===${NC}"
./scripts/StatusCheck.sh
}
# Function to validate MCP servers
validate() {
echo -e "${GREEN}=== Validating MCP Servers ===${NC}"
./scripts/validate-mcp.sh
}
# Function to show logs
logs() {
echo -e "${GREEN}=== Service Logs ===${NC}"
docker compose logs -f
}
# Function to show process status
ps() {
echo -e "${GREEN}=== Service Process Status ===${NC}"
docker compose ps
}
# Function to start services
up() {
local profile=${1:-dev}
echo -e "${GREEN}=== Starting Services (profile: $profile) ===${NC}"
docker compose up -d --profile "$profile"
}
# Function to stop services
down() {
echo -e "${GREEN}=== Stopping Services ===${NC}"
docker compose down
}
# Function to rebuild service
rebuild() {
local service=$1
if [ -z "$service" ]; then
echo -e "${RED}Error: Service name required${NC}"
echo "Usage: $0 rebuild <service-name>"
exit 1
fi
echo -e "${GREEN}=== Rebuilding $service ===${NC}"
docker compose build --no-cache "$service"
docker compose up -d "$service"
}
# Main script logic
case "${1:-help}" in
clone-vendors)
clone_vendors
;;
build-all)
build_all
;;
build)
build_service "$2"
;;
clean-vendor)
clean_vendor
;;
status)
status
;;
validate)
validate
;;
logs)
logs
;;
ps)
ps
;;
up)
up "$2"
;;
down)
down
;;
rebuild)
rebuild "$2"
;;
help|--help|-h)
show_usage
;;
*)
echo -e "${RED}Unknown command: $1${NC}"
echo ""
show_usage
exit 1
;;
esac

22
mcp-actual-wrapper.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Wrapper script for actual-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-actual-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-actual-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e ACTUAL_SERVER_URL="${ACTUAL_SERVER_URL}" \
-e ACTUAL_PASSWORD="${ACTUAL_PASSWORD}" \
-e ACTUAL_BUDGET_SYNC_ID="${ACTUAL_BUDGET_SYNC_ID}" \
"${IMAGE_NAME}" "$@"

21
mcp-ansible-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for mcp-ansible
# Ensures clean container with proper name, playbooks mount, and Docker socket
CONTAINER_NAME="kneldevstack-aimiddleware-mcp-ansible-crush"
IMAGE_NAME="kneldevstack-aimiddleware-mcp-ansible"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name, playbooks mount, and Docker socket
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-v "${HOME}/Projects/KNEL/KNEL-AIMiddleware/ansible-playbooks:/playbooks:ro" \
-v /var/run/docker.sock:/var/run/docker.sock \
"${IMAGE_NAME}" "$@"

20
mcp-audiobook-wrapper.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
# Wrapper script for audiobook-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-audiobook-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-audiobook-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "AUDIOBOOK_ROOT=${AUDIOBOOK_ROOT:-/audiobooks}" \
"${IMAGE_NAME}" "$@"

22
mcp-beszel-wrapper.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Wrapper script for beszel-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-beszel-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-beszel-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e BESZEL_URL="${BESZEL_URL}" \
-e BESZEL_USERNAME="${BESZEL_USERNAME}" \
-e BESZEL_PASSWORD="${BESZEL_PASSWORD}" \
"${IMAGE_NAME}" "$@"

23
mcp-bitwarden-wrapper.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/sh
# Wrapper script for bitwarden-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-bitwarden-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-bitwarden-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "BITWARDEN_CLIENT_ID=${BITWARDEN_CLIENT_ID:-}" \
-e "BITWARDEN_CLIENT_SECRET=${BITWARDEN_CLIENT_SECRET:-}" \
-e "BITWARDEN_PASSWORD=${BITWARDEN_PASSWORD:-}" \
-e "BITWARDEN_SERVER_URL=${BITWARDEN_SERVER_URL:-https://vault.bitwarden.com}" \
"${IMAGE_NAME}" "$@"

21
mcp-blender-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for blender-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-blender-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-blender-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "BLENDER_HOST=${BLENDER_HOST:-localhost}" \
-e "BLENDER_PORT=${BLENDER_PORT:-8888}" \
"${IMAGE_NAME}" "$@"

21
mcp-cloudron-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for cloudron-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-cloudron-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-cloudron-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "CLOUDRON_URL=${CLOUDRON_URL:-}" \
-e "CLOUDRON_TOKEN=${CLOUDRON_TOKEN:-}" \
"${IMAGE_NAME}" "$@"

21
mcp-context7-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for context7-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-context7-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-context7-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "UPSTASH_REDIS_REST_URL=${UPSTASH_REDIS_REST_URL:-}" \
-e "UPSTASH_REDIS_REST_TOKEN=${UPSTASH_REDIS_REST_TOKEN:-}" \
"${IMAGE_NAME}" "$@"

22
mcp-discourse-wrapper.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Wrapper script for discourse-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-discourse-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-discourse-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "DISCOURSE_URL=${DISCOURSE_URL:-}" \
-e "DISCOURSE_API_KEY=${DISCOURSE_API_KEY:-}" \
-e "DISCOURSE_API_USERNAME=${DISCOURSE_API_USERNAME:-}" \
"${IMAGE_NAME}" "$@"

21
mcp-docker-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for docker-mcp
# Ensures clean container with proper name and Docker socket
CONTAINER_NAME="kneldevstack-aimiddleware-docker-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-docker-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name, Docker socket, and config
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "${HOME}/.docker/config.json:/root/.docker/config.json:ro" \
"${IMAGE_NAME}" "$@"

21
mcp-docspace-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for docspace-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-docspace-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-docspace-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "DOCSPACE_HOST=${DOCSPACE_HOST:-}" \
-e "DOCSPACE_TOKEN=${DOCSPACE_TOKEN:-}" \
"${IMAGE_NAME}" "$@"

20
mcp-drawio-wrapper.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
# Wrapper script for drawio-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-drawio-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-drawio-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "DRAWIO_URL=${DRAWIO_URL:-https://app.diagrams.net}" \
"${IMAGE_NAME}" "$@"

22
mcp-elasticsearch-wrapper.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Wrapper script for elasticsearch-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-elasticsearch-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-elasticsearch-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "ES_URL=${ES_URL:-http://localhost:9200}" \
-e "ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME:-}" \
-e "ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD:-}" \
"${IMAGE_NAME}" "$@"

15
mcp-firefly-iii-wrapper.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
# Firefly III MCP wrapper script for Crush
CONTAINER_NAME="kneldevstack-aimiddleware-firefly-iii-mcp-crush"
# Force remove existing container (suppress output)
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true
sleep 0.5
# Run container with explicit name and environment variables
docker run -i --rm \
--name "${CONTAINER_NAME}" \
-e FIREFLY_III_BASE_URL="${FIREFLY_III_BASE_URL:-}" \
-e FIREFLY_III_PAT="${FIREFLY_III_PAT:-}" \
-e FIREFLY_III_PRESET="${FIREFLY_III_PRESET:-default}" \
kneldevstack-aimiddleware-firefly-iii-mcp

20
mcp-freecad-wrapper.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
# Wrapper script for freecad-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-freecad-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-freecad-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "PYTHONUNBUFFERED=1" \
"${IMAGE_NAME}" "$@"

21
mcp-ghost-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for ghost-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-ghost-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-ghost-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "GHOST_API_URL=${GHOST_API_URL:-http://localhost:2368}" \
-e "GHOST_ADMIN_API_KEY=${GHOST_ADMIN_API_KEY:-}" \
"${IMAGE_NAME}" "$@"

20
mcp-gimp-wrapper.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
# Wrapper script for gimp-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-gimp-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-gimp-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "PYTHONUNBUFFERED=1" \
"${IMAGE_NAME}" "$@"

21
mcp-gitea-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for gitea-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-gitea-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-gitea-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e GITEA_URL="${GITEA_URL}" \
-e GITEA_TOKEN="${GITEA_TOKEN}" \
"${IMAGE_NAME}" "$@"

21
mcp-grafana-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for mcp-grafana
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-mcp-grafana-crush"
IMAGE_NAME="kneldevstack-aimiddleware-mcp-grafana"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e GRAFANA_URL="${GRAFANA_URL}" \
-e GRAFANA_TOKEN="${GRAFANA_TOKEN}" \
"${IMAGE_NAME}" "$@"

21
mcp-ha-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for ha-mcp (Home Assistant)
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-ha-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-ha-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e HOMEASSISTANT_URL="${HOMEASSISTANT_URL}" \
-e HOMEASSISTANT_TOKEN="${HOMEASSISTANT_TOKEN}" \
"${IMAGE_NAME}" "$@"

24
mcp-imap-wrapper.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
# Wrapper script for imap-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-imap-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-imap-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "PYTHONUNBUFFERED=1" \
-e "IMAP_HOST=${IMAP_HOST:-}" \
-e "IMAP_PORT=${IMAP_PORT:-993}" \
-e "IMAP_USER=${IMAP_USER:-}" \
-e "IMAP_PASSWORD=${IMAP_PASSWORD:-}" \
"${IMAGE_NAME}" "$@"

5
mcp-kubernetes-wrapper.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
docker run -i --rm \
-v ~/.kube/config:/root/.kube/config:ro \
kneldevstack-aimiddleware-kubernetes-mcp \
--transport stdio

22
mcp-limesurvey-wrapper.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Wrapper script for limesurvey-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-limesurvey-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-limesurvey-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e LIMESURVEY_URL="${LIMESURVEY_URL}" \
-e LIMESURVEY_USERNAME="${LIMESURVEY_USERNAME}" \
-e LIMESURVEY_PASSWORD="${LIMESURVEY_PASSWORD}" \
"${IMAGE_NAME}" "$@"

21
mcp-linkwarden-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for linkwarden-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-linkwarden-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-linkwarden-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e LINKWARDEN_URL="${LINKWARDEN_URL}" \
-e LINKWARDEN_TOKEN="${LINKWARDEN_TOKEN}" \
"${IMAGE_NAME}" "$@"

21
mcp-matomo-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for matomo-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-matomo-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-matomo-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "MATOMO_URL=${MATOMO_URL:-}" \
-e "MATOMO_TOKEN=${MATOMO_TOKEN:-}" \
"${IMAGE_NAME}" "$@"

22
mcp-nextcloud-wrapper.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Wrapper script for nextcloud-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-nextcloud-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-nextcloud-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "NEXTCLOUD_HOST=${NEXTCLOUD_HOST:-}" \
-e "NEXTCLOUD_USERNAME=${NEXTCLOUD_USERNAME:-}" \
-e "NEXTCLOUD_PASSWORD=${NEXTCLOUD_PASSWORD:-}" \
"${IMAGE_NAME}" "$@"

15
mcp-paperless-wrapper.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
# Paperless-NGX MCP wrapper script for Crush
CONTAINER_NAME="kneldevstack-aimiddleware-paperless-mcp-crush"
# Force remove existing container (suppress output)
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true
sleep 0.5
# Run container with explicit name and environment variables
docker run -i --rm \
--name "${CONTAINER_NAME}" \
-e PAPERLESS_URL="${PAPERLESS_URL:-}" \
-e PAPERLESS_TOKEN="${PAPERLESS_TOKEN:-}" \
kneldevstack-aimiddleware-paperless-mcp \
"${PAPERLESS_URL:-http://localhost:8000}" "${PAPERLESS_TOKEN:-}"

21
mcp-penpot-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for penpot-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-penpot-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-penpot-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "PENPOT_URL=${PENPOT_URL:-https://design.penpot.app}" \
-e "PENPOT_TOKEN=${PENPOT_TOKEN:-}" \
"${IMAGE_NAME}" "$@"

21
mcp-postizz-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for postizz-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-postizz-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-postizz-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "POSTIZ_API_KEY=${POSTIZ_API_KEY:-}" \
-e "POSTIZ_URL=${POSTIZ_URL:-}" \
"${IMAGE_NAME}" "$@"

23
mcp-proxmox-wrapper.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/sh
# Wrapper script for proxmox-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-proxmox-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-proxmox-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "PROXMOX_HOST=${PROXMOX_HOST:-}" \
-e "PROXMOX_USER=${PROXMOX_USER:-}" \
-e "PROXMOX_TOKEN=${PROXMOX_TOKEN:-}" \
-e "PROXMOX_NODE=${PROXMOX_NODE:-}" \
"${IMAGE_NAME}" "$@"

21
mcp-redmine-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for mcp-redmine
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-mcp-redmine-crush"
IMAGE_NAME="kneldevstack-aimiddleware-mcp-redmine"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "REDMINE_URL=${REDMINE_URL:-}" \
-e "REDMINE_API_KEY=${REDMINE_API_KEY:-}" \
"${IMAGE_NAME}" "$@"

21
mcp-snipeit-wrapper.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# Wrapper script for snipeit-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-snipeit-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-snipeit-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment variables
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e "SNIPEIT_URL=${SNIPEIT_URL:-}" \
-e "SNIPEIT_TOKEN=${SNIPEIT_TOKEN:-}" \
"${IMAGE_NAME}" "$@"

22
mcp-superset-wrapper.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Wrapper script for superset-mcp
# Ensures clean container with proper name
CONTAINER_NAME="kneldevstack-aimiddleware-superset-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-superset-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" 2>/dev/null
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and environment
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-e SUPERSET_URL="${SUPERSET_URL}" \
-e SUPERSET_USERNAME="${SUPERSET_USERNAME}" \
-e SUPERSET_PASSWORD="${SUPERSET_PASSWORD}" \
"${IMAGE_NAME}" "$@"

20
mcp-terraform-wrapper.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
# Wrapper script for terraform-mcp
# Ensures clean container with proper name and Terraform credentials
CONTAINER_NAME="kneldevstack-aimiddleware-terraform-mcp-crush"
IMAGE_NAME="kneldevstack-aimiddleware-terraform-mcp"
# Force remove existing container if it exists (in any state)
if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
# Wait for container to be fully removed
while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do
sleep 0.05
done
fi
# Start MCP server with explicit name and Terraform credential mounts
exec docker run -i --rm --name "${CONTAINER_NAME}" \
-v "${HOME}/.terraform.d:/terraform/.terraform.d:ro" \
"${IMAGE_NAME}" "$@"

4
mcp-webserial-wrapper.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
docker run -i --rm \
kneldevstack-aimiddleware-webserial-mcp \
ws://host.docker.internal:3000

172
run.sh Executable file
View File

@@ -0,0 +1,172 @@
#!/bin/bash
# KNEL-AIMiddleware Docker Registry Management Script
# Push container images to Gitea Docker registry at git.knownelement.com
set -e
REGISTRY="git.knownelement.com"
REGISTRY_ORG="knel"
REGISTRY_REPO="knel-aimiddleware"
PREFIX="kneldevstack-aimiddleware-"
usage() {
echo "KNEL-AIMiddleware Docker Registry Management"
echo ""
echo "Usage: $0 <command> [options]"
echo ""
echo "Commands:"
echo " list List all built images ready to push"
echo " tag <service> Tag a specific service image for registry"
echo " tag-all Tag all built images for registry"
echo " push <service> Push a specific service image to registry"
echo " push-all Push all built images to registry"
echo " help Show this help message"
echo ""
echo "Examples:"
echo " $0 list"
echo " $0 tag docker-mcp"
echo " $0 push docker-mcp"
echo " $0 push-all"
echo ""
echo "Registry: ${REGISTRY}/${REGISTRY_ORG}/${REGISTRY_REPO}"
exit 1
}
get_built_images() {
docker images --format '{{.Repository}}' | grep "^${PREFIX}" | sort -u || true
}
get_registry_tag() {
local service="$1"
echo "${REGISTRY}/${REGISTRY_ORG}/${REGISTRY_REPO}/${service}:latest"
}
cmd_list() {
echo "Built images ready to push:"
echo ""
for image in $(get_built_images); do
service="${image#"${PREFIX}"}"
registry_tag=$(get_registry_tag "$service")
echo " $image"
echo " -> $registry_tag"
done
echo ""
}
cmd_tag() {
local service="$1"
if [ -z "$service" ]; then
echo "Error: Service name required"
usage
fi
local local_image="${PREFIX}${service}"
local registry_tag
registry_tag=$(get_registry_tag "$service")
if ! docker image inspect "$local_image" &>/dev/null; then
echo "Error: Image $local_image not found. Build it first with: docker compose build $service"
exit 1
fi
echo "Tagging: $local_image -> $registry_tag"
docker tag "$local_image" "$registry_tag"
echo "Done."
}
cmd_tag_all() {
echo "Tagging all built images..."
echo ""
for image in $(get_built_images); do
service="${image#"${PREFIX}"}"
registry_tag=$(get_registry_tag "$service")
echo "Tagging: $image -> $registry_tag"
docker tag "$image" "$registry_tag"
done
echo ""
echo "All images tagged."
}
cmd_push() {
local service="$1"
if [ -z "$service" ]; then
echo "Error: Service name required"
usage
fi
local local_image="${PREFIX}${service}"
local registry_tag
registry_tag=$(get_registry_tag "$service")
if ! docker image inspect "$local_image" &>/dev/null; then
echo "Error: Image $local_image not found. Build it first with: docker compose build $service"
exit 1
fi
echo "Tagging: $local_image -> $registry_tag"
docker tag "$local_image" "$registry_tag"
echo "Pushing: $registry_tag"
docker push "$registry_tag"
echo "Done."
}
cmd_push_all() {
echo "Pushing all built images to ${REGISTRY}/${REGISTRY_ORG}/${REGISTRY_REPO}"
echo ""
local count=0
local failed=0
for image in $(get_built_images); do
service="${image#"${PREFIX}"}"
registry_tag=$(get_registry_tag "$service")
count=$((count + 1))
echo "[${count}] Processing: $service"
echo " Tagging: $image -> $registry_tag"
docker tag "$image" "$registry_tag"
echo " Pushing: $registry_tag"
if docker push "$registry_tag"; then
echo " Success"
else
echo " Failed"
failed=$((failed + 1))
fi
echo ""
done
echo "================================"
echo "Push complete: $count images processed, $failed failed"
}
case "${1:-help}" in
list)
cmd_list
;;
tag)
cmd_tag "$2"
;;
tag-all)
cmd_tag_all
;;
push)
cmd_push "$2"
;;
push-all)
cmd_push_all
;;
help|--help|-h)
usage
;;
*)
echo "Unknown command: $1"
usage
;;
esac

99
scripts/CloneVendorRepos.sh Executable file
View File

@@ -0,0 +1,99 @@
#!/bin/bash
# CloneVendorRepos.sh
# Script to clone all vendor MCP/LSP repositories for KNEL-AIMiddleware
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Vendor directory
VENDOR_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/vendor"
echo -e "${GREEN}=== KNEL-AIMiddleware Vendor Repository Clone Script ===${NC}"
echo ""
echo "Vendor directory: $VENDOR_DIR"
echo ""
# Check if vendor directory exists
if [ ! -d "$VENDOR_DIR" ]; then
echo -e "${YELLOW}Creating vendor directory...${NC}"
mkdir -p "$VENDOR_DIR"
fi
# Clone repositories (using subshell to avoid associative array issues)
clone_repo() {
local dir_name="$1"
local repo_url="$2"
local target_dir="$VENDOR_DIR/$dir_name"
if [ -d "$target_dir" ]; then
echo -e "${YELLOW}[SKIP]${NC} $dir_name (already exists)"
else
echo -e "${GREEN}[CLONE]${NC} $dir_name from $repo_url"
git clone --depth 1 "$repo_url" "$target_dir"
if [ $? -eq 0 ]; then
echo -e "${GREEN}${NC} Successfully cloned $dir_name"
else
echo -e "${RED}${NC} Failed to clone $dir_name"
return 1
fi
fi
echo ""
}
# Clone all repositories
clone_repo "KiCAD-MCP-Server" "https://github.com/mixelpixx/KiCAD-MCP-Server.git"
clone_repo "blender-mcp" "https://github.com/ahujasid/blender-mcp.git"
clone_repo "freecad-mcp" "https://github.com/neka-nat/freecad-mcp.git"
clone_repo "context7" "https://github.com/upstash/context7.git"
clone_repo "gimp-mcp" "https://github.com/maorcc/gimp-mcp.git"
clone_repo "bash-language-server" "https://github.com/bash-lsp/bash-language-server.git"
clone_repo "docker-language-server" "https://github.com/docker/docker-language-server.git"
clone_repo "marksman" "https://github.com/artempyanykh/marksman.git"
clone_repo "drawio-mcp-server" "https://github.com/lgazo/drawio-mcp-server.git"
clone_repo "matomo-mcp-client" "https://github.com/openmost/matomo-mcp-client.git"
clone_repo "imap-mcp" "https://github.com/non-dirty/imap-mcp.git"
clone_repo "mcp-redmine" "https://github.com/runekaagaard/mcp-redmine.git"
clone_repo "ghost-mcp" "https://github.com/MFYDev/ghost-mcp.git"
clone_repo "discourse-mcp" "https://github.com/discourse/discourse-mcp.git"
clone_repo "mcp-cloudron" "https://github.com/serenichron/mcp-cloudron.git"
clone_repo "postizz-MCP" "https://github.com/oculairmedia/postizz-MCP.git"
clone_repo "snipeit-mcp" "https://github.com/Wil-Collier/snipeit-mcp.git"
clone_repo "nextcloud-mcp-server" "https://github.com/cbcoutinho/nextcloud-mcp-server.git"
clone_repo "docspace-mcp" "https://github.com/ONLYOFFICE/docspace-mcp.git"
clone_repo "docker-mcp" "https://github.com/QuantGeekDev/docker-mcp.git"
clone_repo "kubernetes-mcp-server" "https://github.com/containers/kubernetes-mcp-server.git"
clone_repo "ProxmoxMCP" "https://github.com/canvrno/ProxmoxMCP.git"
clone_repo "terraform-mcp-server" "https://github.com/hashicorp/terraform-mcp-server.git"
clone_repo "mcp-ansible" "https://github.com/bsahane/mcp-ansible.git"
clone_repo "mcp-server" "https://github.com/bitwarden/mcp-server.git"
clone_repo "mcp-adapter" "https://github.com/WordPress/mcp-adapter.git"
clone_repo "audiobook-mcp-server" "https://github.com/joelmale/audiobook-mcp-server.git"
clone_repo "paperless-mcp" "https://github.com/nloui/paperless-mcp.git"
clone_repo "penpot-mcp" "https://github.com/penpot/penpot-mcp.git"
clone_repo "ghidra-mcp" "https://github.com/bethington/ghidra-mcp.git"
clone_repo "reverse-engineering-assistant" "https://github.com/cyberkaida/reverse-engineering-assistant.git"
clone_repo "webserial-mcp" "https://github.com/DG1001/webserial-mcp.git"
clone_repo "terraform-ls" "https://github.com/hashicorp/terraform-ls.git"
clone_repo "actual-mcp" "https://github.com/s-stefanov/actual-mcp.git"
clone_repo "superset-mcp" "https://github.com/aptro/superset-mcp.git"
clone_repo "beszel-mcp" "https://github.com/Red5d/beszel-mcp.git"
clone_repo "mcp-grafana" "https://github.com/grafana/mcp-grafana.git"
clone_repo "ha-mcp" "https://github.com/homeassistant-ai/ha-mcp.git"
clone_repo "gitea-mcp" "https://gitea.com/gitea/gitea-mcp.git"
clone_repo "limesurvey-mcp" "https://github.com/TonisOrmisson/limesurvey-mcp.git"
clone_repo "linkwarden-mcp-server" "https://github.com/irfansofyana/linkwarden-mcp-server.git"
clone_repo "firefly-iii-mcp" "https://github.com/etnperlong/firefly-iii-mcp.git"
echo -e "${GREEN}=== All repositories cloned successfully! ===${NC}"
echo ""
echo "Next steps:"
echo " 1. Review and configure environment variables in .env"
echo " 2. Build and test services: docker compose build <service-name>"
echo " 3. Start services: docker compose up -d --profile dev"

View File

@@ -32,7 +32,7 @@ echo ""
for SERVICE in $SERVICES; do
TOTAL=$((TOTAL + 1))
# Construct expected image name
IMAGE_NAME="knel-aimiddleware-$SERVICE"
IMAGE_NAME="kneldevstack-aimiddleware-$SERVICE"
# Check if image exists
if docker images --format '{{.Repository}}' | grep -q "^${IMAGE_NAME}$"; then

348
scripts/validate-all.sh Executable file
View File

@@ -0,0 +1,348 @@
#!/bin/bash
# Comprehensive MCP/LSP Server Validation Script
# Tests all servers with actual protocol messages
#
# Usage:
# ./scripts/validate-all.sh # Test all servers
# ./scripts/validate-all.sh mcp # Test only MCP servers
# ./scripts/validate-all.sh lsp # Test only LSP servers
# ./scripts/validate-all.sh <service> # Test specific service
set -e
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Protocol messages
MCP_INIT='{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"protocolVersion":"2024-11-05","clientInfo":{"name":"validate-all","version":"1.0.0"}},"id":1}'
LSP_INIT='{"jsonrpc":"2.0","method":"initialize","params":{"processId":null,"capabilities":{},"rootUri":null,"workspaceFolders":null},"id":1}'
# Counters
PASSED=0
FAILED=0
SKIPPED=0
NEEDS_ENV=0
NEEDS_SERVICE=0
TRANSPORT_MISMATCH=0
# Results arrays
declare -a RESULTS_PASS
declare -a RESULTS_FAIL
declare -a RESULTS_SKIP
declare -a RESULTS_ENV
declare -a RESULTS_SERVICE
declare -a RESULTS_TRANSPORT
# MCP Servers configuration (container_name, timeout, env_vars...)
declare -A MCP_SERVERS
MCP_SERVERS=(
# Design & Engineering
["kneldevstack-aimiddleware-blender-mcp"]="10"
["kneldevstack-aimiddleware-freecad-mcp"]="10"
["kneldevstack-aimiddleware-gimp-mcp"]="10"
["kneldevstack-aimiddleware-kicad-mcp"]="10 KICAD_HOST=host.docker.internal KICAD_PORT=5555"
# Hosting & Infrastructure
["kneldevstack-aimiddleware-kubernetes-mcp"]="10"
["kneldevstack-aimiddleware-docker-mcp"]="10"
["kneldevstack-aimiddleware-proxmox-mcp"]="10 PROXMOX_HOST=https://proxmox.example.com PROXMOX_USER=root@pam PROXMOX_TOKEN=dummy PROXMOX_NODE=pve"
["kneldevstack-aimiddleware-terraform-mcp"]="10"
["kneldevstack-aimiddleware-cloudron-mcp"]="10 CLOUDRON_URL=https://cloudron.example.com CLOUDRON_TOKEN=dummy"
# Development Tools
["kneldevstack-aimiddleware-context7-mcp"]="10 UPSTASH_REDIS_REST_URL=https://dummy.upstash.io UPSTASH_REDIS_REST_TOKEN=dummy"
# Content Management
["kneldevstack-aimiddleware-nextcloud-mcp"]="10 NEXTCLOUD_HOST=https://nextcloud.example.com NEXTCLOUD_USERNAME=dummy NEXTCLOUD_PASSWORD=dummy"
["kneldevstack-aimiddleware-ghost-mcp"]="10 GHOST_API_URL=https://ghost.example.com GHOST_ADMIN_API_KEY=012345678901234567890123:0123456789012345678901234567890123456789012345678901234567890123"
["kneldevstack-aimiddleware-docspace-mcp"]="10 DOCSPACE_HOST=https://docspace.example.com DOCSPACE_TOKEN=dummy"
["kneldevstack-aimiddleware-wordpress-mcp"]="10 WORDPRESS_URL=https://wordpress.example.com WORDPRESS_USERNAME=dummy WORDPRESS_APPLICATION_PASSWORD=dummy"
# Communication & Collaboration
["kneldevstack-aimiddleware-discourse-mcp"]="10 DISCOURSE_URL=https://discourse.example.com DISCOURSE_API_KEY=dummy DISCOURSE_API_USERNAME=dummy"
["kneldevstack-aimiddleware-imap-mcp"]="10 IMAP_HOST=imap.example.com IMAP_PORT=993 IMAP_USERNAME=dummy IMAP_PASSWORD=dummy"
["kneldevstack-aimiddleware-postizz-mcp"]="10 POSTIZ_API_KEY=dummy POSTIZ_URL=https://postiz.example.com"
# Analytics & Security
["kneldevstack-aimiddleware-matomo-mcp"]="10 MATOMO_URL=https://matomo.example.com MATOMO_TOKEN=dummy"
["kneldevstack-aimiddleware-bitwarden-mcp"]="15 BITWARDEN_CLIENT_ID=dummy BITWARDEN_CLIENT_SECRET=dummy BITWARDEN_PASSWORD=dummy BITWARDEN_SERVER_URL=https://vault.bitwarden.com"
# Productivity & Automation
["kneldevstack-aimiddleware-audiobook-mcp"]="10"
["kneldevstack-aimiddleware-snipeit-mcp"]="10 SNIPEIT_URL=https://snipeit.example.com SNIPEIT_TOKEN=dummy"
["kneldevstack-aimiddleware-mcp-redmine"]="10 REDMINE_URL=https://redmine.example.com REDMINE_API_KEY=dummy"
["kneldevstack-aimiddleware-mcp-ansible"]="10"
["kneldevstack-aimiddleware-elasticsearch-mcp"]="10 ELASTICSEARCH_URL=http://localhost:9200 ELASTICSEARCH_USERNAME=dummy ELASTICSEARCH_PASSWORD=dummy"
["kneldevstack-aimiddleware-drawio-mcp"]="10"
# Additional Tools
["kneldevstack-aimiddleware-penpot-mcp"]="10 PENPOT_URL=https://design.penpot.app PENPOT_TOKEN=dummy"
["kneldevstack-aimiddleware-webserial-mcp"]="10 WEBSOCKET_URL=ws://host.docker.internal:3000"
# Reverse Engineering
["kneldevstack-aimiddleware-ghidra-mcp"]="15"
["kneldevstack-aimiddleware-reverse-engineering-assistant"]="15"
)
# LSP Servers configuration
declare -A LSP_SERVERS
LSP_SERVERS=(
["kneldevstack-aimiddleware-bash-language-server"]="10"
["kneldevstack-aimiddleware-docker-language-server"]="10"
["kneldevstack-aimiddleware-marksman"]="10"
["kneldevstack-aimiddleware-terraform-ls"]="10"
)
# Test MCP server
test_mcp() {
local container=$1
local timeout=$2
shift 2
local env_vars=("$@")
# Check if image exists
if ! docker image inspect "$container" &>/dev/null; then
echo -e "${YELLOW}SKIP${NC} $container: Image not built"
SKIPPED=$((SKIPPED + 1))
RESULTS_SKIP+=("$container: image not built")
return 2
fi
# Build env args
local env_args=""
for env_var in "${env_vars[@]}"; do
env_args="$env_args -e $env_var"
done
# Run test
local result
result=$( (echo "$MCP_INIT" | timeout "$timeout" docker run --rm -i $env_args "$container" 2>&1) || true )
# Check for valid MCP response
if echo "$result" | grep -q '"result".*"serverInfo"'; then
local server_name version
server_name=$(echo "$result" | grep -o '"name":"[^"]*"' | head -1 | cut -d'"' -f4)
version=$(echo "$result" | grep -o '"version":"[^"]*"' | head -1 | cut -d'"' -f4)
echo -e "${GREEN}PASS${NC} $container: $server_name v${version:-unknown}"
PASSED=$((PASSED + 1))
RESULTS_PASS+=("$container: $server_name v${version:-unknown}")
return 0
fi
# Check for specific failure modes
if echo "$result" | grep -qi "environment variable\|missing.*env\|required.*variable"; then
echo -e "${YELLOW}ENV${NC} $container: Needs environment variables"
NEEDS_ENV=$((NEEDS_ENV + 1))
RESULTS_ENV+=("$container")
return 3
fi
if echo "$result" | grep -qi "connection refused\|not connected\|ECONNREFUSED\|ETIMEDOUT\|network unreachable"; then
echo -e "${YELLOW}SVC${NC} $container: Needs backend service"
NEEDS_SERVICE=$((NEEDS_SERVICE + 1))
RESULTS_SERVICE+=("$container")
return 4
fi
if echo "$result" | grep -qi "http\|websocket\|ws://\|transport"; then
echo -e "${BLUE}TRN${NC} $container: Transport mismatch (not stdio)"
TRANSPORT_MISMATCH=$((TRANSPORT_MISMATCH + 1))
RESULTS_TRANSPORT+=("$container")
return 5
fi
# Generic failure
echo -e "${RED}FAIL${NC} $container: No valid response"
FAILED=$((FAILED + 1))
RESULTS_FAIL+=("$container: $(echo "$result" | head -1 | cut -c1-60)")
return 1
}
# Test LSP server
test_lsp() {
local container=$1
local timeout=$2
# Check if image exists
if ! docker image inspect "$container" &>/dev/null; then
echo -e "${YELLOW}SKIP${NC} $container: Image not built"
SKIPPED=$((SKIPPED + 1))
RESULTS_SKIP+=("$container: image not built")
return 2
fi
# Run test
local result
result=$( (echo "$LSP_INIT" | timeout "$timeout" docker run --rm -i "$container" 2>&1) || true )
# Check for valid LSP response
if echo "$result" | grep -q '"result".*"capabilities"'; then
echo -e "${GREEN}PASS${NC} $container: LSP initialized"
PASSED=$((PASSED + 1))
RESULTS_PASS+=("$container: LSP initialized")
return 0
fi
# Generic failure
echo -e "${RED}FAIL${NC} $container: No valid response"
FAILED=$((FAILED + 1))
RESULTS_FAIL+=("$container: $(echo "$result" | head -1 | cut -c1-60)")
return 1
}
# Print summary
print_summary() {
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}VALIDATION SUMMARY${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo -e "${GREEN}PASSED ($PASSED):${NC}"
if [ ${#RESULTS_PASS[@]} -gt 0 ]; then
for r in "${RESULTS_PASS[@]}"; do
echo "$r"
done
else
echo " (none)"
fi
echo ""
if [ ${#RESULTS_ENV[@]} -gt 0 ]; then
echo -e "${YELLOW}NEEDS ENV VARS ($NEEDS_ENV):${NC}"
for r in "${RESULTS_ENV[@]}"; do
echo "$r"
done
echo ""
fi
if [ ${#RESULTS_SERVICE[@]} -gt 0 ]; then
echo -e "${YELLOW}NEEDS BACKEND SERVICE ($NEEDS_SERVICE):${NC}"
for r in "${RESULTS_SERVICE[@]}"; do
echo "$r"
done
echo ""
fi
if [ ${#RESULTS_TRANSPORT[@]} -gt 0 ]; then
echo -e "${BLUE}TRANSPORT MISMATCH ($TRANSPORT_MISMATCH):${NC}"
for r in "${RESULTS_TRANSPORT[@]}"; do
echo "$r"
done
echo ""
fi
if [ ${#RESULTS_SKIP[@]} -gt 0 ]; then
echo -e "${YELLOW}SKIPPED ($SKIPPED):${NC}"
for r in "${RESULTS_SKIP[@]}"; do
echo " - $r"
done
echo ""
fi
if [ ${#RESULTS_FAIL[@]} -gt 0 ]; then
echo -e "${RED}FAILED ($FAILED):${NC}"
for r in "${RESULTS_FAIL[@]}"; do
echo "$r"
done
echo ""
fi
echo -e "${BLUE}========================================${NC}"
echo -e "Total: ${GREEN}$PASSED passed${NC}, ${RED}$FAILED failed${NC}, ${YELLOW}$SKIPPED skipped${NC}"
echo -e " ${YELLOW}$NEEDS_ENV need env${NC}, ${YELLOW}$NEEDS_SERVICE need service${NC}, ${BLUE}$TRANSPORT_MISMATCH transport mismatch${NC}"
echo -e "${BLUE}========================================${NC}"
# Return non-zero if any hard failures
[ $FAILED -eq 0 ]
}
# Main
main() {
local mode="${1:-all}"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}KNEL-AIMiddleware Validation${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
case "$mode" in
mcp)
echo -e "${BLUE}Testing MCP Servers...${NC}"
echo ""
for container in "${!MCP_SERVERS[@]}"; do
config="${MCP_SERVERS[$container]}"
read -ra parts <<< "$config"
timeout="${parts[0]}"
env_vars=("${parts[@]:1}")
test_mcp "$container" "$timeout" "${env_vars[@]}" || true
done
;;
lsp)
echo -e "${BLUE}Testing LSP Servers...${NC}"
echo ""
for container in "${!LSP_SERVERS[@]}"; do
config="${LSP_SERVERS[$container]}"
read -ra parts <<< "$config"
timeout="${parts[0]}"
test_lsp "$container" "$timeout" || true
done
;;
all)
echo -e "${BLUE}Testing MCP Servers...${NC}"
echo ""
for container in "${!MCP_SERVERS[@]}"; do
config="${MCP_SERVERS[$container]}"
read -ra parts <<< "$config"
timeout="${parts[0]}"
env_vars=("${parts[@]:1}")
test_mcp "$container" "$timeout" "${env_vars[@]}" || true
done
echo ""
echo -e "${BLUE}Testing LSP Servers...${NC}"
echo ""
for container in "${!LSP_SERVERS[@]}"; do
config="${LSP_SERVERS[$container]}"
read -ra parts <<< "$config"
timeout="${parts[0]}"
test_lsp "$container" "$timeout" || true
done
;;
*)
# Test specific service
if [[ -v MCP_SERVERS["kneldevstack-aimiddleware-$mode"] ]]; then
container="kneldevstack-aimiddleware-$mode"
config="${MCP_SERVERS[$container]}"
read -ra parts <<< "$config"
timeout="${parts[0]}"
env_vars=("${parts[@]:1}")
test_mcp "$container" "$timeout" "${env_vars[@]}"
elif [[ -v LSP_SERVERS["kneldevstack-aimiddleware-$mode"] ]]; then
container="kneldevstack-aimiddleware-$mode"
config="${LSP_SERVERS[$container]}"
read -ra parts <<< "$config"
timeout="${parts[0]}"
test_lsp "$container" "$timeout"
else
echo -e "${RED}Unknown service: $mode${NC}"
echo "Available MCP services: ${!MCP_SERVERS[@]#kneldevstack-aimiddleware-}"
echo "Available LSP services: ${!LSP_SERVERS[@]#kneldevstack-aimiddleware-}"
exit 1
fi
;;
esac
if [ "$mode" != "all" ] && [ "$mode" != "mcp" ] && [ "$mode" != "lsp" ]; then
# Single service test, no summary
exit $?
fi
print_summary
}
main "$@"

View File

@@ -13,7 +13,7 @@ INIT_MSG='{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"pr
# Test a container with initialize message
test_mcp_server() {
local container_name=$1
local timeout=${2:-5}
local timeout=${2:-10}
shift 2
local env_vars=("$@")
@@ -26,11 +26,8 @@ test_mcp_server() {
done
# Run container with stdin input and environment variables
result=$(timeout $timeout docker run --rm -i --name "$container_name-test" \
$env_args \
"$container_name" \
<<<"$INIT_MSG" \
2>&1)
# Note: Using subshell with timeout for the docker run command
result=$( (echo "$INIT_MSG" | timeout $timeout docker run --rm -i --name "$container_name-test" $env_args "$container_name" 2>&1) || true )
# Check for valid JSON-RPC response
if echo "$result" | grep -q '"result"'; then
@@ -65,32 +62,32 @@ test_mcp_server() {
echo -e "${YELLOW}=== MCP Server Validation ===${NC}\n"
# Stdio-based MCP servers
test_mcp_server "kneldevstack-aimiddleware-ghost-mcp" \
"GHOST_URL=https://ghost.example.com" \
"GHOST_API_KEY=dummy-key"
test_mcp_server "kneldevstack-aimiddleware-ghost-mcp" 5 \
"GHOST_API_URL=https://ghost.example.com" \
"GHOST_ADMIN_API_KEY=012345678901234567890123:0123456789012345678901234567890123456789012345678901234567890123"
test_mcp_server "kneldevstack-aimiddleware-penpot-mcp" \
test_mcp_server "kneldevstack-aimiddleware-penpot-mcp" 5 \
"PENPOT_URL=https://design.penpot.app" \
"PENPOT_TOKEN=dummy-token"
test_mcp_server "kneldevstack-aimiddleware-imap-mcp" \
test_mcp_server "kneldevstack-aimiddleware-imap-mcp" 5 \
"IMAP_HOST=imap.example.com" \
"IMAP_USERNAME=user@example.com" \
"IMAP_PASSWORD=dummy-password"
test_mcp_server "kneldevstack-aimiddleware-proxmox-mcp" \
test_mcp_server "kneldevstack-aimiddleware-proxmox-mcp" 5 \
"PROXMOX_HOST=https://proxmox.example.com" \
"PROXMOX_USER=root@pam" \
"PROXMOX_TOKEN=dummy-token" \
"PROXMOX_NODE=pve"
test_mcp_server "kneldevstack-aimiddleware-context7-mcp"
test_mcp_server "kneldevstack-aimiddleware-context7-mcp" 5
test_mcp_server "kneldevstack-aimiddleware-docker-mcp"
test_mcp_server "kneldevstack-aimiddleware-docker-mcp" 5
test_mcp_server "kneldevstack-aimiddleware-drawio-mcp"
test_mcp_server "kneldevstack-aimiddleware-drawio-mcp" 5
test_mcp_server "kneldevstack-aimiddleware-mcp-redmine" \
test_mcp_server "kneldevstack-aimiddleware-mcp-redmine" 5 \
"REDMINE_URL=https://redmine.example.com" \
"REDMINE_API_KEY=dummy-key"