Koskamo

PrivacyPill MCP

An MCP server for PrivacyPill that allows AI agents to perform pre-consent scans of websites to detect cookies and trackers loading before user consent, and manage GDPR cookie consent banners, sites, and compliance scans via OAuth-protected tools.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

PrivacyPill MCP logo, by PrivacyPillVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by PrivacyPill
MCP endpoint (Streamable HTTP)
https://privacy-pill-consent-studio.lovable.app/mcp
Vendor documentation

What you can do with it

  • Scan a URL for trackers loading before consent
  • List and manage consent banner sites
  • Configure cookie consent banners
  • Run compliance scans on websites

Source and maintenance

Vendor evidenceRegistry 1.0.0

Protocol and capabilities

Server
privacypill 1.1.1
MCP protocol
2025-06-18
Tools
9 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": false
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

PrivacyPill is a lightweight GDPR / ePrivacy cookie banner with Google Consent Mode v2. You're connected without signing in: pre_consent_scan is free (10 checks per hour per visitor) and reports which cookies and trackers load on a public page before the visitor consents. The other tools act on a PrivacyPill account — the first call to one asks the user to sign in (OAuth), after which the flow is create_site → configure_banner → get_embed_snippet → run_compliance_scan.

Tools

9 advertised

pre_consent_scan — Check what loads before consent (free)
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Free, no sign-in: fetch a public page as a first-time visitor and report which trackers (GA4, Google Ads, Meta Pixel, TikTok, LinkedIn, Hotjar…) and cookies load before the visitor consents, which ones wait, which other sites the page contacts (e.g. Google Fonts), and how to fix it. Static check of the HTML and headers (no JavaScript runs). Limited to 10 checks per hour per visitor.

pre_consent_scan input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "url"
  ],
  "properties": {
    "url": {
      "type": "string",
      "maxLength": 2048,
      "minLength": 3,
      "description": "Public page to check, e.g. https://example.com"
    }
  },
  "additionalProperties": false
}
pre_consent_scan annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_account — Get account
Advertised by the server during the last successful anonymous check.
Advertised read-only

Show the signed-in PrivacyPill account: number of sites, licenses (Free, Pro, Lifetime) and limits.

get_account input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {},
  "additionalProperties": false
}
get_account annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}
list_sites — List sites
Advertised by the server during the last successful anonymous check.
Advertised read-only

List the domains (sites) on the PrivacyPill account with their plan, site key and last scan score.

list_sites input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {},
  "additionalProperties": false
}
list_sites annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}
get_site — Get site and banner settings
Advertised by the server during the last successful anonymous check.
Advertised read-only

Get one site with its full cookie banner settings (layout, colours, categories, Consent Mode, languages).

get_site input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "site_id"
  ],
  "properties": {
    "site_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "Site id from list_sites or create_site."
    }
  },
  "additionalProperties": false
}
get_site annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}
create_site — Create site
Advertised by the server during the last successful anonymous check.

Add a domain to PrivacyPill and create its cookie banner. Returns the site, its banner settings and the embed snippet. The free plan includes one site.

create_site input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "domain"
  ],
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 80,
      "description": "Friendly name shown in the dashboard."
    },
    "design": {
      "type": "object",
      "properties": {
        "gcm": {
          "type": "object",
          "properties": {
            "wait": {
              "type": "number",
              "maximum": 5000,
              "minimum": 0
            },
            "redact": {
              "type": "boolean"
            },
            "enabled": {
              "type": "boolean"
            },
            "passthrough": {
              "type": "boolean"
            }
          }
        },
        "side": {
          "enum": [
            "left",
            "right"
          ],
          "type": "string"
        },
        "equal": {
          "type": "boolean",
          "description": "Give Accept and Reject equal visual weight."
        },
        "theme": {
          "type": "object",
          "properties": {
            "bg": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "fg": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "font": {
              "type": "string",
              "pattern": "^[\\w\\s,'\"\\-.]+$",
              "maxLength": 160
            },
            "size": {
              "type": "number",
              "maximum": 18,
              "minimum": 12
            },
            "accent": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "border": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "radius": {
              "type": "number",
              "maximum": 40,
              "minimum": 0
            },
            "shadow": {
              "type": "boolean"
            },
            "buttons": {
              "enum": [
                "outline",
                "soft",
                "text"
              ],
              "type": "string"
            },
            "accentFg": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "btnRadius": {
              "type": "number",
              "maximum": 999,
              "minimum": 0
            }
          }
        },
        "layout": {
          "enum": [
            "pill",
            "bar",
            "modal",
            "corner"
          ],
          "type": "string"
        },
        "preset": {
          "enum": [
            "mint",
            "slate",
            "paper",
            "lagoon",
            "sand",
            "contrast"
          ],
          "type": "string",
          "description": "Apply a built-in colour preset (see GET /presets)."
        },
        "reopen": {
          "type": "boolean",
          "description": "Show a small button to reopen preferences."
        },
        "autoLang": {
          "type": "boolean"
        },
        "services": {
          "type": "object",
          "propertyNames": {
            "enum": [
              "necessary",
              "analytics",
              "marketing",
              "functional"
            ],
            "type": "string"
          },
          "additionalProperties": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 120
            },
            "maxItems": 40
          }
        },
        "languages": {
          "type": "array",
          "items": {
            "enum": [
              "en",
              "de",
              "fr",
              "nl",
              "es",
              "it"
            ],
            "type": "string"
          },
          "minItems": 1
        },
        "overrides": {
          "type": "object",
          "propertyNames": {
            "enum": [
              "en",
              "de",
              "fr",
              "nl",
              "es",
              "it"
            ],
            "type": "string"
          },
          "additionalProperties": {
            "type": "object",
            "properties": {
              "body": {
                "type": "string",
                "maxLength": 600
              },
              "title": {
                "type": "string",
                "maxLength": 120
              },
              "accept": {
                "type": "string",
                "maxLength": 40
              },
              "reject": {
                "type": "string",
                "maxLength": 40
              },
              "customize": {
                "type": "string",
                "maxLength": 40
              }
            }
          }
        },
        "policyUrl": {
          "type": "string",
          "maxLength": 500
        },
        "categories": {
          "type": "object",
          "properties": {
            "analytics": {
              "type": "boolean"
            },
            "marketing": {
              "type": "boolean"
            },
            "functional": {
              "type": "boolean"
            }
          }
        },
        "expiryDays": {
          "type": "integer",
          "maximum": 395,
          "minimum": 1
        },
        "defaultLang": {
          "enum": [
            "en",
            "de",
            "fr",
            "nl",
            "es",
            "it"
          ],
          "type": "string"
        },
        "reloadOnWithdraw": {
          "type": "boolean"
        }
      },
      "description": "Optional starting banner settings; see configure_banner for the fields.",
      "additionalProperties": false
    },
    "domain": {
      "type": "string",
      "maxLength": 253,
      "minLength": 3,
      "description": "Bare domain such as example.com (no https://)."
    },
    "license_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "Attach a Pro or Lifetime license from get_account."
    }
  },
  "additionalProperties": false
}
create_site annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
configure_banner — Configure banner
Advertised by the server during the last successful anonymous check.

Update a site's cookie banner: layout (pill, bar, modal, corner), colours or preset, categories, services, Google Consent Mode v2, languages and wording. Only the fields you pass change. Pro sites can also switch geo-targeting and monthly rescans.

configure_banner input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "site_id"
  ],
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 80
    },
    "design": {
      "type": "object",
      "properties": {
        "gcm": {
          "type": "object",
          "properties": {
            "wait": {
              "type": "number",
              "maximum": 5000,
              "minimum": 0
            },
            "redact": {
              "type": "boolean"
            },
            "enabled": {
              "type": "boolean"
            },
            "passthrough": {
              "type": "boolean"
            }
          }
        },
        "side": {
          "enum": [
            "left",
            "right"
          ],
          "type": "string"
        },
        "equal": {
          "type": "boolean",
          "description": "Give Accept and Reject equal visual weight."
        },
        "theme": {
          "type": "object",
          "properties": {
            "bg": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "fg": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "font": {
              "type": "string",
              "pattern": "^[\\w\\s,'\"\\-.]+$",
              "maxLength": 160
            },
            "size": {
              "type": "number",
              "maximum": 18,
              "minimum": 12
            },
            "accent": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "border": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "radius": {
              "type": "number",
              "maximum": 40,
              "minimum": 0
            },
            "shadow": {
              "type": "boolean"
            },
            "buttons": {
              "enum": [
                "outline",
                "soft",
                "text"
              ],
              "type": "string"
            },
            "accentFg": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "btnRadius": {
              "type": "number",
              "maximum": 999,
              "minimum": 0
            }
          }
        },
        "layout": {
          "enum": [
            "pill",
            "bar",
            "modal",
            "corner"
          ],
          "type": "string"
        },
        "preset": {
          "enum": [
            "mint",
            "slate",
            "paper",
            "lagoon",
            "sand",
            "contrast"
          ],
          "type": "string",
          "description": "Apply a built-in colour preset (see GET /presets)."
        },
        "reopen": {
          "type": "boolean",
          "description": "Show a small button to reopen preferences."
        },
        "autoLang": {
          "type": "boolean"
        },
        "services": {
          "type": "object",
          "propertyNames": {
            "enum": [
              "necessary",
              "analytics",
              "marketing",
              "functional"
            ],
            "type": "string"
          },
          "additionalProperties": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 120
            },
            "maxItems": 40
          }
        },
        "languages": {
          "type": "array",
          "items": {
            "enum": [
              "en",
              "de",
              "fr",
              "nl",
              "es",
              "it"
            ],
            "type": "string"
          },
          "minItems": 1
        },
        "overrides": {
          "type": "object",
          "propertyNames": {
            "enum": [
              "en",
              "de",
              "fr",
              "nl",
              "es",
              "it"
            ],
            "type": "string"
          },
          "additionalProperties": {
            "type": "object",
            "properties": {
              "body": {
                "type": "string",
                "maxLength": 600
              },
              "title": {
                "type": "string",
                "maxLength": 120
              },
              "accept": {
                "type": "string",
                "maxLength": 40
              },
              "reject": {
                "type": "string",
                "maxLength": 40
              },
              "customize": {
                "type": "string",
                "maxLength": 40
              }
            }
          }
        },
        "policyUrl": {
          "type": "string",
          "maxLength": 500
        },
        "categories": {
          "type": "object",
          "properties": {
            "analytics": {
              "type": "boolean"
            },
            "marketing": {
              "type": "boolean"
            },
            "functional": {
              "type": "boolean"
            }
          }
        },
        "expiryDays": {
          "type": "integer",
          "maximum": 395,
          "minimum": 1
        },
        "defaultLang": {
          "enum": [
            "en",
            "de",
            "fr",
            "nl",
            "es",
            "it"
          ],
          "type": "string"
        },
        "reloadOnWithdraw": {
          "type": "boolean"
        }
      },
      "description": "Banner fields to change; nested objects merge.",
      "additionalProperties": false
    },
    "domain": {
      "type": "string",
      "maxLength": 253,
      "minLength": 3,
      "description": "Change the domain (bare domain)."
    },
    "site_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "Site id from list_sites or create_site."
    },
    "geo_targeting": {
      "type": "boolean",
      "description": "Pro: only show the banner where consent law applies."
    },
    "monthly_rescan": {
      "type": "boolean",
      "description": "Pro: rescan the site automatically every month."
    }
  },
  "additionalProperties": false
}
configure_banner annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_embed_snippet — Get embed snippet
Advertised by the server during the last successful anonymous check.
Advertised read-only

Get the one-line PrivacyPill embed (with Consent Mode fallback) for a site, plus install steps for HTML, Google Tag Manager, WordPress, Shopify and Webflow.

get_embed_snippet input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "site_id"
  ],
  "properties": {
    "site_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "Site id from list_sites or create_site."
    }
  },
  "additionalProperties": false
}
get_embed_snippet annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}
run_compliance_scan — Run compliance scan
Advertised by the server during the last successful anonymous check.
Open-world

Scan a public web page for trackers (GA4, Google Ads, GTM, Meta Pixel, Hotjar, TikTok, LinkedIn…), cookies and Consent Mode setup, and get a 0–100 compliance score. Scans of your own domains are saved; apply=true adds the detected services to that site's banner.

run_compliance_scan input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "url"
  ],
  "properties": {
    "url": {
      "type": "string",
      "maxLength": 2048,
      "minLength": 3,
      "description": "Page URL, e.g. https://example.com"
    },
    "apply": {
      "type": "boolean",
      "description": "Add detected services and cookie names to the site's banner."
    },
    "site_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "Save the scan to this site (otherwise matched by domain)."
    }
  },
  "additionalProperties": false
}
run_compliance_scan annotations
{
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
list_banner_presets — List banner presets
Advertised by the server during the last successful anonymous check.
Advertised read-only

List the built-in banner colour presets and the allowed layouts, languages and categories.

list_banner_presets input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {},
  "additionalProperties": false
}
list_banner_presets annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1107 ms
95th percentile latency
1107 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1107 ms · metadata changed · 9 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http privacypill-mcp https://privacy-pill-consent-studio.lovable.app/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add privacypill-mcp --url https://privacy-pill-consent-studio.lovable.app/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable privacypill-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "privacypill-mcp": {
      "url": "https://privacy-pill-consent-studio.lovable.app/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "privacypill-mcp": {
      "type": "streamableHttp",
      "url": "https://privacy-pill-consent-studio.lovable.app/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start privacypill-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "privacypill-mcp": {
      "type": "http",
      "url": "https://privacy-pill-consent-studio.lovable.app/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http privacypill-mcp https://privacy-pill-consent-studio.lovable.app/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "privacypill-mcp": {
      "url": "https://privacy-pill-consent-studio.lovable.app/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "privacypill-mcp": {
      "serverUrl": "https://privacy-pill-consent-studio.lovable.app/mcp"
    }
  }
}

Let your agent find its tools

Find servers like PrivacyPill MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run PrivacyPill MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing