Agent frameworks
@tuppence/agent-tools gives an agent framework the same tools as the
MCP server — it asks the server for them, with your key — so an agent built with
any of them can take payments, and is offered only what its key may do.
npm install @tuppence/agent-toolsGive the agent a restricted key in TUPPENCE_SECRET_KEY, with only the scopes it needs —
say payment_links:read and payment_links:write for an agent that sells with links.
OpenAI Agents SDK
Section titled “OpenAI Agents SDK”import { Agent, run } from "@openai/agents";import { tuppenceTools } from "@tuppence/agent-tools/openai-agents";
const { tools, close } = await tuppenceTools();const agent = new Agent({ name: "Billing assistant", instructions: "Amounts are integers in pence. When you create a payment link, reply with its URL.", tools,});const result = await run(agent, "Make a £15 payment link for a deep research report.");console.log(result.finalOutput);await close();LangChain
Section titled “LangChain”import { createAgent } from "langchain";import { tuppenceTools } from "@tuppence/agent-tools/langchain";
const { tools, close } = await tuppenceTools();const agent = createAgent({ model: "openai:gpt-5", tools });const result = await agent.invoke({ messages: [{ role: "user", content: "Make a £15 payment link for a deep research report." }],});await close();Claude Agent SDK
Section titled “Claude Agent SDK”The Claude Agent SDK connects to MCP servers itself, so the pack is the connection:
import { query } from "@anthropic-ai/claude-agent-sdk";import { TUPPENCE_TOOLS, tuppenceMcpServer } from "@tuppence/agent-tools/claude-agent-sdk";
for await (const message of query({ prompt: "Make a £15 payment link for a deep research report.", options: { mcpServers: { tuppence: tuppenceMcpServer() }, allowedTools: [TUPPENCE_TOOLS], // or one by one: mcp__tuppence__create_payment_link },})) { console.log(message);}When the API says no
Section titled “When the API says no”A refused call is an answer, not a crash: the tool returns the API’s error — code, message,
param — for the agent to read and correct. Money-moving tools require an idempotency_key;
an agent that retries must send the same one, and the money moves once.
Each example above runs in our CI against the real API, with a scripted model standing in for the LLM: the agent really makes the link, and really gets its URL back.