SiteCallDevelopers

Client, CLI and MCP

One package for code, terminals and agents.

@sitecall/cli holds the typed REST client, webhook verification, and two programs: the sitecall CLI and the sitecall-mcp server. Node 20.3 or later, and any modern browser for the client.

The typed client

Every method maps to one operation of the reference, and its argument and result types come from the same contract SiteCall's routes validate with.

server.ts

import { createSiteCallClient, SiteCallApiError } from "@sitecall/cli";

const sitecall = createSiteCallClient({
  apiKey: process.env.SITECALL_API_KEY,
  externalWorkspaceId: "acme-42", // or workspaceId: SiteCall's id
});

const live = await sitecall.calls.list({ state: "live" });
await sitecall.calls.transfer(live.data[0].id, { target: { queueId }, warm: true });

try {
  await sitecall.calls.dial({ to: "+15125550123", from: { phoneNumberId }, agent: { externalUserId: "user-7" } });
} catch (error) {
  if (error instanceof SiteCallApiError && error.code === "caller_id_forbidden") {
    // error.status, error.message, error.callId, error.idempotencyKey
  }
}

What it does for you

As one user: the token hook

In a browser or a phone, pass getToken instead of a key. It runs before every request; refresh: true means SiteCall refused the last token (expired or revoked), so fetch a new one. The client retries that request once with it, under the same Idempotency-Key.

browser.ts

import { createSiteCallClient } from "@sitecall/cli";

const asUser = createSiteCallClient({
  workspaceId,
  getToken: async ({ refresh }) => (refresh || !cached ? (cached = await fetchToken()) : cached),
});
await asUser.emergencyLocations.resolve({ deviceId });

On a server acting as one user, createSessionTokenProvider mints tokens with your key and caches each until a minute before it expires:

import { createSessionTokenProvider, createSiteCallClient } from "@sitecall/cli";

const asDana = createSiteCallClient({
  externalWorkspaceId: "acme-42",
  getToken: createSessionTokenProvider({
    mint: (body) => sitecall.sessions.create(body),
    session: { externalWorkspaceId: "acme-42", externalUserId: "user-7", scopes: ["calls:*"] },
  }),
});

Webhooks

verifyWebhook checks a delivery's signature and timestamp and reads its event. See Webhooks.

The CLI

The CLI provisions with your own SiteCall login (an owner or admin of the company): it never needs a carrier, database or application key.

terminal

npx sitecall login       # a code to your phone or email
npx sitecall tools       # every tool and its JSON input schema
echo '{"workspaceId":"…"}' | npx sitecall activation_get   # JSON on stdin
npx sitecall numbers_quote quote.json                       # or a JSON file
npx sitecall logout

Provision in order: choose or create the company, confirm its facts, search and quote a number, buy it with the quote's exact confirmation, then submit texting registration. The CLI refuses a purchase without a quote it saved, and never buys a replacement number after a timeout. Sessions are stored privately under ~/.config/sitecall/.

The MCP server

Sign in with the CLI first, then point your MCP host at the server. It speaks stdio with the same provisioning tools and schemas; tokens and codes never appear in tool output.

mcp config

{
  "mcpServers": {
    "sitecall": { "command": "npx", "args": ["-y", "-p", "@sitecall/cli", "sitecall-mcp"] }
  }
}

The host must get the person's approval for the exact company, number and monthly price before it calls numbers_buy.