> Source: https://wexa.ai/docs/connectors/list-user-connectors

# list-user-connectors

List the project's user-defined connectors: published ones, and your own drafts. Needs the `fabric:orchestrate.read` grant.

**List user-defined connectors**

**Wexa MCP server**

```bash
curl -sS -X POST https://fabric.wexa.ai/mcp/$FABRIC_PROJECT_ID \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "Mcp-Session-Id: $MCP_SESSION_ID" \
  -H "content-type: application/json" -H "accept: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list-user-connectors","arguments":{}}}'
```

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000017\",\"result\":{\"connectors\":[{\"connector_id\":\"6b1a3d5e7f9c0b2a4d6e8f02\",\"name\":\"Payroll\",\"mode\":\"live\",\"lifecycle\":\"draft\",\"access_scope\":\"individual\",\"action_count\":1}]}}"
    }
  ],
  "isError": false
}
```

**REST API**

```bash
curl -sS https://fabric.wexa.ai/v1/list-user-connectors \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```json
{
  "lifecycle_id": "qlc_000017",
  "result": {
    "connectors": [
      {
        "connector_id": "6b1a3d5e7f9c0b2a4d6e8f02",
        "name": "Payroll",
        "mode": "live",
        "lifecycle": "draft",
        "access_scope": "individual",
        "action_count": 1
      }
    ]
  }
}
```

**TypeScript SDK**

```ts
import { Fabric } from '@wexa-fabric/sdk'

const fabric = new Fabric()
const result = await fabric.listUserConnectors()
```

```ts
// result is the payload itself, with no `.result` to read
{
  connectors: [
    {
      connector_id: '6b1a3d5e7f9c0b2a4d6e8f02',
      name: 'Payroll',
      mode: 'live',
      lifecycle: 'draft',
      access_scope: 'individual',
      action_count: 1
    }
  ]
}
```

**Python SDK**

```python
from wexa import Fabric

fabric = Fabric()
out = fabric.list_user_connectors()
```

```python
# out is the result, already unwrapped
{
    "connectors": [
        {
            "connector_id": "6b1a3d5e7f9c0b2a4d6e8f02",
            "name": "Payroll",
            "mode": "live",
            "lifecycle": "draft",
            "access_scope": "individual",
            "action_count": 1
        }
    ]
}
```

## Parameters

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| none | | | This tool takes no parameters. |

**Show full response**

An example response, with one draft.

**Result of list-user-connectors**

**REST API**

```json
{
  "lifecycle_id": "qlc_000017",
  "result": {
    "connectors": [
      {
        "connector_id": "6b1a3d5e7f9c0b2a4d6e8f02",
        "name": "Payroll",
        "category": "user_payroll",
        "description": "Read employees from the payroll API.",
        "logo": "",
        "mode": "live",
        "connected": false,
        "lifecycle": "draft",
        "access_scope": "individual",
        "user_id": "6a0f1e2d3c4b5a6978877665",
        "has_credentials": true,
        "base_url": "https://payroll.example.com/v1",
        "action_count": 1,
        "actions": [
          {
            "key": "get_employee",
            "name": "Get employee"
          }
        ],
        "project_id": "6a0f1e2d3c4b5a6978877601",
        "org_id": "6a0f1e2d3c4b5a6978877600"
      }
    ]
  }
}
```

**Wexa MCP server**

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000017\",\"result\":{\"connectors\":[{\"connector_id\":\"6b1a3d5e7f9c0b2a4d6e8f02\",\"name\":\"Payroll\",\"category\":\"user_payroll\",\"description\":\"Read employees from the payroll API.\",\"logo\":\"\",\"mode\":\"live\",\"connected\":false,\"lifecycle\":\"draft\",\"access_scope\":\"individual\",\"user_id\":\"6a0f1e2d3c4b5a6978877665\",\"has_credentials\":true,\"base_url\":\"https://payroll.example.com/v1\",\"action_count\":1,\"actions\":[{\"key\":\"get_employee\",\"name\":\"Get employee\"}],\"project_id\":\"6a0f1e2d3c4b5a6978877601\",\"org_id\":\"6a0f1e2d3c4b5a6978877600\"}]}}"
    }
  ],
  "isError": false
}
```

**TypeScript SDK**

```ts
// the object you get back IS the result — there is no `.result` to read
{
  "connectors": [
    {
      "connector_id": "6b1a3d5e7f9c0b2a4d6e8f02",
      "name": "Payroll",
      "category": "user_payroll",
      "description": "Read employees from the payroll API.",
      "logo": "",
      "mode": "live",
      "connected": false,
      "lifecycle": "draft",
      "access_scope": "individual",
      "user_id": "6a0f1e2d3c4b5a6978877665",
      "has_credentials": true,
      "base_url": "https://payroll.example.com/v1",
      "action_count": 1,
      "actions": [
        {
          "key": "get_employee",
          "name": "Get employee"
        }
      ],
      "project_id": "6a0f1e2d3c4b5a6978877601",
      "org_id": "6a0f1e2d3c4b5a6978877600"
    }
  ]
}

// The TS SDK names these camelCase — lifecycleId, traceId — where Python uses
// lifecycle_id and trace_id. Both are non-enumerable: readable, but omitted by
// Object.keys() and JSON.stringify(). `result.lifecycleId` here is undefined.
result.lifecycleId // 'qlc_000017'
```

**Python SDK**

```python
# a dict subclass; `result` is already unwrapped
{
 "connectors": [
  {
   "connector_id": "6b1a3d5e7f9c0b2a4d6e8f02",
   "name": "Payroll",
   "category": "user_payroll",
   "description": "Read employees from the payroll API.",
   "logo": "",
   "mode": "live",
   "connected": False,
   "lifecycle": "draft",
   "access_scope": "individual",
   "user_id": "6a0f1e2d3c4b5a6978877665",
   "has_credentials": True,
   "base_url": "https://payroll.example.com/v1",
   "action_count": 1,
   "actions": [
    {
     "key": "get_employee",
     "name": "Get employee"
    }
   ],
   "project_id": "6a0f1e2d3c4b5a6978877601",
   "org_id": "6a0f1e2d3c4b5a6978877600"
  }
 ]
}

out.lifecycle_id  # 'qlc_000017' — an attribute, not a key
```

Keeping the `lifecycle_id` is what lets you ask later why a call was allowed, refused or held.

**More details**

**Response fields**

`connectors` is the list. Each connector has these fields:

- `connector_id`: The connector's id.
- `name`: Its name.
- `category`: Its category. A user-defined connector's category starts with `user_`.
- `description`: Its description; empty when it has none.
- `logo`: Its logo; empty when it has none.
- `mode`: `live` (calls the real API) or `simulated`.
- `connected`: Whether its actions are skills agents can use.
- `lifecycle`: `draft` or `published`.
- `access_scope`: `individual` (a draft), `project` or `organization`.
- `user_id`: Its author.
- `has_credentials`: Whether credentials are saved. The credentials themselves are never returned.
- `base_url`: A live connector's base URL.
- `action_count`: How many actions it has.
- `actions`: Its actions, each with a `key` and a `name`.
- `project_id`: This project.
- `org_id`: This organization.

These are the connectors people built from an API description, as opposed to the ones Wexa offers in its catalog. You see the published ones, and your own drafts. Another person's draft is never listed.

A draft is its author's alone. A published connector is visible in its project, or in every project of its organization when it was published there. For one connector's full definition, call [`get-user-connector`](/docs/connectors/get-user-connector).

Only reads, so not marked consequential: it is audited lightly and is never held for approval.

Every tool call works the same way: [How every tool call works](/docs/sdks-and-apis/how-every-tool-call-works).
