This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A collection of self-contained Python samples showing how to drive the Predactiv MCP server (https://mcp.predactiv.com) as a set of AI-agent tools from different frameworks and SDKs. Each top-level directory is one sample. All samples are implemented.
claude/— Anthropic Claude via its native server-side MCP connector (LLM: Claude)openai/— OpenAI GPT via its native server-side MCP connector (Responses API; LLM: OpenAI)langchain/— LangChaincreate_agent+langchain-mcp-adapters, client-side loop (LLM: OpenAI)mcp-sdk/— raw MCP Python SDK with a hand-written client-side tool-calling loop (LLM: OpenAI)oauth-token-lib/— shared, locally-installed package handling Predactiv OAuth2 auth
Two architectural patterns are represented. Client-side samples (
langchain/,mcp-sdk/) connect to the MCP server themselves, fetch tools, and run the tool-calling loop in your process. Server-side connector samples (claude/,openai/) hand the MCP server definition to the provider's API and let the provider run the loop.langchain/agent.pyis the simplest client-side reference;mcp-sdk/agent.pyshows the same loop without a framework.
All samples share the same auth layer; they differ in who runs the MCP connection and tool loop.
-
Auth (shared) —
oauth_token_libperforms an OAuth2 client-credentials exchange againsthttps://platform-api.predactiv.com/v2/oauth/tokenusingCLIENT_ID/CLIENT_SECRETfrom the environment, and caches the token in-process until ~60s before expiry. It exposesget_bearer_token()(raw token string) andauth_headers()({"Authorization": "Bearer <token>"}). This package is the single source of truth for authentication — all samples depend on it rather than re-implementing the token exchange. The MCP server is stateless (noMcp-Session-Id) and every tool requires the OAuth bearer token. -
MCP connection + agent loop — two patterns:
- Client-side (
langchain/,mcp-sdk/) — the sample connects tohttps://mcp.predactiv.comover HTTP, fetches tools dynamically (tools/list), converts them to the LLM's tool format, and runs the call → execute-tool → feed-result loop in-process.mcp-sdk/usesstreamable_http_client+ClientSessionand a hand-written loop;langchain/usesMultiServerMCPClient+create_agent, which hide the loop. - Server-side connector (
claude/,openai/) — the sample passes the MCP server definition (URL + bearer token) to the provider's API (Anthropic Messages APImcp_servers/mcp_toolset+mcp-client-2025-11-20beta; OpenAI Responses APImcptool), and the provider connects to the server and runs the tool loop. The sample makes a single API call and reads the final answer.
- Client-side (
The Predactiv MCP tools expose the data platform: audiences, datasets, datasources, destinations, filters/predictors, and insights (predactiv_* tool families).
Each sample is run from inside its own directory. Using langchain as the template:
cd langchain
pip install -r requirements.txt # also installs ../oauth-token-lib in editable mode (-e)
export CLIENT_ID=... # Predactiv OAuth (all samples)
export CLIENT_SECRET=...
export OPENAI_API_KEY=... # langchain/, openai/, mcp-sdk/
# export ANTHROPIC_API_KEY=... # claude/ instead of OPENAI_API_KEY
python agent.pyEach sample needs the Predactiv CLIENT_ID/CLIENT_SECRET plus its LLM provider key: OPENAI_API_KEY for langchain/, openai/, and mcp-sdk/; ANTHROPIC_API_KEY for claude/. Note mcp-sdk/ requires Python 3.10+ (MCP Python SDK); the others run on 3.9+.
Verify auth independently (prints a truncated token):
cd oauth-token-lib && python oauth_token_lib.py- Reuse
oauth_token_libfor auth; do not re-implement the token exchange. Add-e ../oauth-token-libto the sample'srequirements.txt. Useauth_headers()for client-side HTTP connections andget_bearer_token()when a connector wants the raw token. - Keep the MCP server URL (
https://mcp.predactiv.com) and aGOALprompt as module-level constants, mirroring the existing samples. - For client-side samples, fetch tools dynamically from the server (
tools/list); do not hardcode the tool list. For connector samples, let the provider discover the tools. - Each sample directory has its own
README.mdfollowing a shared structure (How it works → Prerequisites → Setup → Configuration → Run → Troubleshooting → Learn more). Keep new samples consistent with it, and update the rootREADME.mdsample table.