watermarkbuster-mcp 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,20 +1,21 @@
1
1
  # Watermark Buster MCP
2
2
 
3
- Connect an MCP client to the hosted Watermark Buster tools. This package is a local stdio bridge. It does not run the cleaning engine on your computer.
3
+ Connect an MCP client to hosted or local Watermark Buster tools. The default mode is a stdio bridge to the hosted service. `--local` starts the separately installed local cleaning package.
4
4
 
5
5
  ## Requirements
6
6
 
7
7
  - Node.js 20 or newer
8
8
  - An internet connection to `https://watermarkbuster.com/mcp`
9
+ - An operator-issued Watermark Buster bearer token in `WATERMARKS_API_TOKEN`
9
10
 
10
- No account, API token, GPU, Python, or local model is required.
11
+ No GPU, Python, or local model is required for the default hosted mode.
11
12
 
12
13
  ## Run without installing
13
14
 
14
15
  Use `npx` to download and start the current package:
15
16
 
16
17
  ```bash
17
- npx -y watermarkbuster-mcp
18
+ WATERMARKS_API_TOKEN=YOUR_CLIENT_BEARER_TOKEN npx -y watermarkbuster-mcp
18
19
  ```
19
20
 
20
21
  The command waits for MCP messages on standard input. It does not open a user interface or show a prompt. Normally, your MCP client starts this command for you.
@@ -27,10 +28,10 @@ Install the command on your computer:
27
28
  npm install --global watermarkbuster-mcp
28
29
  ```
29
30
 
30
- Your MCP client can then start:
31
+ Your MCP client can then start it with `WATERMARKS_API_TOKEN` in its environment:
31
32
 
32
33
  ```text
33
- watermarkbuster-mcp
34
+ WATERMARKS_API_TOKEN=YOUR_CLIENT_BEARER_TOKEN watermarkbuster-mcp
34
35
  ```
35
36
 
36
37
  To add the package to one Node.js project instead, run:
@@ -39,6 +40,28 @@ To add the package to one Node.js project instead, run:
39
40
  npm install watermarkbuster-mcp
40
41
  ```
41
42
 
43
+ ## Run all cleaning locally
44
+
45
+ Install the local Python package once:
46
+
47
+ ```bash
48
+ pipx install watermarkbuster-local
49
+ ```
50
+
51
+ Then use the npm launcher in local mode:
52
+
53
+ ```bash
54
+ npx -y watermarkbuster-mcp --local --root "$PWD"
55
+ ```
56
+
57
+ Or, after the global npm install:
58
+
59
+ ```bash
60
+ watermarkbuster-mcp --local --root "$PWD"
61
+ ```
62
+
63
+ `--root` limits agent file access to one folder. Add `--allow-network` only when the local agent must run the website sitemap audit.
64
+
42
65
  ## Add the npx bridge to an MCP client
43
66
 
44
67
  Set these values in your MCP client:
@@ -55,7 +78,8 @@ Clients that use an `mcpServers` JSON object commonly use this form:
55
78
  "mcpServers": {
56
79
  "watermark-buster": {
57
80
  "command": "npx",
58
- "args": ["-y", "watermarkbuster-mcp"]
81
+ "args": ["-y", "watermarkbuster-mcp"],
82
+ "env": {"WATERMARKS_API_TOKEN": "YOUR_CLIENT_BEARER_TOKEN"}
59
83
  }
60
84
  }
61
85
  }
@@ -63,7 +87,7 @@ Clients that use an `mcpServers` JSON object commonly use this form:
63
87
 
64
88
  ## Connect directly to the remote server
65
89
 
66
- Clients that support remote Streamable HTTP MCP do not need this npm bridge. Connect them directly to:
90
+ Clients that support remote Streamable HTTP MCP do not need this npm bridge. Connect them directly to the URL below and send `Authorization: Bearer YOUR_CLIENT_BEARER_TOKEN` on every protocol request:
67
91
 
68
92
  ```text
69
93
  https://watermarkbuster.com/mcp
@@ -71,30 +95,22 @@ https://watermarkbuster.com/mcp
71
95
 
72
96
  ### Codex
73
97
 
74
- Add this to `~/.codex/config.toml`:
75
-
76
- ```toml
77
- [mcp_servers.watermark_buster]
78
- url = "https://watermarkbuster.com/mcp"
98
+ ```bash
99
+ export WATERMARKS_API_TOKEN='YOUR_CLIENT_BEARER_TOKEN'
100
+ codex mcp add watermark-buster \
101
+ --url https://watermarkbuster.com/mcp \
102
+ --bearer-token-env-var WATERMARKS_API_TOKEN
79
103
  ```
80
104
 
81
105
  Restart Codex, then run `codex mcp list` or use `/mcp` inside Codex.
82
106
 
83
107
  ### Claude Code
84
108
 
85
- ```bash
86
- claude mcp add --transport http watermark-buster https://watermarkbuster.com/mcp
87
- ```
88
-
89
- Run `claude mcp list` or use `/mcp` inside Claude Code.
109
+ Use the authenticated npm bridge configuration above, then run `claude mcp list` or use `/mcp` inside Claude Code.
90
110
 
91
111
  ### Gemini CLI
92
112
 
93
- ```bash
94
- gemini mcp add --transport http watermark-buster https://watermarkbuster.com/mcp
95
- ```
96
-
97
- Run `gemini mcp list` to confirm the connection.
113
+ Use the authenticated npm bridge configuration above, then run `gemini mcp list` to confirm the connection.
98
114
 
99
115
  ### Cursor
100
116
 
@@ -104,7 +120,9 @@ Add this to `.cursor/mcp.json` for one project or `~/.cursor/mcp.json` for all p
104
120
  {
105
121
  "mcpServers": {
106
122
  "watermark-buster": {
107
- "url": "https://watermarkbuster.com/mcp"
123
+ "command": "npx",
124
+ "args": ["-y", "watermarkbuster-mcp"],
125
+ "env": {"WATERMARKS_API_TOKEN": "YOUR_CLIENT_BEARER_TOKEN"}
108
126
  }
109
127
  }
110
128
  }
@@ -120,7 +138,9 @@ Add this to `~/.gemini/config/mcp_config.json` for all workspaces or `.agents/mc
120
138
  {
121
139
  "mcpServers": {
122
140
  "watermark-buster": {
123
- "serverUrl": "https://watermarkbuster.com/mcp"
141
+ "command": "npx",
142
+ "args": ["-y", "watermarkbuster-mcp"],
143
+ "env": {"WATERMARKS_API_TOKEN": "YOUR_CLIENT_BEARER_TOKEN"}
124
144
  }
125
145
  }
126
146
  }
@@ -134,22 +154,30 @@ The bridge reads the current tool list from the hosted MCP server when it starts
134
154
 
135
155
  - `inspect_text` — report supported hidden Unicode without changing the text
136
156
  - `clean_text` — remove supported hidden Unicode and exotic spaces
157
+ - `scan_and_rewrite_text` — run the model-free English light rewrite and return estimate-only scores, quality metrics, highlights, and a diff; input is limited to 128 KB
137
158
  - `clean_file` — clean a supported file and return the cleaned copy
159
+ - `clean_synthid_image` — run the supported best-effort CPU SynthID scan on one PNG or JPEG and return the PNG plus residual report
138
160
  - `get_capabilities` — read the current formats, limits, and behavior
139
161
 
140
162
  Example agent requests:
141
163
 
142
164
  - “Inspect this text for hidden Unicode.”
165
+ - “Scan and lightly rewrite this English text, then show the diff and limits.”
143
166
  - “Clean this file and return the cleaned copy.”
167
+ - “Run the SynthID image scan and tell me if a residual remains.”
144
168
  - “Show the current Watermark Buster capabilities.”
145
169
 
170
+ Local mode exposes the larger local tool set: direct file paths, folder audit, opt-in website audit, local Ollama rewriting, and an adapter for the optional `noai-watermark` pixel tool. See the [local package guide](https://pypi.org/project/watermarkbuster-local/).
171
+
146
172
  ## Data flow
147
173
 
148
- Tool input is sent to `https://watermarkbuster.com` for processing. The hosted service processes content for the call and does not archive it. Do not use this npm bridge if content must stay on your computer.
174
+ In the default mode, tool input is sent to `https://watermarkbuster.com` for processing. In `--local` mode, normal cleaning stays on the computer. Optional website audit uses the network, and optional pixel cleaning can download model files.
149
175
 
150
176
  ## Connection errors
151
177
 
152
- If the hosted service cannot be reached, the command writes `Watermark Buster MCP: <reason>` to standard error and exits with a failure status. Check that `https://watermarkbuster.com/mcp` is reachable, then let the MCP client start the command again.
178
+ If the token is missing or the hosted service cannot be reached, the command writes `Watermark Buster MCP: <reason>` to standard error and exits with a failure status. Check `WATERMARKS_API_TOKEN` and connectivity, then let the MCP client start the command again.
179
+
180
+ If local mode says that the local package is missing, run `pipx install watermarkbuster-local`, then start the command again.
153
181
 
154
182
  For more setup help, see [the full MCP guide](https://watermarkbuster.com/mcp).
155
183
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "watermarkbuster-mcp",
3
- "version": "1.0.1",
4
- "description": "Connect local MCP clients to the hosted Watermark Buster tools.",
3
+ "version": "1.2.0",
4
+ "description": "Connect MCP clients to hosted or local Watermark Buster tools.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "watermarkbuster-mcp": "src/cli.js"
@@ -15,7 +15,7 @@
15
15
  "node": ">=20"
16
16
  },
17
17
  "scripts": {
18
- "check": "node --check src/cli.js && node --check src/server.js",
18
+ "check": "node --check src/cli.js && node --check src/local.js && node --check src/server.js",
19
19
  "test": "node --test"
20
20
  },
21
21
  "keywords": [
@@ -31,7 +31,7 @@
31
31
  "access": "public"
32
32
  },
33
33
  "dependencies": {
34
- "@modelcontextprotocol/client": "2.0.0",
35
- "@modelcontextprotocol/server": "2.0.0"
34
+ "@modelcontextprotocol/client": "2.4.0",
35
+ "@modelcontextprotocol/server": "2.4.0"
36
36
  }
37
37
  }
package/src/cli.js CHANGED
@@ -9,8 +9,39 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
9
9
  import {
10
10
  PACKAGE_VERSION,
11
11
  REMOTE_MCP_ENDPOINT,
12
+ authenticatedRequestInit,
12
13
  createBridgeServer,
13
14
  } from "./server.js";
15
+ import { startLocalServer } from "./local.js";
16
+
17
+ const HELP = `Watermark Buster MCP
18
+
19
+ Usage:
20
+ watermarkbuster-mcp Connect to the hosted MCP server
21
+ watermarkbuster-mcp --local Start the installed local MCP server
22
+
23
+ Local options:
24
+ --root <folder> Limit agent file access to this folder
25
+ --allow-network Let the local website audit access the network
26
+ -h, --help Show this help
27
+ `;
28
+
29
+ function parseArguments(argumentsList) {
30
+ const options = { local: false, root: null, allowNetwork: false, help: false };
31
+ for (let index = 0; index < argumentsList.length; index += 1) {
32
+ const argument = argumentsList[index];
33
+ if (argument === "--local") options.local = true;
34
+ else if (argument === "--allow-network") options.allowNetwork = true;
35
+ else if (argument === "--root") options.root = argumentsList[++index];
36
+ else if (argument === "--help" || argument === "-h") options.help = true;
37
+ else throw new Error(`unknown option: ${argument}`);
38
+ }
39
+ if (options.root === undefined) throw new Error("--root needs a folder");
40
+ if (!options.local && (options.root || options.allowNetwork)) {
41
+ throw new Error("--root and --allow-network need --local");
42
+ }
43
+ return options;
44
+ }
14
45
 
15
46
  function reportFailure(error) {
16
47
  const message = error instanceof Error ? error.message : String(error);
@@ -50,6 +81,7 @@ async function startBridge() {
50
81
  });
51
82
  const remoteTransport = new StreamableHTTPClientTransport(
52
83
  new URL(REMOTE_MCP_ENDPOINT),
84
+ { requestInit: authenticatedRequestInit() },
53
85
  );
54
86
  await remoteClient.connect(remoteTransport);
55
87
  const { tools } = await remoteClient.listTools();
@@ -60,7 +92,27 @@ async function startBridge() {
60
92
  registerShutdown(stdioHandle, remoteClient);
61
93
  }
62
94
 
63
- startBridge().catch((error) => {
64
- reportFailure(error);
65
- process.exitCode = 1;
66
- });
95
+ function main() {
96
+ let options;
97
+ try {
98
+ options = parseArguments(process.argv.slice(2));
99
+ } catch (error) {
100
+ reportFailure(error);
101
+ process.exitCode = 2;
102
+ return;
103
+ }
104
+ if (options.help) {
105
+ process.stdout.write(HELP);
106
+ return;
107
+ }
108
+ if (options.local) {
109
+ startLocalServer(options);
110
+ return;
111
+ }
112
+ startBridge().catch((error) => {
113
+ reportFailure(error);
114
+ process.exitCode = 1;
115
+ });
116
+ }
117
+
118
+ main();
package/src/local.js ADDED
@@ -0,0 +1,30 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ export const LOCAL_EXECUTABLE = "watermarkbuster-local";
4
+
5
+ export function localArguments(options) {
6
+ const argumentsList = ["mcp"];
7
+ if (options.root) argumentsList.push("--root", options.root);
8
+ if (options.allowNetwork) argumentsList.push("--allow-network");
9
+ return argumentsList;
10
+ }
11
+
12
+ export function startLocalServer(options) {
13
+ const child = spawn(LOCAL_EXECUTABLE, localArguments(options), {
14
+ stdio: "inherit",
15
+ });
16
+ child.once("error", (error) => {
17
+ if (error.code === "ENOENT") {
18
+ console.error(
19
+ "Watermark Buster MCP: local package not found. Run: pipx install watermarkbuster-local",
20
+ );
21
+ } else {
22
+ console.error(`Watermark Buster MCP: ${error.message}`);
23
+ }
24
+ process.exitCode = 1;
25
+ });
26
+ child.once("exit", (code, signal) => {
27
+ if (signal) process.kill(process.pid, signal);
28
+ else process.exitCode = code ?? 1;
29
+ });
30
+ }
package/src/server.js CHANGED
@@ -14,6 +14,14 @@ const SERVER_INSTRUCTIONS = [
14
14
  "The hosted service does not archive submitted content.",
15
15
  ].join(" ");
16
16
 
17
+ export function authenticatedRequestInit(environment = process.env) {
18
+ const apiToken = environment.WATERMARKS_API_TOKEN?.trim();
19
+ if (!apiToken) {
20
+ throw new Error("WATERMARKS_API_TOKEN is required for the hosted MCP server");
21
+ }
22
+ return { headers: { Authorization: `Bearer ${apiToken}` } };
23
+ }
24
+
17
25
  function remoteToolConfiguration(remoteTool) {
18
26
  const configuration = {
19
27
  title: remoteTool.title,