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.
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.
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(), andcall_model_chat()- Exponential backoff retry (503 only)
- Context manager lifecycle
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
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.
| 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 irreversiblebackup_recommended: whether the gateway advises taking a snapshot firstprincipal_levelandprincipal_role: resolved authority contextprincipal_capabilitiesandauth_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",
)
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.
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.