Skip to main content
Glama

nc-forms-mcp

MCP server for the Nextcloud Forms API v3. Create, update, clone, and validate forms β€” without ever leaking an app password into the agent's context.

Python MCP License



🀨 The Problem

Nextcloud Forms has a REST API at /ocs/v2.php/apps/forms/api/v3/ that uses HTTP Basic Auth with an app password. When an AI agent calls this API directly:

Issue

What happens

Consequence

Credential leakage

The password passes through the LLM's context

Stored in logs, prompt caches, conversation history

Tool sprawl

Every Forms operation is a raw curl invocation

Inconsistent error handling, no validation

No isolation

The same credential gets reused for WebDAV, shares, etc.

Scope creep β€” operations outside Forms API

Repetition

Auth headers, error parsing, and retry logic in every call

Wasteful tokens and fragile code

Bottom line: credentials in agent context = risk. Raw API calls in conversation = tech debt.


Related MCP server: Google Forms MCP

βœ… The Solution

Wrap the Forms API in an MCP server that:

  1. Reads credentials from environment variables only β€” the agent never sees them

  2. Exposes 16 focused tools β€” forms_get, questions_add, options_update, etc.

  3. Runs as a stdio subprocess managed by the Hermes MCP client

  4. Returns structured JSON β€” no parsing needed

  5. Validates form health with a single tool call

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   MCP stdio    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   HTTPS Basic Auth   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              β”‚ ──────────────→│                  β”‚ ────────────────────→│                  β”‚
β”‚  Hermes      β”‚ ←──────────────│  nc-forms-mcp    β”‚ ←────────────────────│  Nextcloud Forms  β”‚
β”‚  Agent       β”‚                β”‚  (Python process) β”‚                     β”‚  API v3          β”‚
β”‚              β”‚                β”‚  NC_FORMS_PASSWORDβ”‚                     β”‚                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚  (env only,       β”‚                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚   never in chat)  β”‚
                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“¦ Installation

Prerequisites

  • Python 3.10+

  • Nextcloud instance with Forms app (v5+)

  • Nextcloud app password (Settings β†’ Security β†’ Devices & sessions)

Install

git clone https://github.com/erniomaldo/nc-forms-mcp.git ~/Proyectos/nc-forms-mcp
cd ~/Proyectos/nc-forms-mcp

# Hermes uses its own venv β€” install there:
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python -e .

Or use your project's venv:

uv venv && uv pip install -e .

πŸ”§ Hermes Configuration

Add to ~/.hermes/config.yaml:

mcp_servers:
  nc-forms:
    command: "uv"
    args:
      - "run"
      - "--directory"
      - "/home/ernesto-personal/Proyectos/nc-forms-mcp"
      - "nc-forms-mcp"
    env:
      NC_FORMS_USER: "erniomaldo"
      NC_FORMS_PASSWORD: "your-app-password-here"
      NC_FORMS_BASE: "https://base.agendasencilla.com"
    timeout: 30

Restart Hermes after adding. On startup it auto-discovers 16 tools prefixed mcp_nc_forms_*.


πŸ› οΈ Tools

Tool

What it does

Use case

forms_list

List all owned forms

Dashboard / overview

forms_get

Get full form with questions, options, shares

Read current state

forms_create

Create an empty form

Start a new brief/survey

forms_update

Update title, description, settings

Iterate on form metadata

forms_clone

Clone a form (no submissions)

V1 β†’ V2 iteration

forms_delete

Permanently delete a form

Cleanup

questions_list

List all questions in a form

Overview

questions_get

Get a single question by ID

Check specific question

questions_add

Add a question (multiple choice, text, etc.)

Build form content

questions_update

Update question text, description, isRequired

Refine wording

questions_delete

Remove a question

Prune sections

questions_reorder

Reorder questions by ID array

Reorganize sections

options_add

Add options to a choice question

Populate answer choices

options_update

Update a single option's text

Fix typos

options_delete

Remove an option

Cleanup

forms_validate

Check all questions have valid optionTypes

QA before publishing

Tool naming

MCP prefix: mcp_nc_forms_ + tool name (underscores replace hyphens).

Example: mcp_nc_forms_forms_get β†’ get form details.


πŸš€ Usage (after Hermes integration)

# List all forms
mcp_nc_forms_forms_list()

# Get form 8 with all questions + options
mcp_nc_forms_forms_get({ "form_id": 8 })

# Add a question to form 8
mcp_nc_forms_questions_add({
    "form_id": 8,
    "type": "multiple_unique",
    "text": "🎨 1.2 ¿Colores definidos?"
})

# Add options
mcp_nc_forms_options_add({
    "form_id": 8,
    "question_id": 74,
    "option_texts": ["βœ… De acuerdo", "🟑 Cerca pero ajustes", "❌ No se parece"],
    "option_type": "choice"
})

# Validate before publishing
mcp_nc_forms_forms_validate({ "form_id": 8 })
# β†’ {"healthy": true, "total_questions": 32, "issues": []}

πŸ§ͺ CLI Testing (without Hermes)

export NC_FORMS_USER="erniomaldo"
export NC_FORMS_PASSWORD="your-app-password"
export NC_FORMS_BASE="https://base.agendasencilla.com"

nc-forms-mcp forms_list '{}'
nc-forms-mcp forms_get '{"form_id": 8}'
nc-forms-mcp forms_validate '{"form_id": 8}'

πŸ—οΈ Project Structure

nc-forms-mcp/
β”œβ”€β”€ pyproject.toml          # Project metadata + dependencies
β”œβ”€β”€ README.md               # This file
β”œβ”€β”€ LICENSE
β”œβ”€β”€ nc_forms_mcp/
β”‚   β”œβ”€β”€ __init__.py         # Package init (re-exports server)
β”‚   β”œβ”€β”€ server.py           # MCP server: auth, route, tools, entry points
└── tests/                  # Coming soon

πŸ” Security

  • Credentials live in env config β€” the agent never sees NC_FORMS_PASSWORD

  • The app password is scoped to Forms API only β€” WebDAV, Shares, Calendar, Collectives, and other Nextcloud features use their own MCP tools with their own auth

  • Error messages redact credential-like patterns

  • The MCP server process inherits a filtered environment (Hermes strips secrets from the subprocess env except what you explicitly set in env)

What NOT to do

# ❌ WRONG β€” password leaks into agent context
mcp_servers:
  nc-forms:
    command: "python3"
    args: ["server.py", "--password", "TEZiJ-..."]
# βœ… CORRECT β€” password stays in env
mcp_servers:
  nc-forms:
    command: "uv"
    args: ["run", "--directory", "~/Proyectos/nc-forms-mcp", "nc-forms-mcp"]
    env:
      NC_FORMS_PASSWORD: "TEZiJ-..."

πŸ’‘ Why not just use curl?

Approach

Secret leaks?

Inconsistent errors?

Token waste?

Reusable?

Raw curl in conversation

βœ… Always

βœ… Every call

βœ… Headers + parsing

❌ No

Python script in /tmp

βœ… In code

βœ… Per script

βœ… Duplicated logic

❌ Per task

MCP server

❌ Never

❌ Unified

❌ One setup

βœ… All tasks


πŸ“‹ Comparison with alternative approaches

nc-forms-mcp

Forms web UI

Direct REST API (curl)

Custom script

Setup

5 lines in config.yaml

Zero (browser)

Zero (curl installed)

Python + requests

Speed

Instant (stdio)

Point-and-click

Fast

Depends on quality

Repeatability

βœ… Always same tools

❌ Manual clicks

❌ Varies per call

βœ… If committed

Validation

βœ… forms_validate built-in

❌ Manual review

❌ Never

❌ Rarely

CI/CD ready

βœ… Yes

❌ No

⚠️ Needs auth wrapper

βœ… If committed

Secret safety

βœ… In env only

❌ Browser session

❌ In command args

⚠️ In code or env

Token cost

Low (one discovery)

N/A

High (per call)

Low (per script)


  • agentcheckpoint β€” atomic state store for multi-agent coordination (SQLite + MCP)

  • Hermes Agent β€” the personal AI agent that runs this MCP server


πŸ“„ License

MIT

Related MCP Connectors

Related MCP Servers