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

# Model Context Protocol (MCP)

> How AI agents discover and invoke NexSpace tools

# Model Context Protocol

NexSpace exposes a JSON-RPC 2.0 MCP server at `https://mcp.nexspace365.com/mcp`.
AI agents (Claude Code, Cursor, ChatGPT, Composio, custom) use this to discover
and invoke 16 workforce management tools.

## Discovery

```bash theme={null}
curl https://mcp.nexspace365.com/.well-known/mcp
```

Returns server metadata including protocol version, capabilities, and auth
configuration.

## Protocol

All MCP communication happens via `POST /mcp` with JSON-RPC 2.0 messages.

### Initialize

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {}
}
```

### List Available Tools

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}
```

Returns all 16 tools with their names, descriptions, input schemas, and
annotations (read-only, destructive, idempotent hints).

### Call a Tool

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "findCredentialedStaff",
    "arguments": {
      "facilityId": 12,
      "specialty": "RN",
      "limit": 5
    }
  }
}
```

### Streaming a Tool Call (Streamable HTTP)

Send `Accept: text/event-stream` on a `tools/call` `POST /mcp` to receive the
response as Server-Sent Events instead of a single JSON body. The stream carries
zero or more `notifications/progress` frames (only when you supply a
`params._meta.progressToken`) followed by the terminal JSON-RPC response, then
closes. Each SSE frame has a monotonic `id`.

The response includes an `Mcp-Stream-Id` header. If the connection drops before
the terminal response, reconnect to `GET /mcp/stream/{streamId}` with a
`Last-Event-ID` header to replay the frames you missed:

```bash theme={null}
curl -N https://mcp.nexspace365.com/mcp \
  -H "Authorization: Bearer nex_live_YOUR_KEY" \
  -H "Accept: text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
       "params":{"name":"findCredentialedStaff","arguments":{"facilityId":12},
                 "_meta":{"progressToken":"p1"}}}'

# Resume a dropped stream (id from the Mcp-Stream-Id response header)
curl -N https://mcp.nexspace365.com/mcp/stream/STREAM_ID \
  -H "Authorization: Bearer nex_live_YOUR_KEY" \
  -H "Last-Event-ID: 1"
```

Clients that don't send `Accept: text/event-stream` continue to get a single
JSON response, so this is fully backward-compatible.

## Available Tools

### Scheduling

| Tool                    | Mutating | Description                                          |
| ----------------------- | -------- | ---------------------------------------------------- |
| `findCredentialedStaff` | No       | Search staff by specialty, facility, and credentials |
| `fillShift`             | Yes      | Assign a staff member to an open shift               |
| `proposeShiftSchedule`  | No       | Draft a shift assignment plan (what-if)              |
| `swapShifts`            | Yes      | Atomically swap two staff between shifts             |
| `getFacilityCoverage`   | No       | Coverage report by specialty                         |

### Credentials

| Tool                      | Mutating | Description                        |
| ------------------------- | -------- | ---------------------------------- |
| `verifyCredential`        | Yes      | Run credential verification        |
| `listExpiringCredentials` | No       | Credentials expiring within N days |

### Staff

| Tool             | Mutating | Description                         |
| ---------------- | -------- | ----------------------------------- |
| `searchStaff`    | No       | Free-text staff search              |
| `getStaffMember` | No       | Full staff profile with credentials |

### Payroll

| Tool                | Mutating | Description                        |
| ------------------- | -------- | ---------------------------------- |
| `previewPayrollRun` | No       | Compute payroll without committing |
| `runPayroll`        | Yes      | Commit payroll (irreversible)      |

### Communications

| Tool              | Mutating | Description                     |
| ----------------- | -------- | ------------------------------- |
| `notifyShiftSwap` | Yes      | Send shift change notifications |

### CRM

| Tool          | Mutating | Description                         |
| ------------- | -------- | ----------------------------------- |
| `qualifyLead` | Yes      | Score and enrich a CRM lead         |
| `searchLeads` | No       | Search leads by name/company/status |

### Facilities

| Tool             | Mutating | Description                |
| ---------------- | -------- | -------------------------- |
| `listFacilities` | No       | List accessible facilities |
| `getFacility`    | No       | Single facility detail     |

## Error Codes

| Code   | Name               | Meaning                    |
| ------ | ------------------ | -------------------------- |
| -32600 | INVALID\_REQUEST   | Malformed JSON-RPC         |
| -32601 | METHOD\_NOT\_FOUND | Unknown method             |
| -32602 | INVALID\_PARAMS    | Schema validation failed   |
| -32001 | NOT\_FOUND         | Unknown tool name          |
| -32003 | FORBIDDEN          | Insufficient API key scope |
| -32603 | INTERNAL           | Server error               |

All error responses include a `suggestion` field with recovery guidance and
a `retryable` boolean.

## Best Practices

1. **Read before write.** Call read tools to confirm scope before mutating.
2. **Confirm with the user** before calling mutating tools.
3. **Respect `FORBIDDEN` errors** — the API key needs a broader scope.
4. **Use `tools/list`** to discover available tools at runtime.
5. **Check `isError`** in tool call results for handler-level failures.
