Claude Found a Workaround to Delete DT4 Records even when MCP Trash Tool is Deactivated

Claude via MCP deleted some files despite the fact that I have the MCP server set to deny Trash requests.

It did not delete anything serious - they were actually drafts or temp files Claude itself created during a long workflow. Nonetheless - my instructions in my Claude setup are explicit to never send anything to the trash but instead to create a folder called “For Richard to Review.”

So I asked Claude how this can happen. Its response:

Confirmed the mechanism definitively — here’s the detailed finding.

How it happened. Disabling the trash_record tool only locks that one door on the DEVONthink MCP server. It does nothing to DEVONthink’s own AppleScript dictionary — and the tasks do a large share of their DEVONthink work through AppleScript, via the Control-your-Mac osascript tool and do shell script "osascript…" in Bash (label-setting, imports, verification, cleanup all run that way). DEVONthink’s AppleScript exposes move record X to (trash group of database) and delete record X, neither gated by the MCP permission. So a cleanup step reaching for that command trashes records right past the disabled tool.

I proved it with a controlled test just now: created a throwaway record in the Inbox, ran move record … to (trash group) via AppleScript — it landed in /Trash/ (recoverable), exactly where your 27 records were — then recovered it. The delete record variant is even more aggressive (removes the record outright rather than to trash). Both succeed with the MCP tool disabled.

Question - do we want/need the Trash and Delete Applescript commands?

[Yes - I know Trash is just ‘another location’ in DT4. Nonetheless moving something there creates a non-trivial risk that I may not notice it before I choose Empty Trash.]

1 Like

Why should DEVONthink modify its script dictionary to accommodate misbehavior by third-party tools?

Removing the AppleScript “Trash” command would affect any script that uses it. “Move Duplicates to Trash” ships with DT, but almost any user-created “cleanup” script would use the same facility.

7 Likes

Of course we do.
I agree with @kewms here. AppleScript predates and is not “made for AI” and there are people want to script but have no interaction with AI.

4 Likes

Fair enough

Any suggestions on how else it might be possible to tighten applescript capabilities when executed via local AI [not via MCP] without impacting regular Applescript automation?

I, for one, use it when importing diary entries from Day One. I currently have no use for AI.

Stephen

4 Likes

DEVONthink does not know how or why an external script is executed. Usage of MCP tools only is highly recommended instead.

1 Like

You need to have stronger rules set up within Claude. You also need to test these skills/rules in a safe manner, which starts with having backups (a Time Machine disk is a great start).

I use the DTP MCP all the time and don’t have any issues with it deleting files that it shouldn’t. My recommendation is to discuss with Claude about setting hard rules that must be followed at all times. This (usually) requires the LLM to analyze its own skills, rules, and default instructions, and to go over many edge cases, in order for it to finally determine where and how the rule needs to be set.

I have it set to always “soft delete” - which means it will send files to the trash instead of removing them permanently. Also, if you have an LLM modifying files in DT, you should enable versioning in your DB, as it lets you roll back any bad changes the LLM makes.

Another tip is to have the LLM add a tag on any file it creates, imports, or edits in DT. This allows you to more easily find and follow up on what it has done inside DT.

2 Likes

P.S: Files moved or trashed via MCP are also logged to DEVONthink’s Window > Log panel.

2 Likes

@RobH that’s a great idea. so you prompt claude to do all this safety procedures when using the DTP MCP server? May you share your “safety” prompt? do you just use it in each chat or how did you instruct claude to behave always like this?

I have set up such rules since Day 1 - a very strict rule to “Never trash anything - only move to a Temp AI Group” and similar reminders at pertinent areas of the rule.

The problem I observe has been noted in a number of articles I have read. As an LLM skill or prompt or context window gets larger, it get harder to keep the LLM focus and assure that it is always considering each of the rules.

So the solution often is on the side of not making it possible for the LLM to do things you don’t want it to do by limiting the tools it has access to. A very effective way is exactly what @cgrunenberg suggested - Only give LLM access to MCP tools and do not give it direct acces to Applescript. That works but the flipside is you lose a lot of capability. Another option is to set up audit steps and logs to methodically identify any item in the trash before it is deleted and then determine how to strengthen the skill logic so this does not recur.

How I have Claude work with DEVONthink

There is no simple, quick-and-easy path to this. It’s taken a lot of trial and error to figure out what works. Much of what’s in here won’t directly map to how your Claude is set up, because I have heavily modified the harness which Claude Cowork runs on. I would think giving your AI this file and having a deep-dive discussion on how to implement it for you is likely the fastest path. Legally, I probably need to state that use is at your own risk and that no guarantees are implied, etc.

A quick overview to keep in mind:

Claude uses the official DEVONthink Model Context Protocol server, and does real work in my databases rather than just answering questions about them. That means it can also break things, so most of these rules exist because something went wrong (at least) once and I had to figure out how to prevent it from happening again.

I rely heavily on the baked-in features of DEVONthink that, once properly enabled, allow the LLM to use the MCP with less fear of losing data.

  • Versioning: this works with files that the AI touches as well; anything modified retains its original content. This is a per-database setting that must be enabled, and I have Claude check that it’s enabled for every open database once a month (since it’s not easy to turn it off by accident).
  • Trash as a real net: Claude has rules telling it to only soft-delete. For DEVONthink, this is moving to the trash. For the file system, it moves files to its own trash folder that I have to review and delete.
  • Exclude from AI access: this keeps documents from being seen by the AI. I keep any files with PII set to exclude.
  • Stable identifiers and item links surviving moves and renames. This one is more important than it first would seem. I originally had Claude run nightly tasks to keep up with any changes in DEVONthink, as its file map depended on knowing where items were stored. After a long series of trial-and-error attempts to optimize this, the best solution was to simply have Claude log the UUIDs for files and Groups, along with minimal metadata. However, it’s important that the AI knows when a new UUID is generated:
    • duplicate_record returns a new UUID. replicate_record returns the same UUID with a second parent.
    • convert_record creates a new record.
    • Re-importing a file creates a second record rather than updating the first. That’s why I now have a rule to revise in place with update_record_content and never re-import.
    • Anything regenerated on a schedule churns its UUID on each refresh, so those are anchored by name within their parent group instead.
  • Logging: As noted above, some things are also logged in the DEVONthink log panel, though I’d like to see more for a better audit trail. Changes to metadata aren’t logged, though it would be nice if it caught these too when the AI made a change.

MCP Tools: The MCP includes many tools, and it took a while for the AI to realize the power already within it. I think we’re still finding better ways to do things, but that is pretty much the course for anything done with an LLM. I would suggest you spend an entire session exploring these with the LLM and running “what if” scenarios to find what works best.

The below is my own instruction layer sitting on top of the MCP (the Rules).

Where the rules live

I think the most important takeaway from this is the rules are not one big document. They are tiered because anything loaded into every session costs context, whether it gets used or not, but more importantly, will be ignored because the rules don’t “pop up” at the right time. I can’t really tell you how to do this on your system, because everybody’s harness will be different. You’ll need to find the best place to add these rules, but here are my tiers:

  1. An always-loaded instructions file holds only the decision rules: when to act, when to stop, what never to do.
  2. A reference file holds the mechanics: folder identifiers, per-database facts, filing tables. It gets loaded on demand, only when Claude is about to file something.
  3. A separate reference holds what has been learned about the MCP tools themselves, and Claude is required to read it before touching any DEVONthink tool.
  4. Filing a finished document is its own procedure, so that got pulled out into a reusable routine instead of being re-derived every time.

Here’s the tabular version of the mapping, which might help visualize when things happen and where the rule resides:

Tier File When it loads
1. Decision rules root CLAUDE.md, the DEVONthink section Every session, automatically
2. Mechanics dt-reference.md On demand, before filing or picking a destination
3. Tool learnings knowledge/devonthink-mcp.md Mandatory read before any DEVONthink call
↳ escalation DT-MCP-CATALOG.md Only when the wiki page isn’t enough
↳ raw evidence DT-MCP-SWEEP-EVIDENCE.md Never by default
4. Filing procedure skills/dt-file/SKILL.md Invoked when a deliverable is ready to file
Audit trail DT-CHANGE-LOG.md Written, not read

Some of these locations are file locations in my harness and won’t map to yours. The audit log is NOT a log of every edit. Content edits are covered by DT versioning and need no entry here. The log contains only deletions, merges, and other operations that are not recoverable via versioning or Trash.

Having multiple files matters more than you might expect. When everything lived in one file, the useful rules got buried in the mechanical ones. This is a recurring issue with LLM rules in general, and the fix often requires asking the AI why something failed or was ignored and how to prevent it.

The following goes into very specific points about each aspect of the rules. I’ll simply point out that this is what works best for me - so far - but I make no claim that it’s the best way.

The safety rules

These are built around what DEVONthink can actually recover, not around being cautious in general.

  • Content edits run unattended. Versioning has them covered, so Claude does not ask permission and does not make a backup copy first. Append or insert is preferred over replace.
  • Metadata changes require confirmation, for the reason above. Claude has to ask before overwriting a value that already contains values. Adding a tag is fine unattended.
  • Every property write gets read back. This is the one that bit me several times. The update call silently ignores any key it does not recognize; no error, no warning, the same success response you would get if it had worked. So a success response is not evidence that anything happened. Claude has to verify with a separate read before it reports the change as done.
  • Deletions and merges are still confirmed and logged to an audit file even though both are recoverable, because recovery depends on knowing it happened at all.
  • Personally identifiable information gets surfaced to me, never decided by Claude. If it finds a document containing a Social Security number or an account number, it tells me which record it is and what is in it, and I decide whether to exclude it from artificial intelligence access. It does not redact, copy, or alter the record on its own. Note: there is an option to redact sensitive content in DEVONthink settings, but I turned it off because it masks only two read paths and does nothing for scanned documents.
  • Outside of DEVONthink: Nothing gets deleted from the file system either. Files move to a dated trash folder that I clear myself.

The filing rules

  • Claude may never create a new top-level group in any database. If something does not fit an existing folder, it stops and asks. Otherwise, you can end up with a database that has too many top-level folders because the AI will tend to create a new one instead of looking harder at what exists. This rule also helps maintain the general structure you create in your database, as it forces the AI to find an already existing location.
  • Every record Claude touches gets exactly one provenance tag: claude-create, claude-import, or claude-edit. Three tags, mutually exclusive. It means I can always answer “Did Claude touch this file?”
  • Authored text and external files take different paths. Markdown that Claude wrote goes in through the record creation call, which handles name, tags, and destination in one step. An external or binary file has to be imported, and import ignores the name and tags you pass it, so those get fixed afterward with a read-back. Importing by reference rather than by copy is banned outright, since the reference breaks the moment the temporary file goes away.
  • Records are addressed by unique identifier, never by path. Paths change when I reorganize, and I reorganize constantly. A truncated identifier is treated as an error rather than a shortcut (something in Claude wants to truncate UUIDs, and so it needs to be aware of this, and when it finds one, it searches and updates it for the full UUID).

I also have a boundary test that Claude uses for what belongs in DEVONthink or what should stay in its filesystem. Will I ever open this to read it? If yes, it goes in DEVONthink. If it is only ever consumed by code or Claude’s own process, it stays on the file system. Source files and scripts never go in.

The retrieval rules

  • Tool choice is specified by job rather than left to judgment, because the tool names are misleading. Exact name goes to lookup, keywords to search, “what do we have on this topic” to the similarity call in content mode, structure to the group tree.
  • The one I wish I had found sooner is the chat call. It answers a specific question against a record with page citations, which means a hundred-page contract never has to be loaded into context at all. That single tool changed how usable the whole setup is.
  • Searches always get scoped to a specific database. I have a large reference library in one database, and an unscoped keyword search will happily return medical textbooks for a contract question.

A few traps worth knowing, since none of them announce themselves:

  • The default search operator matches whole words, not substrings. Searching a partial word returns zero results rather than an error.
  • Negation in search queries does nothing. You get the whole database back looking like it was filtered, which is worse than an error.
  • Similarity scores scale with how much text you give them. A three-word query silently returns nothing, while a full sentence works.
  • Claude doesn’t like the automatic classification suggestions. This is an artifact of how much content already exists in a group, and I think Claude is expecting something more from this tool. What seems to work better is for it to run searches on key phrases and then drill down to those locations to find the best spot to file something. It doesn’t always work well, but good enough to be usable.

How it all gets applied

As previously noted, the rules are only useful if they fire when needed. Relying on a large text dump of rules in the CLAUDE.md file doesn’t work, or at least not consistently, so they have to be attached to triggers. The tool reference is a mandatory read before any DEVONthink call. Filing a finished document invokes the filing routine, rather than having the AI figure it out on the fly. A nightly maintenance pass audits for drift and reports what it finds, and a save routine checks format rules on the files it touches.

I know this is likely way more text than anyone wanted, but this is how I got Claude to work nearly flawlessly with DEVONthink.

6 Likes

Very interesting @RobH - thank you

I think these are great examples of the concept that while agentic LLM workflows may not require “coding” in a classic sense, in reality you are coding with natural language - and overal database and networking design remain just as important as ever to have a human in the loop.

Both points are spot on. I often wish I could just add code to the harness so it follows the rules strictly, because even as good as these are running now, future models will need to be “hand-held” to make changes that work better for them.

And regarding always needing a human in the loop… 100%. An AI / LLM is just another tool. Just because I bought Excel doesn’t mean I can fire the accounting department.

2 Likes