SDK Overview
The Leash SDK gives every app you deploy four things from the platform — env vars, pre-built integrations, custom OAuth, and custom MCP. Available for TypeScript, Python, Go, Ruby, Rust, and Java.
The four primitives
Org owners register things once on the dashboard — Slack OAuth client, internal MCP URL, env vars. Every app in the org gets typed access through the SDK. No client_secret in your code, no refresh tokens to handle, no MCP boilerplate.
Env vars
Database URLs, API keys, the boring stuff. Stored at the org level (or pulled from your existing Doppler / 1Password / GCP Secret Manager). Apps fetch at runtime.
await client.getEnv('DATABASE_URL')Pre-built integrations
Gmail, Google Calendar, Google Drive. The user logs in once on leash.build; every app gets typed access on their behalf.
await client.gmail.listMessages({ maxResults: 5 })Custom OAuth providers
Bring your own OAuth client (Slack, Notion, your company SSO). Leash holds client_id/secret and refreshes tokens; your app gets a fresh access token to call the third-party API directly.
await client.getAccessToken('slack')Custom MCP servers
Bring your own MCP endpoint (internal tools, third-party MCPs we haven’t pre-built). Leash holds the bearer token; your app gets {url, headers} to plug straight into an MCP client.
await client.getCustomMcpConfig('acme-tools')Install
$ npm install @leash/sdk
All four, end-to-end
One client, all four primitives. The exact same shape across every supported language.
import { LeashIntegrations } from '@leash/sdk/integrations'const client = new LeashIntegrations({apiKey: process.env.LEASH_API_KEY, // create at /dashboard/organization → API keys})// 1. Env var (resolves through your configured secret source)const dbUrl = await client.getEnv('DATABASE_URL')// 2. Pre-built integrationconst messages = await client.gmail.listMessages({ maxResults: 5 })// 3. Custom OAuth — fresh token for any provider you've registeredconst slackToken = await client.getAccessToken('slack')// 4. Custom MCP — { url, headers } including bearer Authorizationconst mcp = await client.getCustomMcpConfig('acme-tools')// then plug { mcp.url, mcp.headers } into your MCP client of choice
Your .env collapses to one line
Once you're on Leash, the only secret your app's local .env actually needs is LEASH_API_KEY. Everything else — database URLs, third-party API keys, OAuth tokens, MCP bearer tokens — comes through the SDK at runtime.
# .env (yes, this is the whole thing) LEASH_API_KEY=lsk_live_...
No more .env.example drift. No more “did we set DATABASE_URL in staging?”. The org owner configures secrets once on the dashboard; every app picks them up.
What it deliberately doesn't do
- Doesn't proxy MCP traffic. The SDK hands you URL + headers; your app calls the MCP directly. Leash isn't in the request path.
- Doesn't force you to use Leash for secrets. Bring your own secret source (Doppler, 1Password, GCP Secret Manager).
getEnvresolves through whichever the org configured. - Doesn't hide refresh. Token refresh happens transparently inside
getAccessToken— no per-app handler to write, but no surprise either.
Auth
Every SDK call needs an API key (which app is calling) plus a user identity (which user's data to use). On apps deployed to Leash, the user identity is the JWT cookie set by the platform — nothing extra to wire. From a server outside Leash, pass an authToken on the client.
For more, see Connections and Error handling.