When we started building the CodeSpar SDK, we had dozens of MCP servers published on npm. Developers could install any of them and wire them into their agents manually. But the developer experience was painful. You had to discover which servers existed, figure out which tools to use, manage authentication for each provider, and handle the orchestration yourself.
We needed an SDK that made all of this invisible. One import, one session, one line to send a message to a commerce agent.
Five lines. That is the target DX. Here is how we got there.
Sessions as context containers
The core abstraction is the Session. When you call codespar.create(userId, options), the SDK creates an immutable context container that bundles together:
- A specific user (scoped by userId, isolated per organization)
- A commerce preset (which MCP servers to connect)
- The user's provider connections (CodeSpar refreshes OAuth tokens)
- The organization's policy rules (budgets, rate limits, approval gates, time windows), checked on every tool call
- An MCP endpoint for framework-agnostic access, when the session has one
- Usage context (every tool call is logged)
Once created, a session's user and servers do not change. Need different servers? Create a new session. This immutability simplifies debugging, makes sessions safe to pass between functions, and eliminates an entire class of state management bugs.
Sessions are also the unit of record. Every tool call within a session is logged to the session_tool_calls table with input/output payloads, duration, and status. Tool calls are not billed: only a settled money movement is (see Billing integration, below).
Meta tools, not raw tools
Each server in a preset brings its own raw tools. Passing every raw tool definition to an LLM would consume a significant portion of the context window and give the model too many choices.
Instead, the agent sees meta tools that route to the right provider. @codespar/types 0.11.4 publishes fifteen of them:
When an agent calls codespar_charge with a Pix method, CodeSpar looks up the routes its catalog has for that meta tool, rail, currency and country, keeps the providers you have connected, and calls that provider's tool. The agent sees the meta tools, not the raw tools behind them.
The right number of tools for an agent is the smallest number that covers all the use cases.
Each meta tool definition carries a name, a description and an input_schema. The schema declares the properties, the required ones, and closed vocabularies (actions, methods, channels) as enums, so a conformance check can compare any runtime's tool with the published definition. CodeSpar maps those properties to the parameters each provider expects.
Managed auth
Each provider requires different authentication. Zoop and NFe.io take an API key. Melhor Envio uses OAuth. Z-API needs an instance ID, an instance token and a Client-Token. Stark Bank signs every request with a key pair. Managing credentials for each provider is a pain developers should not have to deal with.
The session hands this to CodeSpar:
Credentials are stored per user, and CodeSpar refreshes OAuth tokens when they expire. Your code never stores them.
The key design decision: auth is per-user, not per-session. When a user authorizes Melhor Envio once, every subsequent session for that user inherits the credential. This means the OAuth flow happens once during onboarding, and every session after that just works.
Framework adapters
The SDK works with any AI framework through adapter packages. Each package converts session tools into the format the framework expects. The adapters are thin: they depend only on @codespar/sdk for types and the session interface. No heavy dependencies.
The await getTools(session) call is async because the session fetches its tool definitions from the CodeSpar API the first time they are asked for, and keeps them for its lifetime. Tools can change between sessions (different presets, different servers), so a new session fetches its own.
Note: @codespar/claude is for the Anthropic API directly. @codespar/vercel is for the Vercel AI SDK (which can use Anthropic, OpenAI, or any provider underneath). @codespar/mcp is an MCP server that gives Claude, Codex, Cursor and ChatGPT a CodeSpar commerce agent over MCP.
Real-time streaming with session.sendStream()
For user-facing applications, waiting for a whole Complete Loop to finish before showing any UI update is unacceptable. session.sendStream() returns a Server-Sent Events stream that emits events as each tool call starts, progresses, and completes:
The stream protocol is compatible with the standard SSE format, so it works with any HTTP client. The CodeSpar dashboard sandbox reads the same streaming endpoint (POST /v1/sessions/:id/send) to show tool execution as it happens.
One important detail: sendStream() handles the full agentic loop internally. The model receives the tools, reasons about which to call, executes them via MCP, reads the results, and continues until the model stops calling tools, up to an iteration limit. You do not need to implement a tool execution loop on the client side -- the SDK manages it server-side and streams events back.
Policy enforcement built in
Policy rules belong to the organization, and every tool call in every session is checked against them. You create them once, through the API: rate limits, time windows and approval gates.
Policy checks happen before every tool execution. A denied call comes back as a policy_denied tool result, and a call held for a person as approval_required; isPolicyDenied() and isApprovalRequired() tell them apart, so your application can handle both gracefully.
The approval gate is particularly important for high-value commerce operations. An AI agent processing a R$50,000 wholesale order should pause and wait for human confirmation. An approval-required rule matches agents and tools, never an amount: the matched call does not dispatch, it waits in the approvals queue in the Dashboard for an admin, and if nobody decides within 24 hours by default it expires and never runs. What holds a payment by its amount is the mandate's per-transaction cap: above it, a person approves a boleto the agent pays or a Pix through the consumer-payments REST routes; other rails refuse, and the periodic and total caps always refuse.
Commerce events as triggers
Triggers deliver commerce events to your endpoint. You subscribe once, through the API:
A trigger matches the event name exactly: commerce.payment.succeeded does not receive commerce.payment.received. Each matching event is posted to the webhook URL, whatever language the agent spoke in.
Triggers run server-side: CodeSpar watches the provider connections in your project and its own runtime, and posts the event; your code decides what follows, such as issuing the NF-e when a payment succeeds or notifying the customer on WhatsApp. This turns the SDK from a tool execution layer into the start of a commerce automation engine.
Billing integration
At v0.2.0, every tool call was a billing unit. This was a deliberate design choice: billing at the tool call level gave precise cost attribution per user, per session, per order. Today tool calls are free under the rate card, and the example below reads what is billed now: the fee lanes.
The v0.2.0 billing model mapped directly to Stripe metered billing: at the end of each billing cycle, the session_tool_calls table was aggregated per organization and reported as metered usage.
Why not bill per session or per API call? Because sessions vary wildly in complexity. A simple "check my balance" query is one tool call. A Complete Loop is four, one per step that has a meta tool. A customer support agent handling a return might make twelve. That was the case for per-tool-call billing; the update below says where pricing went.
This section describes the metering design as we shipped it in v0.2.0. Pricing has since moved up one level of abstraction, and tool calls are no longer billed: plans are now priced per settled money movement (the payment is the billable event; the invoicing, shipping, messaging, and ERP calls around it are included). Current plans live on the pricing page.
What we shipped
Five packages. All typed. All building via Turborepo. Published on npm at v0.2.0.
| Package | Purpose |
|---|---|
| @codespar/sdk | Core: sessions, tools, execute, send, sendStream, loop, managed auth |
| @codespar/claude | Claude API adapter (getTools, handleToolUse, toToolResultBlock) |
| @codespar/openai | OpenAI function calling adapter |
| @codespar/vercel | Vercel AI SDK adapter with execute() functions |
| @codespar/mcp | MCP transport: connects Claude Desktop, Cursor and VS Code to CodeSpar sessions |
The architecture decision that made shipping fast: all adapters depend on @codespar/sdk for types and the session interface, but they do not depend on each other. Installing @codespar/openai does not pull in Vercel AI SDK. Installing @codespar/vercel does not pull in the Anthropic SDK. You only pay for the dependencies you actually use.
What is next
The SDK at v0.2.0 covers the core surface: sessions, tools, send, sendStream, execute, loop, managed auth, and billing tracking. Here is what is coming next, in order of priority:
- Stripe billing integration (Marco 3). Wire metered billing from
session_tool_callsto Stripe. Quota enforcement in the execute and send endpoints. Self-serve plan upgrades from the dashboard. This is the monetization milestone. - Real MCP routing. Currently, the meta tools execute against mock servers. The next step connects them to the live MCP servers via Streamable HTTP transport. Tool calls will hit real Zoop, the fiscal provider, Melhor Envio, and Omie APIs.
- Managed connection UI. An OAuth connection flow in the dashboard where users click "Connect Zoop" and complete the authorization without writing code. Tokens stored server-side, auto-refreshed, never exposed to the client.
- Python SDK. Same API surface, same session model, targeting LangChain and CrewAI adapters. Python is essential for reaching the ML/data science agent community.
- Server-side triggers. Define automation rules in the dashboard: "When
payment.completed, auto-issue NF-e" or "Whenshipping.label_created, notify customer on WhatsApp." This turns CodeSpar from a tool execution layer into a commerce automation engine that runs with no code at all. - Mexico and Colombia presets. The MCP server catalog already covers 4 countries. Adding presets for Mexico (SAT/CFDI, Conekta, Envia) and Colombia (DIAN, Wompi, Envia) unlocks the rest of LatAm.
The SDK is the product. Everything else -- dashboard, servers, docs -- exists to make the SDK easier to adopt.
The SDK is open source. The code is at github.com/codespar/codespar-core. Install it with npm install @codespar/sdk and tell us what breaks.
This post was written at @codespar/sdk@0.2.0; its examples compile against 0.16.11. For a hands-on tutorial, see the Complete Loop tutorial. The enterprise packages (PolicyEngine, MandateGenerator, PaymentGateway) are covered in the thesis post.
Updated on 2026.10.07: the link to the SDK's code points to its repository, codespar/codespar-core.
Updated on 2026.10.07: the examples now compile against @codespar/sdk 0.16.11. They were labelled 0.2.0 but used APIs no published version had (budgetLimit, AuthManager, codespar.on, session.usage). Policies are organization rules that match agents and tools, never an amount; above the mandate's per-transaction cap, a person approves a boleto the agent pays or a Pix through the consumer-payments REST routes, and other rails refuse. Tool calls are not billed; settled money movement is. The meta tools are the fifteen that @codespar/types 0.11.4 publishes, routed by CodeSpar's catalog; the OAuth example uses Melhor Envio, the OAuth provider in the catalog; and the counts and timings nobody measured are gone.