Initial commit: Caddy MCP Server

This commit is contained in:
2026-04-10 21:57:20 -07:00
commit 2a3107f9e2
21 changed files with 2194 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
package main
import (
"fmt"
"log"
)
func (c *CaddyClient) AddBasicAuth(domain, username, password string) error {
log.Printf("[WARNING] Password for user %s on domain %s is being transmitted in plaintext through MCP", username, domain)
config, err := c.GetConfig()
if err != nil {
return err
}
apps, _ := config["apps"].(map[string]interface{})
httpApps, _ := apps["http"].(map[string]interface{})
servers, _ := httpApps["servers"].(map[string]interface{})
for srvName, server := range servers {
srv, _ := server.(map[string]interface{})
routes, _ := srv["routes"].([]interface{})
for routeIdx, route := range routes {
routeMap, _ := route.(map[string]interface{})
matches, _ := routeMap["match"].([]interface{})
for _, match := range matches {
matchMap, _ := match.(map[string]interface{})
hosts, _ := matchMap["host"].([]interface{})
if len(hosts) > 0 {
d, _ := hosts[0].(string)
if d == domain {
handle, _ := routeMap["handle"].([]interface{})
for i, h := range handle {
handlerMap, ok := h.(map[string]interface{})
if !ok {
continue
}
if handlerMap["handler"] == "subroute" {
subRoutes, _ := handlerMap["routes"].([]interface{})
if len(subRoutes) > 0 {
mainRoute, _ := subRoutes[0].(map[string]interface{})
handlers, _ := mainRoute["handle"].([]interface{})
// Check if auth already exists
var authIdx = -1
for idx, handler := range handlers {
hm, _ := handler.(map[string]interface{})
if hm["handler"] == "authentication" {
authIdx = idx
break
}
}
// WARNING: Passwords are transmitted in plaintext through MCP protocol.
// This is an architectural limitation of the Model Context Protocol.
// The password is stored hashed in Caddy (bcrypt), but travels
// unencrypted from the MCP client to this server.
newAccount := map[string]interface{}{
"username": username,
"password": password,
}
if authIdx >= 0 {
// Add to existing auth
authHandler, _ := handlers[authIdx].(map[string]interface{})
providers, _ := authHandler["providers"].(map[string]interface{})
httpBasic, _ := providers["http_basic"].(map[string]interface{})
accounts, _ := httpBasic["accounts"].([]interface{})
accounts = append(accounts, newAccount)
httpBasic["accounts"] = accounts
providers["http_basic"] = httpBasic
authHandler["providers"] = providers
handlers[authIdx] = authHandler
} else {
// Create new auth handler
authHandler := map[string]interface{}{
"handler": "authentication",
"providers": map[string]interface{}{
"http_basic": map[string]interface{}{
"accounts": []interface{}{newAccount},
"hash": map[string]interface{}{
"algorithm": "bcrypt",
},
},
},
}
handlers = append([]interface{}{authHandler}, handlers...)
}
mainRoute["handle"] = handlers
subRoutes[0] = mainRoute
handlerMap["routes"] = subRoutes
handle[i] = handlerMap
routeMap["handle"] = handle
routes[routeIdx] = routeMap
configPath := fmt.Sprintf("apps/http/servers/%s/routes", srvName)
return c.SetConfig(configPath, routes)
}
}
}
}
}
}
}
}
return fmt.Errorf("site not found: %s", domain)
}
func (c *CaddyClient) RemoveBasicAuth(domain string) error {
config, err := c.GetConfig()
if err != nil {
return err
}
apps, _ := config["apps"].(map[string]interface{})
httpApps, _ := apps["http"].(map[string]interface{})
servers, _ := httpApps["servers"].(map[string]interface{})
for srvName, server := range servers {
srv, _ := server.(map[string]interface{})
routes, _ := srv["routes"].([]interface{})
for routeIdx, route := range routes {
routeMap, _ := route.(map[string]interface{})
matches, _ := routeMap["match"].([]interface{})
for _, match := range matches {
matchMap, _ := match.(map[string]interface{})
hosts, _ := matchMap["host"].([]interface{})
if len(hosts) > 0 {
d, _ := hosts[0].(string)
if d == domain {
handle, _ := routeMap["handle"].([]interface{})
for i, h := range handle {
handlerMap, ok := h.(map[string]interface{})
if !ok {
continue
}
if handlerMap["handler"] == "subroute" {
subRoutes, _ := handlerMap["routes"].([]interface{})
if len(subRoutes) > 0 {
mainRoute, _ := subRoutes[0].(map[string]interface{})
handlers, _ := mainRoute["handle"].([]interface{})
var newHandlers []interface{}
for _, handler := range handlers {
hm, _ := handler.(map[string]interface{})
if hm["handler"] != "authentication" {
newHandlers = append(newHandlers, handler)
}
}
mainRoute["handle"] = newHandlers
subRoutes[0] = mainRoute
handlerMap["routes"] = subRoutes
handle[i] = handlerMap
routeMap["handle"] = handle
routes[routeIdx] = routeMap
configPath := fmt.Sprintf("apps/http/servers/%s/routes", srvName)
return c.SetConfig(configPath, routes)
}
}
}
}
}
}
}
}
return fmt.Errorf("site not found: %s", domain)
}