> ## Documentation Index
> Fetch the complete documentation index at: https://docs.humanos.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Server

> Connect AI assistants to Humanos through the Model Context Protocol for real-time authorization and mandate management.

Humanos exposes a remote [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that lets AI assistants interact with your organization's agents, mandates, and authorization flows directly from the tools they already use.

<div className="hm-tip">
  **Endpoint:** `https://mcp.humanos.tech`
</div>

## What it does

The Humanos MCP server gives AI clients secure, scoped access to the Humanos platform. Through it, an assistant can:

* Register and inspect agents affiliated with your organization
* Request, poll, and manage mandates on behalf of an agent
* Verify tool calls against a mandate's policy and report outcomes
* Browse an agent's signed actor chain and cryptographic snapshots
* Propose new actions for your organization to publish

Authentication follows the same two paths as the REST API: **organization API keys** (with HMAC-signed requests) or **OAuth access tokens** issued by the Humanos authorization server.

## Supported clients

Any MCP-compatible client can connect. The following have been tested:

* Claude Code
* Claude Desktop
* Cursor
* VS Code (with GitHub Copilot)
* Grok
* ChatGPT Desktop
* Windsurf
* Codex CLI

## Setup

Pick the tab that matches your client.

<Tabs>
  <Tab title="Claude Code">
    Add the Humanos MCP server from your terminal:

    ```bash theme={"dark"}
    claude mcp add --transport http humanos https://mcp.humanos.tech
    ```

    Then start Claude Code and authenticate the connection:

    ```bash theme={"dark"}
    claude
    ```

    Inside the session, run `/mcp` to confirm the server is connected and list the available tools.
  </Tab>

  <Tab title="Claude Desktop">
    <Steps>
      <Step title="Open Settings">
        In Claude Desktop, open the sidebar and go to **Settings**.
      </Step>

      <Step title="Add a connector">
        Navigate to **Connectors** and select **Add custom connector**.
      </Step>

      <Step title="Configure the server">
        Fill in the following:

        | Field | Value |
        | - | - |
        | **Name** | Humanos |
        | **URL** | `https://mcp.humanos.tech` |
      </Step>

      <Step title="Authorize">
        Follow the OAuth prompt to grant access to your Humanos organization.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Cursor">
    Add the following to your `.cursor/mcp.json` file (project-level or global):

    ```json theme={"dark"}
    {
      "mcpServers": {
        "humanos": {
          "url": "https://mcp.humanos.tech"
        }
      }
    }
    ```

    Restart Cursor. When the server shows **Needs login**, click the prompt to authorize with your Humanos account.
  </Tab>

  <Tab title="VS Code">
    <Steps>
      <Step title="Open the Command Palette">
        Press `Cmd+Shift+P` (macOS) or `Ctrl+Shift+P` (Windows/Linux).
      </Step>

      <Step title="Add the MCP server">
        Run **MCP: Add Server**, select **HTTP**, and enter:

        | Field | Value |
        | - | - |
        | **URL** | `https://mcp.humanos.tech` |
        | **Name** | Humanos |

        Choose **Global** or **Workspace** depending on your needs.
      </Step>

      <Step title="Authorize">
        Open the Command Palette again, run **MCP: List Servers**, select **Humanos**, and click **Start Server**. Complete the OAuth sign-in when prompted.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Windsurf">
    Add to your `mcp_config.json`:

    ```json theme={"dark"}
    {
      "mcpServers": {
        "humanos": {
          "serverUrl": "https://mcp.humanos.tech"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Codex CLI">
    ```bash theme={"dark"}
    codex mcp add humanos --url https://mcp.humanos.tech
    ```

    When you start Codex, the CLI will detect OAuth support and open a browser window to authorize the connection.
  </Tab>
</Tabs>

## Verifying the connection

Once connected, ask your assistant to run the `server_info` tool. A successful response returns the server's identity, the MCP protocol version, and the authenticated subject, confirming that authentication and transport are working.

## Authentication

The MCP server accepts two credential types:

| Credential | How it works | Best for |
| - | - | - |
| **Organization API key** | HMAC-SHA256 signed requests, same as the [REST API](/essentials/authentication) | Server-to-server integrations, SDK agents |
| **OAuth access token** | Issued by the Humanos authorization server via the standard OAuth flow | Interactive MCP clients (Claude, Cursor, etc.) |

OAuth clients discover the authorization server automatically through the [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728) protected-resource metadata at `https://mcp.humanos.tech/.well-known/oauth-protected-resource`.

## Security considerations

* **Always verify the endpoint.** Confirm you are connecting to `https://mcp.humanos.tech`, never a third-party proxy or relay.
* **Scope is enforced server-side.** Every query is scoped to your authenticated organization. A DID outside your scope is indistinguishable from one that does not exist.
* **Enable human-in-the-loop confirmation.** Most MCP clients support a confirmation step before executing tools. Keep it enabled, especially for tools that create or modify mandates.
* **Review tool permissions.** When connecting through a new client, audit which tools are exposed and what data each one can access.

## Tools

**18 tools** registered on the Humanos MCP connector (v0.3.0).

### server\_info

**Title:** Check your connection

**Description:** Check your connection to Humanos. Returns the server version, your authenticated identity, what this credential can do, and which tools are available. No arguments needed.

**Annotations:** `readOnly`

**Parameters:**
None

***

### onboard

**Title:** Start here

**Description:** ALWAYS call this FIRST when you connect to Humanos, before any other tool. It detects your progress and returns the exact next step. Call it again after each step.

**Annotations:** `readOnly`

**Parameters:**
None

***

### list\_agents

**Title:** List agents

**Description:** List the agents registered under your organization, newest first, one page at a time. `totalPages` says how many pages there are; ask for the next with `pageIndex`.

**Annotations:** `readOnly`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `pageIndex` | `integer` | No | Zero-based page; 0 holds the newest agents. *(min: 0)* |
| `pageSize` | `integer` | No | Agents per page (5–100). *(min: 5, max: 100)* |

***

### get\_events

**Title:** Get event history

**Description:** Get the event history of an actor — an agent, an organization or a person — or of a mandate, by its credential URN, oldest first, one page at a time. Each event is cryptographically linked to the previous one. Use this when you need the audit trail.

**Annotations:** `readOnly`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `string` | No | Whose chain: an actor DID — an agent, an organization or a person, e.g. did:key:z6Mk… — or a mandate’s credential URN, e.g. urn:via:credential:… *(minLength: 1, maxLength: 512)* |
| `did` | `string` | No | An actor DID, as `id` takes it — accepted while clients move to `id`. Give `id` or `did`, not both. *(minLength: 1, maxLength: 512)* |
| `pageIndex` | `integer` | No | Zero-based page; 0 holds the oldest events. *(min: 0)* |
| `pageSize` | `integer` | No | Events per page (5–100). *(min: 5, max: 100)* |
| `chain` | `string` | No | A retired actor merged into this one (its DID, the `id` get\_actor's retiredActors gives it): page THAT chain instead. Omit for this actor's own chain; a credential has none. *(minLength: 1, maxLength: 512)* |

***

### get\_actor

**Title:** Get actor details

**Description:** Get an actor — an agent, an organization or a person: its VIAActor record under `record` (status, keys, verification level, accreditation, aliases and, for an agent, the organization it acts for; null while its registration is queued), the date of its last event, `pending` — true while an event of it is accepted and not yet on its chain, which the record already shows — and the actors merged into it. Use this to check an actor before interacting with it.

**Annotations:** `readOnly`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `did` | `string` | Yes | The DID of an actor — an agent, an organization or a person, e.g. did:key:z6Mk… *(minLength: 1, maxLength: 512)* |

***

### challenge

**Title:** Get a verification nonce

**Description:** Get a single-use nonce before calling verify or report\_outcome. Required before EVERY verification or outcome report; each nonce can only be used once. Requires an organization API key.

**Annotations:** `readOnly`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `mandateId` | `string` | Yes | The mandate URN, e.g. urn:via:credential:… *(minLength: 1, maxLength: 512)* |

***

### verify

**Title:** Verify a tool call against a mandate

**Description:** Check whether an agent is allowed to call a specific tool with specific parameters under a mandate. Returns one of three answers:

* **allow**: proceed with the tool call, then report the outcome with report\_outcome.
* **deny**: the call is not permitted under this mandate. Do not retry.
* **rechallenge**: the person must co-approve this specific call. Show them the `stepUp.approveLink`, poll stepup\_status until approved, then call verify again with the same parameters plus `stepUpId`.
  For custodial agents (registered with no key), omit `pop` as the platform signs automatically.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: false`, `openWorldHint: false`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `mandateId` | `string` | Yes | The mandate URN, e.g. urn:via:credential:… *(minLength: 1, maxLength: 512)* |
| `tool` | `string` | Yes | The tool the agent wants to call *(minLength: 1, maxLength: 256)* |
| `params` | `Record<string, unknown>` | Yes | The full parameters for this tool call, including the `tool` name |
| `pop` | `string` | No | Proof-of-possession JWT. Omit for custodial agents (the platform signs automatically) *(minLength: 1, maxLength: 16384)* |
| `stepUpId` | `string` | No | The step-up id from a previous rechallenge, after the person approved it *(minLength: 1, maxLength: 64)* |

***

### stepup\_status

**Title:** Check step-up approval status

**Description:** Check whether a person has approved a step-up request. Returns: pending, approved, declined, expired, or consumed. After 'approved', call verify again with the same parameters plus the stepUpId.

**Annotations:** `readOnly`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `string` | Yes | The step-up id from the rechallenge reply *(minLength: 1, maxLength: 64)* |

***

### report\_outcome

**Title:** Report tool call result

**Description:** After verify allowed a tool call, report whether it succeeded or failed. This completes the verify-then-act cycle: call verify first, execute the tool, then report here. For custodial agents, omit `pop` as the platform signs automatically.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: false`, `openWorldHint: false`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `mandateId` | `string` | Yes | The mandate URN, e.g. urn:via:credential:… *(minLength: 1, maxLength: 512)* |
| `decisionEventId` | `string` | Yes | The decisionEventId verify returned *(minLength: 1, maxLength: 512)* |
| `outcome` | `"completed" \| "failed"` | Yes | |
| `error` | `string` | No | Error message when outcome is "failed" *(maxLength: 4096)* |
| `pop` | `string` | No | Proof-of-possession JWT. Omit for custodial agents (the platform signs automatically) *(minLength: 1, maxLength: 16384)* |

***

### get\_mandate

**Title:** Get agent mandates

**Description:** Get all active mandates for an agent. Each comes in the credential’s shape — its status, the uses it has left (`executionsRemaining`) and the signed VC under `w3cCredential` (again under `mandate`, the name earlier clients read) — with the published action it pins under `action`: its rules, parameters and limits, so you know what the agent is authorized to do. Call this at startup to discover available permissions.

**Annotations:** `readOnly`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `did` | `string` | Yes | The agent DID, e.g. did:key:z6Mk… *(minLength: 1, maxLength: 512)* |

***

### declare\_client

**Title:** Declare your identity

**Description:** Record which AI model and host application you are (e.g. model: "claude-sonnet-5", host: "Cursor"). Shown to operators for transparency. Call once after connecting.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: false`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `model` | `string` | No | e.g. "grok-4" *(minLength: 1, maxLength: 120)* |
| `host` | `string` | No | e.g. "Grok Bot", "Claude Desktop", "Cursor" *(minLength: 1, maxLength: 120)* |

***

### declare\_tools

**Title:** Declare your tools

**Description:** Report every tool you can call to the organization, so it can put guardrails on them. Do NOT include this Humanos server's own tools (onboard, declare\_tools, propose\_action, verify and the rest): they are never recorded. For each tool, copy what your host knows about it VERBATIM, never paraphrased or summarized: its name exactly as its server defines it; its title; its full description; its inputSchema, the whole JSON Schema object, with every property, nested object, enum, format, range, default and required list; its outputSchema when it has one; its MCP annotations (title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint); and the service it comes from (the MCP server or app, as your host names it, e.g. "Slack", "Gmail", "Google Calendar"). Long text is cut and recorded as cut, never refused; a malformed tool is skipped and reported, and the rest are recorded. Up to 500 tools per call: declare each service in one call. Declaring again updates the list for the named services, so you can declare one service at a time: a tool you leave out is kept and marked as no longer declared, never deleted, and two services may each have a tool of the same name. To say a service has no tools any more, name it in services and send none of its tools.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: false`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `tools` | `object[]` | Yes | *(maxItems: 500)* |
| `tools[].name` | `string` | Yes | The tool name exactly as its server defines it *(minLength: 1, maxLength: 200)* |
| `tools[].title` | `string` | No | The tool's title, when it has one |
| `tools[].description` | `string` | No | The tool's full description, verbatim |
| `tools[].service` | `string` | No | The service this tool comes from — the MCP server, or your host's own — as your host names it, e.g. "Slack", "Gmail", "Google Calendar" |
| `tools[].inputSchema` | `Record<string, unknown>` | No | The tool's input schema, verbatim: the JSON Schema object with every property, nested object, enum, format, range, default and required list |
| `tools[].outputSchema` | `Record<string, unknown>` | No | The tool's output schema, verbatim, when it has one |
| `tools[].annotations` | `object` | No | The tool's MCP annotations, verbatim |
| `tools[].annotations.title` | `string` | No | |
| `tools[].annotations.readOnlyHint` | `boolean` | No | |
| `tools[].annotations.destructiveHint` | `boolean` | No | |
| `tools[].annotations.idempotentHint` | `boolean` | No | |
| `tools[].annotations.openWorldHint` | `boolean` | No | |
| `tools[].calledAs` | `string` | No | The name you call the tool by, when it differs from its name (e.g. a prefix your host adds) *(maxLength: 200)* |
| `tools[].server` | `object` | No | |
| `tools[].server.name` | `string` | No | The server's name, from its initialize response (serverInfo.name) |
| `tools[].server.version` | `string` | No | The server's version, from serverInfo.version |
| `tools[].server.title` | `string` | No | The server's title, from serverInfo.title |
| `tools[].server.transport` | `string` | No | "stdio" for a local server, "http" for a remote one |
| `tools[].server.host` | `string` | No | A remote server's host only (e.g. mcp.slack.com), or a local server's command name only (e.g. npx) |
| `tools[].params` | `Record<string, unknown>` | No | Legacy: the input parameters flattened, keyed by name. Send inputSchema instead; ignored when it is sent |
| `tools[].readOnlyHint` | `boolean` | No | Legacy: send annotations instead |
| `tools[].destructiveHint` | `boolean` | No | Legacy: send annotations instead |
| `services` | `string[]` | No | Services this call covers besides those its tools name: each one named here with none of its tools sent has all its tools marked as no longer declared *(maxItems: 50)* |
| `did` | `string` | No | The agent DID. Required with an API key; omit for custodial agents *(minLength: 1, maxLength: 512)* |

***

### list\_mandate\_kinds

**Title:** List available mandate types

**Description:** See what types of mandates you can request. Two categories:

* **authorization**: a simple approval where the person agrees to terms you describe in plain language.
* **policy**: bound to a published action with rules and parameter limits the person controls.
  Also shows draft actions awaiting publication by the organization.

**Annotations:** `readOnly`

**Parameters:**
None

***

### request\_mandate

**Title:** Request a mandate from a person

**Description:** Request permission from a person to act under a guardrail.

* For **authorization**: provide `name` and `terms` describing what you will do in plain language.
* For **policy**: provide the `actionId` from a published action and the `userParams` values.
* **grantor.contact**: use the connected person's email from the server instructions. Do not ask the user for it.
  Returns a `consentCard` with a link to show the person. They approve on their own device with a verification code. Poll mandate\_status until ACTIVE, then use get\_mandate to see the mandate details.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: false`, `openWorldHint: true`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `kind` | `"authorization" \| "policy"` | Yes | "authorization": simple approval with written terms. "policy": under a published guardrail |
| `grantor` | `object` | Yes | |
| `grantor.contact` | `string` | Yes | The email or phone of the person who authorizes *(minLength: 3, maxLength: 320)* |
| `name` | `string` | No | The label the person sees (required for an authorization) *(maxLength: 200)* |
| `terms` | `string` | No | For authorization: plain-language description of what the person is approving *(maxLength: 4000)* |
| `description` | `string` | No | Context the person sees under the name *(maxLength: 1000)* |
| `actionId` | `string` | No | For policy: the action id from list\_mandate\_kinds *(minLength: 1, maxLength: 512)* |
| `userParams` | `Record<string, unknown>` | No | For policy: the limit values the person sets (e.g. maxMessages: 10) |
| `validUntil` | `string` | No | When this mandate expires (ISO-8601 date) |
| `maxExecutions` | `integer` | No | How many times this mandate can be used. Set to 1 for one-time approvals *(exclusiveMin: 0)* |
| `did` | `string` | No | The agent DID. Required with an API key; omit for custodial agents *(minLength: 1, maxLength: 512)* |

***

### propose\_action

**Title:** Propose a guardrail for the organization

**Description:** Propose a new action (guardrail template) for the organization to review and publish. Include the tools it covers, their parameters, and which values the person controls (role "grantor"). You may propose CEL rules that enforce limits (e.g. `userParams.maxAmount >= executionParams.amount`).

IMPORTANT: Write ALL descriptions in plain, non-technical language a regular person can understand:

* Parameter descriptions: explain what the setting does in everyday terms (e.g. "Maximum number of messages the agent can send before asking again", NOT "Upper bound for messageCount").
* Rule descriptions: explain the protection simply (e.g. "Prevents the agent from sending more messages than you allowed").
* Action description: one sentence explaining what this guardrail controls.

The person reviews and publishes through the Humanos dashboard. Once published, it appears in list\_mandate\_kinds.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: false`, `openWorldHint: false`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | Guardrail name, e.g. "slack\_messaging" or "email\_access" *(minLength: 1, maxLength: 200)* |
| `description` | `string` | No | *(maxLength: 1000)* |
| `tools` | `object[]` | Yes | One entry per tool; params keyed by parameter name *(minItems: 1, maxItems: 100)* |
| `tools[].name` | `string` | Yes | *(minLength: 1, maxLength: 200)* |
| `tools[].description` | `string` | No | *(maxLength: 1000)* |
| `tools[].params` | `Record<string, unknown>` | Yes | |
| `grantorParams` | `Record<string, unknown>` | No | Limits the person controls when approving (e.g. allowed channels, max amounts). Use plain, non-technical descriptions |
| `rules` | `object[]` | No | Rules that enforce the guardrail limits. Write descriptions in plain language the person can understand *(maxItems: 20)* |
| `rules[].name` | `string` | Yes | Rule name, e.g. "message\_limit" *(minLength: 1, maxLength: 200)* |
| `rules[].description` | `string` | No | Plain-language explanation of what this rule protects (e.g. "Prevents the agent from sending more messages than you allowed") *(maxLength: 500)* |
| `rules[].expression` | `string` | Yes | CEL expression, e.g. "userParams.maxMessages >= executionParams.messageCount" *(minLength: 1, maxLength: 2000)* |
| `did` | `string` | No | The agent DID. Required with an API key; omit for custodial agents *(minLength: 1, maxLength: 512)* |

***

### mandate\_status

**Title:** Check mandate status

**Description:** Check the status of a mandate request. Returns PENDING (waiting for approval), ACTIVE (ready to use), or REFUSED.

**Annotations:** `readOnly`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `mandateId` | `string` | Yes | The mandate URN, e.g. urn:via:credential:… *(minLength: 1, maxLength: 512)* |

***

### register\_challenge

**Title:** Start agent registration

**Description:** Step 1 of agent registration: get a single-use nonce and `aud`, the platform DID. An SDK agent then signs a `via-reg+jwt` over both with its P-256 key and calls register. Requires an organization API key.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: false`, `openWorldHint: false`

**Parameters:**
None

***

### register

**Title:** Register an agent

**Description:** Step 2 of agent registration. Two modes:

* **With a key** (SDK agents): pass publicKeyJwk, evidence, and regNonce. You hold the private key, and the evidence proves it (`proof`).
* **Without a key** (custodial): call with no arguments. The platform creates and holds the key for you.
  Returns the agent DID and key id. Requires an organization API key.

**Annotations:** `readOnlyHint: false`, `destructiveHint: false`, `idempotentHint: false`, `openWorldHint: false`

**Parameters:**

| Name | Type | Required | Description |
| - | - | - | - |
| `publicKeyJwk` | `Record<string, unknown>` | No | P-256 public key as JWK: `{ kty: "EC", crv: "P-256", x, y }`. Omit to create a custodial agent (platform holds the key) |
| `evidence` | `Record<string, unknown>` | No | Key evidence, proving the key is held: `{ "type": "device-self", "proof": <via-reg+jwt signed by the key over the nonce and aud> }` for a software key (v0.3 §16.5). Ignored for custodial agents |
| `regNonce` | `string` | No | Nonce from register\_challenge. Required when providing a key; not needed for custodial agents *(minLength: 1, maxLength: 256)* |
| `tools` | `object[]` | No | Your tool surface, each tool as declare\_tools takes it: recorded as declared, shown with coverage in the dashboard *(maxItems: 500)* |
| `tools[].name` | `string` | Yes | The tool name exactly as its server defines it *(minLength: 1, maxLength: 200)* |
| `tools[].title` | `string` | No | The tool's title, when it has one |
| `tools[].description` | `string` | No | The tool's full description, verbatim |
| `tools[].service` | `string` | No | The service this tool comes from — the MCP server, or your host's own — as your host names it, e.g. "Slack", "Gmail", "Google Calendar" |
| `tools[].inputSchema` | `Record<string, unknown>` | No | The tool's input schema, verbatim: the JSON Schema object with every property, nested object, enum, format, range, default and required list |
| `tools[].outputSchema` | `Record<string, unknown>` | No | The tool's output schema, verbatim, when it has one |
| `tools[].annotations` | `object` | No | The tool's MCP annotations, verbatim |
| `tools[].annotations.title` | `string` | No | |
| `tools[].annotations.readOnlyHint` | `boolean` | No | |
| `tools[].annotations.destructiveHint` | `boolean` | No | |
| `tools[].annotations.idempotentHint` | `boolean` | No | |
| `tools[].annotations.openWorldHint` | `boolean` | No | |
| `tools[].calledAs` | `string` | No | The name you call the tool by, when it differs from its name (e.g. a prefix your host adds) *(maxLength: 200)* |
| `tools[].server` | `object` | No | |
| `tools[].server.name` | `string` | No | The server's name, from its initialize response (serverInfo.name) |
| `tools[].server.version` | `string` | No | The server's version, from serverInfo.version |
| `tools[].server.title` | `string` | No | The server's title, from serverInfo.title |
| `tools[].server.transport` | `string` | No | "stdio" for a local server, "http" for a remote one |
| `tools[].server.host` | `string` | No | A remote server's host only (e.g. mcp.slack.com), or a local server's command name only (e.g. npx) |
| `tools[].params` | `Record<string, unknown>` | No | Legacy: the input parameters flattened, keyed by name. Send inputSchema instead; ignored when it is sent |
| `tools[].readOnlyHint` | `boolean` | No | Legacy: send annotations instead |
| `tools[].destructiveHint` | `boolean` | No | Legacy: send annotations instead |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.