Skip to main content
Salty — the CRM built for AI agents (trysalty.com) — exposes an MCP server at $SALTY_MCP/mcp. Set the env var to match your deployment:
Any MCP-compliant client — Claude.ai web, ChatGPT, Cursor, Windsurf, Claude Desktop — can connect, authorize via OAuth, and call exactly 15 tools.
Using Claude Code? Skip the manual setup — install the Salty plugin: /plugin marketplace add ankshvayt/salty-plugin then /plugin install salty@salty.
Built on @modelcontextprotocol/sdk 1.x with WebStandardStreamableHTTPServerTransport — the Streamable HTTP transport from the 2025-06 MCP spec. Single endpoint (POST /mcp), stateless mode, plain JSON responses.

The 15 tools

Tight by design — more tools = bigger context window = worse agent performance. Notably absent: delete_* tools. Deletion is destructive — agents go through the REST API or CLI where a human can review. This is a deliberate safety choice. Every tool description ends with Returns errors with code and message; respect rate limit headers. Input schemas avoid oneOf/anyOf at the top level (breaks Claude’s MCP client).

How clients connect

You don’t configure anything per-client beyond pointing it at the MCP URL. The discovery + OAuth flow is automatic:
  1. The client POSTs /mcp with no auth → server returns 401 + WWW-Authenticate: Bearer resource_metadata=….
  2. The client GETs the well-known protected-resource metadata to discover the auth server (it’s the same host as $SALTY_API).
  3. The client GETs /.well-known/oauth-authorization-server to discover the token + registration endpoints.
  4. The client POSTs /oauth/register (RFC 7591 dynamic client registration) → gets a client_id.
  5. The client redirects the user’s browser to /oauth/authorize?…&code_challenge=… → user lands on Salty’s consent page → clicks Approve → browser returns to client with ?code=….
  6. The client POSTs /oauth/token with code + code_verifier → gets salty_oat_… access token (24-hour lifetime) + a rotating refresh token (180-day).
  7. The client retries POST /mcp with Authorization: Bearer salty_oat_… → server forwards the bearer to the Salty API and returns the tool result.
See Concepts → Authentication for the full OAuth surface.

Adding Salty to Claude.ai (web)

Settings → Connectors → Add custom connector. URL: $SALTY_MCP/mcp. Click Connect; the OAuth flow above runs in a popup. Done.

Adding Salty to Claude Desktop / Cursor

These clients only speak stdio MCP, so we bridge through mcp-remote — a stdio↔HTTP shim that forwards every JSON-RPC call to $SALTY_MCP/mcp. Two ways to authenticate. Pick the one that matches your use case. The client runs the full PKCE dance on first connect. mcp-remote opens a browser, you approve at /oauth/consent, the salty_oat_… token is cached in ~/.mcp-auth. Subsequent launches are silent.
Skip the browser flow by passing a long-lived sk_live_… key via --header. The MCP server forwards any bearer to the Salty API, which accepts all three kinds — sk_live_…, salty_oat_…, and Supabase JWTs (see Authentication).
Why pick this:
  • No ~/.mcp-auth cache to invalidate if you reset local DB or rotate OAuth client rows.
  • One value to swap (env.SALTY_API_KEY) — useful if a dev workspace gets reseeded.
  • Works in non-interactive contexts where there’s no browser to open.
Mint a key from the admin UI’s API keys page or POST /api-keys. Fully quit the client (⌘Q on macOS) after editing the config — most MCP clients only re-read on cold start.

Sample tool call

After the client is authorized, calls look like JSON-RPC 2.0:
Response (truncated):

What MCP inherits from the REST API

Every tool forwards to the corresponding REST endpoint with the user’s bearer token, so MCP gets:
  • RLS — agents can only touch their own workspace
  • Rate limits — per-plan sustained + burst
  • Usage capsalty_oat_… tokens count as agent traffic
  • Idempotency — pass Idempotency-Key in the tool’s HTTP layer
  • Audit log — every call lands in api_call_log
No special MCP-only code paths to maintain. The 15 tools are a thin shim over the same surface that drives curl and the SDK.