Skip to main content

MCP server for the Eclipse Ditto digital twin HTTP API

Project description

Eclipse Ditto MCP Server

A Model Context Protocol (MCP) server for Eclipse Ditto — the open-source (EPL-2.0) digital twin framework. It exposes Ditto's HTTP API as MCP tools so an AI agent can manage devices ("things"), their attributes/features, policies, connections, and cluster admin — the full Ditto HTTP API surface.

Since Bosch IoT Things and other commercial IoT platforms are built on Ditto's open protocol, this server also works against those deployments — nothing in the code is vendor-specific.

Built with FastMCP.

Tools

Things

Tool Description
list_things(namespaces, filter, fields, limit) Search/list things. filter is a Ditto RQL expression, e.g. eq(attributes/location,"lab-1").
count_things(namespaces, filter) Count things matching a filter without fetching them.
get_things(thing_ids, fields) Bulk-fetch multiple things by ID in one request.
get_thing(thing_id, fields) Fetch the full digital twin for one thing.
put_thing(thing_id, thing, overwrite=False) Create a thing, or replace one with overwrite=True.
patch_thing(thing_id, patch) Partially update a thing via RFC-7396 JSON Merge Patch.
delete_thing(thing_id, confirm=False) Delete a thing. Irreversible.
get_thing_policy_id / set_thing_policy_id Read/repoint the policy controlling a thing.
get_thing_definition / set_thing_definition / delete_thing_definition Manage a thing's WoT/model definition.
whoami() Return the identity Ditto authenticated this connector as — useful to sanity-check credentials.

Attributes & Features

Tool Description
get_thing_attributes(thing_id, path=None) Get all attributes, or one by JSON pointer path.
set_thing_attributes(thing_id, value, path=None, overwrite=False) Set the whole attributes object, or one attribute.
delete_thing_attributes(thing_id, path=None, confirm=False) Delete attributes (whole object or one path).
get_thing_features(thing_id) Get all features (sensor/actuator state).
get_feature / put_feature / delete_feature Read/create-replace/delete one whole feature.
get_feature_properties / set_feature_properties / delete_feature_properties Read/write/delete feature properties or desiredProperties, whole or by path.
get_feature_definition / set_feature_definition / delete_feature_definition Manage a feature's definition.

Messages

Tool Description
send_message(thing_id, subject, payload, feature_id=None, direction="inbox", timeout=10) Send a live message to/from a thing or feature (e.g. invoke a device operation).
claim_thing(thing_id, payload=None, timeout=10) Send a claim message to gain access to a thing.

Policies

Tool Description
get_policy / put_policy / delete_policy Read/create-replace/delete a policy.
get_policy_entries(policy_id, label=None) Read all entries, or one by label.
set_policy_entry / delete_policy_entry Create-replace/delete one policy entry.

Connectivity & DevOps (require DITTO_DEVOPS_USERNAME/DITTO_DEVOPS_PASSWORD)

Ditto's Connections API and DevOps API (log levels, cluster config, piggyback commands) sit behind a separate "devops" Basic-auth realm on the gateway, independent of the policy-based auth used for things/policies.

Tool Description
list_connections / get_connection List/fetch connection configs.
create_connection(connection, dry_run=False) Create a connection (ID generated by Ditto).
update_connection(connection_id, connection) Update an existing connection (404 if it doesn't exist).
delete_connection(connection_id, confirm=False) Delete a connection.
get_connection_status / get_connection_metrics / get_connection_logs Inspect a connection's live state.
send_connection_command(connection_id, command) Open/close/reset-metrics/enable-logs/reset-logs.
get_logging_config / set_logging_config Read/set cluster log levels.
get_devops_config(path) Read cluster-wide runtime config.
send_devops_piggyback(command, service_name=None, instance_index=None) Low-level admin command — Ditto's most powerful, least-guarded API. Use with care.

Live events

Tool Description
poll_thing_changes(thing_ids, namespaces, filter, fields, duration_seconds=10, max_events=50) Open a short-lived SSE connection and collect live thing-change events. A request/response approximation of Ditto's persistent change feed — see caveat below.

Safety conventions

  • Create vs. replace: every put_*/set_*/create_* tool defaults to overwrite=False, using Ditto's If-None-Match: * header so create-only is race-free (not a check-then-set). Pass overwrite=True to replace existing data.
  • Deletes are confirm-gated: every delete_* tool requires confirm=True. There is no bulk/cascading delete.
  • Not covered (deliberately): WoT Web-of-Things descriptor endpoints (/.well-known/wot, /devops/wot/*), and fine-grained policy sub-resources (subjects/{id}, resources/{path}, imports, token-integration actions) — whole-entry set_policy_entry/get_policy_entries covers the common case. Add these later if you need them.

Configuration

Env var Required Description
DITTO_BASE_URL Yes Base URL of the Ditto HTTP API, e.g. http://localhost:8080 or your gateway's public URL.
DITTO_USERNAME / DITTO_PASSWORD No Basic auth for the Things/Policies/Messages/Search API. Typical for self-hosted Ditto (nginx demo setup uses ditto/ditto).
DITTO_BEARER_TOKEN No Bearer token, used instead of Basic auth for the same API. Typical for OAuth2-fronted deployments (e.g. Bosch IoT Things).
DITTO_DEVOPS_USERNAME / DITTO_DEVOPS_PASSWORD No Basic auth for the separate DevOps/Connections realm (self-hosted default: devops/foobar). Required only for the Connectivity and DevOps tools.

If both DITTO_BEARER_TOKEN and Basic auth credentials are set, the bearer token takes precedence. If neither is set, requests are sent unauthenticated (only works if your Ditto instance allows anonymous/pre-authenticated access).

Running locally

uv sync
export DITTO_BASE_URL=http://localhost:8080
export DITTO_USERNAME=ditto
export DITTO_PASSWORD=ditto
export DITTO_DEVOPS_USERNAME=devops    # only needed for connectivity/devops tools
export DITTO_DEVOPS_PASSWORD=foobar
uv run dittomcpserver.py

See mcp.json for ready-to-use client configs (stdio and Docker).

Testing against a real Ditto instance

This repo's design principles call for testing against a real instance rather than mocks. docker-compose.yml (adapted from Ditto's official example, trimmed to the services this connector needs) spins up a full local Ditto stack — MongoDB, the Ditto microservices, and an nginx front door with Basic auth.

docker compose up -d       # start Ditto on http://localhost:8080 (user: ditto / pass: ditto; devops: devops / foobar)
uv run pytest -v           # tests/conftest.py also starts/stops the stack automatically
docker compose down        # stop it manually if you started it yourself

The 47 tests cover every tool group (things, attributes/features, messages, policies, connectivity, devops, live events) against this real stack, including delete/confirm gating and create/overwrite gating.

A note on the live-events approximation

poll_thing_changes opens Ditto's SSE change feed for a bounded window instead of holding a persistent subscription (which doesn't map cleanly onto a single MCP tool call). Ditto's SSE stream sends periodic empty data: keepalive lines even when nothing has changed — the tool checks its deadline on every line received, including keepalives, so it reliably returns within duration_seconds regardless of how chatty or quiet the stream is.

License notes

docker-compose.yml and the files under docker/ are adapted from the Eclipse Ditto project (EPL-2.0) and are used here only to spin up a local test instance — they are not part of the MCP server itself.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eclipse_ditto_mcp_server-0.1.1.tar.gz (102.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eclipse_ditto_mcp_server-0.1.1-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file eclipse_ditto_mcp_server-0.1.1.tar.gz.

File metadata

  • Download URL: eclipse_ditto_mcp_server-0.1.1.tar.gz
  • Upload date:
  • Size: 102.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for eclipse_ditto_mcp_server-0.1.1.tar.gz
Algorithm Hash digest
SHA256 3c05cb734c5b97b4d1b7a2794d43e5635e0f292b025f910b113c255fd8ba1550
MD5 25793ec7a048ae135e393014479562e6
BLAKE2b-256 a8a8df7f721bbb0fefc45565b56df2ce9034cc8debd8bdd02b172dbda9062ad3

See more details on using hashes here.

File details

Details for the file eclipse_ditto_mcp_server-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: eclipse_ditto_mcp_server-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 13.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for eclipse_ditto_mcp_server-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a9cc9b33bd914b5601bd8d14d5af850e63f11ef316b26423d0946a4e77e03b4d
MD5 a42708704be6b38a822004c571edb5f1
BLAKE2b-256 fe42966ec06704fa4b2fe6c9fd415be6b3eb29ecbe6981efe79c737c9a5a2ff7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page