Compare commits
65 Commits
aefeaa30fc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
616085e0cf | ||
|
|
e886950c40 | ||
|
|
ad9c4c450e | ||
|
|
afa88abda4 | ||
|
|
fedd591b75 | ||
|
|
855b6e1f22 | ||
|
|
1526af86d8 | ||
|
|
a73699ad8b | ||
|
|
787fe1f702 | ||
|
|
d97fb09a9d | ||
|
|
d80eff6df6 | ||
|
|
cde8838133 | ||
|
|
b1965c8161 | ||
|
|
bdadb891f2 | ||
|
|
ea3b0907ae | ||
|
|
32c003d2d9 | ||
|
|
5fd45d48c9 | ||
|
|
72d5058659 | ||
|
|
671b9f57d1 | ||
|
|
ff5c73de7c | ||
|
|
ff897aec58 | ||
|
|
bc89169265 | ||
|
|
55166db065 | ||
|
|
30cb9a8829 | ||
|
|
0972556b38 | ||
|
|
e7df499874 | ||
|
|
0c20861103 | ||
|
|
af1a823683 | ||
|
|
7304d1e4a8 | ||
|
|
60f317e92c | ||
|
|
3bdf281a4a | ||
|
|
04e9d80025 | ||
|
|
feea0945c1 | ||
| b211d36bd2 | |||
| d067f195c2 | |||
| 2596cc42e0 | |||
| 2b79f5dd95 | |||
| fcfb6f486a | |||
| 834d3524a0 | |||
| 475bc39111 | |||
| 2cb5f29683 | |||
| c5393f9b5e | |||
| 5398e4b7e6 | |||
| fa0b2b95c5 | |||
| 6017d996fe | |||
| 8c67bbcf77 | |||
| 15c5cd8446 | |||
| 2c0e19ab2b | |||
| a024b4c353 | |||
| a08204920d | |||
| 1638fffbdb | |||
| b6e4499bec | |||
| 2c26012c01 | |||
| c023d939bd | |||
| ea1c90d53e | |||
| 7c583e2821 | |||
| 3c0565d0e9 | |||
| 8f0c366686 | |||
| 34844512a8 | |||
| a7e5c61e6a | |||
| 982f6afd6d | |||
| c3f216e6bd | |||
| fea9473d83 | |||
| a0ca7c9eaf | |||
| 1b01b3303b |
96
.env
96
.env
@@ -1,86 +1,14 @@
|
|||||||
# Dummy environment variables for MCP servers
|
# Nextcloud MCP
|
||||||
# Replace with actual values as needed
|
NEXTCLOUD_HOST=
|
||||||
|
NEXTCLOUD_USERNAME=
|
||||||
|
NEXTCLOUD_APP_PASSWORD=
|
||||||
|
|
||||||
# KiCAD
|
# IMAP MCP
|
||||||
KICAD_HOST=host.docker.internal
|
IMAP_SERVER=
|
||||||
KICAD_PORT=5555
|
IMAP_PORT=
|
||||||
|
IMAP_USERNAME=
|
||||||
|
IMAP_PASSWORD=
|
||||||
|
|
||||||
# Proxmox
|
# Home Assistant (if needed)
|
||||||
PROXMOX_HOST=https://proxmox.example.com:8006
|
HOMEASSISTANT_URL=
|
||||||
PROXMOX_USER=root@pam
|
HOMEASSISTANT_TOKEN=
|
||||||
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
|
|
||||||
|
|||||||
100
.env.example
Normal file
100
.env.example
Normal 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
25
.githooks/pre-push
Executable 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
3
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
vendor/
|
vendor
|
||||||
|
.env
|
||||||
|
|||||||
268
AGENTS.md
268
AGENTS.md
@@ -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)
|
## SDLC Compliance
|
||||||
| 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 |
|
|
||||||
|
|
||||||
#### Hosting & Infrastructure (5 servers)
|
All MCP/LSP development MUST follow [docs/SDLC.md](docs/SDLC.md).
|
||||||
| 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 |
|
|
||||||
|
|
||||||
#### Development Tools (2 servers)
|
**Key rule**: Protocol handshake is NON-NEGOTIABLE - build + start + protocol validation ALL required before marking a server as "working".
|
||||||
| 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 |
|
|
||||||
|
|
||||||
#### Content Management (4 servers)
|
## Status Tracking
|
||||||
| 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 |
|
|
||||||
|
|
||||||
#### Communication & Collaboration (3 servers)
|
Current operational status of all MCP servers is maintained in [STATUS.md](STATUS.md).
|
||||||
| 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.
|
|
||||||
|
|
||||||
When working on any MCP server:
|
When working on any MCP server:
|
||||||
1. **Before starting work**: Review current status in STATUS.md
|
1. **Before starting**: Review current status in STATUS.md
|
||||||
2. **During work**: Update STATUS.md immediately after each significant milestone (build, start, validation, issues)
|
2. **During work**: Update STATUS.md immediately after each significant milestone
|
||||||
3. **After completing work**: Ensure STATUS.md accurately reflects final status with relevant notes
|
3. **After completing**: Ensure STATUS.md accurately reflects final status
|
||||||
4. **Commit STATUS.md changes**: Always commit STATUS.md updates in separate atomic commits with clear commit messages
|
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
|
ALL work performed on this project MUST be documented in [JOURNAL.md](JOURNAL.md).
|
||||||
- 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
|
|
||||||
|
|
||||||
### 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
|
```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)
|
2. `crush.json` (project-local)
|
||||||
3. `$HOME/.config/crush/crush.json` (global)
|
3. `$HOME/.config/crush/crush.json` (global)
|
||||||
|
|
||||||
**For Docker-based LSP/MCP instances:**
|
**Docker-based instances:**
|
||||||
- Use `docker` as the command
|
- Use `docker` as command
|
||||||
- Include container name as the main argument
|
- Include container name as main argument
|
||||||
- Use `-i` for interactive mode (required for stdio communication)
|
- Use `-i` for interactive mode (required for stdio)
|
||||||
- Use `--rm` to automatically clean up containers after use
|
- Use `--rm` to auto-cleanup containers
|
||||||
|
|
||||||
## Validation Checklist
|
## Validation Checklist
|
||||||
|
|
||||||
For each agent, verify:
|
For each agent, verify in order:
|
||||||
- [ ] Container builds successfully
|
- [ ] Container builds successfully
|
||||||
- [ ] Container starts without errors
|
- [ ] Container starts without errors
|
||||||
|
- [ ] **Protocol handshake returns valid response** (MANDATORY - see SDLC)
|
||||||
- [ ] Logs show proper initialization
|
- [ ] Logs show proper initialization
|
||||||
- [ ] Environment variables are correctly set (if required)
|
- [ ] Environment variables correctly set (if required)
|
||||||
- [ ] MCP protocol handshake completes
|
- [ ] Tools registered and available
|
||||||
- [ ] Tools are registered and available
|
- [ ] Resources accessible (if applicable)
|
||||||
- [ ] Resources are 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 Handshake Command
|
||||||
- [MCP SDK](https://github.com/modelcontextprotocol/sdk)
|
|
||||||
- [AIWorkStack-dev](https://github.com/stars/ReachableCEO/lists/aiworkstack-dev)
|
```bash
|
||||||
- [AIWorkStack-ops](https://github.com/stars/ReachableCEO/lists/aiworkstack-ops)
|
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
|
||||||
|
|||||||
@@ -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
1900
JOURNAL.md
Normal file
File diff suppressed because it is too large
Load Diff
129
LSP_SETUP.md
Normal file
129
LSP_SETUP.md
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# LSP Container Configuration
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
- **bash-language-server**: ✅ Working - Fixed crash by adding `start` command
|
||||||
|
- **docker-language-server**: ✅ Working - Fixed by adding `start --stdio` command
|
||||||
|
- **marksman**: ✅ Working - Fixed by adding `server` command
|
||||||
|
|
||||||
|
## Architecture Notes
|
||||||
|
|
||||||
|
### Why LSP Containers Don't Run Continuously
|
||||||
|
|
||||||
|
The bash, docker, and markdown LSP servers are **stdio-based LSP servers**. This means:
|
||||||
|
|
||||||
|
1. They communicate via stdin/stdout (not network sockets)
|
||||||
|
2. Each LSP client needs its own process instance
|
||||||
|
3. They exit when the client disconnects (end of stdin)
|
||||||
|
|
||||||
|
This is **by design** and is the standard way LSP servers work:
|
||||||
|
|
||||||
|
```
|
||||||
|
Crush Session 1 → docker run -i bash-lsp → [bash-language-server process]
|
||||||
|
Crush Session 2 → docker run -i bash-lsp → [bash-language-server process]
|
||||||
|
```
|
||||||
|
|
||||||
|
Each session needs its own container instance because the stdio connection is 1-to-1.
|
||||||
|
|
||||||
|
### Startup Performance
|
||||||
|
|
||||||
|
Despite creating new containers for each session, startup is fast because:
|
||||||
|
|
||||||
|
1. **Docker images are pre-built**: No build time
|
||||||
|
2. **Container creation is fast**: < 1 second typically
|
||||||
|
3. **Layers are cached**: All dependencies already present
|
||||||
|
|
||||||
|
The main delay only happens on the first startup when the image is built.
|
||||||
|
|
||||||
|
### Alternatives for Persistent Containers
|
||||||
|
|
||||||
|
If you truly need persistent containers to avoid all startup delay, you would need:
|
||||||
|
|
||||||
|
#### Option 1: TCP-based LSP Servers
|
||||||
|
- Modify LSP servers to listen on TCP ports instead of stdio
|
||||||
|
- Run containers in detached mode with exposed ports
|
||||||
|
- Connect to existing containers
|
||||||
|
|
||||||
|
Pros: Zero startup delay, true persistent containers
|
||||||
|
Cons: Requires modifying LSP servers or finding TCP-compatible alternatives
|
||||||
|
|
||||||
|
#### Option 2: Proxy Wrapper (Complex)
|
||||||
|
- Run containers in detached mode with a proxy process
|
||||||
|
- Proxy handles multiple Crush sessions
|
||||||
|
- Routes stdio between Crush and LSP servers
|
||||||
|
|
||||||
|
Pros: Persistent containers, no LSP server modifications
|
||||||
|
Cons: Complex implementation, potential performance overhead, single point of failure
|
||||||
|
|
||||||
|
#### Option 3: Current Implementation (Recommended)
|
||||||
|
- Run on-demand with `docker run -i --rm`
|
||||||
|
- Each Crush session gets its own container
|
||||||
|
- Fast startup with pre-built images
|
||||||
|
|
||||||
|
Pros: Simple, reliable, standard LSP architecture
|
||||||
|
Cons: ~1 second startup per session
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The current `crush.json` configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lsp": {
|
||||||
|
"bash": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bash-language-server", "start"]
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-docker-language-server", "start", "--stdio"]
|
||||||
|
},
|
||||||
|
"markdown": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-marksman", "server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Points
|
||||||
|
|
||||||
|
- `-i`: Interactive mode (required for stdio)
|
||||||
|
- `--rm`: Remove container after exit (cleanup)
|
||||||
|
- Command arguments: `start`, `start --stdio`, `server` (varies by LSP)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Container keeps crashing"
|
||||||
|
|
||||||
|
If you see LSP containers restarting repeatedly, check:
|
||||||
|
|
||||||
|
1. **Is the container configured for detached mode?**
|
||||||
|
- LSP servers should NOT run in detached mode
|
||||||
|
- They should be started on-demand via `docker run -i`
|
||||||
|
|
||||||
|
2. **Is the command specified?**
|
||||||
|
- `bash-language-server` needs `start`
|
||||||
|
- `docker-language-server` needs `start --stdio`
|
||||||
|
- `marksman` needs `server`
|
||||||
|
|
||||||
|
3. **Check crush.json configuration**
|
||||||
|
- Ensure all command arguments are included
|
||||||
|
- See configuration section above
|
||||||
|
|
||||||
|
### Testing LSP Servers
|
||||||
|
|
||||||
|
Test each LSP manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test bash LSP
|
||||||
|
echo '{}' | timeout 2 docker run -i --rm kneldevstack-aimiddleware-bash-language-server start
|
||||||
|
|
||||||
|
# Test docker LSP
|
||||||
|
echo '{}' | timeout 2 docker run -i --rm kneldevstack-aimiddleware-docker-language-server start --stdio
|
||||||
|
|
||||||
|
# Test marksman
|
||||||
|
echo '{}' | timeout 2 docker run -i --rm kneldevstack-aimiddleware-marksman server
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: Exit code 124 (timeout), meaning the LSP server is running and waiting for input.
|
||||||
63
Makefile
63
Makefile
@@ -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
206
PRODUCTION-READY.md
Normal 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
305
README.md
@@ -4,34 +4,159 @@
|
|||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
[](https://modelcontextprotocol.io/)
|
[](https://modelcontextprotocol.io/)
|
||||||
[](https://microsoft.github.io/language-server-protocol/)
|
[](https://microsoft.github.io/language-server-protocol/)
|
||||||
|
[](PRODUCTION-READY.md)
|
||||||
|
|
||||||
> MCP and LSP infrastructure for OpenWebUI and Crush to utilize
|
> 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.
|
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
|
- **OpenWebUI Integration**: Provide MCP servers for enhanced AI context and tooling
|
||||||
- **Crush Integration**: LSP servers for intelligent code completion and analysis
|
- **Crush Integration**: LSP servers for intelligent code completion and analysis
|
||||||
- **Development**: Individual server isolation for easy debugging and updates
|
- **Development**: Individual server isolation for easy debugging and updates
|
||||||
- **Production**: Scalable, containerized service deployment
|
- **Production**: Scalable, containerized service deployment
|
||||||
|
|
||||||
## 🚀 Features
|
### Features
|
||||||
|
|
||||||
- ✅ **Modular Architecture**: Each service runs in its own container
|
- Modular architecture with each service in its own container
|
||||||
- ✅ **Docker Compose**: Easy orchestration and management
|
- Docker Compose orchestration and management
|
||||||
- ✅ **Prebuilt Images**: Optimized container images with minimal dependencies
|
- Prebuilt images with minimal dependencies
|
||||||
- ✅ **Crush Ready**: Pre-configured LSP servers for `crush.json`
|
- Crush-ready LSP server configuration
|
||||||
- ✅ **Environment Variables**: Secure configuration via `.env` file
|
- Environment variables for secure configuration
|
||||||
- ✅ **Health Monitoring**: Built-in logging and container health checks
|
- 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).
|
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
|
### Prerequisites
|
||||||
|
|
||||||
@@ -64,75 +189,33 @@ For detailed build and configuration status of all MCP/LSP servers, see [STATUS.
|
|||||||
|
|
||||||
### Setup Scripts
|
### 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:
|
Clone all upstream vendor MCP/LSP repositories:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./CloneVendorRepos.sh
|
./scripts/CloneVendorRepos.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This script clones all 27 vendor repositories into `vendor/` directory.
|
#### scripts/BuildAll.sh
|
||||||
|
|
||||||
#### BuildAll.sh
|
|
||||||
Build all MCP/LSP services:
|
Build all MCP/LSP services:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./BuildAll.sh
|
./scripts/BuildAll.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This script iterates through all services in `docker-compose.yml` and builds each one.
|
#### scripts/CleanVendor.sh
|
||||||
|
|
||||||
#### CleanVendor.sh
|
|
||||||
Remove all cloned vendor repositories:
|
Remove all cloned vendor repositories:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./CleanVendor.sh
|
./scripts/CleanVendor.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
⚠️ **Warning**: This permanently deletes all cloned vendor repositories. You'll need to re-clone them.
|
#### scripts/StatusCheck.sh
|
||||||
|
|
||||||
#### StatusCheck.sh
|
|
||||||
Check build status of all services:
|
Check build status of all services:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./StatusCheck.sh
|
./scripts/StatusCheck.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This script checks which Docker images exist and compares with `STATUS.md`.
|
## Usage
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
### Docker Compose Commands
|
### Docker Compose Commands
|
||||||
|
|
||||||
@@ -190,7 +273,36 @@ docker compose --profile prod up
|
|||||||
docker compose --profile design 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.
|
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/
|
KNEL-AIMiddleware/
|
||||||
├── docker-compose.yml # Service orchestration
|
├── docker-compose.yml # Service orchestration
|
||||||
├── .env # Environment variables (not committed)
|
├── .env # Environment variables (not committed)
|
||||||
├── .env.example # Environment template
|
├── .env.example # Environment template
|
||||||
├── dockerfiles/ # Custom Dockerfiles (tracked in git)
|
├── dockerfiles/ # Custom Dockerfiles (tracked in git)
|
||||||
│ ├── bash-language-server/
|
│ ├── bash-language-server/
|
||||||
│ ├── docker-language-server/
|
│ ├── docker-language-server/
|
||||||
│ └── marksman/
|
│ └── marksman/
|
||||||
├── vendor/ # Cloned repositories (gitignored)
|
├── vendor/ # Cloned repositories (gitignored)
|
||||||
│ ├── bash-language-server/
|
├── docs/ # Documentation
|
||||||
│ ├── docker-language-server/
|
│ └── SDLC.md # Software Development Lifecycle
|
||||||
│ └── marksman/
|
├── AGENTS.md # AI agent guidelines and rules
|
||||||
├── AGENTS.md # Development workflow and conventions
|
├── STATUS.md # Server status and progress tracking
|
||||||
├── STATUS.md # Server status and progress tracking
|
├── JOURNAL.md # Development journal (ADRs, insights)
|
||||||
└── README.md # This file
|
└── README.md # This file
|
||||||
```
|
```
|
||||||
|
|
||||||
### Dockerfile Management
|
### Dockerfile Management
|
||||||
@@ -277,22 +389,7 @@ This approach:
|
|||||||
- Uses vendor repository as build context
|
- Uses vendor repository as build context
|
||||||
- Maintains clean separation of concerns
|
- Maintains clean separation of concerns
|
||||||
|
|
||||||
## 🌍 Environment Variables
|
## Troubleshooting
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
### Container Not Starting
|
### Container Not Starting
|
||||||
|
|
||||||
@@ -331,32 +428,22 @@ ports:
|
|||||||
- "8081:8080" # Change host port
|
- "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
|
## References
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
||||||
- [Language Server Protocol](https://microsoft.github.io/language-server-protocol/)
|
- [Language Server Protocol](https://microsoft.github.io/language-server-protocol/)
|
||||||
|
- [MCP SDK](https://github.com/modelcontextprotocol/sdk)
|
||||||
- [Docker](https://www.docker.com/)
|
- [Docker](https://www.docker.com/)
|
||||||
- [Charmbracelet Crush](https://github.com/charmbracelet/crush)
|
- [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
|
**Maintained by**: KNEL Development Team
|
||||||
**Last Updated**: 2024-01-21
|
|
||||||
|
|||||||
211
STATUS.md
211
STATUS.md
@@ -2,37 +2,190 @@
|
|||||||
|
|
||||||
Tracking the setup and validation of MCP/LSP servers via Docker Compose.
|
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 |
|
| Repository | Status | Notes |
|
||||||
|------------|--------|-------|
|
|------------|--------|-------|
|
||||||
| KiCAD-MCP-Server | Documented | Host-only - requires KiCAD installed on host. Connects via TCP to KICAD_HOST:KICAD_PORT |
|
| audiobook-mcp | Built | Container built from source (361MB). MCP stdio-based, requires AUDIOBOOK_ROOT env var. Version 1.1.0. |
|
||||||
| freecad-mcp | Built | Container built successfully with uvx entrypoint |
|
| bitwarden-mcp | Built | Container built from bitwarden/mcp-server. MCP stdio-based, requires Bitwarden credentials. |
|
||||||
| blender-mcp | Built | Container built successfully with uvx entrypoint |
|
| 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. |
|
||||||
| context7 | Pending | |
|
| cloudron-mcp | Built | Container built from source (374MB). MCP stdio-based, requires CLOUDRON_URL env var. Version 0.1.0. |
|
||||||
| gimp-mcp | Built | Container built successfully with uvx entrypoint |
|
| 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. |
|
||||||
| bash-language-server | Built | Container built using prebuilt npm package (190MB). Configured for Crush via docker run with -i flag for stdio. |
|
| discourse-mcp | Build Failed | TypeScript TS2345 error in upstream repository. Cannot build locally. |
|
||||||
| docker-language-server | Built | Container built from Go source (49.2MB). Configured for Crush via docker run with -i flag for stdio. |
|
| 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. |
|
||||||
| marksman | Built | Container built from prebuilt binary (144MB). Configured for Crush via docker run with -i flag for stdio. |
|
| 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-server | Pending | |
|
| 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. |
|
||||||
| matomo-mcp-client | Pending | |
|
| 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. |
|
||||||
| imap-mcp | Built | Container built successfully with uvx entrypoint |
|
| 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. |
|
||||||
| mcp-redmine | Built | Container built successfully with uvx entrypoint |
|
| 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. |
|
||||||
| ghost-mcp | Working | 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. |
|
| 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. |
|
||||||
| discourse-mcp | Pending | |
|
| imap-mcp | Runtime Issue | Container builds but crashes on startup if IMAP server unreachable. Cannot validate MCP protocol without live IMAP connection. |
|
||||||
| mcp-cloudron | Pending | |
|
| 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. |
|
||||||
| postizz-MCP | Pending | |
|
| 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. |
|
||||||
| snipeit-mcp | Pending | |
|
| 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. |
|
||||||
| nextcloud-mcp-server | Built | Container built successfully (798MB) |
|
| mcp-ansible | Built | Container built from Python source. MCP stdio-based. Fixed to run local source instead of uvx. Version 1.26.0. |
|
||||||
| docspace-mcp | Pending | |
|
| 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. |
|
||||||
| docker-mcp | Built | Container built successfully with uvx entrypoint |
|
| nextcloud-mcp | Runtime Issue | Container builds but crashes on startup - requires reachable OAuth endpoint. Cannot validate MCP protocol without live Nextcloud instance. |
|
||||||
| kubernetes-mcp-server | Pending | |
|
| 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. |
|
||||||
| ProxmoxMCP | Built | Container built successfully with uvx entrypoint |
|
| 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. |
|
||||||
| terraform-mcp-server | Pending | |
|
| 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. |
|
||||||
| mcp-ansible | Pending | |
|
| postizz-mcp | Built | Container built from TypeScript source. MCP stdio-based. Fixed to use stdio transport instead of HTTP. Version 1.0.0. |
|
||||||
| mcp-server (Bitwarden) | Pending | |
|
| 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. |
|
||||||
| mcp-adapter (WordPress) | Pending | |
|
| reverse-engineering-assistant | Build Failed | Ghidra download URL returns 404. Version mismatch in download URL. |
|
||||||
| audiobook-mcp-server | Pending | |
|
| 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. |
|
||||||
| mcp-server-elasticsearch | Pending | |
|
| 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. |
|
||||||
| penpot-mcp | Built | Container built successfully with uvx entrypoint |
|
| 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
|
## Usage
|
||||||
|
|
||||||
|
|||||||
191
crush.json
191
crush.json
@@ -2,34 +2,193 @@
|
|||||||
"$schema": "https://charm.land/crush.json",
|
"$schema": "https://charm.land/crush.json",
|
||||||
"lsp": {
|
"lsp": {
|
||||||
"bash": {
|
"bash": {
|
||||||
"command": "docker",
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-bash-wrapper.sh"
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bash-language-server", "start"]
|
|
||||||
},
|
|
||||||
"context7": {
|
|
||||||
"command": "docker",
|
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-context7-mcp"]
|
|
||||||
},
|
},
|
||||||
"docker": {
|
"docker": {
|
||||||
"command": "docker",
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-docker-wrapper.sh"
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-docker-language-server", "start", "--stdio"]
|
|
||||||
},
|
},
|
||||||
"markdown": {
|
"markdown": {
|
||||||
"command": "docker",
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-marksman-wrapper.sh"
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-marksman", "server"]
|
},
|
||||||
|
"terraform": {
|
||||||
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/lsp-terraform-wrapper.sh"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mcp": {
|
"mcp": {
|
||||||
"audiobook": {
|
"audiobook": {
|
||||||
"command": "docker",
|
"type": "stdio",
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-audiobook-mcp"]
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-audiobook-wrapper.sh",
|
||||||
|
"timeout": 60
|
||||||
},
|
},
|
||||||
"bitwarden": {
|
"bitwarden": {
|
||||||
"command": "docker",
|
"type": "stdio",
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bitwarden-mcp"]
|
"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": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-context7-wrapper.sh",
|
||||||
|
"timeout": 60
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-docker-wrapper.sh",
|
||||||
|
"timeout": 180
|
||||||
|
},
|
||||||
|
"drawio": {
|
||||||
|
"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": {
|
"ghost": {
|
||||||
"command": "docker",
|
"type": "stdio",
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-ghost-mcp"]
|
"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": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-imap-wrapper.sh",
|
||||||
|
"timeout": 60
|
||||||
|
},
|
||||||
|
"kubernetes": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "/home/charles/Projects/KNEL-AIMiddleware/mcp-kubernetes-wrapper.sh",
|
||||||
|
"timeout": 60
|
||||||
|
},
|
||||||
|
"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": {
|
||||||
|
"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": {
|
||||||
|
"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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-kicad-mcp
|
image: kneldevstack-aimiddleware-kicad-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/KiCAD-MCP-Server
|
context: ./vendor/KiCAD-MCP-Server
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/kicad-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-kicad-mcp
|
container_name: kneldevstack-aimiddleware-kicad-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -26,7 +26,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-blender-mcp
|
image: kneldevstack-aimiddleware-blender-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/blender-mcp
|
context: ./vendor/blender-mcp
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/blender-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-blender-mcp
|
container_name: kneldevstack-aimiddleware-blender-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -39,7 +39,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-freecad-mcp
|
image: kneldevstack-aimiddleware-freecad-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/freecad-mcp
|
context: ./vendor/freecad-mcp
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/freecad-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-freecad-mcp
|
container_name: kneldevstack-aimiddleware-freecad-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -47,6 +47,23 @@ services:
|
|||||||
profiles:
|
profiles:
|
||||||
- dev
|
- 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)
|
# Hosting & Infrastructure (5 servers)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -59,8 +76,6 @@ services:
|
|||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-kubernetes-mcp
|
container_name: kneldevstack-aimiddleware-kubernetes-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
|
||||||
- "8081:8080"
|
|
||||||
volumes:
|
volumes:
|
||||||
- ~/.kube/config:/root/.kube/config:ro
|
- ~/.kube/config:/root/.kube/config:ro
|
||||||
profiles:
|
profiles:
|
||||||
@@ -71,7 +86,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-docker-mcp
|
image: kneldevstack-aimiddleware-docker-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/docker-mcp
|
context: ./vendor/docker-mcp
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/docker-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-docker-mcp
|
container_name: kneldevstack-aimiddleware-docker-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
@@ -122,7 +137,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-cloudron-mcp
|
image: kneldevstack-aimiddleware-cloudron-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/mcp-cloudron
|
context: ./vendor/mcp-cloudron
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/cloudron-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-cloudron-mcp
|
container_name: kneldevstack-aimiddleware-cloudron-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -132,7 +147,7 @@ services:
|
|||||||
- ops
|
- ops
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# Development Tools (2 servers)
|
# Development Tools (3 servers)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|
||||||
# Bash Language Server - LSP for bash
|
# Bash Language Server - LSP for bash
|
||||||
@@ -147,6 +162,18 @@ services:
|
|||||||
profiles:
|
profiles:
|
||||||
- dev
|
- 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
|
# Context7 MCP - Documentation framework
|
||||||
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
|
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
|
||||||
context7-mcp:
|
context7-mcp:
|
||||||
@@ -166,21 +193,21 @@ services:
|
|||||||
# Content Management (4 servers)
|
# Content Management (4 servers)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|
||||||
# Nextcloud MCP - 90+ tools across 8 apps
|
# Nextcloud MCP - 90+ tools across 8 apps (HTTP-based)
|
||||||
nextcloud-mcp:
|
nextcloud-mcp:
|
||||||
image: kneldevstack-aimiddleware-nextcloud-mcp
|
image: kneldevstack-aimiddleware-nextcloud-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/nextcloud-mcp-server
|
context: ./vendor/nextcloud-mcp-server
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/nextcloud-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-nextcloud-mcp
|
container_name: kneldevstack-aimiddleware-nextcloud-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8083:8000"
|
||||||
environment:
|
environment:
|
||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- NEXTCLOUD_HOST=${NEXTCLOUD_HOST}
|
- NEXTCLOUD_HOST=${NEXTCLOUD_HOST}
|
||||||
- NEXTCLOUD_USERNAME=${NEXTCLOUD_USERNAME}
|
- NEXTCLOUD_USERNAME=${NEXTCLOUD_USERNAME}
|
||||||
- NEXTCLOUD_APP_PASSWORD=${NEXTCLOUD_APP_PASSWORD}
|
- NEXTCLOUD_PASSWORD=${NEXTCLOUD_PASSWORD}
|
||||||
ports:
|
|
||||||
- "8083:8080"
|
|
||||||
profiles:
|
profiles:
|
||||||
- ops
|
- ops
|
||||||
|
|
||||||
@@ -212,12 +239,27 @@ services:
|
|||||||
profiles:
|
profiles:
|
||||||
- ops
|
- 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 Adapter
|
||||||
wordpress-mcp:
|
wordpress-mcp:
|
||||||
image: kneldevstack-aimiddleware-wordpress-mcp
|
image: kneldevstack-aimiddleware-wordpress-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/mcp-adapter
|
context: ./vendor/mcp-adapter
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/wordpress-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-wordpress-mcp
|
container_name: kneldevstack-aimiddleware-wordpress-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -288,7 +330,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-matomo-mcp
|
image: kneldevstack-aimiddleware-matomo-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/matomo-mcp-client
|
context: ./vendor/matomo-mcp-client
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/matomo-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-matomo-mcp
|
container_name: kneldevstack-aimiddleware-matomo-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -302,7 +344,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-bitwarden-mcp
|
image: kneldevstack-aimiddleware-bitwarden-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/mcp-server
|
context: ./vendor/mcp-server
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/bitwarden-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-bitwarden-mcp
|
container_name: kneldevstack-aimiddleware-bitwarden-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -335,8 +377,8 @@ services:
|
|||||||
snipeit-mcp:
|
snipeit-mcp:
|
||||||
image: kneldevstack-aimiddleware-snipeit-mcp
|
image: kneldevstack-aimiddleware-snipeit-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/snipeit-mcp
|
context: ./vendor
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../dockerfiles/snipeit-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-snipeit-mcp
|
container_name: kneldevstack-aimiddleware-snipeit-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -348,18 +390,18 @@ services:
|
|||||||
- ops
|
- ops
|
||||||
|
|
||||||
# Redmine MCP - Project management
|
# Redmine MCP - Project management
|
||||||
|
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
|
||||||
mcp-redmine:
|
mcp-redmine:
|
||||||
image: kneldevstack-aimiddleware-mcp-redmine
|
image: kneldevstack-aimiddleware-mcp-redmine
|
||||||
build:
|
build:
|
||||||
context: ./vendor/mcp-redmine
|
context: ./vendor/mcp-redmine
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/mcp-redmine/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-mcp-redmine
|
container_name: kneldevstack-aimiddleware-mcp-redmine
|
||||||
restart: unless-stopped
|
restart: "no"
|
||||||
environment:
|
environment:
|
||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- REDMINE_URL=${REDMINE_URL}
|
- REDMINE_URL=${REDMINE_URL}
|
||||||
- REDMINE_API_KEY=${REDMINE_API_KEY}
|
- REDMINE_API_KEY=${REDMINE_API_KEY}
|
||||||
command: ["uvx", "mcp-redmine"]
|
|
||||||
profiles:
|
profiles:
|
||||||
- ops
|
- ops
|
||||||
|
|
||||||
@@ -368,7 +410,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-mcp-ansible
|
image: kneldevstack-aimiddleware-mcp-ansible
|
||||||
build:
|
build:
|
||||||
context: ./vendor/mcp-ansible
|
context: ./vendor/mcp-ansible
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/mcp-ansible/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-mcp-ansible
|
container_name: kneldevstack-aimiddleware-mcp-ansible
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -385,11 +427,11 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-elasticsearch-mcp
|
image: kneldevstack-aimiddleware-elasticsearch-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/mcp-server-elasticsearch
|
context: ./vendor/mcp-server-elasticsearch
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/elasticsearch-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-elasticsearch-mcp
|
container_name: kneldevstack-aimiddleware-elasticsearch-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- ELASTICSEARCH_URL=${ELASTICSEARCH_URL:-http://localhost:9200}
|
- ES_URL=${ES_URL:-http://localhost:9200}
|
||||||
- ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
|
- ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
|
||||||
- ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
|
- ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
|
||||||
ports:
|
ports:
|
||||||
@@ -422,12 +464,11 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-drawio-mcp
|
image: kneldevstack-aimiddleware-drawio-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/drawio-mcp-server
|
context: ./vendor/drawio-mcp-server
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/drawio-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-drawio-mcp
|
container_name: kneldevstack-aimiddleware-drawio-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- DRAWIO_URL=${DRAWIO_URL:-https://app.diagrams.net}
|
- DRAWIO_URL=${DRAWIO_URL:-https://app.diagrams.net}
|
||||||
command: ["npx", "-y", "drawio-mcp-server"]
|
|
||||||
profiles:
|
profiles:
|
||||||
- dev
|
- dev
|
||||||
|
|
||||||
@@ -465,7 +506,7 @@ services:
|
|||||||
image: kneldevstack-aimiddleware-penpot-mcp
|
image: kneldevstack-aimiddleware-penpot-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/penpot-mcp
|
context: ./vendor/penpot-mcp
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/penpot-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-penpot-mcp
|
container_name: kneldevstack-aimiddleware-penpot-mcp
|
||||||
restart: "no"
|
restart: "no"
|
||||||
environment:
|
environment:
|
||||||
@@ -473,3 +514,227 @@ services:
|
|||||||
- PENPOT_TOKEN=${PENPOT_TOKEN}
|
- PENPOT_TOKEN=${PENPOT_TOKEN}
|
||||||
profiles:
|
profiles:
|
||||||
- dev
|
- 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:
|
||||||
|
|||||||
13
dockerfiles/actual-mcp/Dockerfile
Normal file
13
dockerfiles/actual-mcp/Dockerfile
Normal 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"]
|
||||||
@@ -6,7 +6,8 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY package.json package-lock.json* ./
|
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 . .
|
COPY . .
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ WORKDIR /app
|
|||||||
# Install prebuilt bash-language-server from npm
|
# Install prebuilt bash-language-server from npm
|
||||||
RUN npm install -g bash-language-server
|
RUN npm install -g bash-language-server
|
||||||
|
|
||||||
# Set entrypoint
|
# Use bash-language-server directly as entrypoint
|
||||||
ENTRYPOINT ["bash-language-server"]
|
ENTRYPOINT ["bash-language-server"]
|
||||||
CMD ["start"]
|
CMD ["start"]
|
||||||
|
|||||||
14
dockerfiles/beszel-mcp/Dockerfile
Normal file
14
dockerfiles/beszel-mcp/Dockerfile
Normal 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"]
|
||||||
14
dockerfiles/bitwarden-mcp/Dockerfile
Normal file
14
dockerfiles/bitwarden-mcp/Dockerfile
Normal 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"]
|
||||||
@@ -5,20 +5,14 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
|||||||
|
|
||||||
WORKDIR /app
|
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 source code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Install the project
|
# Install the project with uv
|
||||||
RUN uv sync --frozen --no-dev --no-editable --no-cache
|
RUN uv venv && uv pip install --no-cache -e .
|
||||||
|
|
||||||
# Set up environment
|
# Set up environment
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
ENV PATH=/app/.venv/bin:$PATH
|
ENV PATH=/app/.venv/bin:$PATH
|
||||||
|
|
||||||
ENTRYPOINT ["uvx", "blender-mcp"]
|
ENTRYPOINT ["python", "-m", "blender_mcp.server"]
|
||||||
|
|||||||
14
dockerfiles/cloudron-mcp/Dockerfile
Normal file
14
dockerfiles/cloudron-mcp/Dockerfile
Normal 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"]
|
||||||
@@ -2,12 +2,17 @@ FROM node:24-alpine
|
|||||||
|
|
||||||
WORKDIR /app
|
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 . .
|
COPY . .
|
||||||
|
|
||||||
RUN npm run build
|
RUN pnpm build
|
||||||
|
|
||||||
CMD ["node", "dist/index.js"]
|
CMD ["node", "dist/index.js"]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy dependency files
|
# Copy dependency files
|
||||||
COPY pyproject.toml ./
|
COPY pyproject.toml uv.lock ./
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN uv sync --frozen --no-dev --no-install-project --no-cache
|
RUN uv sync --frozen --no-dev --no-install-project --no-cache
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
FROM node:22-alpine
|
FROM node:22-alpine
|
||||||
|
|
||||||
|
# Install pnpm
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package.json package-lock.json* ./
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
|
||||||
RUN npm ci
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN npm run build
|
RUN pnpm run build
|
||||||
|
|
||||||
CMD ["node", "dist/index.js"]
|
CMD ["node", "build/index.js"]
|
||||||
|
|||||||
28
dockerfiles/elasticsearch-mcp/Dockerfile
Normal file
28
dockerfiles/elasticsearch-mcp/Dockerfile
Normal 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"]
|
||||||
18
dockerfiles/firefly-iii-mcp/Dockerfile
Normal file
18
dockerfiles/firefly-iii-mcp/Dockerfile
Normal 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"]
|
||||||
@@ -5,20 +5,14 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
|||||||
|
|
||||||
WORKDIR /app
|
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 source code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Install the project
|
# Install the project with uv
|
||||||
RUN uv sync --frozen --no-dev --no-editable --no-cache
|
RUN uv venv && uv pip install --no-cache -e .
|
||||||
|
|
||||||
# Set up environment
|
# Set up environment
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
ENV PATH=/app/.venv/bin:$PATH
|
ENV PATH=/app/.venv/bin:$PATH
|
||||||
|
|
||||||
ENTRYPOINT ["uvx", "freecad-mcp"]
|
ENTRYPOINT ["python", "-m", "freecad_mcp.server"]
|
||||||
|
|||||||
@@ -21,4 +21,4 @@ RUN uv sync --frozen --no-dev --no-editable --no-cache
|
|||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
ENV PATH=/app/.venv/bin:$PATH
|
ENV PATH=/app/.venv/bin:$PATH
|
||||||
|
|
||||||
ENTRYPOINT ["uvx", "gimp-mcp-server"]
|
ENTRYPOINT ["python", "-m", "gimp_mcp_server"]
|
||||||
|
|||||||
18
dockerfiles/gitea-mcp/Dockerfile
Normal file
18
dockerfiles/gitea-mcp/Dockerfile
Normal 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"]
|
||||||
14
dockerfiles/ha-mcp/Dockerfile
Normal file
14
dockerfiles/ha-mcp/Dockerfile
Normal 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"]
|
||||||
13
dockerfiles/limesurvey-mcp/Dockerfile
Normal file
13
dockerfiles/limesurvey-mcp/Dockerfile
Normal 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"]
|
||||||
18
dockerfiles/linkwarden-mcp/Dockerfile
Normal file
18
dockerfiles/linkwarden-mcp/Dockerfile
Normal 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"]
|
||||||
@@ -4,10 +4,8 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY package.json package-lock.json* ./
|
COPY package.json package-lock.json* ./
|
||||||
|
|
||||||
RUN npm ci
|
RUN npm install
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN npm run build
|
CMD ["node", "matomo-mcp-client.js"]
|
||||||
|
|
||||||
CMD ["node", "dist/index.js"]
|
|
||||||
|
|||||||
19
dockerfiles/mcp-ansible/Dockerfile
Normal file
19
dockerfiles/mcp-ansible/Dockerfile
Normal 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"]
|
||||||
18
dockerfiles/mcp-grafana/Dockerfile
Normal file
18
dockerfiles/mcp-grafana/Dockerfile
Normal 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"]
|
||||||
11
dockerfiles/mcp-redmine/Dockerfile
Normal file
11
dockerfiles/mcp-redmine/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM python:3.13-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
RUN pip install --upgrade pip \
|
||||||
|
&& pip install uv \
|
||||||
|
&& uv sync
|
||||||
|
|
||||||
|
CMD ["uv", "run", "--directory", "/app", "-m", "mcp_redmine.server"]
|
||||||
44
dockerfiles/nextcloud-mcp/Dockerfile
Normal file
44
dockerfiles/nextcloud-mcp/Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
FROM docker.io/library/python:3.12-slim
|
||||||
|
|
||||||
|
# Install uv
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN apt update && apt install --no-install-recommends --no-install-suggests -y \
|
||||||
|
git \
|
||||||
|
tesseract-ocr \
|
||||||
|
sqlite3 && apt clean
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY pyproject.toml uv.lock README.md ./
|
||||||
|
|
||||||
|
RUN uv sync --no-dev --no-install-project --no-cache
|
||||||
|
|
||||||
|
# Copy source code (create permissive .dockerignore first)
|
||||||
|
# We need to override the vendor .dockerignore
|
||||||
|
RUN rm -f /app/.dockerignore 2>/dev/null || true
|
||||||
|
RUN cat > /app/.dockerignore << 'EOF'
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
.venv/
|
||||||
|
.DS_Store
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
uv.lock
|
||||||
|
README.md
|
||||||
|
ARCHITECTURE.md
|
||||||
|
CONTRIBUTING.md
|
||||||
|
DEVELOPMENT.md
|
||||||
|
PROMPTS.md
|
||||||
|
TROUBLESHOOTING.md
|
||||||
|
EOF
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN uv sync --no-dev --no-editable --no-cache
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV PATH=/app/.venv/bin:$PATH
|
||||||
|
|
||||||
|
ENTRYPOINT ["/app/.venv/bin/nextcloud-mcp-server"]
|
||||||
|
CMD ["run"]
|
||||||
25
dockerfiles/paperless-mcp/Dockerfile
Normal file
25
dockerfiles/paperless-mcp/Dockerfile
Normal 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"]
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../vendor/penpot-mcp/Dockerfile
|
|
||||||
39
dockerfiles/penpot-mcp/Dockerfile
Normal file
39
dockerfiles/penpot-mcp/Dockerfile
Normal 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"]
|
||||||
1
dockerfiles/postizz-mcp/Dockerfile
Symbolic link
1
dockerfiles/postizz-mcp/Dockerfile
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../vendor/postizz-MCP/Dockerfile
|
||||||
@@ -1,23 +1,21 @@
|
|||||||
FROM python:3.12-slim
|
FROM python:3.12-slim
|
||||||
|
|
||||||
# Install git for git+ dependencies
|
# Install uv for faster package management and git for any git dependencies
|
||||||
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install uv for faster package management
|
|
||||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
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
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy dependency files
|
# Copy all source code first
|
||||||
COPY pyproject.toml ./
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN uv sync --no-dev --no-install-project --no-cache
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
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
|
RUN uv sync --no-dev --no-editable --no-cache
|
||||||
|
|
||||||
# Set up environment
|
# Set up environment
|
||||||
|
|||||||
47
dockerfiles/reverse-engineering-assistant/Dockerfile
Normal file
47
dockerfiles/reverse-engineering-assistant/Dockerfile
Normal 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"]
|
||||||
@@ -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
|
RUN echo '#!/bin/sh' > /entrypoint.sh && \
|
||||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
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
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|
||||||
# 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"]
|
|
||||||
|
|||||||
14
dockerfiles/superset-mcp/Dockerfile
Normal file
14
dockerfiles/superset-mcp/Dockerfile
Normal 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"]
|
||||||
27
dockerfiles/terraform-ls/Dockerfile
Normal file
27
dockerfiles/terraform-ls/Dockerfile
Normal 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"]
|
||||||
26
dockerfiles/webserial-mcp/Dockerfile
Normal file
26
dockerfiles/webserial-mcp/Dockerfile
Normal 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"]
|
||||||
@@ -1,13 +1,2 @@
|
|||||||
FROM node:22-alpine
|
FROM node:22-slim
|
||||||
|
ENTRYPOINT ["npx", "-y", "@wordpress/mcp-adapter"]
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY package.json package-lock.json* ./
|
|
||||||
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
CMD ["node", "dist/index.js"]
|
|
||||||
|
|||||||
411
docs/SDLC.md
Normal file
411
docs/SDLC.md
Normal 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**
|
||||||
178
docs/audit/2026-02-20/01-dockerfile-security.md
Normal file
178
docs/audit/2026-02-20/01-dockerfile-security.md
Normal 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 |
|
||||||
230
docs/audit/2026-02-20/02-shell-script-security.md
Normal file
230
docs/audit/2026-02-20/02-shell-script-security.md
Normal 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
|
||||||
|
```
|
||||||
246
docs/audit/2026-02-20/03-docker-compose-security.md
Normal file
246
docs/audit/2026-02-20/03-docker-compose-security.md
Normal 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 |
|
||||||
239
docs/audit/2026-02-20/04-secrets-audit.md
Normal file
239
docs/audit/2026-02-20/04-secrets-audit.md
Normal 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**
|
||||||
233
docs/audit/2026-02-20/05-vulnerability-scan.md
Normal file
233
docs/audit/2026-02-20/05-vulnerability-scan.md
Normal 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
|
||||||
234
docs/audit/2026-02-20/FINAL-REPORT.md
Normal file
234
docs/audit/2026-02-20/FINAL-REPORT.md
Normal 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
18
lsp-bash-wrapper.sh
Executable 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
18
lsp-docker-wrapper.sh
Executable 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
18
lsp-marksman-wrapper.sh
Executable 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
4
lsp-terraform-wrapper.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
docker run -i --rm \
|
||||||
|
-v "$(pwd):/workspace" \
|
||||||
|
kneldevstack-aimiddleware-terraform-ls
|
||||||
177
maintenance.sh
Executable file
177
maintenance.sh
Executable 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
22
mcp-actual-wrapper.sh
Executable 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
21
mcp-ansible-wrapper.sh
Executable 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
20
mcp-audiobook-wrapper.sh
Executable 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
22
mcp-beszel-wrapper.sh
Executable 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
23
mcp-bitwarden-wrapper.sh
Executable 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
21
mcp-blender-wrapper.sh
Executable 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
21
mcp-cloudron-wrapper.sh
Executable 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
21
mcp-context7-wrapper.sh
Executable 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
22
mcp-discourse-wrapper.sh
Executable 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
21
mcp-docker-wrapper.sh
Executable 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
21
mcp-docspace-wrapper.sh
Executable 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
20
mcp-drawio-wrapper.sh
Executable 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
22
mcp-elasticsearch-wrapper.sh
Executable 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
15
mcp-firefly-iii-wrapper.sh
Executable 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
20
mcp-freecad-wrapper.sh
Executable 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
21
mcp-ghost-wrapper.sh
Executable 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
20
mcp-gimp-wrapper.sh
Executable 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
21
mcp-gitea-wrapper.sh
Executable 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
21
mcp-grafana-wrapper.sh
Executable 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
21
mcp-ha-wrapper.sh
Executable 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
24
mcp-imap-wrapper.sh
Executable 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
5
mcp-kubernetes-wrapper.sh
Executable 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
22
mcp-limesurvey-wrapper.sh
Executable 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
21
mcp-linkwarden-wrapper.sh
Executable 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
21
mcp-matomo-wrapper.sh
Executable 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
22
mcp-nextcloud-wrapper.sh
Executable 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
15
mcp-paperless-wrapper.sh
Executable 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
21
mcp-penpot-wrapper.sh
Executable 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
21
mcp-postizz-wrapper.sh
Executable 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
23
mcp-proxmox-wrapper.sh
Executable 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
21
mcp-redmine-wrapper.sh
Executable 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
21
mcp-snipeit-wrapper.sh
Executable 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
22
mcp-superset-wrapper.sh
Executable 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
20
mcp-terraform-wrapper.sh
Executable 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
4
mcp-webserial-wrapper.sh
Executable 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
172
run.sh
Executable 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
99
scripts/CloneVendorRepos.sh
Executable 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"
|
||||||
@@ -32,7 +32,7 @@ echo ""
|
|||||||
for SERVICE in $SERVICES; do
|
for SERVICE in $SERVICES; do
|
||||||
TOTAL=$((TOTAL + 1))
|
TOTAL=$((TOTAL + 1))
|
||||||
# Construct expected image name
|
# Construct expected image name
|
||||||
IMAGE_NAME="knel-aimiddleware-$SERVICE"
|
IMAGE_NAME="kneldevstack-aimiddleware-$SERVICE"
|
||||||
|
|
||||||
# Check if image exists
|
# Check if image exists
|
||||||
if docker images --format '{{.Repository}}' | grep -q "^${IMAGE_NAME}$"; then
|
if docker images --format '{{.Repository}}' | grep -q "^${IMAGE_NAME}$"; then
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user