Quickstart
Get your first AI agent commerce interaction running in under 5 minutes.
Quickstart
This guide walks you through installing the SDK, creating a session, executing a tool call, and wiring it into a full agent loop -- all in under 5 minutes. By the end, you will have a working commerce agent that can process payments in Brazil.
Prerequisites
- Node.js 18+ installed
- A CodeSpar API key (get one at codespar.dev/dashboard/settings)
- An LLM provider account (Anthropic, OpenAI, or any Vercel AI SDK provider)
Install the SDK and an adapter
Install the core SDK and the adapter for your preferred framework:
npm install @codespar/sdk @codespar/claude @anthropic-ai/sdknpm install @codespar/sdk @codespar/openai openainpm install @codespar/sdk @codespar/vercel ai @ai-sdk/anthropic[!TIP] Using pnpm or yarn? Replace
npm installwithpnpm addoryarn add. All packages are published on the public npm registry.
Set your API keys
You need two environment variables -- one for CodeSpar, one for your LLM provider:
export CODESPAR_API_KEY="csk_live_your_key_here"
export ANTHROPIC_API_KEY="sk-ant-your_key_here"export CODESPAR_API_KEY="csk_live_your_key_here"
export OPENAI_API_KEY="sk-your_key_here"export CODESPAR_API_KEY="csk_live_your_key_here"
export ANTHROPIC_API_KEY="sk-ant-your_key_here"[!NOTE] API keys prefixed with
csk_test_route to sandbox servers with mock data. Usecsk_live_for production. Both share the same API surface, so you can develop against sandbox and switch to production by changing one variable.
Create a session
A session is a scoped connection to one or more MCP servers. It manages authentication, tool routing, and usage tracking. Think of it as a database connection pool -- you create one, use it for the duration of your interaction, and close it when done.
import { CodeSpar } from "@codespar/sdk";
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
const session = await codespar.sessions.create({
servers: ["stripe", "mercadopago"],
});
console.log("Session ID:", session.id);
console.log("Status:", session.status);
console.log("Servers:", session.servers);{
"id": "ses_a1b2c3d4e5f6",
"status": "active",
"servers": ["stripe", "mercadopago"],
"created_at": "2026-04-15T14:30:00Z",
"expires_at": "2026-04-15T15:30:00Z"
}[!WARNING] Sessions expire after 1 hour of inactivity. For long-running agents, implement session renewal or create a new session per interaction. See Sessions for lifecycle details.
List available tools
Once your session is active, retrieve the tools available from the connected servers. The session.tools() method is async and returns an array of tool definitions:
const tools = await session.tools();
console.log(`${tools.length} tools available:`);
tools.forEach((t) => {
console.log(` - ${t.name}: ${t.description}`);
});[
{
"name": "codespar_discover",
"description": "Find available commerce tools by domain",
"input_schema": {
"type": "object",
"properties": {
"domain": {
"type": "string",
"enum": ["payments", "fiscal", "logistics", "messaging", "banking", "erp", "crypto"]
}
},
"required": ["domain"]
}
},
{
"name": "codespar_checkout",
"description": "Create a checkout session for a product or service",
"input_schema": { "..." : "..." }
},
{
"name": "codespar_pay",
"description": "Process a payment via Pix, boleto, or card",
"input_schema": { "..." : "..." }
}
][!NOTE] The tools returned depend on which servers you connected in the session. Connecting
["stripe", "mercadopago"]gives you payment tools. Add"correios"to also get shipping tools.
Execute a tool call
Call a tool directly against the session to verify everything is wired correctly:
const result = await session.execute({
name: "codespar_discover",
arguments: { domain: "payments" },
});
console.log(JSON.stringify(result, null, 2));{
"domain": "payments",
"servers": ["stripe", "mercadopago"],
"tools": [
{
"name": "codespar_checkout",
"description": "Create a checkout session for a product or service"
},
{
"name": "codespar_pay",
"description": "Process a payment via Pix, boleto, or card"
}
],
"capabilities": ["pix", "boleto", "credit_card", "checkout_link", "recurring"]
}Now try creating a checkout link:
const checkout = await session.execute({
name: "codespar_checkout",
arguments: {
provider: "stripe",
amount: 4990,
currency: "BRL",
description: "Pro Plan - Monthly",
payment_methods: ["pix", "card"],
},
});
console.log(JSON.stringify(checkout, null, 2));{
"checkout_id": "chk_7f8g9h0i1j2k",
"url": "https://checkout.stripe.com/c/pay/cs_live_a1b2c3...",
"amount": 4990,
"currency": "BRL",
"description": "Pro Plan - Monthly",
"payment_methods": ["pix", "card"],
"status": "open",
"expires_at": "2026-04-16T14:30:00Z"
}Wire it into an agent
Now connect everything to a real LLM. Choose your framework:
import Anthropic from "@anthropic-ai/sdk";
import { CodeSpar } from "@codespar/sdk";
import { getTools, handleToolUse, toToolResultBlock } from "@codespar/claude";
const anthropic = new Anthropic();
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
async function run(userMessage: string) {
// 1. Create session with the servers you need
const session = await codespar.sessions.create({
servers: ["stripe", "mercadopago"],
});
// 2. Get tools in Anthropic format
const tools = await getTools(session);
// 3. Start the conversation
const messages: Anthropic.MessageParam[] = [
{ role: "user", content: userMessage },
];
let response = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 4096,
system:
"You are a commerce assistant for a Brazilian e-commerce store. " +
"Use the available tools to help with payments, invoicing, and shipping. " +
"Always confirm amounts and details before processing payments.",
tools,
messages,
});
// 4. Tool-use loop: keep going until Claude stops calling tools
while (response.stop_reason === "tool_use") {
const toolUseBlocks = response.content.filter(
(b) => b.type === "tool_use"
);
const toolResults = await Promise.all(
toolUseBlocks.map(async (block) => {
try {
const result = await handleToolUse(session, block);
return toToolResultBlock(block.id, result);
} catch (error) {
return toToolResultBlock(block.id, {
error: error instanceof Error ? error.message : "Tool call failed",
});
}
})
);
messages.push({ role: "assistant", content: response.content });
messages.push({ role: "user", content: toolResults });
response = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 4096,
tools,
messages,
});
}
// 5. Clean up
await session.close();
// 6. Return the final text
const text = response.content.find((b) => b.type === "text");
return text?.type === "text" ? text.text : "";
}
// Run it
const reply = await run("Create a R$49.90 checkout link for 'Pro Plan' using Stripe");
console.log(reply);See the full Claude adapter guide for streaming, error handling, and advanced patterns.
import OpenAI from "openai";
import { CodeSpar } from "@codespar/sdk";
import { getTools, handleToolCall } from "@codespar/openai";
const openai = new OpenAI();
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
async function run(userMessage: string) {
const session = await codespar.sessions.create({
servers: ["stripe", "mercadopago"],
});
const tools = await getTools(session);
const messages: OpenAI.ChatCompletionMessageParam[] = [
{
role: "system",
content:
"You are a commerce assistant for a Brazilian store. " +
"Use the available tools for payments, invoicing, and shipping.",
},
{ role: "user", content: userMessage },
];
let response = await openai.chat.completions.create({
model: "gpt-4o",
tools,
messages,
});
let message = response.choices[0].message;
while (message.tool_calls && message.tool_calls.length > 0) {
messages.push(message);
for (const toolCall of message.tool_calls) {
let content: string;
try {
content = await handleToolCall(session, toolCall);
} catch (error) {
content = JSON.stringify({
error: error instanceof Error ? error.message : "Tool call failed",
});
}
messages.push({
role: "tool",
tool_call_id: toolCall.id,
content,
});
}
response = await openai.chat.completions.create({
model: "gpt-4o",
tools,
messages,
});
message = response.choices[0].message;
}
await session.close();
return message.content ?? "";
}
const reply = await run("Generate a Pix QR code for R$250");
console.log(reply);See the full OpenAI adapter guide for streaming and advanced patterns.
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { CodeSpar } from "@codespar/sdk";
import { getTools } from "@codespar/vercel";
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
const session = await codespar.sessions.create({
servers: ["stripe", "mercadopago"],
});
const tools = await getTools(session);
const { text } = await generateText({
model: anthropic("claude-sonnet-4-20250514"),
tools,
maxSteps: 5,
system:
"You are a commerce assistant for a Brazilian e-commerce store. " +
"Use the available tools for payments, invoicing, and shipping.",
prompt: "Create a R$49.90 checkout link for 'Pro Plan' via Stripe",
});
console.log(text);
await session.close();See the full Vercel AI SDK guide for streamText, Next.js API routes, and the useChat hook.
The Complete Loop in action
Here is what happens when you run the Claude example above. The agent performs the Complete Loop automatically:
- Claude receives the prompt and sees the available tools from
getTools. - Claude calls
codespar_discover(optional) to understand available payment providers. - Claude calls
codespar_checkoutwith the amount, currency, and provider. - CodeSpar routes the request to the Stripe MCP server, which creates a real checkout session.
- Claude receives the result (checkout URL, status, expiry) and formats a response for the user.
User: "Create a R$49.90 checkout link for 'Pro Plan' using Stripe"
Claude thinks: I need to create a checkout link. I have the codespar_checkout tool.
Claude calls: codespar_checkout({
provider: "stripe",
amount: 4990,
currency: "BRL",
description: "Pro Plan",
payment_methods: ["pix", "card"]
})
CodeSpar returns: {
checkout_id: "chk_7f8g9h0i1j2k",
url: "https://checkout.stripe.com/c/pay/cs_live_...",
status: "open"
}
Claude responds: "I've created your checkout link for the Pro Plan at R$49.90.
Here it is: https://checkout.stripe.com/c/pay/cs_live_...
The link accepts both Pix and card payments and expires in 24 hours."Try the sandbox
Don't want to set up locally? Try the interactive sandbox at codespar.dev/dashboard/sandbox. It provides a live chat interface where you can test tool calls with mock servers -- no API key required.
[!TIP] The sandbox uses
csk_test_keys internally. All tool calls return realistic mock data. It is a great way to explore the 6 meta-tools before writing any code.
Common errors
| Error | Cause | Fix |
|---|---|---|
INVALID_API_KEY | Missing or malformed API key | Check that CODESPAR_API_KEY is set and starts with csk_live_ or csk_test_ |
SESSION_EXPIRED | Session timed out after 1 hour of inactivity | Create a new session |
SERVER_NOT_FOUND | Requested a server that does not exist | Check available servers with codespar_discover |
TOOL_NOT_FOUND | Called a tool not available in the current session | Verify the tool exists with session.tools() |
RATE_LIMITED | Too many requests in a short period | Implement exponential backoff or reduce request frequency |
Next steps
Sessions
Deep dive into the session lifecycle, server selection, and scoping
Claude Adapter
Full guide for building Claude-powered commerce agents
OpenAI Adapter
Integrate with GPT-4o and the OpenAI function-calling API
Vercel AI SDK
Streaming-first agents for Next.js applications
MCP
Use CodeSpar tools in Claude Desktop and Cursor
Tools and Meta-Tools
Understand the 6 meta-tools and how server routing works