From c1f0117b804f9699708cd1f05a5bf6707074c65a Mon Sep 17 00:00:00 2001 From: Michal Date: Wed, 30 Sep 2026 01:35:43 +0100 Subject: [PATCH 1/3] templates: jmap, dav, karakeep, ttrss for personal-service projects jmap and ttrss are custom images (mysources.co.uk/michal/{jmap-mcp,ttrss-mcp}); dav-mcp and @karakeep/mcp run on the node runner. Health checks are real backend calls. Applied live 2026-09-30; these seeds keep the next mcpd image rebuild from reverting them. Co-Authored-By: Claude Fable 5 --- templates/dav.yaml | 27 +++++++++++++++++++++++++++ templates/jmap.yaml | 41 +++++++++++++++++++++++++++++++++++++++++ templates/karakeep.yaml | 24 ++++++++++++++++++++++++ templates/ttrss.yaml | 26 ++++++++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 templates/dav.yaml create mode 100644 templates/jmap.yaml create mode 100644 templates/karakeep.yaml create mode 100644 templates/ttrss.yaml diff --git a/templates/dav.yaml b/templates/dav.yaml new file mode 100644 index 0000000..e16d0d1 --- /dev/null +++ b/templates/dav.yaml @@ -0,0 +1,27 @@ +name: dav +version: "1.0.0" +description: CalDAV/CardDAV/VTODO (Stalwart or any RFC 4791/6352 server) — calendars, events, tasks, contacts +packageName: "dav-mcp" +runtime: node +transport: STDIO +repositoryUrl: https://github.com/PhilflowIO/dav-mcp +healthCheck: + # A real CalDAV PROPFIND: a pass proves server URL and credentials. + tool: list_calendars + arguments: {} + intervalSeconds: 60 + timeoutSeconds: 10 +env: + - name: CALDAV_SERVER_URL + description: DAV base URL (e.g. http://stalwart.stalwart.svc.cluster.local:8080) + required: true + - name: CALDAV_USERNAME + description: DAV username + required: true + - name: CALDAV_PASSWORD + description: DAV password (use an app password) + required: true + - name: NODE_OPTIONS + description: V8 heap cap; Node sizes its heap off host RAM, not the cgroup limit + required: false + defaultValue: "--max-old-space-size=384" diff --git a/templates/jmap.yaml b/templates/jmap.yaml new file mode 100644 index 0000000..c19fcea --- /dev/null +++ b/templates/jmap.yaml @@ -0,0 +1,41 @@ +name: jmap +version: "1.0.0" +description: JMAP email (Stalwart) — search/read/organize + drafts; send and delete gated off by env +dockerImage: "mysources.co.uk/michal/jmap-mcp:0.6.5-drafts2" +transport: STDIO +repositoryUrl: https://mysources.co.uk/michal/jmap-mcp +# No command: the image's entrypoint IS the MCP server (deno run), mcpd +# attaches to PID 1 stdin/stdout. Fork of wyattjoh/jmap-mcp adding +# create_draft/create_draft_reply, JMAP_DISABLE_* gating, and Basic auth +# (jmap-jam upstream only speaks Bearer). +healthCheck: + # A real Mailbox/get: a pass proves session URL, auth, and account + # resolution, not just process liveness. + tool: get_mailboxes + arguments: {} + intervalSeconds: 60 + timeoutSeconds: 10 +env: + - name: JMAP_SESSION_URL + description: JMAP session URL (e.g. http://stalwart.stalwart.svc.cluster.local:8080/.well-known/jmap) + required: true + - name: JMAP_BEARER_TOKEN + description: Bearer token. Provide either this OR JMAP_USERNAME + JMAP_PASSWORD. + required: false + - name: JMAP_USERNAME + description: Username for HTTP Basic auth (e.g. with a Stalwart app password) + required: false + - name: JMAP_PASSWORD + description: Password/app password for HTTP Basic auth + required: false + - name: JMAP_ACCOUNT_ID + description: Account ID (auto-detected when empty) + required: false + - name: JMAP_DISABLE_SUBMISSION + description: "true = do not register send_email/reply_to_email (drafts only)" + required: false + defaultValue: "true" + - name: JMAP_DISABLE_DELETE + description: "true = do not register delete_emails (move to Trash still works)" + required: false + defaultValue: "true" diff --git a/templates/karakeep.yaml b/templates/karakeep.yaml new file mode 100644 index 0000000..1026000 --- /dev/null +++ b/templates/karakeep.yaml @@ -0,0 +1,24 @@ +name: karakeep +version: "1.0.0" +description: Karakeep bookmarks — search, read, create, lists, tags, highlights +packageName: "@karakeep/mcp" +runtime: node +transport: STDIO +repositoryUrl: https://github.com/karakeep-app/karakeep +healthCheck: + # A real API call (lists all lists): a pass proves address and API key. + tool: get-lists + arguments: {} + intervalSeconds: 60 + timeoutSeconds: 10 +env: + - name: KARAKEEP_API_ADDR + description: Karakeep base URL (e.g. http://karakeep-web.karakeep.svc.cluster.local:3000) + required: true + - name: KARAKEEP_API_KEY + description: API key created in the Karakeep UI (Settings → API Keys) + required: true + - name: NODE_OPTIONS + description: V8 heap cap; Node sizes its heap off host RAM, not the cgroup limit + required: false + defaultValue: "--max-old-space-size=384" diff --git a/templates/ttrss.yaml b/templates/ttrss.yaml new file mode 100644 index 0000000..8e859a2 --- /dev/null +++ b/templates/ttrss.yaml @@ -0,0 +1,26 @@ +name: ttrss +version: "1.0.0" +description: Tiny Tiny RSS — feeds, headlines, article content, read/star state, subscribe +dockerImage: "mysources.co.uk/michal/ttrss-mcp:1.0.0" +transport: STDIO +repositoryUrl: https://mysources.co.uk/michal/ttrss-mcp +# No command: the image's entrypoint IS the MCP server. Custom server; the +# public tt-rss MCPs only take a pre-made session id and die when it expires. +# This one logs in with user/password and re-logs-in on NOT_LOGGED_IN. +healthCheck: + # A real getCategories call: a pass proves URL, login, and that the + # user's "Enable API access" preference is on. + tool: list_categories + arguments: {} + intervalSeconds: 60 + timeoutSeconds: 10 +env: + - name: TTRSS_URL + description: Full API endpoint (e.g. http://ttrss.ttrss.svc.cluster.local/api/) + required: true + - name: TTRSS_USER + description: tt-rss user with "Enable API access" set in preferences + required: true + - name: TTRSS_PASSWORD + description: That user's password + required: true From 709068ce689e1d26ea380ec31526ccbd65b89f8b Mon Sep 17 00:00:00 2001 From: Michal Date: Wed, 30 Sep 2026 01:42:05 +0100 Subject: [PATCH 2/3] templates/jmap: drafts3 image + JMAP_REBASE_SESSION_URLS Stalwart's session advertises publicUrl-absolute endpoints; over the ClusterIP those hairpin through Envoy and 403. Verified in-cluster: apiUrl came back as https://smtp.ad.itaz.eu/jmap/. Co-Authored-By: Claude Fable 5 --- templates/jmap.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/templates/jmap.yaml b/templates/jmap.yaml index c19fcea..8b2bab1 100644 --- a/templates/jmap.yaml +++ b/templates/jmap.yaml @@ -1,7 +1,7 @@ name: jmap version: "1.0.0" description: JMAP email (Stalwart) — search/read/organize + drafts; send and delete gated off by env -dockerImage: "mysources.co.uk/michal/jmap-mcp:0.6.5-drafts2" +dockerImage: "mysources.co.uk/michal/jmap-mcp:0.6.5-drafts3" transport: STDIO repositoryUrl: https://mysources.co.uk/michal/jmap-mcp # No command: the image's entrypoint IS the MCP server (deno run), mcpd @@ -39,3 +39,7 @@ env: description: "true = do not register delete_emails (move to Trash still works)" required: false defaultValue: "true" + - name: JMAP_REBASE_SESSION_URLS + description: "true = rewrite the session's apiUrl/downloadUrl/uploadUrl/eventSourceUrl onto the session URL's origin. Required over a ClusterIP: Stalwart advertises its publicUrl and the hairpinned call 403s at Envoy." + required: false + defaultValue: "true" From 1180bbdc1d8eef23403dc7cacc9ede863b44a415 Mon Sep 17 00:00:00 2001 From: Michal Date: Thu, 1 Oct 2026 23:47:12 +0100 Subject: [PATCH 3/3] templates/dav: baked stdio image instead of npx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dav-mcp declares tsdav/tsdav-utils as GitHub-URL deps — npx on the git-less node-runner dies with 'spawn git ENOENT' (observed: dav-michal CrashLoopBackOff on first deploy). Upstream's ghcr image PID-1s the HTTP server, so mysources.co.uk/michal/dav-mcp bakes the install and execs src/server-stdio.js. Co-Authored-By: Claude Fable 5 --- templates/dav.yaml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/templates/dav.yaml b/templates/dav.yaml index e16d0d1..6eaacfe 100644 --- a/templates/dav.yaml +++ b/templates/dav.yaml @@ -1,10 +1,13 @@ name: dav version: "1.0.0" description: CalDAV/CardDAV/VTODO (Stalwart or any RFC 4791/6352 server) — calendars, events, tasks, contacts -packageName: "dav-mcp" -runtime: node +# NOT packageName: dav-mcp declares tsdav/tsdav-utils as GitHub-URL deps, so +# `npx -y dav-mcp` dies with `spawn git ENOENT` on the git-less node-runner, +# and the upstream ghcr image starts the HTTP server as PID 1. This image +# bakes the install and execs the stdio entrypoint (NODE_OPTIONS baked in). +dockerImage: "mysources.co.uk/michal/dav-mcp:4.0.1-stdio1" transport: STDIO -repositoryUrl: https://github.com/PhilflowIO/dav-mcp +repositoryUrl: https://mysources.co.uk/michal/dav-mcp-image healthCheck: # A real CalDAV PROPFIND: a pass proves server URL and credentials. tool: list_calendars @@ -21,7 +24,3 @@ env: - name: CALDAV_PASSWORD description: DAV password (use an app password) required: true - - name: NODE_OPTIONS - description: V8 heap cap; Node sizes its heap off host RAM, not the cgroup limit - required: false - defaultValue: "--max-old-space-size=384"