duplicacy-mcp
Summarizes Duplicacy backups by exposing read-only backup, prune, and storage metrics from a Prometheus exporter over MCP.
Answer “are my backups OK?” with
get_backup_overviewverdicts (ok/running/stale/never/failed), reasons, ages, and counts.List valid snapshot IDs, storage targets, and machines via
list_snapshots.Inspect one snapshot’s current state and last-run details with
get_backup_status.Get the last completed run’s duration, files, bytes, chunks, revision, and exit code with
get_backup_history.Check whether a prune is running and when the last successful prune occurred with
get_prune_status.View storage size/chunk counts and revisions per snapshot via
get_storage_usage.Read
duplicacy://status,duplicacy://progress, andduplicacy://healthresources.Use stdio or Streamable HTTP; every tool is read-only.
Integrates with a Prometheus exporter to monitor Duplicacy backup metrics, enabling the tracking of backup status, progress, health, history, and snapshot lists.
Features
Reads the metrics of duplicacy-exporter and serves them over MCP.
One call answers "are my backups OK?":
get_backup_overviewgives every backup a verdict (ok, running, stale, never, failed) with a reason.Speaks MCP 2026-07-28 (
server/discover, stateless requests) and every earlier revision down to 2024-11-05 (theinitializehandshake) from the same binary, over stdio and Streamable HTTP. Clients that still use the old handshake keep working.Read-only by design: every tool and resource only reads the exporter, so there is no read-only flag to set. Every tool carries
readOnlyHint, a title, an output schema and structured results.HTTP listens on
127.0.0.1:8080by default. On any other address it refuses to start without a bearer token, rejects cross-origin browser requests and caps request bodies.Ships as Go binaries for several platforms (GoReleaser), a Docker image and an npm wrapper.
Related MCP server: duplicati-mcp
Tools and resources
Tool | What it answers |
| Health of every backup in one call: verdict, reason, age of the last success. |
| Every snapshot ID, storage target and machine, for use as filter values. |
| State and last-run details of one snapshot, per storage target and machine. |
| The last completed run of one snapshot. The exporter keeps only the last run. |
| Whether a prune is running and when the last one succeeded, per storage target. |
| Storage size and chunks, and revisions per snapshot, from the exporter's storage poller. |
Resources: duplicacy://status, duplicacy://progress and duplicacy://health. Parameters and output fields are on Usage.
Install
The npm package runs the server over stdio; set DUPLICACY_EXPORTER_URL to your exporter.
Claude Code
claude mcp add --transport stdio --env DUPLICACY_EXPORTER_URL=http://localhost:9750 duplicacy -- npx -y duplicacy-mcpClaude Desktop (claude_desktop_config.json) and Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"duplicacy": {
"command": "npx",
"args": ["-y", "duplicacy-mcp"],
"env": { "DUPLICACY_EXPORTER_URL": "http://localhost:9750" }
}
}
}VS Code (.vscode/mcp.json)
{
"servers": {
"duplicacy": {
"type": "stdio",
"command": "npx",
"args": ["-y", "duplicacy-mcp"],
"env": { "DUPLICACY_EXPORTER_URL": "http://localhost:9750" }
}
}
}Codex (~/.codex/config.toml)
[mcp_servers.duplicacy]
command = "npx"
args = ["-y", "duplicacy-mcp"]
env = { DUPLICACY_EXPORTER_URL = "http://localhost:9750" }npm 12, pnpm and Bun skip install scripts, so the wrapper downloads and verifies the binary on first start. Versions up to 0.1.2 relied on the install script alone; with npm 12 run them as npx -y --allow-scripts=duplicacy-mcp duplicacy-mcp.
Docker (Streamable HTTP)
export MCP_AUTH_TOKEN=$(openssl rand -hex 32)
docker run -d -p 127.0.0.1:8080:8080 -e MCP_AUTH_TOKEN \
-e DUPLICACY_EXPORTER_URL=http://duplicacy-exporter:9750 drumsergio/duplicacy-mcp:v0.2.0
claude mcp add --transport http duplicacy http://127.0.0.1:8080/mcp --header "Authorization: Bearer $MCP_AUTH_TOKEN"The image listens on 0.0.0.0:8080 inside the container, so it will not start without MCP_AUTH_TOKEN (or MCP_ALLOW_UNAUTHENTICATED=true behind a reverse proxy that authenticates). Compose, a global npm install and a local build are in Getting started; every variable is in Configuration.
Documentation
Getting started: Docker Compose, npm, local build, first run
Configuration: environment variables, HTTP security, client config for stdio and HTTP
Usage: tools, parameters, output fields and resources
Development: testing with Inspector, credits, contributing
Related projects: the Duplicacy family, other MCP servers, registry listings
Related projects
Part of the Duplicacy family: duplicacy-exporter, duplicacy-cli-cron, duplicacy-ha, duplicacy-container.
License
Available Tools
6 toolsget_backup_historyLast backup runARead-onlyIdempotent
Details of the last completed run of one Duplicacy snapshot: duration in seconds, files total and new, bytes uploaded and new, new chunks, revision, exit_code (0 = success, null = unknown). The exporter keeps only the last run, so this is not a list of past runs. Get valid IDs from list_snapshots.
| Name | Required | Description | Default |
|---|---|---|---|
| machine | No | Only this machine, exactly as list_snapshots returns it in machines, for example "nas". Omit for all. | |
| snapshot_id | Yes | Duplicacy snapshot ID, exactly as list_snapshots returns it, for example "photos". | |
| storage_target | No | Only this storage target, exactly as list_snapshots returns it in storage_targets, for example "b2". Omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| backups | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so the safety profile is covered. The description adds genuine value beyond them: the exporter retains only the last run (a data-retention constraint the annotation cannot express) and exit_code semantics including null = unknown.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences; the return-value inventory and the last-run caveat are front-loaded, and the ID-source tip closes it with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the return value need not be enumerated, yet the description still summarizes the key fields helpfully. The last-run limitation and ID sourcing are covered; only an explicit contrast with get_backup_status/get_backup_overview is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters including machine and storage_target are documented in the schema itself. The description only reinforces that IDs come from list_snapshots, which the schema already states. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Details of the last completed run of one Duplicacy snapshot') and enumerates exactly what is returned (duration, files, bytes, chunks, revision, exit_code). It explicitly rules out the misreading that this is a history list, though it does not distinguish itself from get_backup_status or get_backup_overview.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete prerequisite and routing hint: 'Get valid IDs from list_snapshots.' It also scopes usage by warning the exporter keeps only the last run, so agents won't expect historical data. It stops short of saying when to prefer this over get_backup_status, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_backup_overviewBackup health overviewARead-onlyIdempotent
Health of every backup in one call. Each snapshot, storage target and machine gets a verdict: ok, running, stale (last success older than max_age_hours), never (no successful run) or failed (last exit code not 0), with a reason and the age of the last success. status is ok, attention or no_data. Use this to answer "are my backups OK?"; use get_backup_status for the details of one snapshot.
| Name | Required | Description | Default |
|---|---|---|---|
| machine | No | Only this machine, exactly as list_snapshots returns it in machines, for example "nas". Omit for all. | |
| snapshot_id | No | Duplicacy snapshot ID, exactly as list_snapshots returns it, for example "photos". | |
| max_age_hours | No | A backup whose last success is older than this many hours is stale. Default 26, which suits daily backups. | |
| storage_target | No | Only this storage target, exactly as list_snapshots returns it in storage_targets, for example "b2". Omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| counts | Yes | |
| status | Yes | ok when every backup is ok or running, attention when any is stale, never ran or failed, no_data when the exporter reports no backups |
| backups | Yes | |
| summary | Yes | |
| exporter | Yes | |
| checked_at | Yes | When the overview was computed, RFC 3339 in UTC |
| max_age_hours | Yes | A backup whose last success is older than this is stale |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool as read-only, idempotent and non-destructive. The description adds meaningful behavioral context: the verdict categories (ok, running, stale, never, failed), what stale means in relation to max_age_hours, and the overall status values (ok, attention, no_data). It does not discuss cost or latency, but the added output semantics are substantive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and front-loaded: the main purpose is stated first, followed by verdict semantics, status values, and the sibling routing. Every sentence carries information useful to an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema, fully documented parameters and annotation coverage, the description only needs to supply purpose, usage and verdict meaning. It does so completely, including a clear alternative for a different use case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema, including max_age_hours and its default. The description states the stale rule but does not add syntax or format details beyond what the schema provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource and scope: it returns the health of every backup in one call, covering each snapshot, storage target and machine. It also distinguishes itself from get_backup_status, so an agent can identify it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly names the question this tool answers ("are my backups OK?") and directs the agent to get_backup_status for details about a single snapshot. That is explicit when-to-use and alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_backup_statusBackup statusARead-onlyIdempotent
Current state and last-run details of one Duplicacy snapshot: running, exit_code (0 = success, null = unknown), last_success (RFC 3339, UTC), duration in seconds, files and bytes. A snapshot backed up to several storage targets or from several machines returns one row each. Get valid IDs from list_snapshots. For a health check across all backups use get_backup_overview instead.
| Name | Required | Description | Default |
|---|---|---|---|
| machine | No | Only this machine, exactly as list_snapshots returns it in machines, for example "nas". Omit for all. | |
| snapshot_id | Yes | Duplicacy snapshot ID, exactly as list_snapshots returns it, for example "photos". | |
| storage_target | No | Only this storage target, exactly as list_snapshots returns it in storage_targets, for example "b2". Omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| backups | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is covered. The description adds genuine context beyond that: exit_code semantics (0 = success, null = unknown), RFC 3339 UTC timestamp format, and the row-multiplication behavior when a snapshot spans multiple storage targets or machines. It stops short of stating pagination or volume expectations, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with what is returned before the ID-sourcing and alternative-tool guidance. No restatement of the title and no filler; each sentence carries either field semantics or routing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return shape needn't be re-explained, yet the description still clarifies the ambiguous value encodings (exit_code null, RFC 3339 UTC) that an agent needs to interpret results. With read-only annotations and full schema coverage, nothing material is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description earns above baseline by explaining that a snapshot backed up to several storage targets or from several machines returns one row each — which is precisely the semantics of the optional machine and storage_target filters, telling the agent why it would narrow them rather than just what they are.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (current state and last-run details of one Duplicacy snapshot) and enumerates the returned fields: running, exit_code, last_success, duration, files, bytes. It also distinguishes itself from list_snapshots (ID source) and get_backup_overview (aggregate health check), so an agent can separate it from siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: 'Get valid IDs from list_snapshots' as a prerequisite and 'For a health check across all backups use get_backup_overview instead' as the when-not case with a named alternative. This is exactly the when/when-not/alternative pattern, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_prune_statusPrune statusARead-onlyIdempotent
Whether a prune is running and when the last one succeeded (RFC 3339, UTC), per storage target and machine. An unknown storage_target is an error that lists the known ones.
| Name | Required | Description | Default |
|---|---|---|---|
| storage_target | No | Only this storage target, exactly as list_snapshots returns it in storage_targets, for example "b2". Omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| prunes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (read-only, idempotent, non-destructive), so the bar is lower. The description usefully adds error behavior—an unknown storage_target is an error listing known targets—and specifies UTC/RFC 3339 timestamps, which are behavioral details not present in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences with no waste. The core purpose is front-loaded, followed by the most important edge-case behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only status tool with an output schema and rich annotations, the description covers what the tool reports, timestamp format, grouping dimensions, and error behavior. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents the storage_target parameter well. The description adds meaning beyond the schema by stating that an unknown storage_target produces an error listing known targets, which helps the agent understand invalid-input behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource (prune status) and exactly what it reports: whether a prune is running and when the last one succeeded, per storage target and machine. This clearly distinguishes it from backup-history siblings, but it does not explicitly name or contrast with any sibling tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool returns but gives no guidance on when to use it versus alternatives, nor any exclusions or preconditions. Use is only implied by the monitoring nature of the data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_storage_usageStorage usageARead-onlyIdempotent
Size in bytes and chunk count of each storage, and how many revisions each snapshot keeps, as the exporter's storage poller last saw them. Empty, with a note, when the poller is off.
| Name | Required | Description | Default |
|---|---|---|---|
| machine | No | Only this machine, exactly as list_snapshots returns it in machines, for example "nas". Omit for all. | |
| snapshot_id | No | Duplicacy snapshot ID, exactly as list_snapshots returns it, for example "photos". | |
| storage_target | No | Only this storage target, exactly as list_snapshots returns it in storage_targets, for example "b2". Omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| storages | Yes | |
| snapshots | Yes | |
| poller_errors_total | Yes | Poller errors since the exporter started |
| poller_last_success | No | Time of the poller's last fully successful cycle, RFC 3339 in UTC |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this a safe, idempotent read, so the bar is lower, and the description still adds real value: the numbers are a stale poller snapshot rather than live data, and an empty result with an explanatory note is returned when the poller is disabled. That is exactly the kind of caveat an agent needs before reporting metrics to a user.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler; the most decision-relevant fact (staleness) and the failure mode (poller off) are both front-loaded. The opening sentence is a grammatical fragment that takes a second read, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a full output schema and complete in-schema parameter docs, the description only needs to supply behavioral caveats — and it does: data freshness and the empty-result condition. Nothing an agent needs to call and interpret this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and each of the three filters is documented in-schema with examples and an 'omit for all' default. The description adds no additional parameter meaning, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource precisely — per-storage size in bytes and chunk count, plus per-snapshot revision retention — which is distinct from the status/history siblings. It omits an explicit verb (it's a noun-phrase fragment), but the returned data is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to reach for this tool versus get_backup_overview, get_backup_status, or list_snapshots, and no mention that the three filters can scope the result. The only contextual note is a data-availability caveat, not usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_snapshotsList snapshotsARead-onlyIdempotent
Every snapshot ID, storage target and machine the exporter reports, sorted. backups lists each snapshot_id, storage_target and machine combination. Call this first to get valid values for the snapshot_id, storage_target and machine arguments of the other tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | Number of snapshot IDs |
| backups | Yes | Every snapshot_id, storage_target and machine combination with backup metrics |
| machines | Yes | Every machine seen, sorted |
| snapshot_ids | Yes | Every snapshot ID the exporter has seen, sorted |
| storage_targets | Yes | Every storage target seen, sorted |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds that results are sorted and that the payload is exposed under a 'backups' key, which annotations cannot convey. It stops short of noting cost or volume, hence a 4.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the resource and return fields in the first sentence, and the call-ordering advice comes last where it belongs. The middle sentence ('backups lists each snapshot_id, storage_target and machine combination') largely restates the first, costing a little density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be detailed, and the description still names the key fields and the 'backups' container. A zero-arg read tool with annotations fully covered needs no more than this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so there is nothing to disambiguate; baseline 4 applies. The description correctly frames the tool as an unfiltered enumeration, which reinforces that no arguments are accepted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (snapshots) and the exact fields returned (snapshot ID, storage target, machine), plus ordering. It is clearly distinguishable from the get_* siblings, which return status/overview rather than the raw enumerated set.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Call this first to get valid values for the snapshot_id, storage_target and machine arguments of the other tools' — a concrete ordering rule plus the reason. No alternatives are left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.2.1- Changed
get_backup_history7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / machineAdded value: +{ + "description": "Only this machine, exactly as list_snapshots returns it in machines, for example \"nas\". Omit for all.", + "maxLength": 256, + "type": "string" +} - changed
Input schema / properties / snapshot_id / descriptionPrevious value: -"The snapshot ID to query history for"New value: +"Duplicacy snapshot ID, exactly as list_snapshots returns it, for example \"photos\"." - added
Input schema / properties / snapshot_id / maxLengthAdded value: +256 - added
Input schema / properties / snapshot_id / minLengthAdded value: +1 - added
Input schema / properties / storage_targetAdded value: +{ + "description": "Only this storage target, exactly as list_snapshots returns it in storage_targets, for example \"b2\". Omit for all.", + "maxLength": 256, + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": false, + "properties": { + "backups": { + "items": { + "additionalProperties": false, + "properties": { + "exit_code": { + "description": "Exit code of the last run: 0 is success, null means unknown", + "type": [ + "null", + "integer" + ] + }, + "last_bytes_new": { + "type": "number" + }, + "last_bytes_uploaded": { + "type": "number" + }, + "last_chunks_new": { + "type": "number" + }, + "last_duration_seconds": { + "description": "Duration of the last run, in seconds", + "type": "number" + }, + "last_files_new": { + "type": "number" + }, + "last_files_total": { + "type": "number" + }, + "last_revision": { + "type": "number" + }, + "last_success": { + "description": "Time of the last successful run, RFC 3339 in UTC", + "type": "string" + }, + "machine": { + "type": "string" + }, + "snapshot_id": { + "type": "string" + }, + "storage_target": { + "type": "string" + }, + "total_bytes_uploaded": { + "type": "number" + } + }, + "required": [ + "snapshot_id", + "storage_target", + "machine", + "last_duration_seconds", + "last_files_total", + "last_files_new", + "last_bytes_uploaded", + "last_bytes_new", + "last_chunks_new", + "exit_code", + "last_revision", + "total_bytes_uploaded" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "count": { + "type": "integer" + } + }, + "required": [ + "backups", + "count" + ], + "type": "object" +}
- Added
get_backup_overview - Changed
get_backup_status7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / machineAdded value: +{ + "description": "Only this machine, exactly as list_snapshots returns it in machines, for example \"nas\". Omit for all.", + "maxLength": 256, + "type": "string" +} - changed
Input schema / properties / snapshot_id / descriptionPrevious value: -"The snapshot ID to query status for"New value: +"Duplicacy snapshot ID, exactly as list_snapshots returns it, for example \"photos\"." - added
Input schema / properties / snapshot_id / maxLengthAdded value: +256 - added
Input schema / properties / snapshot_id / minLengthAdded value: +1 - added
Input schema / properties / storage_targetAdded value: +{ + "description": "Only this storage target, exactly as list_snapshots returns it in storage_targets, for example \"b2\". Omit for all.", + "maxLength": 256, + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": false, + "properties": { + "backups": { + "items": { + "additionalProperties": false, + "properties": { + "exit_code": { + "description": "Exit code of the last run: 0 is success, anything else is a failure, null means the exporter has not reported one", + "type": [ + "null", + "integer" + ] + }, + "last_bytes_new": { + "description": "New bytes in the last run", + "type": "number" + }, + "last_bytes_uploaded": { + "description": "Bytes uploaded by the last run", + "type": "number" + }, + "last_chunks_new": { + "description": "New chunks in the last run", + "type": "number" + }, + "last_chunks_size_bytes": { + "description": "Compressed size of the chunks the last snapshot references, in bytes", + "type": "number" + }, + "last_duration_seconds": { + "description": "Duration of the last run, in seconds", + "type": "number" + }, + "last_files_new": { + "description": "Files new in the last run", + "type": "number" + }, + "last_files_size_bytes": { + "description": "Logical size of all files in the last snapshot, in bytes", + "type": "number" + }, + "last_files_total": { + "description": "Files in the last snapshot", + "type": "number" + }, + "last_revision": { + "description": "Revision number created by the last run", + "type": "number" + }, + "last_success": { + "description": "Time of the last successful run, RFC 3339 in UTC", + "type": "string" + }, + "machine": { + "description": "Machine that runs the backup", + "type": "string" + }, + "running": { + "description": "True while a backup is in progress", + "type": "boolean" + }, + "snapshot_id": { + "description": "Duplicacy snapshot ID", + "type": "string" + }, + "storage_target": { + "description": "Storage the snapshot is backed up to", + "type": "string" + }, + "total_bytes_uploaded": { + "description": "Bytes uploaded since the exporter started counting", + "type": "number" + } + }, + "required": [ + "snapshot_id", + "storage_target", + "machine", + "running", + "exit_code" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "count": { + "type": "integer" + } + }, + "required": [ + "backups", + "count" + ], + "type": "object" +}
- Changed
get_prune_status4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / storage_target / descriptionPrevious value: -"(optional) Filter prune status to a specific storage target"New value: +"Only this storage target, exactly as list_snapshots returns it in storage_targets, for example \"b2\". Omit for all." - added
Input schema / properties / storage_target / maxLengthAdded value: +256 - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": false, + "properties": { + "count": { + "type": "integer" + }, + "prunes": { + "items": { + "additionalProperties": false, + "properties": { + "last_success": { + "description": "Time of the last successful prune, RFC 3339 in UTC", + "type": "string" + }, + "machine": { + "type": "string" + }, + "running": { + "description": "True while a prune is in progress", + "type": "boolean" + }, + "storage_target": { + "type": "string" + } + }, + "required": [ + "storage_target", + "machine", + "running" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "prunes", + "count" + ], + "type": "object" +}
- Added
get_storage_usage - Changed
list_snapshots2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": false, + "properties": { + "backups": { + "description": "Every snapshot_id, storage_target and machine combination with backup metrics", + "items": { + "additionalProperties": false, + "properties": { + "machine": { + "type": "string" + }, + "snapshot_id": { + "type": "string" + }, + "storage_target": { + "type": "string" + } + }, + "required": [ + "snapshot_id", + "storage_target", + "machine" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "count": { + "description": "Number of snapshot IDs", + "type": "integer" + }, + "machines": { + "description": "Every machine seen, sorted", + "items": { + "type": "string" + }, + "type": [ + "null", + "array" + ] + }, + "snapshot_ids": { + "description": "Every snapshot ID the exporter has seen, sorted", + "items": { + "type": "string" + }, + "type": [ + "null", + "array" + ] + }, + "storage_targets": { + "description": "Every storage target seen, sorted", + "items": { + "type": "string" + }, + "type": [ + "null", + "array" + ] + } + }, + "required": [ + "snapshot_ids", + "count", + "backups", + "storage_targets", + "machines" + ], + "type": "object" +}
4 tool updates
v0.1.0- First observed
get_backup_history - First observed
get_backup_status - First observed
get_prune_status - First observed
list_snapshots
TDQS
Scored across 6 tools
The tools mostly have clearly distinct monitoring purposes: overview is an aggregate health check, status is one snapshot, and history is the last completed run. The main ambiguity is between get_backup_status and get_backup_history, since both return last-run details, but the descriptions explicitly distinguish current state versus completed-run history.
All tool names follow a consistent snake_case verb_noun pattern: get_backup_history, get_backup_overview, get_backup_status, get_prune_status, get_storage_usage, and list_snapshots. The use of list_snapshots instead of get_snapshots is still a conventional verb_noun choice and does not break readability.
Six tools is well-scoped for a read-only Duplicacy backup monitoring server. Each tool maps to a distinct monitoring concern: discovery, per-snapshot status/history, aggregate health, prune status, and storage usage.
The surface covers the core monitoring workflows: discovering snapshots, checking backup health, inspecting a snapshot, reviewing last-run history, prune status, and storage usage. Minor gaps exist, such as no explicit standalone tool for listing storage targets or machines, but list_snapshots exposes those values and agents can work around this.
Maintenance
Related MCP Connectors
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
MCP server for OpenAI API (chat completions, image generation, embeddings) via AceDataCloud
MCP server for AI dialogue using various LLM models via AceDataCloud
MCP server exposing the Backtest360 engine API as tools for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceAn MCP server that enables Large Language Models to retrieve, analyze, and query metric data from Prometheus databases through pre-defined routes.33MIT
- AlicenseAqualityDmaintenanceMCP server for managing Duplicati backups from an LLM.17MIT
- AlicenseNot gradedqualityDmaintenanceA lean MCP server that provides LLM agents with transparent access to multiple Prometheus instances for metrics analysis and SRE operations.4GPL 2.0
- AlicenseAqualityCmaintenanceMCP server for administering Duplicacy backups via the duplicacy-web API, enabling AI clients to inspect and manage storages, repositories, schedules, and jobs.15MIT