---
title: "Update a client"
method: PATCH
path: "/projects/{projectId}/clients/{client}"
tags: ["Clients"]
---

# Update a client

`PATCH /projects/{projectId}/clients/{client}`

Edit a client's display name and/or its config. Two ways to change the config: `config` replaces it wholesale, and `set` changes named fields over the config read inside the write transaction — prefer `set`, because a whole-config round-trip composed from a stale read reverts whatever landed in between.

Config edits require `expectedConfigId` and renames require `expectedName`. A stale token is `409 CONFLICT` whose `details` carries the current value: re-read the client and retry. A config edit that resolves to byte-identical settings writes nothing at all.

Guest callers are denied (a write).

## Path parameters

- `projectId` string, required
- `client` string, required

## Request body

- union — Edit a client. Provide at least one of `name`, `config` (whole-config replacement) or `set` (named fields); `config` and `set` are mutually exclusive. Config edits require `expectedConfigId` and renames require `expectedName`, so a concurrent edit is rejected rather than overwritten.
  - object
    - `name` string, required — New display name.
    - `expectedName` string — The `name` you last read for this client. REQUIRED whenever the request sends `name`: a rename does not rotate the config, so `expectedConfigId` cannot detect a concurrent one. A mismatch is `409 CONFLICT` carrying `details.currentName`.
    - `expectedConfigId` string — The `configId` you last read for this client. REQUIRED whenever the request changes the config (`config` or `set`): without it a write composed from a stale read silently reverts whatever landed in between. A mismatch is `409 CONFLICT` carrying `details.currentConfigId`.
    - `expectedImpact` ClientImpact — What a config edit to this client would follow. These are the DURABLE consumers that re-resolve the client's current config; past runs, per-turn traces and pinned eval-suite snapshots hold a config id and are unaffected. Direct playground and client-chat use follows the edit too and has no row to count.
      - `liveEnvironmentCount` integer, required — Non-archived project environments selecting this client.
      - `scenarioAttachmentCount` integer, required — Scenario attachments re-materialized inside the edit transaction.
      - `activeLegacyJourneyCount` integer, required — Active journeys with no environments that pin this client.
    - `config` object — Replacement client config v2. Replaces the config wholesale; use `set` to change named fields instead.
    - `set` ClientFieldSet — Named fields to change, applied over the client's current config INSIDE the write transaction. Absent always means keep. `null` means "make it go away", and what that means depends on the field: a required field resets to its documented default, an optional one clears to absent. Object-valued fields are whole-object replacements, not merges — to change a deep knob, read the client, overlay the sub-object, and send it back whole. `hostStyle`, `clientCapabilities`, `hostContext` and server membership are deliberately not settable here (use a whole-`config` replacement, or the servers operation).
      - `modelId` string — Model id the client pins. Value only — there is no `null`, and a blank string is refused: a client that pins a model cannot be edited into one that does not.
      - `systemPrompt` string, nullable — Send `null` to reset this field to its canonical default. Default: `""`.
      - `temperature` number, nullable — Send `null` to reset this field to its canonical default. Default: `0.7`.
      - `requireToolApproval` boolean, nullable — Send `null` to reset this field to its canonical default. Default: `false`.
      - `connectionDefaults` object, nullable — Send `null` to reset this field to its canonical default. Default: empty headers and the platform's default request timeout.
        - `headers` object, required
        - `requestTimeout` number, required
      - `respectToolVisibility` boolean, nullable — Send `null` to clear this field back to absent.
      - `progressiveToolDiscovery` boolean, nullable — Send `null` to clear this field back to absent.
      - `harness` 'claude-code' | 'codex' | 'null', nullable — Execution runtime selector. Send `null` to clear this field back to absent. Setting one requires the matching feature flag; clearing never does.
      - `computer` object, nullable — Send `null` to clear this field back to absent. Attaching one requires the computers feature flag; detaching never does.
        - `kind` 'personal', required
        - `toolset` 'bash'
        - `workdir` string
      - `builtInToolIds` string[], nullable — Send `null` to clear this field back to absent.
      - `skillSelection` object, nullable — `{ mode: "all-visible" }` or `{ mode: "explicit", skillIds: [...] }`. Send `null` to clear this field back to absent.
      - `modelVisibleMcpToolResults` object, nullable — Send `null` to clear this field back to absent.
      - `mcpToolResultImageRendering` object, nullable — Send `null` to clear this field back to absent.
      - `mcpProfile` object, nullable — Send `null` to clear this field back to absent.
      - `hostCapabilitiesOverride` object, nullable — Send `null` to clear this field back to absent.
      - `chatUiOverride` object, nullable — Send `null` to clear this field back to absent.
  - object
    - `name` string — New display name.
    - `expectedName` string — The `name` you last read for this client. REQUIRED whenever the request sends `name`: a rename does not rotate the config, so `expectedConfigId` cannot detect a concurrent one. A mismatch is `409 CONFLICT` carrying `details.currentName`.
    - `expectedConfigId` string — The `configId` you last read for this client. REQUIRED whenever the request changes the config (`config` or `set`): without it a write composed from a stale read silently reverts whatever landed in between. A mismatch is `409 CONFLICT` carrying `details.currentConfigId`.
    - `expectedImpact` ClientImpact — What a config edit to this client would follow. These are the DURABLE consumers that re-resolve the client's current config; past runs, per-turn traces and pinned eval-suite snapshots hold a config id and are unaffected. Direct playground and client-chat use follows the edit too and has no row to count.
      - `liveEnvironmentCount` integer, required — Non-archived project environments selecting this client.
      - `scenarioAttachmentCount` integer, required — Scenario attachments re-materialized inside the edit transaction.
      - `activeLegacyJourneyCount` integer, required — Active journeys with no environments that pin this client.
    - `config` object, required — Replacement client config v2. Replaces the config wholesale; use `set` to change named fields instead.
    - `set` ClientFieldSet — Named fields to change, applied over the client's current config INSIDE the write transaction. Absent always means keep. `null` means "make it go away", and what that means depends on the field: a required field resets to its documented default, an optional one clears to absent. Object-valued fields are whole-object replacements, not merges — to change a deep knob, read the client, overlay the sub-object, and send it back whole. `hostStyle`, `clientCapabilities`, `hostContext` and server membership are deliberately not settable here (use a whole-`config` replacement, or the servers operation).
      - `modelId` string — Model id the client pins. Value only — there is no `null`, and a blank string is refused: a client that pins a model cannot be edited into one that does not.
      - `systemPrompt` string, nullable — Send `null` to reset this field to its canonical default. Default: `""`.
      - `temperature` number, nullable — Send `null` to reset this field to its canonical default. Default: `0.7`.
      - `requireToolApproval` boolean, nullable — Send `null` to reset this field to its canonical default. Default: `false`.
      - `connectionDefaults` object, nullable — Send `null` to reset this field to its canonical default. Default: empty headers and the platform's default request timeout.
        - `headers` object, required
        - `requestTimeout` number, required
      - `respectToolVisibility` boolean, nullable — Send `null` to clear this field back to absent.
      - `progressiveToolDiscovery` boolean, nullable — Send `null` to clear this field back to absent.
      - `harness` 'claude-code' | 'codex' | 'null', nullable — Execution runtime selector. Send `null` to clear this field back to absent. Setting one requires the matching feature flag; clearing never does.
      - `computer` object, nullable — Send `null` to clear this field back to absent. Attaching one requires the computers feature flag; detaching never does.
        - `kind` 'personal', required
        - `toolset` 'bash'
        - `workdir` string
      - `builtInToolIds` string[], nullable — Send `null` to clear this field back to absent.
      - `skillSelection` object, nullable — `{ mode: "all-visible" }` or `{ mode: "explicit", skillIds: [...] }`. Send `null` to clear this field back to absent.
      - `modelVisibleMcpToolResults` object, nullable — Send `null` to clear this field back to absent.
      - `mcpToolResultImageRendering` object, nullable — Send `null` to clear this field back to absent.
      - `mcpProfile` object, nullable — Send `null` to clear this field back to absent.
      - `hostCapabilitiesOverride` object, nullable — Send `null` to clear this field back to absent.
      - `chatUiOverride` object, nullable — Send `null` to clear this field back to absent.
  - object
    - `name` string — New display name.
    - `expectedName` string — The `name` you last read for this client. REQUIRED whenever the request sends `name`: a rename does not rotate the config, so `expectedConfigId` cannot detect a concurrent one. A mismatch is `409 CONFLICT` carrying `details.currentName`.
    - `expectedConfigId` string — The `configId` you last read for this client. REQUIRED whenever the request changes the config (`config` or `set`): without it a write composed from a stale read silently reverts whatever landed in between. A mismatch is `409 CONFLICT` carrying `details.currentConfigId`.
    - `expectedImpact` ClientImpact — What a config edit to this client would follow. These are the DURABLE consumers that re-resolve the client's current config; past runs, per-turn traces and pinned eval-suite snapshots hold a config id and are unaffected. Direct playground and client-chat use follows the edit too and has no row to count.
      - `liveEnvironmentCount` integer, required — Non-archived project environments selecting this client.
      - `scenarioAttachmentCount` integer, required — Scenario attachments re-materialized inside the edit transaction.
      - `activeLegacyJourneyCount` integer, required — Active journeys with no environments that pin this client.
    - `config` object — Replacement client config v2. Replaces the config wholesale; use `set` to change named fields instead.
    - `set` ClientFieldSet, required — Named fields to change, applied over the client's current config INSIDE the write transaction. Absent always means keep. `null` means "make it go away", and what that means depends on the field: a required field resets to its documented default, an optional one clears to absent. Object-valued fields are whole-object replacements, not merges — to change a deep knob, read the client, overlay the sub-object, and send it back whole. `hostStyle`, `clientCapabilities`, `hostContext` and server membership are deliberately not settable here (use a whole-`config` replacement, or the servers operation).
      - `modelId` string — Model id the client pins. Value only — there is no `null`, and a blank string is refused: a client that pins a model cannot be edited into one that does not.
      - `systemPrompt` string, nullable — Send `null` to reset this field to its canonical default. Default: `""`.
      - `temperature` number, nullable — Send `null` to reset this field to its canonical default. Default: `0.7`.
      - `requireToolApproval` boolean, nullable — Send `null` to reset this field to its canonical default. Default: `false`.
      - `connectionDefaults` object, nullable — Send `null` to reset this field to its canonical default. Default: empty headers and the platform's default request timeout.
        - `headers` object, required
        - `requestTimeout` number, required
      - `respectToolVisibility` boolean, nullable — Send `null` to clear this field back to absent.
      - `progressiveToolDiscovery` boolean, nullable — Send `null` to clear this field back to absent.
      - `harness` 'claude-code' | 'codex' | 'null', nullable — Execution runtime selector. Send `null` to clear this field back to absent. Setting one requires the matching feature flag; clearing never does.
      - `computer` object, nullable — Send `null` to clear this field back to absent. Attaching one requires the computers feature flag; detaching never does.
        - `kind` 'personal', required
        - `toolset` 'bash'
        - `workdir` string
      - `builtInToolIds` string[], nullable — Send `null` to clear this field back to absent.
      - `skillSelection` object, nullable — `{ mode: "all-visible" }` or `{ mode: "explicit", skillIds: [...] }`. Send `null` to clear this field back to absent.
      - `modelVisibleMcpToolResults` object, nullable — Send `null` to clear this field back to absent.
      - `mcpToolResultImageRendering` object, nullable — Send `null` to clear this field back to absent.
      - `mcpProfile` object, nullable — Send `null` to clear this field back to absent.
      - `hostCapabilitiesOverride` object, nullable — Send `null` to clear this field back to absent.
      - `chatUiOverride` object, nullable — Send `null` to clear this field back to absent.

## Response `200`

The updated client settings.

- ClientDetail — A client plus its resolved config (model, capabilities, host context, MCP profile) and the read-backs an editor needs.
  - `id` string, required
  - `name` string, required
  - `configId` string — The concurrency token — see `Client.configId`.
  - `config` object, required — Client config v2 DTO. Opaque object; shape mirrors the inspector's client editor.
  - `ownerScope` object, nullable, required
  - `hasComputer` boolean
  - `createdAt` number — Unix epoch milliseconds.
  - `updatedAt` number — Unix epoch milliseconds.
  - `impact` ClientImpact — What a config edit to this client would follow. These are the DURABLE consumers that re-resolve the client's current config; past runs, per-turn traces and pinned eval-suite snapshots hold a config id and are unaffected. Direct playground and client-chat use follows the edit too and has no row to count.
    - `liveEnvironmentCount` integer, required — Non-archived project environments selecting this client.
    - `scenarioAttachmentCount` integer, required — Scenario attachments re-materialized inside the edit transaction.
    - `activeLegacyJourneyCount` integer, required — Active journeys with no environments that pin this client.

## Other responses

- `400` — Malformed body or parameters.
- `401` — Missing, invalid, revoked, or orphaned key (`UNAUTHORIZED`) — or the **target MCP server** needs an OAuth grant (`OAUTH_REQUIRED`), which is a property of the server, not your key.
- `403` — Key is valid but not allowed to do this.
- `404` — Unknown project, server, or resource.
- `409` — The resource is not in a state that accepts this write — a stale `expectedRevision`, a duplicate name, or an environment that cannot currently be launched. The request was well-formed; re-read the resource and retry.
- `429` — Per-key rate limit exceeded (60 requests/minute sustained, bursts up to 10). Honor `Retry-After` and back off with jitter.
- `500` — Something failed on MCPJam's side.
- `502` — Could not connect to the target MCP server.

## Changes

- **2026-08-26** `7e8a9aa1d828` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/mcpjam/apis/mcpjam-api/changes/projects/:projectId/clients/:client/patch.md)

---

[API](https://skmtc.dev/mcpjam/apis/mcpjam-api.md) · [All operations](https://skmtc.dev/mcpjam/apis/mcpjam-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/mcpjam/mcpjam-api/revisions/c628a0e95b06/schema)
