by street1983nk
Exposes Nextcloud files, calendar, notes, Deck, contacts, Tables, Talk, and mail as read‑only tools for AI assistants, enforcing user permissions and never modifying or deleting data.
The connector runs as a Nextcloud ExApp and acts as an OAuth 2.1 authorization server that proxies read‑only operations from AI assistants (Claude, ChatGPT, Cursor, etc.) to the user’s Nextcloud data. Every call is executed with the exact permissions of the signed‑in user, and the server never performs destructive actions.
NC_MCP_FILES_ROOT, NC_MCP_DISABLED_TOOLS, NC_MCP_TALK_SEND) to limit exposure.files_read, calendar_list_events, prepare_context, etc., via the MCP protocol.prepare_context bundles search results, upcoming events, waiting Talk conversations, and unread mail counts in one call.NC_MCP_DISABLED_TOOLS.kein-ki collaborative tag.talk_send) while keeping full read‑only access to other data.Q: Can the connector delete or modify my files?
A: No. All tools are either read or create‑only. Deleting, overwriting, moving, renaming, or changing shares is blocked by contract tests.
Q: Is my data ever copied or indexed on another server? A: No. The connector forwards requests directly to your own Nextcloud instance; no background indexing or external storage is used.
Q: How do I restrict the assistant from certain folders?
A: Tag the folder (or any parent) with the collaborative tag kein-ki. The connector will omit those items from all read results.
Q: Can I disable specific tool groups?
A: Yes. Set the environment variable NC_MCP_DISABLED_TOOLS with a comma‑separated list of bundle names (e.g., mail,calendar). The server will exit on start if an unknown name is provided.
Q: What about outbound actions like sending Talk messages?
A: Outbound talk_send is behind the NC_MCP_TALK_SEND switch, which can be turned off globally via the admin settings.
Q: Do I need a separate installation for each AI model? A: No. The same connector can serve multiple assistants; each assistant receives its own OAuth client registration.
Q: How is audit logging handled?
A: When enabled in the admin UI, every tool call is logged with user, tool name, timestamp, and outcome. Entries are hash‑chained for tamper detection and can be read/verified with occ mcp_connector:audit:read and occ mcp_connector:audit:verify.
Q: Is there a standalone (non‑AppAPI) mode?
A: Yes. Since version 0.2.0 the server can run as a standalone OAuth service (nc-mcp-oauth) that talks to a remote Nextcloud instance over HTTPS.
A curated MCP server that connects your Nextcloud (files, calendar, notes, Deck, contacts, Tables, Talk and Mail) to AI assistants such as Claude, Cursor, ChatGPT or your own agents. Installed as a Nextcloud ExApp, it is its own OAuth 2.1 authorization server as well.
Findling + Nextcloud MCP Connector = the retrieval layer for your own RAG. Findling makes the content of your documents searchable, scans included. The connector hands those hits to any MCP client, with exactly the rights of the asking user; measured in tests/integration/test_content_hit_fidelity.py. You bring the model, and no content leaves your server.
prepare_context bundles a search, the coming week of events, the waiting Talk conversations
and the unread mail counts into one call, each source with its own time budgetfiles_upload refuses an existing path with a
clear error instead of replacing itThat is a design constraint and not a promise of good behaviour: a contract test reads the modules and fails on the first destructive call, tests/contract/test_no_destructive_calls.py.
read means the tool only reads, create-only means it can create new objects but never modifies or removes existing ones. The table is not maintained by hand: a contract test reads the live registry and fails if a name or a level disagrees with it.
| Tool | Permission | What it does |
|---|---|---|
files_search |
read | Files and folders by name via WebDAV search; contents are not indexed |
files_list |
read | The direct children of a folder, with size and modification time |
files_read |
read | The content of one file |
files_download |
read | Any-size file as bounded embedded-resource chunks |
files_read_as_markdown |
read | A DOCX, XLSX, PPTX or PDF file converted to Markdown, in slices |
files_upload |
create-only | A new text file or any-size binary upload in base64 chunks; an existing path is refused, never overwritten |
calendar_list_events |
read | Events in an explicit time range, with an explicit time zone |
calendar_create_event |
create-only | A new event; existing events are never changed |
notes_search |
read | Notes by title and content, via the Nextcloud notes search provider |
notes_read |
read | One note |
notes_create |
create-only | A new note; existing notes are never changed |
deck_browse |
read | Deck boards, stacks and cards |
deck_create_card |
create-only | A new card in a stack; existing cards are never changed |
tables_browse |
read | Tables: the tables, the columns of one, or its rows |
tables_create_row |
create-only | A row addressed by column titles; existing rows are never changed |
talk_browse |
read | Talk conversations and the history of one; reading leaves no trace |
talk_send |
create-only | One message into a conversation; never edited or deleted, switchable off instance wide |
mail_browse |
read | Mail accounts, their mailboxes and message envelopes; strictly read only |
contacts_search |
read | Address book contacts |
unified_search |
read | The Nextcloud unified search across providers, permission aware |
prepare_context |
read | Files, notes, cards, the next week of events, waiting Talk conversations and unread mail counts in one call |
search |
read | OpenAI compatible search entry point, delegates to unified search |
fetch |
read | OpenAI compatible fetch, resolves an id to a file, note, card, event, mail, Talk message or table |
search and fetch exist because the ChatGPT connector profile requires exactly these two
names and schemas. They are thin wrappers over the tools above, not a second implementation.
An answer of unified_search, with both honest cases in it: a hit whose id the read tools
resolve, and a provider whose entries stay a URL instead of an invented id. A provider that
fails or stalls is named under degraded, so a partial answer is visibly partial. Notes,
Deck, Tables, Talk and Mail are optional apps; the tool list stays the same everywhere and a
missing app is answered in one sentence, never with an empty result.
{"query":"budget","count":2,"results":[{"id":"file:4711","title":"Budget 2026.md","url":"https://cloud.example.org/index.php/f/4711","provider":"files","kind":"file"},{"id":"url:https://cloud.example.org/index.php/call/abc123","title":"Khaled","url":"https://cloud.example.org/index.php/call/abc123","provider":"talk-conversations","kind":"url","resolvable":false}]}
NC_MCP_DISABLED_TOOLS, comma separated bundle names, read at start.occ app_api:app:register mcp_connector --env "NC_MCP_DISABLED_TOOLS=mail,calendar"
(unregister first on an existing installation; user connections survive, the container
is recreated). The start log names the bundles that are off.export NC_MCP_DISABLED_TOOLS=mail,calendar, useful when a second MCP server
already offers mail and calendar and a smaller model confuses the two.calendar: calendar_list_events, calendar_create_eventchatgpt: search, fetchcontacts: contacts_searchcontext: prepare_contextdeck: deck_browse, deck_create_cardfiles: files_search, files_list, files_read, files_download,
files_read_as_markdown, files_uploadmail: mail_browsenotes: notes_search, notes_read, notes_createsearch: unified_searchtables: tables_browse, tables_create_rowtalk: talk_browse, talk_sendsearch, fetch and prepare_context still reach the content
of a switched off bundle. Use Nextcloud permissions, the kein-ki tag or
NC_MCP_FILES_ROOT to keep content away from the assistant.chatgpt bundle (search, fetch).Tag a folder or file with the collaborative tag kein-ki and the assistant no longer sees it or anything below it.
Check the setup with php occ mcp_connector:exclusion:check --admin=<uid>.
Most important limit: a tag above the root of a share does not protect the shared folder for the recipient, so tag the folder you share.
Setup, all limits and the findings they rest on: docs/exclusion.md.
This server holds private data, it takes in untrusted content (a mail or a Talk message
is written by somebody else, and for a mail that somebody needs no account on your instance),
and it has an outgoing channel, talk_send. Those three together are what Simon Willison
calls the lethal trifecta, and a
language model does not reliably separate data from instructions. So talk_send sits behind
the administration switch NC_MCP_TALK_SEND, which closes the outgoing channel for the whole
instance while reading stays untouched, and Mail adds reach with deliberately no way out of its
own. Neither makes prompt injection impossible. The long form, with every countermeasure and
the honest remainder, is in docs/privacy.md. The switches sit under
Settings, Administration, Security:

Listed in the Nextcloud App Store as MCP Connector and installed as an ExApp: enable AppAPI, register a deploy daemon, then deploy and enable the app. Nextcloud 32 to 35. On 34.0.3 the apps management interface does this for you, on earlier versions occ is the reliable path. The walkthrough with the exact commands and the pitfalls that actually happen: docs/exapp-install.md.
Since 0.2.0 the server also runs without AppAPI. nc-mcp-oauth serves the same endpoint,
authorization server and consent screen for a Nextcloud it reaches over HTTPS, and because
no AppAPI header names the account behind a browser there, the consent decision is confirmed
by the OIDC single sign-on Nextcloud already trusts. Setup, secrets and operation:
docs/standalone-oauth.md.
Claude.ai and ChatGPT connect over OAuth with one URL. Claude Desktop, Claude Code, Cursor and other local clients run the same server over stdio, with a Nextcloud app password:
uv tool install nextcloud-mcp-connector
export NC_MCP_URL=https://cloud.example.com
export NC_MCP_USER=alice
export NC_MCP_APP_PASSWORD=xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
# Optional: expose only this Nextcloud directory to file tools
export NC_MCP_FILES_ROOT=/Documents/AI
nc-mcp
The same server speaks Streamable HTTP for remote clients, on POST /mcp, where
NC_MCP_ALLOWED_HOSTS is required in practice. Setup step by step, every environment variable
and the three errors that actually happen: docs/client-setup.md. OAuth
for administrators: docs/oauth-setup.md. Automation platforms are
clients too, with one OAuth connection per person: docs/n8n-setup.md.
When NC_MCP_FILES_ROOT is set, / becomes that directory for the file tools. For example,
/scan.pdf is resolved under /Documents/AI, and no file tool can reach its parent folders.

Every call goes to your Nextcloud and returns: nothing runs in the background, no result is cached, no index is kept. In the HTTP modes the credentials travel per request and are never stored. Questions users ask: docs/faq.md.
The audit log is part of this app and not of an add-on. With it on, every tool call is written
down with the account it ran for, the tool, the time, the calling app and the outcome, and
never a parameter value or any part of a result. It is off by default, an administrator
switches it on in the admin settings of this app, and the entries are read with
occ mcp_connector:audit:read. Every entry is hash chained to the one before it, and
occ mcp_connector:audit:verify walks the chains and names the first place one of them is
broken.
Sign in through the identity provider your organisation already runs arrived with 0.2.0, in
the deployment without AppAPI: the consent decision is confirmed by the OIDC single sign-on
Nextcloud already trusts through user_oidc. A service of the organisation can also act in a
user's name with a token it exchanged at that provider, and the setup, the measured limits of
the route and what is still open about it are in
docs/token-exchange.md. Still planned on that road are group
policies.
Request a quote: admin@infranode.dev
uv sync
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run pytest starts nothing and needs nothing. uv run pytest -m matrix starts the HTTP
server as a subprocess, uv run pytest -m integration needs the local test Nextcloud from
compose.test.yml.
App id, package names and repository name are frozen, see docs/app-id-freeze.md.
AGPL-3.0-or-later, see LICENSE. Donations: PayPal and Stripe.
Please log in to share your review and rating for this MCP.
Explore related MCPs that share similar capabilities and solve comparable challenges
by modelcontextprotocol
An MCP server implementation that provides a tool for dynamic and reflective problem-solving through a structured thinking process.
by zylon-ai
Provides an open-source API layer that enables local OpenAI‑compatible models to be used for production AI applications, offering standardized message handling, document ingestion, retrieval‑augmented generation, tool integration, and MCP connectivity.
by danny-avila
Provides a self‑hosted ChatGPT‑style interface supporting numerous AI models, agents, code interpreter, image generation, multimodal interactions, and secure multi‑user authentication.
by block
Automates engineering tasks on local machines, executing code, building projects, debugging, orchestrating workflows, and interacting with external APIs using any LLM.
by RooCodeInc
Provides an autonomous AI coding partner inside the editor that can understand natural language, manipulate files, run commands, browse the web, and be customized via modes and instructions.
by pydantic
A Python framework that enables seamless integration of Pydantic validation with large language models, providing type‑safe agent construction, dependency injection, and structured output handling.
by mcp-use
A Python SDK that simplifies interaction with MCP servers and enables developers to create custom agents with tool‑calling capabilities.
by lastmile-ai
Build effective agents using Model Context Protocol and simple, composable workflow patterns.
by Klavis-AI
Provides production‑ready MCP servers and a hosted service for integrating AI applications with over 50 third‑party services via standardized APIs, OAuth, and easy Docker or hosted deployment.