MCP TypeScript SDK

@autociso/mcp-client is the first-party TypeScript SDK for the AutoCISO MCP server. It gives you a typed method per tool, autocomplete, and built-in retries — no raw JSON-RPC.

Install

npm install @autociso/mcp-client

Create a client

baseUrl is required — there is no default, because AutoCISO runs in multiple environments. Pass the full URL including /mcp:

import { AutocisoMcpClient } from '@autociso/mcp-client';

const client = new AutocisoMcpClient({
baseUrl: 'https://api.autociso.io/mcp',
token:   process.env.AUTOCISO_MCP_TOKEN!, // mcp:read scope
});

First call

Every tool maps to a namespaced, camelCase method. Here’s posture_summary:

import { AutocisoMcpClient } from '@autociso/mcp-client';

const client = new AutocisoMcpClient({
baseUrl: 'https://api.autociso.io/mcp',
token:   process.env.AUTOCISO_MCP_TOKEN!,
});

const posture = await client.posture.summary();
console.log('Overall score:', posture.overallScore);

const stale = await client.access.staleAccounts();
console.log('Stale accounts:', stale.length);

Results are PII-masked — emails appear as a***@domain.com and personal names are redacted (to resolve an employeeId to a name, see Employee identity):

{
  "overallScore": 72,
  "staleAccounts": 14,
  "openRisks": 6,
  "isoGapsOpen": 23,
  "topConcern": "14 stale accounts pending review"
}

Typed results

Methods for typed tools return ToolResult<XResult>, for example ToolResult<UarStatusResult>; the .data you read is now typed. Tools without a published schema stay unknown. The client reads structuredContent when the server sends it and falls back to the text block otherwise.

If a result does not match its type the SDK throws ResultShapeError. It names the tool and the received typeof only, never values. The client no longer runs the upstream MCP client’s schema validation, which could put result values in error text.

One type-level change: casting .data straight to an unrelated type, such as res.data as MyType, now fails to compile with TS2352. Cast through unknown (res.data as unknown as MyType) or use the generated result type.

Patterns

  • Typed method per tool. client.access.staleAccounts(), client.risk.get({ id }), client.iso.gapStatus() — autocomplete shows every tool and its arguments. See the Tool Catalog for the full list.
  • No org_id, ever. Your org is bound to the token on the server (see Org binding). The method signatures don’t accept an org argument — there’s no way to query another tenant. This is by design.
  • Retries on reads. Idempotent read calls retry automatically on 429 and transient errors with exponential backoff and jitter (capped at ~3 attempts).
  • Writes are not auto-retried. There are five write tools (risk_create_draft, iso_audit_simulate, supplier_questionnaire_clone, supplier_questionnaire_update_question, supplier_questionnaire_update_option), for example client.risk.createDraft({ title }). None is ever retried automatically: the server has no idempotency key, so a blind retry could create a duplicate or spend a second AI request.
  • Timeout override. Pass a per-call timeout if a tool is slow:
const risks = await client.risk.registerList({ timeoutMs: 10_000 });
  • callRaw escape hatch. For a tool the typed surface doesn’t cover yet, call it by name. The result is untyped (unknown):
const raw = await client.callRaw('audit_trail_search', { limit: 25, offset: 0 });
// raw is unknown — validate before use

Error handling

Tool failures surface as typed exceptions (e.g. AutocisoScopeError, AutocisoRateLimitError). See MCP Errors and Retries for the full code-to-exception mapping and retry behavior.

Last reviewed: 2026-10-14

Was this page helpful?

Esc