Connect a client

A token with the scopes your agent needs, then Claude Code, Claude Desktop, any other MCP client, or curl.

Create a token

Every client connects with an API token (Authentication). Give each client its own, so revoking one leaves the others working.

  1. In the portal, open Settings → API tokens.

  2. Under New token, name it for the client and the machine it runs on, such as Claude Code, laptop.

  3. Set a level for each resource the client's tools need:

    Tools Resource Level
    os.list_runs, os.get_run runs read
    os.list_blockers blockers read
    os.list_open_gates gates read

    Leave everything else at none. Every tool reads, so no tool needs write, and gates:write would let the token decide gates over the API. You can only grant scopes you hold yourself.

  4. Create, and copy the token. It starts zhos_, and it is shown once.

A token without a scope a tool needs can still connect: that tool's calls are refused, naming the scope. Add it later with Edit scopes on the token. The secret does not change, so nothing in the client does.

Connect your client

The server is at https://mcp.zerohuman.com/v1/mcp. It speaks Streamable HTTP, and reads the token from one header:

Authorization: Bearer zhos_…

Claude Code

claude mcp add --transport http zerohuman https://mcp.zerohuman.com/v1/mcp \
  --header "Authorization: Bearer zhos_…"

zerohuman is the name Claude Code knows the server by; choose any. The server is added for the current project only. Add --scope user to have it in every project.

To share the server with everyone working in a repository without sharing a token, add it to the project's .mcp.json with the token read from each person's environment:

{
  "mcpServers": {
    "zerohuman": {
      "type": "http",
      "url": "https://mcp.zerohuman.com/v1/mcp",
      "headers": { "Authorization": "Bearer ${ZEROHUMAN_TOKEN}" }
    }
  }
}

Each person sets ZEROHUMAN_TOKEN to their own token before starting Claude Code.

Claude Desktop

Claude Desktop's own config file starts local programs, so a remote server that takes a header is reached through a bridge: mcp-remote, an open-source bridge that runs on your computer and needs Node.js 18 or later. If Claude offers you request headers, a custom connector needs no bridge.

  1. In Claude Desktop, open Settings → Developer → Edit Config.

  2. Add the server to mcpServers:

    {
      "mcpServers": {
        "zerohuman": {
          "command": "npx",
          "args": [
            "-y",
            "mcp-remote",
            "https://mcp.zerohuman.com/v1/mcp",
            "--header",
            "Authorization:${AUTH_HEADER}"
          ],
          "env": { "AUTH_HEADER": "Bearer zhos_…" }
        }
      }
    }
    

    Keep the header written as it is here, with no space after the colon and the token in env: Claude Desktop on Windows breaks an argument that contains a space.

  3. Quit Claude Desktop completely, and open it again.

The token stays on your computer, in that file.

Claude, with a custom connector

If the Add custom connector dialog in Claude shows Request headers (Anthropic offers it to some organisations while it is in beta), you can add the server as a custom connector instead, with no bridge. Enter the server URL, choose No sign-in, and add the header authorization with the value Bearer zhos_…, including Bearer and the space.

Claude stores the token and sends it from Anthropic's servers. A connector an Owner adds for a Team or Enterprise organisation is shared: everyone who uses it acts with that one token, so give it only what everyone may read.

Planned

A custom connector will be able to sign in with Zero Human instead, with no token to paste. See Connected apps.

Any other MCP client

Give it:

  • the URL, https://mcp.zerohuman.com/v1/mcp;
  • the transport: Streamable HTTP, which some clients call "HTTP" or streamable-http;
  • the header Authorization: Bearer zhos_….

A client that only starts local programs can reach the server through mcp-remote, as Claude Desktop does above. A client that can only sign in to remote servers, with no way to send a header, cannot connect yet.

curl

Every request is a POST of one JSON-RPC message, with the token and Content-Type: application/json. There is no session: each request stands alone, so you can call a tool without initialising first. The server answers in JSON, never an event stream, so no Accept header is needed.

Initialise:

curl https://mcp.zerohuman.com/v1/mcp \
  -H "Authorization: Bearer $ZEROHUMAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
{"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"zerohuman-os","version":"…"}},"jsonrpc":"2.0","id":1}

List the tools:

curl https://mcp.zerohuman.com/v1/mcp \
  -H "Authorization: Bearer $ZEROHUMAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

Each tool comes with its name, a description ending in the scope it needs, and the JSON Schema of its arguments.

Call one:

curl https://mcp.zerohuman.com/v1/mcp \
  -H "Authorization: Bearer $ZEROHUMAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"os.list_runs","arguments":{"status":"failed","limit":5}}}'

The result holds one text item: the API's JSON answer, as a string. A refusal is a result too, with "isError": true and the reason as its text (Errors).

If you send an MCP-Protocol-Version header, it has to name a version the server supports; leave it out and the server assumes one.

Check it works

  1. The server is up. https://mcp.zerohuman.com/v1/health answers {"ok":true, …}, with no token.
  2. The client connected. In Claude Code, claude mcp list shows the server connected, and /mcp lists its tools. In Claude Desktop, the server is listed under Connectors in a chat's + menu.
  3. The token works. Only a tool call proves it: connecting and listing tools do not check the token. Ask your agent what is blocked in your enterprise, or call os.list_open_gates with curl. An answer, even an empty list, means the token and its scope are good.
  4. The portal agrees. Reload Settings → API tokens: the token's Last used shows your call, where it said never before.

If a step fails, Errors says what each refusal means.

Disconnect

  • Revoke the token on Settings → API tokens. It stops at once: the client may still connect and list tools, but every call is refused. The token stays listed, revoked.
  • Rotate the token to replace a secret you think has leaked. The old one stops at once; put the new one in the client's header.
  • Remove the server from the client: claude mcp remove zerohuman in Claude Code, or delete its entry from Claude Desktop's config file and restart Claude Desktop.