# MCP TypeScript SDK
URL: https://docs.autociso.io/developers/mcp/typescript-sdk/
Description: Install @autociso/mcp-client and make your first typed MCP tool call from Node.

`@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

```bash
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`:

**TypeScript**

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

**Warning — Treat your token like a password**

Read the token from the `AUTOCISO_MCP_TOKEN` environment variable rather than inlining it. Never commit a real token to source control; revoke it from **user menu → API Tokens** if exposed (see [API tokens](https://docs.autociso.io/developers/api-tokens/)).

## First call

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

**TypeScript**

```typescript
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](https://docs.autociso.io/developers/employee-identity/)):

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

## Typed results

Methods for typed tools return `ToolResult`, for example `ToolResult`; 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](https://docs.autociso.io/developers/mcp/tools/) for the full list.
- **No `org_id`, ever.** Your org is bound to the token on the server (see [Org binding](https://docs.autociso.io/developers/mcp/authentication/#org-binding--no-org_id-from-the-client)). 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:

**TypeScript**

```typescript
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`):

**TypeScript**

```typescript
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](https://docs.autociso.io/developers/mcp/errors/) for the full code-to-exception mapping and retry behavior.
