PRECINCT SDKs

First-class SDK support in Python and Go for integrating agents with the PRECINCT gateway. Both SDKs handle SPIFFE identity injection, structured error mapping, metadata-aware calls, and gateway communication automatically.

First Time Integrating?

The Integration Guide walks through identity registration, tool setup, and policy configuration before you start using the SDK.

Overview

PRECINCT provides two official SDKs that mirror each other's semantics across languages. Both SDKs wrap the gateway's JSON-RPC API and provide idiomatic interfaces for tool invocation, error handling, and identity management.

Roadmap: Rust, TypeScript, and Elixir SDKs are planned. Follow the GitHub repository for updates.

Python SDK: mcp_gateway_sdk

Synchronous Python client built on httpx. Includes a unified GatewayError, runtime helpers for PydanticAI/DSPy/LangGraph, and OpenTelemetry integration.

  • Python 3.13
  • GatewayClient, call(), call_rpc(), and call_model_chat()
  • Exponential backoff retry (503 only)
  • Context manager lifecycle

Full Python SDK Reference →

Go SDK: mcpgateway

Idiomatic Go client with functional options, context-based cancellation, and zero external dependencies beyond google/uuid.

  • Go 1.26.1 (supported baseline)
  • Auto-detects protocol methods vs tool names
  • Goroutine-safe with connection pooling
  • mTLS via custom http.Client
  • SPIKE token helpers: BuildSPIKETokenRef, BuildSPIKETokenRefWithScope

Full Go SDK Reference →

Error Code Mapping

Both SDKs preserve the gateway's structured deny codes. Python raises GatewayError; Go returns *mcpgateway.GatewayError. Inspect the code / Code field to branch on specific outcomes.

SDK error type mapping for gateway deny codes
Gateway Code Layer Python Surface Go Surface
spiffe_auth_required 3 GatewayError(code="spiffe_auth_required") *mcpgateway.GatewayError{Code: "spiffe_auth_required"}
tool_not_in_registry 5 GatewayError(code="tool_not_in_registry") *mcpgateway.GatewayError{Code: "tool_not_in_registry"}
tool_hash_mismatch 5 GatewayError(code="tool_hash_mismatch") *mcpgateway.GatewayError{Code: "tool_hash_mismatch"}
authz_policy_denied 6 GatewayError(code="authz_policy_denied") *mcpgateway.GatewayError{Code: "authz_policy_denied"}
dlp_credentials_detected 7 GatewayError(code="dlp_credentials_detected") *mcpgateway.GatewayError{Code: "dlp_credentials_detected"}
stepup_required 9 GatewayError(code="stepup_required") *mcpgateway.GatewayError{Code: "stepup_required"}
rate_limit_exceeded 11 GatewayError(code="rate_limit_exceeded") *mcpgateway.GatewayError{Code: "rate_limit_exceeded"}
circuit_breaker_open 12 GatewayError(code="circuit_breaker_open") *mcpgateway.GatewayError{Code: "circuit_breaker_open"}

Response Metadata for Safer Agents

Both SDKs expose metadata-aware calls so applications can react to gateway guidance before taking risky actions. Python provides call_with_metadata(); Go provides CallWithMetadata().

What You Get Back

  • reversibility: reversible, costly_reversible, partially_reversible, or irreversible
  • backup_recommended: whether the gateway advises taking a snapshot first
  • principal_level and principal_role: resolved authority context
  • principal_capabilities and auth_method: caller capability and authentication hints

Why It Matters

Agents can pause before destructive actions, request operator confirmation, or surface better UX instead of treating every successful tool call as equally safe. Denied calls also preserve response metadata on the returned GatewayError.

Python

result = client.call_with_metadata("delete_resource", id="acct_123")
if result.meta.backup_recommended:
    snapshot_state()
print(result.meta.reversibility)

Go

cr, err := client.CallWithMetadata(ctx, "delete_resource", map[string]any{
    "id": "acct_123",
})
if err != nil {
    return err
}
if cr.Meta.BackupRecommended {
    snapshotState()
}
fmt.Println(cr.Meta.Reversibility)

Transport and Identity

Both SDKs require you to supply a SPIFFE ID string to the client constructor. In local and development flows, that value is sent as the X-SPIFFE-ID header. In production, authentication should come from the underlying mTLS transport while the constructor still receives the caller's SPIFFE ID for correlation and request metadata.

Python

# Dev/local usage: explicit SPIFFE ID header
client = GatewayClient(
    url="http://localhost:9090",
    spiffe_id="spiffe://poc.local/agents/example/dev",
)

Go

// Dev/local usage: explicit SPIFFE ID header
client := mcpgateway.NewClient(
    "http://localhost:9090",
    "spiffe://poc.local/agents/example/dev",
)
Production Mode

The shipped SDKs do not auto-discover SVIDs from the SPIRE Workload API. For production gateways, provide a preconfigured httpx.Client or *http.Client with mTLS transport wiring.

Installation

Python

uv add ./sdk/python

See the Python SDK installation guide for optional dependency groups.

Go

go get github.com/precinct-dev/precinct/sdk/go/mcpgateway

See the Go SDK installation guide for local development setup.

Version Note

Both SDKs are part of the PRECINCT proof-of-concept and are versioned alongside the main repository. For production use, pin to a specific commit or tag.