SDK

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')
Read

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 })
Read

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')
Read

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')
Read

Install

Terminal

$ 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 integration
const messages = await client.gmail.listMessages({ maxResults: 5 })
// 3. Custom OAuth — fresh token for any provider you've registered
const slackToken = await client.getAccessToken('slack')
// 4. Custom MCP — { url, headers } including bearer Authorization
const 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). getEnv resolves 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.