Skip to main content
Glama
hortusfox-mcp

hortusfox-mcp

by tomfrenzel

HortusFox MCP Server

A Model Context Protocol (MCP) stdio server for HortusFox, the self-hosted plant management system. It exposes the complete HortusFox REST API (/api/*) as MCP tools so AI assistants can read and manage your plants, locations, tasks, inventory, calendar, chat and backups.

Written in TypeScript for Node.js, using the official @modelcontextprotocol/sdk.

Features

Every endpoint of the HortusFox ApiController is covered — 42 tools across 7 domains:

Domain

Tools

Plants (22)

get, add, update, remove, list, search; custom attributes add/edit/remove; main photo update; gallery list/add/edit/remove; attachments fetch/add/edit/remove; log add/edit/remove/fetch

Locations (2)

list, get info

Tasks (4)

fetch, add, edit, remove

Inventory (6)

fetch, add, edit, increment, decrement, remove

Calendar (4)

fetch, add, edit, remove

Chat (2)

fetch, post message

Backup (2)

export, import

Related MCP server: MCP Enterprise Architecture Practice 01

Prerequisites

  • Node.js 18+ (uses the built-in fetch).

  • A running HortusFox instance.

  • A HortusFox API key. In HortusFox, go to Admin → API and create a key.

Installation

npm install
npm run build

This produces the runnable server at dist/index.js.

Configuration

The server is configured entirely through environment variables:

Variable

Required

Description

HORTUSFOX_URL

✅

Base URL of your HortusFox instance, e.g. https://garden.example.com

HORTUSFOX_API_TOKEN

✅

API key created in the HortusFox admin panel

HORTUSFOX_TIMEOUT

❌

Request timeout in milliseconds (default 30000)

HORTUSFOX_UPLOAD_DIR

❌

Directory local files may be uploaded from. Unset, every upload is refused

HORTUSFOX_MAX_UPLOAD_MB

❌

Upload size ceiling in MiB (default 25)

See .env.example.

Usage

Run directly

HORTUSFOX_URL=https://garden.example.com \
HORTUSFOX_API_TOKEN=your-token \
node dist/index.js

The server speaks MCP over stdio. Diagnostic messages are written to stderr; the JSON-RPC protocol uses stdout.

Run with npx

Once published to npm, the server can be run without a local checkout:

HORTUSFOX_URL=https://garden.example.com \
HORTUSFOX_API_TOKEN=your-token \
npx @tomfrenzel/hortusfox-mcp

Register with an MCP client

Add the server to your client's MCP configuration. The recommended way is via npx:

{
  "mcpServers": {
    "hortusfox": {
      "command": "npx",
      "args": ["-y", "@tomfrenzel/hortusfox-mcp"],
      "env": {
        "HORTUSFOX_URL": "https://garden.example.com",
        "HORTUSFOX_API_TOKEN": "your-token"
      }
    }
  }
}

Alternatively, point at a local build:

{
  "mcpServers": {
    "hortusfox": {
      "command": "node",
      "args": ["/absolute/path/to/hortusfox-mcp/dist/index.js"],
      "env": {
        "HORTUSFOX_URL": "https://garden.example.com",
        "HORTUSFOX_API_TOKEN": "your-token"
      }
    }
  }
}

If installed globally (npm install -g .), you can use the hortusfox-mcp binary instead of node dist/index.js.

Tool reference

All tools are prefixed with hortusfox_. Each returns the raw HortusFox JSON response (pretty-printed). Errors (network failures, auth rejection, or API error codes) are returned as MCP tool errors with a descriptive message.

Plants

Tool

Endpoint

Key arguments

hortusfox_get_plant

plants/get

plant

hortusfox_add_plant

plants/add

name, location

hortusfox_update_plant

plants/update

plant, attribute, value

hortusfox_remove_plant

plants/remove

plant

hortusfox_list_plants

plants/list

location?, limit?, from?, sort?

hortusfox_search_plants

plants/search

expression, limit?

hortusfox_add_plant_attribute

plants/attributes/add

plant, label, datatype, content

hortusfox_edit_plant_attribute

plants/attributes/edit

plant, label, datatype, content

hortusfox_remove_plant_attribute

plants/attributes/remove

plant, label

hortusfox_update_plant_photo

plants/photo/update

plant, path? or (external?, photo?), move_to_gallery?

hortusfox_list_plant_gallery

plants/gallery/list

plant

hortusfox_add_plant_gallery_photo

plants/gallery/add

plant, label?, path? or (external?, photo?)

hortusfox_edit_plant_gallery_photo

plants/gallery/edit

plant, item, label

hortusfox_remove_plant_gallery_photo

plants/gallery/remove

item

hortusfox_fetch_plant_attachments

plants/attachments/fetch

plant, paginate?

hortusfox_add_plant_attachment

plants/attachments/add

plant, label, path

hortusfox_edit_plant_attachment

plants/attachments/edit

item, label

hortusfox_remove_plant_attachment

plants/attachments/remove

item

hortusfox_add_plant_log_entry

plants/log/add

plant, content

hortusfox_edit_plant_log_entry

plants/log/edit

logid, content

hortusfox_remove_plant_log_entry

plants/log/remove

logid

hortusfox_fetch_plant_log

plants/log/fetch

plant, paginate?, limit?

Photos and attachments: the photo tools accept either an external image URL (external: true with a photo URL) or a local file (path), sent as multipart/form-data. Attachments are always local files. Local uploads are only allowed from HORTUSFOX_UPLOAD_DIR: the path is resolved with realpath first, so neither .. nor a symlink can reach outside it, and files above HORTUSFOX_MAX_UPLOAD_MB are refused before being read.

Locations

Tool

Endpoint

Key arguments

hortusfox_list_locations

locations/list

only_active?, include_plants?, include_info?, paginate?, limit?

hortusfox_get_location

locations/info

location, include_plants?

Tasks

Tool

Endpoint

Key arguments

hortusfox_fetch_tasks

tasks/fetch

done?, limit?

hortusfox_add_task

tasks/add

title, description?, due_date?, recurring_time?, recurring_scope?, plant?

hortusfox_edit_task

tasks/edit

task, title?, description?, due_date?, recurring_time?, recurring_scope?, done?

hortusfox_remove_task

tasks/remove

task

Inventory

Tool

Endpoint

Key arguments

hortusfox_fetch_inventory

inventory/fetch

–

hortusfox_add_inventory_item

inventory/add

name, description?, tags?, location?, amount?, group?, photo?

hortusfox_edit_inventory_item

inventory/edit

item, plus any of the add fields

hortusfox_increment_inventory_item

inventory/amount/inc

item

hortusfox_decrement_inventory_item

inventory/amount/dec

item

hortusfox_remove_inventory_item

inventory/remove

item

Calendar

Tool

Endpoint

Key arguments

hortusfox_fetch_calendar

calendar/fetch

date_from?, date_till?

hortusfox_add_calendar_entry

calendar/add

name, date_from, date_till?, class?

hortusfox_edit_calendar_entry

calendar/edit

ident, name?, date_from, date_till?, class?

hortusfox_remove_calendar_entry

calendar/remove

ident

Chat

Tool

Endpoint

Key arguments

hortusfox_fetch_chat

chat/fetch

limit?

hortusfox_add_chat_message

chat/message/add

message

Backup

Tool

Endpoint

Key arguments

hortusfox_export_backup

backup/export

locations?, plants?, gallery?, tasks?, inventory?, calendar?

hortusfox_import_backup

backup/import

same category flags

Development

npm run dev        # tsc --watch
npm run typecheck  # type-check without emitting
npm run build      # compile to dist/

A dev container config is provided in .devcontainer/ for a ready-to-use Node.js + TypeScript environment.

Releasing

Releases are published to npm automatically by the Release GitHub Actions workflow whenever a v* tag is pushed. The workflow type-checks, builds, verifies the tag matches the package.json version, and publishes with npm provenance.

To cut a release:

npm version patch   # or minor / major — bumps package.json and creates a tag
git push --follow-tags

This requires an NPM_TOKEN secret to be configured in the repository settings.

How it works

The Asatru framework behind HortusFox merges POST body, query string and JSON body into a single request argument bag, and the API authenticates via a token parameter. This server therefore sends each request as an application/x-www-form-urlencoded POST (including the token and all parameters), which works uniformly for every route and avoids URL-length limits for larger text fields. Requests are retried up to 3 times on transient network/timeout failures; deterministic API and auth errors are surfaced immediately.

License

MIT — see LICENSE.

Available Tools

38 tools
hortusfox_add_calendar_entryAdd calendar entryB

Add a calendar entry with a name, start date and optional end date and class. Returns the new item ID. Endpoint: /api/calendar/add.

Inputs: name (required), date_from (required), class, date_till.

hortusfox_add_chat_messagePost chat messageB

Post a message to the workspace chat (sent via the API/bot identity). Endpoint: /api/chat/message/add.

Inputs: message (required).

hortusfox_add_inventory_itemAdd inventory itemB

Add a new inventory item. Returns the new item ID. Endpoint: /api/inventory/add.

Inputs: name (required), tags, group, photo, +3 more.

hortusfox_add_plantAdd plantB

Create a new plant with a name and a location ID. Returns the new plant ID. Endpoint: /api/plants/add.

Inputs: name (required), location (required).

hortusfox_add_plant_attributeAdd custom plant attributeB

Add a custom attribute to a plant. Endpoint: /api/plants/attributes/add.

Inputs: label (required), plant (required), content (required), datatype (required).

hortusfox_add_plant_log_entryAdd plant log entryB

Add a log/journal entry to a plant. Returns the new log entry ID. Endpoint: /api/plants/log/add.

Inputs: plant (required), content (required).

hortusfox_add_taskAdd taskA

Create a task. Supports an optional due date, recurrence, and association with a plant. Returns the new task ID. Endpoint: /api/tasks/add.

Inputs: title (required), plant, due_date, description, +2 more.

hortusfox_decrement_inventory_itemDecrement inventory amountA

Decrement the amount of an inventory item by one. Returns the new amount. Endpoint: /api/inventory/amount/dec.

Inputs: item (required).

hortusfox_edit_calendar_entryEdit calendar entryB

Edit an existing calendar entry by its identifier. Endpoint: /api/calendar/edit.

Inputs: ident (required), date_from (required), name, class, +1 more.

hortusfox_edit_inventory_itemEdit inventory itemB

Edit an existing inventory item by ID. Endpoint: /api/inventory/edit.

Inputs: item (required), name, tags, group, +4 more.

hortusfox_edit_plant_attributeEdit custom plant attributeB

Edit an existing custom attribute of a plant, identified by its label. Endpoint: /api/plants/attributes/edit.

Inputs: label (required), plant (required), content (required), datatype (required).

hortusfox_edit_plant_log_entryEdit plant log entryB

Edit an existing plant log entry by its ID. Endpoint: /api/plants/log/edit.

Inputs: logid (required), content (required).

hortusfox_edit_taskEdit taskB

Edit an existing task by ID, including toggling its done state. Endpoint: /api/tasks/edit.

Inputs: task (required), done, title, due_date, +3 more.

hortusfox_export_backupExport backupA

Export a backup archive for the selected data categories. Returns a downloadable file URL. Endpoint: /api/backup/export.

Inputs: tasks, plants, gallery, calendar, +2 more.

hortusfox_fetch_calendarFetch calendar entriesB

Fetch calendar entries within a date range. Defaults to today through the next 30 days when omitted. Endpoint: /api/calendar/fetch.

Inputs: date_from, date_till.

hortusfox_fetch_chatFetch chat messagesB

Fetch recent workspace chat messages. Endpoint: /api/chat/fetch.

Inputs: limit.

hortusfox_fetch_inventoryFetch inventoryA

Fetch the full inventory list. Endpoint: /api/inventory/fetch.

Inputs: no named parameters.

hortusfox_fetch_plant_logFetch plant log entriesB

Fetch log entries for a plant, with optional pagination. Endpoint: /api/plants/log/fetch.

Inputs: plant (required), limit, paginate.

hortusfox_fetch_tasksFetch tasksA

Fetch tasks, optionally including completed ones. Endpoint: /api/tasks/fetch.

Inputs: done, limit.

hortusfox_get_locationGet location infoB

Fetch details of a single location by ID, optionally including its plants. Endpoint: /api/locations/info.

Inputs: location (required), include_plants.

hortusfox_get_plantGet plant detailsA

Fetch full details of a single plant by its ID, including default fields and any custom attributes. Endpoint: /api/plants/get.

Inputs: plant (required).

hortusfox_import_backupImport backupB

Import previously staged backup data for the selected categories. Endpoint: /api/backup/import.

Inputs: tasks, plants, gallery, calendar, +2 more.

hortusfox_increment_inventory_itemIncrement inventory amountA

Increment the amount of an inventory item by one. Returns the new amount. Endpoint: /api/inventory/amount/inc.

Inputs: item (required).

hortusfox_list_locationsList locationsB

List locations, optionally including the plants at each location. Endpoint: /api/locations/list.

Inputs: limit, paginate, only_active, include_info, +1 more.

hortusfox_list_plantsList plantsB

List plants, optionally filtered by location, with paging and sorting. Endpoint: /api/plants/list.

Inputs: from, sort, limit, location.

hortusfox_remove_calendar_entryRemove calendar entryC

Remove a calendar entry by its identifier. Endpoint: /api/calendar/remove.

Inputs: ident (required).

hortusfox_remove_inventory_itemRemove inventory itemB

Remove an inventory item by ID. Endpoint: /api/inventory/remove.

Inputs: item (required).

hortusfox_remove_plantRemove plantB

Delete a plant by its ID. Endpoint: /api/plants/remove.

Inputs: plant (required).

hortusfox_remove_plant_attributeRemove custom plant attributeB

Remove a custom attribute from a plant by its label. Endpoint: /api/plants/attributes/remove.

Inputs: label (required), plant (required).

hortusfox_remove_plant_log_entryRemove plant log entryB

Remove a plant log entry by its ID. Endpoint: /api/plants/log/remove.

Inputs: logid (required).

hortusfox_remove_taskRemove taskB

Remove a task by ID. Endpoint: /api/tasks/remove.

Inputs: task (required).

hortusfox_search_plantsSearch plantsA

Search plants by a free-text expression (matches name, location, attributes and more). Endpoint: /api/plants/search.

Inputs: expression (required), limit.

hortusfox_update_plantUpdate plant attributeC

Update a single attribute of a plant by name (e.g. name, location, description, humidity, etc.). Endpoint: /api/plants/update.

Inputs: plant (required), value (required), attribute (required).

hortusfox_update_plant_photoUpdate plant main photoA

Update the main preview photo of a plant. Set external=true and provide a photo URL to use an external image. Optionally move the current photo into the gallery first. Endpoint: /api/plants/photo/update.

Inputs: plant (required), photo, external, move_to_gallery.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 38 tools

    Disambiguation4/5

    Most tools are clearly separated by resource and action, so an agent can usually pick the right one. The main overlap is hortusfox_update_plant vs hortusfox_edit_plant_attribute, both of which can look like attribute modification, and the numerous read variants (get/list/fetch/search) require careful description reading.

    Naming Consistency4/5

    Every tool uses the hortusfox_<verb>_<noun> snake_case pattern, and CRUD verbs are mostly consistent. However, reads mix get, list, fetch, and search, and modifications mix update and edit, so the verb choice is not fully predictable.

    Tool Count3/5

    38 tools is a high count, but it is organized into logical modules (plants, locations, calendar, tasks, inventory, chat, backup) and each tool maps to a distinct endpoint. Even so, the set is larger than ideal for an MCP server and may feel heavy to an agent.

    Completeness3/5

    Core plant management is well covered: plant CRUD, custom attributes, gallery photos, log entries, plus tasks, calendar, inventory, and backup. The notable gap is locations only support list/get, with no create/update/delete, which can block workflows that need to set up or modify locations.

    Maintenance

    ActivityActive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server and CLI for controlling FarmBot hardware, enabling AI agents to manage gardening tasks through tools like gantry movement and device status monitoring. It supports executing Lua scripts and core hardware commands like homing and emergency stops via the Model Context Protocol.
      3
      MIT
    • F
      license
      Not graded
      quality
      D
      maintenance
      Enterprise MCP server providing a suite of tools including file, database, GitHub, Slack, calendar, email, vector search, and Python execution, with safe defaults and OpenAI integration for automatic tool selection.
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      A local-first MCP server for tracking indoor horticulture metrics, enabling cold-stratification timelines, ericaceous soil pH validation, and transplant-shock recovery through a LangGraph agent with a local LLM.
      MIT