post_groups

Changes data · you confirm first

Calls POST /api/groups as the signed-in person · REST reference

Create a group inside exactly one organization

Requires execute:CreateGroupCommand; platform staff bypass that gate. A non-platform-staff caller must additionally be a member of the target org (403 ORG_CREATE_DENIED). SINGLE-ORGANIZATION MODEL: orgId is a single value and an array is rejected with SINGLE_ORG_VIOLATION. The BELONGS_TO edge is established server-side from orgId when the group is saved. A group has NO permission list: a body naming permissions is a 400. A group grants what its roles grant — PUT /api/org-admin/groups/{groupId}/roles. type defaults to FUNCTIONAL. The 201 body echoes the LOCAL model instance, not the DAL's stored entity, so id is the uuid the model generated — not the stored group's id, which the DAL assigns — and memberCount is 0.

Arguments

ArgumentTypeDescription
bodyJSONobjectrequiredThe request body, as a JSON object. Its fields are listed below.

Fields of body

FieldTypeDescription
descriptionstring
namestringrequiredTrimmed before validation.
orgIdstring (uuid)required
type"FUNCTIONAL" | "DEPARTMENTAL" | "ROLE_BASED" | "PROJECT"ADMIN exists on the model but is NOT accepted here — the DAL creates admin groups itself when an org is created.

Example call

A client sends this over the MCP session; Claude and other agents build it for you. The values are placeholders — the shape is real.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "post_groups",
    "arguments": {
      "body": {
        "name": "string",
        "orgId": "11111111-1111-4111-8111-111111111111",
        "description": "string",
        "type": "FUNCTIONAL"
      }
    }
  }
}
Confirmation
The client shows the person the exact request and waits. Nothing runs until they tick Make this change. See Reading and changing.

Result

On success (HTTP 201) the tool returns one text item holding the API's JSON, pretty-printed.

The created group, wrapped in the success envelope with a message.

json
{
  "data": {
    "createdAt": "2026-01-15T12:00:00Z",
    "id": "11111111-1111-4111-8111-111111111111",
    "memberCount": 0,
    "name": "string",
    "status": "ACTIVE",
    "type": "string",
    "createdBy": "11111111-1111-4111-8111-111111111111",
    "description": "string",
    "orgId": "11111111-1111-4111-8111-111111111111"
  },
  "message": "string",
  "success": true
}

Fields

FieldTypeDescription
dataobjectThe in-memory Group model, not the persisted entity.
data.createdAtstring (date-time)
data.createdBystring (uuid) | null
data.descriptionstring | null
data.idstring (uuid)Model-generated uuid; NOT the stored group's id.
data.memberCount0
data.namestring
data.orgIdstring (uuid)
data.status"ACTIVE"
data.typestring
messagestring
successtrue

When it fails

A failed call returns isError: true with the API's message as text. A change the person declines, or lets time out, also comes back this way and nothing changes.

400

express-validator rejected the body (error: "Validation failed", ARRAY details), or orgId was an array (code: SINGLE_ORG_VIOLATION, canon body).

403

Missing execute:CreateGroupCommand, or the caller does not belong to the target org (code: ORG_CREATE_DENIED).

409

The DAL refused the group as it stands: the org already has a group of that name, or the type is OWNER or MEMBER, which the organization manages itself. Carries the DAL's sentence.

What the model is shown

This is the tool exactly as the server lists it in tools/list. The description starts with the REST call it makes.

json
{
  "name": "post_groups",
  "description": "POST /api/groups — Requires `execute:CreateGroupCommand`; platform staff bypass that gate. A non-platform-staff caller must additionally be a member of the target org (403 `ORG_CREATE_DENIED`). SINGLE-ORGANIZATION MODEL: `orgId` is a single value and an array is rejected with `SINGLE_ORG_VIOLATION`. The BELONGS_TO edge is established server-side from `orgId` when the group is saved. A group has NO permission list: a body naming `permissions` is a 400. A group grants what its roles grant — `PUT /api/org-admin/groups/{groupId}/roles`. `type` defaults to FUNCTIONAL. The 201 body echoes the LOCAL model instance, not the DAL's stored entity, so `id` is the uuid the model generated — not the stored group's id, which the DAL assigns — and `memberCount` is 0.\n\nThis changes data. The person is asked to confirm it before it runs, and nothing happens if they decline.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "body": {
        "type": "string",
        "description": "The JSON request body: { description: string; name*: string (Trimmed before validation.); orgId*: string; type: one of \"FUNCTIONAL\" | \"DEPARTMENTAL\" | \"ROLE_BASED\" | \"PROJECT\" (ADMIN exists on the model but is NOT accepted here — the DAL creates admin groups itsel...) }"
      }
    },
    "required": [
      "body"
    ]
  },
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": true,
    "idempotentHint": false,
    "openWorldHint": false
  }
}