Skip to main content
Glama
lukegskw

kitchenowl-insights-mcp

KitchenOwl Insights MCP

TypeScript CI Container

KitchenOwl Insights MCP is a standalone, read-only Model Context Protocol server that estimates which ingredients may still be available in a KitchenOwl household and ranks recipes already saved in KitchenOwl.

It uses strict validation, stdio and Streamable HTTP transports, a hardened container, and automated GHCR publication. It runs alongside KitchenOwl without modifying or forking it, and every estimate includes its supporting evidence.

Navigation

Related MCP server: Mealie MCP Server

Use this server

Use the published container image for a standard HTTP deployment, or clone the repository for local stdio use and development. Both workflows are documented in Installation.

Fork this repository when you want to propose changes through a pull request. See Contributing before submitting changes.

If this server is useful to you, consider giving the repository a star. It helps other KitchenOwl users discover the integration.

About

KitchenOwl records when items are added to and removed from shopping lists, but it does not maintain a confirmed household inventory. This server uses that history to produce evidence-based estimates without writing back to KitchenOwl.

The TypeScript foundation is based on the MCP TypeScript Starter, adapted with KitchenOwl-specific database access, domain logic, tools, and tests.

The default stdio transport is intended for local clients that launch the server as a child process. Streamable HTTP is stateless and creates a fresh MCP server for each request while sharing the read-only application context, so it can be replicated without MCP session storage.

The server reads one existing SQLite or PostgreSQL KitchenOwl database. It does not perform migrations, persist its own data, modify KitchenOwl records, provide telemetry, or authenticate HTTP callers.

Features

  • Registers tools with strict Zod input and output schemas.

  • Returns both human-readable content and typed structured content.

  • Includes accurate read-only MCP safety annotations.

  • Supports stdio and stateless Streamable HTTP.

  • Connects through read-only SQLite or PostgreSQL sessions.

  • Validates the required KitchenOwl schema before accepting MCP traffic.

  • Reconstructs item-consumption cycles from shopping-list history.

  • Reports probability, confidence, evidence, and warnings for every estimate.

  • Ranks recipes already saved in the selected KitchenOwl household.

  • Associates recipes and inventory by KitchenOwl item ID rather than item name.

  • Uses Hono with Host and Origin validation against DNS rebinding.

  • Limits tool inputs and HTTP request bodies.

  • Keeps stdout exclusive to MCP protocol messages in stdio mode.

  • Handles SIGINT and SIGTERM with idempotent graceful shutdown.

  • Runs as a non-root container with read-only-root-filesystem support.

  • Tests configuration, database behavior, MCP behavior, Hono routes, and real traffic.

  • Publishes multi-architecture images only after quality checks pass.

MCP tools

get_inventory_estimate

Returns estimated inventory states for a household, optionally filtered by shopping list or item IDs.

Example input:

{
  "household_id": 1,
  "list_id": 1,
  "item_ids": [225, 469],
  "include_unknown": true
}

Example structured output:

{
  "household_id": 1,
  "as_of": "2026-07-19T18:00:00Z",
  "items": [
    {
      "item_id": 225,
      "name": "Eggs",
      "state": "uncertain",
      "availability_probability": 0.5,
      "confidence": "low",
      "typical_duration_days": 10,
      "completed_cycles": 2,
      "currently_on_list": false,
      "last_dropped_at": "2026-07-15T12:00:00Z",
      "evidence": [
        {
          "kind": "legacy_drop",
          "occurred_at": "2026-07-15T12:00:00Z",
          "interpretation": "Removed from the shopping list; possible purchase"
        }
      ],
      "warnings": [
        "KitchenOwl does not distinguish a purchase from deletion in legacy history"
      ]
    }
  ]
}

Possible states are probably_available, uncertain, probably_missing, and unknown.

recommend_available_recipes

Ranks recipes saved in a household according to estimated ingredient availability.

Example input:

{
  "household_id": 1,
  "list_id": 1,
  "top_k": 5,
  "include_optional": false
}

Example structured output:

{
  "household_id": 1,
  "as_of": "2026-07-19T18:00:00Z",
  "recommendations": [
    {
      "recipe_id": 100,
      "name": "Omelette",
      "score": 0.75,
      "classification": "possible_with_uncertainty",
      "likely_available": ["Eggs"],
      "uncertain": ["Cheese"],
      "likely_missing": [],
      "unknown": [],
      "ignored_optional": ["Parsley"],
      "evidence": {
        "Eggs": "Removed from the shopping list; possible purchase"
      },
      "warnings": [
        "Estimated availability; it does not represent food safety or expiry."
      ]
    }
  ]
}

Possible classifications are probably_possible, possible_with_uncertainty, probably_missing_ingredients, and insufficient_data.

How estimates work

  • ADDED means an item entered a shopping list and likely needs replenishment.

  • DROPPED means it left a shopping list and may have been purchased, deleted, or corrected.

  • A complete consumption cycle starts at DROPPED and ends at the next ADDED event for the same item.

  • Typical duration is the median of complete cycles.

  • One or two complete cycles produce low confidence; three or more produce medium confidence.

  • An item currently on a shopping list is treated as probably missing.

Recipe scores use these weights:

Ingredient state

Weight

probably_available

1.00

uncertain

0.50

unknown

0.25

probably_missing

0.00

Optional ingredients are excluded by default.

Tech stack

Installation

Prerequisites

  • A running KitchenOwl installation.

  • Read-only access to its SQLite or PostgreSQL database.

  • Node.js 24+ and pnpm 11 for local development.

  • Docker and Docker Compose for container deployment.

Docker Compose

The recommended HTTP deployment uses the published multi-architecture image:

ghcr.io/lukegskw/kitchenowl-insights-mcp:latest

Download the Compose example and provide the database path and hostname clients will use:

curl -O https://raw.githubusercontent.com/lukegskw/kitchenowl-insights-mcp/main/compose.example.yaml
export KITCHENOWL_DATABASE_PATH=/path/to/kitchenowl/database.db
export KITCHENOWL_INSIGHTS_ALLOWED_HOSTS='mcp.example.internal'
docker compose -f compose.example.yaml up -d

The Streamable HTTP and health endpoints will be available at:

http://<host>:8099/mcp
http://<host>:8099/healthz

The database file must be readable by UID/GID 10001:10001. To use another identity that already has read access, set KITCHENOWL_INSIGHTS_UID_GID. To publish a different host port, set KITCHENOWL_INSIGHTS_PUBLISHED_PORT; the application still uses port 8099 inside the container.

The latest tag follows the newest successful build from the default branch. Use a version or immutable sha-* tag for controlled deployment and rollback.

Docker run

docker run -d \
  --name kitchenowl-insights \
  --restart unless-stopped \
  --read-only \
  --user 10001:10001 \
  --cap-drop ALL \
  --security-opt no-new-privileges:true \
  --tmpfs /tmp:size=16m,mode=1777 \
  -v /path/to/kitchenowl/database.db:/kitchenowl/database.db:ro \
  -e 'KITCHENOWL_INSIGHTS_DATABASE_URL=sqlite+pysqlite:///file:/kitchenowl/database.db?mode=ro&uri=true' \
  -e KITCHENOWL_INSIGHTS_TRANSPORT=streamable-http \
  -e KITCHENOWL_INSIGHTS_HOST=0.0.0.0 \
  -e KITCHENOWL_INSIGHTS_ALLOWED_HOSTS=127.0.0.1,localhost,mcp.example.internal \
  -p 8099:8099 \
  ghcr.io/lukegskw/kitchenowl-insights-mcp:latest

Build the container from source

git clone https://github.com/lukegskw/kitchenowl-insights-mcp.git
cd kitchenowl-insights-mcp
docker buildx build --load -t kitchenowl-insights-mcp:local .

Local Node.js installation

git clone https://github.com/lukegskw/kitchenowl-insights-mcp.git
cd kitchenowl-insights-mcp
pnpm install --frozen-lockfile
pnpm build
export KITCHENOWL_INSIGHTS_DATABASE_URL='sqlite+pysqlite:///file:/path/to/database.db?mode=ro&uri=true'
pnpm start -- --transport stdio

For local Streamable HTTP development:

KITCHENOWL_INSIGHTS_DATABASE_URL='sqlite:////path/to/database.db' \
KITCHENOWL_INSIGHTS_TRANSPORT=streamable-http \
KITCHENOWL_INSIGHTS_HOST=127.0.0.1 \
pnpm dev

PostgreSQL

Use a dedicated PostgreSQL role with only CONNECT, schema USAGE, and table SELECT permissions, and set default_transaction_read_only=on. Both native and existing SQLAlchemy-style URLs are accepted:

postgresql://<user>:<password>@<host>:5432/<database>
postgresql+psycopg://<user>:<password>@<host>:5432/<database>

Do not reuse an administrative KitchenOwl credential. The standard image contains both database drivers; no alternative image is required.

Configuration

All settings use the KITCHENOWL_INSIGHTS_ prefix. A local .env file is loaded when present.

Variable

Required

Default

Description

KITCHENOWL_INSIGHTS_DATABASE_URL

Yes

None

SQLite or PostgreSQL database URL.

KITCHENOWL_INSIGHTS_TRANSPORT

No

stdio

stdio or streamable-http.

KITCHENOWL_INSIGHTS_HOST

No

0.0.0.0

HTTP bind address.

KITCHENOWL_INSIGHTS_PORT

No

8099

HTTP listening port.

KITCHENOWL_INSIGHTS_ALLOWED_HOSTS

External HTTP

None

Comma-separated Host and Origin hostname list.

KITCHENOWL_INSIGHTS_LOG_LEVEL

No

INFO

Application log-level contract.

KITCHENOWL_INSIGHTS_MAX_HISTORY_EVENTS

No

5000

Maximum history events loaded per request.

KITCHENOWL_INSIGHTS_DEFAULT_TOP_K

No

5

Default number of recommendations.

KITCHENOWL_INSIGHTS_MAX_TOP_K

No

20

Maximum allowed recommendations.

KITCHENOWL_INSIGHTS_NOW_OVERRIDE

No

None

Deterministic clock override intended for tests.

The --transport command-line option overrides KITCHENOWL_INSIGHTS_TRANSPORT. KITCHENOWL_INSIGHTS_ALLOWED_HOSTS contains hostnames, not URLs; include every hostname legitimate clients and health checks use.

The database URL is a secret. Supply it through the deployment platform or environment, never as an MCP tool argument or committed file.

MCP client setup

For a client that accepts Streamable HTTP server definitions:

mcp_servers:
  kitchenowl_insights:
    url: http://127.0.0.1:8099/mcp

For a client that launches a local stdio server:

{
  "mcpServers": {
    "kitchenowl_insights": {
      "command": "node",
      "args": [
        "/absolute/path/to/kitchenowl-insights-mcp/dist/main.js",
        "--transport",
        "stdio"
      ],
      "env": {
        "KITCHENOWL_INSIGHTS_DATABASE_URL": "sqlite:////absolute/path/to/database.db"
      }
    }
  }
}

To let a local client launch the container over stdio, use docker run -i --rm, mount the database read-only, supply KITCHENOWL_INSIGHTS_DATABASE_URL, and pass --transport stdio after the image name. -i is required so the client can exchange MCP messages through standard input and output.

Client configuration formats differ. Consult the client's documentation for its exact schema and restart or reload the client after changing its server definition.

Architecture and development

The main extension points remain intentionally direct:

  1. Define domain models and output contracts in src/models/index.ts.

  2. Keep database access in src/repository/index.ts.

  3. Coordinate domain behavior in src/service/index.ts.

  4. Define strict input and output schemas in src/tools/index.ts.

  5. Register tool behavior through src/server.ts.

  6. Add MCP behavior tests and database integration tests for every visible change.

The application creates one read-only database context and service at startup. Stdio uses one MCP server for the process; stateless HTTP creates request-scoped MCP servers that share the application context. Transport modules remain independent from domain logic, and shutdown closes transports before the database context.

Verification

Run the complete repository suite:

pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test:unit
pnpm test:integration
pnpm build

The PostgreSQL integration test runs when KITCHENOWL_TEST_POSTGRES_URL points to a disposable database named kitchenowl_insights_test; CI supplies this automatically.

Verify schema compatibility and write protection against a database:

pnpm verify:read-only \
  'sqlite+pysqlite:///file:/path/to/database.db?mode=ro&uri=true'

For container changes:

docker buildx build --load -t kitchenowl-insights-mcp:test .

Finally, connect an MCP client and confirm that both tools are listed and return text and structured content. In HTTP mode, confirm /healthz reports {"status":"ok"}.

Limitations

  • KitchenOwl legacy history does not distinguish purchases from deletions.

  • Estimates do not account for free-text quantities, freshness, expiry, or food safety.

  • Only recipes already saved in KitchenOwl are ranked.

  • Sparse history produces low confidence or unknown states.

  • The server fails closed when required KitchenOwl tables or columns are missing.

  • A live SQLite database in WAL mode may require access to its sidecar files. Use a consistent read-only snapshot if live reads are unstable.

  • Streamable HTTP has no authentication. Restrict it to loopback, a trusted LAN, a VPN, a private container network, or an authenticated reverse proxy.

  • Host and Origin allowlists prevent classes of DNS rebinding attacks but do not authenticate callers.

  • The HTTP transport is stateless and contains no MCP session storage.

  • Rate limiting, tracing, and metrics are not included.

Review SECURITY.md before exposing the HTTP transport or reporting a security issue.

Contributing

Contributions are welcome. Before opening a pull request:

pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test
pnpm build
docker buildx build --load -t kitchenowl-insights-mcp:test .

Changes must preserve strict typing, bounded validation, structured MCP results, stdout protocol purity, secure HTTP defaults, deterministic tests, household isolation, database URL redaction, SQLite and PostgreSQL support, layered read-only enforcement, and documentation for user-visible behavior. Do not add abstractions without a concrete use case for them.

License

This repository does not currently declare a software license.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server for managing recipes, meal plans, shopping lists, and more through a self-hosted Mealie instance.
    1
    MIT
  • A
    license
    Not graded
    quality
    F
    maintenance
    MCP server for MealMastery AI meal planning that enables users to manage meal plans, recipes, and grocery lists through natural language conversation with AI agents like Claude.
    52
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    MCP server for meal planning and grocery list generation, enabling recipe storage, meal plan creation, and automated grocery lists with ignored ingredients.
    8
    2
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lukegskw/kitchenowl-insights-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server