Integrations

Drop DataDam into any agent stack.

MCP server configs for the IDE clients teams already use, plus tool definitions for the SDKs your application code already calls. Replace the value placeholder with your proxy URL and API key. Every snippet is a copy-paste.

MCP clients

One MCP server in the IDE config: DataDam.

The IDE connects to DataDam over MCP; DataDam holds the connections to every upstream tool (GitHub MCP, Postgres MCP, your internal MCP). The alternative, N sibling MCP servers in the IDE config, bypasses governance and is the failure mode this layer exists to prevent. Modern clients speak Streamable HTTP and connect directly. Older clients use the stdio shim.

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%/Claude/claude_desktop_config.json (Windows). The shim bridges Claude Desktop's stdio MCP transport to the proxy's Streamable HTTP /mcp endpoint.

{
  "mcpServers": {
    "datadam": {
      "command": "npx",
      "args": ["-y", "@datadam/mcp", "https://proxy.acme.example"],
      "env": {
        "DATADAM_API_KEY": "dd_pk_live_..."
      }
    }
  }
}

Cursor

Settings → Tools & Integrations → MCP servers. Cursor 0.45+ speaks Streamable HTTP natively, so connect directly without the shim.

{
  "mcpServers": {
    "datadam": {
      "url": "https://proxy.acme.example/mcp",
      "headers": {
        "Authorization": "Bearer dd_pk_live_..."
      }
    }
  }
}

Continue

Edit ~/.continue/config.json. Continue speaks Streamable HTTP for MCP since 0.10.

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "streamable-http",
          "url": "https://proxy.acme.example/mcp",
          "headers": {
            "Authorization": "Bearer dd_pk_live_..."
          }
        }
      }
    ]
  }
}

Cline

Cline 3.x reads ~/.cline/mcp.json. Same shape as Cursor; both connect over Streamable HTTP.

{
  "mcpServers": {
    "datadam": {
      "url": "https://proxy.acme.example/mcp",
      "headers": {
        "Authorization": "Bearer dd_pk_live_..."
      }
    }
  }
}

LLM egress

Scan outbound prompts and image attachments.

Point each vendor SDK at the proxy with a base URL. DataDam scans the outbound prompt (and any image attachments) for PII, applies the org policy (warn, redact, or block), and forwards to the vendor. Streaming responses redact in flight. The vendor API key never leaves the proxy host: the SDK only needs the DataDam API key.

Anthropic SDK

Point the Anthropic SDK at the proxy with base_url. Every Messages call routes through DataDam first: outbound prompt and image attachments scan for PII before the vendor receives the request. The vendor API key stays on the proxy host as an environment variable.

import os
from anthropic import Anthropic

# Point the SDK at the proxy. Vendor key lives on the proxy host;
# the SDK only needs the DataDam API key.
client = Anthropic(
    base_url="https://proxy.acme.example/llm/anthropic",
    api_key=os.environ["DATADAM_API_KEY"],
)

response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Summarize this chart."}],
)

OpenAI Chat Completions

Same idea, OpenAI SDK. base_url + DataDam API key. Streaming is supported: the proxy redacts deltas in flight without breaking the stream.

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://proxy.acme.example/llm/openai/v1",
    api_key=os.environ["DATADAM_API_KEY"],
)

response = client.chat.completions.create(
    model="gpt-5",
    messages=[{"role": "user", "content": "Top customers this quarter."}],
)

OpenAI Responses API

The Responses API supercedes Chat Completions for new builds. Same base_url pattern; the SDK shape differs.

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://proxy.acme.example/llm/openai/v1",
    api_key=os.environ["DATADAM_API_KEY"],
)

response = client.responses.create(
    model="gpt-5",
    input="Summarize this contract.",
)

Google Gemini

Gemini uses an x-goog-api-key header instead of Authorization, but the base-URL pattern is identical. Point google-genai at the proxy and let DataDam handle vendor auth.

import os
from google import genai

client = genai.Client(
    api_key=os.environ["DATADAM_API_KEY"],
    http_options={"base_url": "https://proxy.acme.example/llm/gemini"},
)

response = client.models.generate_content(
    model="gemini-2.0-flash",
    contents="Summarize this patient note.",
)

LLM SDKs

Tool definitions for application code.

When the agent runs inside your application instead of an IDE, declare DataDam as a function-calling tool. The pattern is identical across providers: define the tool, let the model emit a call, forward the arguments to the proxy, return the response.

Anthropic Messages API (tool_use)

Define DataDam as a tool. The model emits a tool_use block; your application code POSTs to /:source/query and returns the row count plus rows in the tool_result.

import os
from anthropic import Anthropic

client = Anthropic()
PROXY = "https://proxy.acme.example"
KEY = os.environ["DATADAM_API_KEY"]

datadam_tool = {
    "name": "query_warehouse",
    "description": "Run a governed SQL query against the production warehouse.",
    "input_schema": {
        "type": "object",
        "properties": {
            "sql": {"type": "string", "description": "Read-only SQL"},
        },
        "required": ["sql"],
    },
}

response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=2048,
    tools=[datadam_tool],
    messages=[{"role": "user", "content": "Top customers by revenue this quarter."}],
)

# When response.content carries a tool_use block, forward it to DataDam:
import httpx

if response.stop_reason == "tool_use":
    tu = next(b for b in response.content if b.type == "tool_use")
    result = httpx.post(
        f"{PROXY}/warehouse/query",
        json={"sql": tu.input["sql"]},
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30.0,
    ).json()
    # Send result back to Claude as a tool_result message and resume.

OpenAI Chat Completions (function calling)

OpenAI's function-calling shape. Same idea as Anthropic tool_use: declare the tool, intercept the function call, forward to the proxy.

import os
from openai import OpenAI
import httpx

client = OpenAI()
PROXY = "https://proxy.acme.example"
KEY = os.environ["DATADAM_API_KEY"]

datadam_tool = {
    "type": "function",
    "function": {
        "name": "query_warehouse",
        "description": "Run a governed SQL query against the production warehouse.",
        "parameters": {
            "type": "object",
            "properties": {
                "sql": {"type": "string"},
            },
            "required": ["sql"],
        },
    },
}

response = client.chat.completions.create(
    model="gpt-5",
    tools=[datadam_tool],
    messages=[{"role": "user", "content": "Top customers by revenue this quarter."}],
)

call = response.choices[0].message.tool_calls[0]
import json
args = json.loads(call.function.arguments)
result = httpx.post(
    f"{PROXY}/warehouse/query",
    json={"sql": args["sql"]},
    headers={"Authorization": f"Bearer {KEY}"},
    timeout=30.0,
).json()

OpenAI Responses API

The Responses API supercedes Chat Completions for new builds. Same wire protocol on our side; the SDK shape differs.

import os
from openai import OpenAI

client = OpenAI()
PROXY = "https://proxy.acme.example"
KEY = os.environ["DATADAM_API_KEY"]

response = client.responses.create(
    model="gpt-5",
    tools=[
        {
            "type": "function",
            "name": "query_warehouse",
            "description": "Governed SQL against production warehouse.",
            "parameters": {
                "type": "object",
                "properties": {"sql": {"type": "string"}},
                "required": ["sql"],
            },
        }
    ],
    input="Top customers by revenue this quarter.",
)

LangChain Tool

A LangChain Tool wrapper around the proxy. Drop it into any agent constructor.

import os
import httpx
from langchain.tools import tool

PROXY = "https://proxy.acme.example"
KEY = os.environ["DATADAM_API_KEY"]

@tool
def query_warehouse(sql: str) -> dict:
    """Run a governed SQL query against the production warehouse."""
    return httpx.post(
        f"{PROXY}/warehouse/query",
        json={"sql": sql},
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30.0,
    ).json()

Vercel AI SDK

TypeScript wrapper for the Vercel AI SDK's tool primitive. Works with streamText / generateText alongside any LLM provider the SDK supports.

import { tool } from "ai";
import { z } from "zod";

const PROXY = "https://proxy.acme.example";
const KEY = process.env.DATADAM_API_KEY!;

export const queryWarehouse = tool({
  description: "Run a governed SQL query against the production warehouse.",
  parameters: z.object({
    sql: z.string().describe("Read-only SQL statement"),
  }),
  execute: async ({ sql }) => {
    const r = await fetch(`${PROXY}/warehouse/query`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${KEY}`,
      },
      body: JSON.stringify({ sql }),
    });
    if (!r.ok) throw new Error(`DataDam denied: ${r.status}`);
    return r.json();
  },
});

Need an integration that is not on this list?

The proxy speaks Streamable HTTP MCP and a plain HTTP API. Anything that talks either protocol works. Email hello@mydatadam.com and we will write the snippet.