feat(community-containers): add Astrolabe - #8489
Draft
cbcoutinho wants to merge 2 commits into
Draft
Conversation
cbcoutinho
force-pushed
the
feat/community-container-astrolabe
branch
from
July 27, 2026 20:38
5930601 to
8336ddb
Compare
Adds a community container running nextcloud-mcp-server, which lets the Nextcloud Assistant's "Chat with AI" agent answer from the user's own files, notes, calendar, contacts and Deck cards. Upstream this needs the Context Agent ExApp, which requires AppAPI and a deploy daemon (HaRP or the Docker Socket Proxy). Since v0.39.0 the Astrolabe app registers an in-process provider for the core task type core:contextagent:interaction instead, so none of that is needed. Scope is deliberately small for a first version: semantic search and background indexing are off, so nothing is embedded or indexed and the agent reads through Nextcloud's own APIs as the asking user. No LLM is bundled -- generation stays with whatever provider already serves core:text2text:chatwithtools. Agent scopes are read-only. Nextcloud is reached over the Docker network via the internal plain-HTTP listener already used for Collabora's WOPI callbacks, while the token audience and OAuth callback use the public mcp.$NC_DOMAIN, which an admin can reverse-proxy at the published port 8000. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Chris Coutinho <chris@coutinho.io>
cbcoutinho
force-pushed
the
feat/community-container-astrolabe
branch
from
July 27, 2026 20:39
8336ddb to
f4b0bef
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a community container that runs
nextcloud-mcp-server, so the Nextcloud Assistant's "Chat with AI" agent can answer from the user's own files, notes, calendar, contacts and Deck cards, with links back to what it used.Opening as a draft — see "Not ready to merge" below. Proposed in #8490.
Why not the Context Agent ExApp
Upstream, that agent needs the Context Agent app, which is an ExApp: it only runs via AppAPI plus a deploy daemon (HaRP, or previously the Docker Socket Proxy), which means giving Nextcloud reach into a Docker socket. That is a recurring source of trouble here — #6613, #8469, #8159, #7861, #7848, #7221, #8225.
Since v0.39.0 the Astrolabe app registers an ordinary in-process TaskProcessing provider for the core task type
core:contextagent:interaction, and the Assistant treats its agent as available as soon as any provider claims that type. No AppAPI, no ExApp, no Context Chat, no Docker socket.Scope
Deliberately small for a first version:
core:text2text:chatwithtools(typicallyintegration_openai, which can point at the existinglocal-aicommunity container).files.read notes.read webdav.read calendar.read contacts.read deck.read). The MCP server hides every tool those scopes do not grant.How it is wired
Everything on the Nextcloud side goes through
nextcloud_exec_commands: install and enableoidc,astrolabeandassistant, register two OIDC clients, point Astrolabe at the MCP server, and switch the agent on. Nothing for the admin to configure by hand.Two OIDC clients, both created with AIO-generated secrets and guarded by an
oidc:list | grep -q … ||check so restarts do not accumulate duplicates:oidcapp'sTokenGenerationRequestEvent;oidcapp deletes dynamically registered clients after about an hour.Internal and public addresses are kept separate:
NEXTCLOUD_HOST=http://nextcloud-aio-apache.nextcloud-aio:23973, and Nextcloud'smcp_server_url→ the MCP containerOIDC_ISSUER/NEXTCLOUD_PUBLIC_ISSUER_URL→https://$NC_DOMAIN, andNEXTCLOUD_MCP_SERVER_URL/mcp_server_public_url→https://mcp.$NC_DOMAINNEXTCLOUD_HOSTreuses the plain-HTTP internal listener already inContainers/apache/Caddyfilefor Collabora's WOPI and callback URLs, so the Nextcloud hop never leaves the host. Port 8000 is published so an admin who also wants to connect an external MCP client can reverse-proxymcp.$NC_DOMAINat it — the same shapevaultwardenuses withbw.$NC_DOMAIN. That step is optional; skipping it costs only the external-client case, since the Assistant agent reaches the server over the Docker network.Not ready to merge
Two things outstanding, which is why this is a draft:
TOKEN_ENCRYPTION_KEYformat. The MCP server currently requires a Fernet key (base64url-encoded 32 bytes), but AIO generatesbin2hex(random_bytes(24))— 48 hex characters — and a community container has no settings UI to paste a real key into. I intend to fix this on the MCP server side by deriving a key from any sufficiently random string while keeping existing Fernet keys working unchanged, and to pinimage_tagto the release that carries it. Happy to hear if you would rather it were solved differently.Testing
CI-equivalent checks were run locally: the JSON validates against
php/containers-schema.json, the folder/readme structure check passes, and codespell is clean. The generatedNEXTCLOUD_EXEC_COMMANDSscript was also checked to be valid bash, and simulated across repeated restarts to confirm it creates each OIDC client exactly once without writing a client secret to the container log. Manual testing on a live AIO instance still to come.This PR was generated with the help of AI, and reviewed by a Human