Reference
Output format
Every StateAnchor sync run produces a gate decision. In full pipeline mode, a passing sync also regenerates your configured output artifacts — one per language, plus optional MCP server, API documentation, and OpenAPI spec. In gate-only mode, no artifacts are generated; the gate decision and Merkle log entry are the outputs.
Product modes
Gate-only— StateAnchor enforces your API contract in CI. No artifacts generated. Use this if you already have a generator (Speakeasy, Fern, etc.) and want contract enforcement without artifact conflict.
Full pipeline— StateAnchor gates AND generates. A passing sync produces: TypeScript SDK, Python SDK (if configured), Go SDK (if configured), MCP server (if configured), API documentation (if configured), OpenAPI 3.1 spec (if configured). All artifacts derive from the same verified IR.
See Gate-only mode for configuration details.
Provenance header
Every generated artifact begins with a provenance comment:
// @stateanchor-provenance: eyJzb3VyY2VfaXJfaGFzaCI6ImE...
// Generated by StateAnchor -- do not edit manuallyThe decoded provenance JSON contains:
| Field | Description |
|---|---|
source_ir_hash | SHA-256 of the IR that produced this artifact |
generator_version | Version of the generation engine |
artifact_type | typescript-sdk, python-sdk, mcp-server, etc. |
project_id | Project UUID |
generated_at | ISO 8601 timestamp |
TypeScript SDK
Single .ts file with zero dependencies. Uses native fetch (Node 18+ or browser). Contains types, error class, and client class.
Structure
// @stateanchor-provenance: ...
// -- Types --------------------------------------
export interface Charge {
id: string;
amount: number;
currency: string;
status: string;
created_at: string;
}
export interface ChargeInput {
amount: number;
currency: string;
}
// -- Error --------------------------------------
export class PaymentsApiError extends Error {
constructor(
public readonly status: number,
message: string,
public readonly body?: unknown
) {
super(message);
this.name = "PaymentsApiError";
}
}
// -- Client -------------------------------------
export class PaymentsApiClient {
private readonly baseUrl: string;
private readonly headers: Record<string, string>;
constructor(opts: { apiKey: string; baseUrl?: string }) {
this.baseUrl = opts.baseUrl ?? "https://api.acme.com/v2";
this.headers = {
"Authorization": `Bearer ${opts.apiKey}`,
"Content-Type": "application/json",
};
}
/** Create a new payment charge */
async createCharge(input: ChargeInput): Promise<Charge> {
const res = await fetch(`${this.baseUrl}/charges`, {
method: "POST",
headers: this.headers,
body: JSON.stringify(input),
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new PaymentsApiError(
res.status, body.message ?? res.statusText, body
);
}
return res.json();
}
/** Get a charge by ID */
async getCharge(id: string): Promise<Charge> { /* ... */ }
/** List all charges */
async listCharges(opts?: {
limit?: number;
offset?: number;
}): Promise<Charge[]> { /* ... */ }
}Usage
import { PaymentsApiClient } from "./payments-api-sdk";
const client = new PaymentsApiClient({ apiKey: process.env.API_KEY });
const charge = await client.createCharge({ amount: 2500, currency: "usd" });
console.log(charge.id);Key features
- Full TypeScript types for every request and response shape
- Custom error class with HTTP status, message, and raw body
- JSDoc on every method with parameter descriptions
- Zero dependencies -- native
fetchonly - Configurable base URL for local development / staging
Python SDK
Single .py file using httpx for async HTTP. Includes dataclasses for types, a custom exception, and async client.
Structure
# @stateanchor-provenance: ...
from dataclasses import dataclass
from typing import Optional, List
import httpx
@dataclass
class Charge:
id: str
amount: int
currency: str
status: str
created_at: str
class PaymentsApiError(Exception):
def __init__(self, status: int, message: str, body=None):
super().__init__(message)
self.status = status
self.body = body
class PaymentsApiClient:
def __init__(self, api_key: str, base_url="https://api.acme.com/v2"):
self.base_url = base_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
async def create_charge(self, amount: int, currency: str) → Charge:
"""Create a new payment charge."""
async with httpx.AsyncClient() as client:
res = await client.post(
f"{self.base_url}/charges",
headers=self.headers,
json={"amount": amount, "currency": currency},
)
if res.status_code >= 400:
body = res.json()
raise PaymentsApiError(res.status_code, body.get("message", ""))
return Charge(**res.json())Usage
import asyncio
from payments_api_sdk import PaymentsApiClient
client = PaymentsApiClient(api_key="sk_live_...")
charge = asyncio.run(client.create_charge(amount=2500, currency="usd"))
print(charge.id)Go SDK
Single .go file using net/http. Struct types with json tags, error type implementing the error interface.
Structure (abbreviated)
// @stateanchor-provenance: ...
package paymentsapi
import (
"encoding/json"
"fmt"
"net/http"
"bytes"
)
type Charge struct {
ID string `json:"id"`
Amount int `json:"amount"`
Currency string `json:"currency"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
}
type ApiError struct {
StatusCode int
Message string
}
func (e *ApiError) Error() string {
return fmt.Sprintf("API error %d: %s", e.StatusCode, e.Message)
}
type Client struct {
BaseURL string
APIKey string
HTTP *http.Client
}
func NewClient(apiKey string) *Client {
return &Client{
BaseURL: "https://api.acme.com/v2",
APIKey: apiKey,
HTTP: &http.Client{},
}
}MCP server
TypeScript file exposing API endpoints as MCP tools via the @modelcontextprotocol/sdk package. Runs on stdio transport.
Structure
// @stateanchor-provenance: ...
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "payments-api",
version: "2.4.0",
});
server.tool(
"createCharge",
"Create a new payment charge",
{ amount: z.number(), currency: z.string() },
async ({ amount, currency }) => {
const res = await fetch("https://api.acme.com/v2/charges", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ amount, currency }),
});
const data = await res.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
};
}
);
async function run() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
run().catch(console.error);Claude Desktop config
{
"mcpServers": {
"payments-api": {
"command": "npx",
"args": ["tsx", "payments-api-mcp.ts"],
"env": { "API_TOKEN": "sk_live_..." }
}
}
}API documentation artifact
Single api-docs.mdfile. Complete Markdown API reference generated deterministically from the IR — the same IR that drives SDK generation. Generated without any LLM call, meaning zero additional token cost and guaranteed accuracy against the verified spec.
Contents: service overview, authentication guide, complete endpoint reference with parameters and response types, model definitions.
Enable in stateanchor.yaml:
outputs:
languages:
- typescript
mcp: true
docs: trueDownload via the DOC badge in the project cockpit.
OpenAPI spec artifact
Gate-stamped OpenAPI 3.1 spec generated from the verified IR after every passing sync. Use this as the authoritative spec input for Speakeasy, Fern, Mintlify, or any other tool that consumes OpenAPI specs — your downstream tools can only generate artifacts from a spec the gate has verified.
Enable in stateanchor.yaml:
outputs:
openapi: trueDownload via the OAS badge in the project cockpit, or retrieve via API.
Artifact comparison
| Feature | TypeScript | Python | Go | MCP | Docs | OAS |
|---|---|---|---|---|---|---|
| HTTP client | Native fetch | httpx (async) | net/http | Native fetch | -- | -- |
| Type system | Interfaces | Dataclasses | Structs + json tags | Zod schemas | -- | -- |
| Error class | Custom Error | Custom Exception | error interface | MCP error | -- | -- |
| Inline docs | JSDoc | Docstrings | Go doc | Tool descriptions | -- | -- |
| Dependencies | None | httpx | None | @modelcontextprotocol/sdk, zod | None | None |
| Output file | *.ts | *.py | *.go | *-mcp.ts | api-docs.md | openapi.json |
| Format | TypeScript | Python | Go | TypeScript | Markdown | JSON (OAS 3.1) |
| Generation | LLM | LLM | LLM | LLM | Deterministic IR transform | Deterministic IR transform |