post_orgs_join

Changes data · you confirm first

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

Request membership of an organization

Authentication only — ANY signed-in person may ASK to join ANY organization by id. The request lands as a REQUESTED membership of the org's MEMBER group — the group every org is created with, carrying the read-only ORG_USER role — so it grants nothing until someone holding admin.groups.members.add IN THAT organization approves it (POST /api/org-admin/{orgId}/join-requests/{userId}/approve), and then only reading the org, its users and its groups. The DAL takes the requester from the caller's own session (the route forwards it); nothing in the body names a user. A pending invitation or an existing membership is left as it is and reported in status (INVITED — accept it from your invitations; ACTIVE — already a member). An organization whose signup the platform has not approved takes no requests.

Arguments

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

Fields of body

FieldTypeDescription
orgIdstring (uuid)required

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_orgs_join",
    "arguments": {
      "body": {
        "orgId": "11111111-1111-4111-8111-111111111111"
      }
    }
  }
}
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 200) the tool returns one text item holding the API's JSON, pretty-printed.

The membership request was recorded. 200, not 201 — nothing addressable is created for the caller to fetch.

json
{
  "message": "Membership request submitted",
  "nextSteps": {
    "message": "string"
  },
  "organization": {
    "id": "11111111-1111-4111-8111-111111111111",
    "name": "string",
    "type": "string"
  },
  "status": "INVITED"
}

Fields

FieldTypeDescription
messagestring
nextStepsobject
nextSteps.messagestring
organizationobjectNarrow projection — three fields only.
organization.idstring (uuid)
organization.namestring
organization.typestring
status"INVITED" | "REQUESTED" | "ACCEPTED" | "APPROVED" | "ACTIVE" | "DECLINED" | … (8 values)The caller's membership of the org's MEMBER group as the DAL read it back: REQUESTED for a new request; INVITED when the org had already invited them (they accept it instead); ACTIVE or APPROVED when they are already a member.

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

orgId missing from the body.

403

A donor-realm bearer, refused by authenticate.

404

No such resource — or none this caller may see.

409

The organization takes no requests (code: NO_JOINABLE_GROUP): it has no MEMBER group to request membership of (every org is created with one, so a live org without one needs repair), or its signup has not been approved by the platform.

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_orgs_join",
  "description": "POST /api/orgs/join — Authentication only — ANY signed-in person may ASK to join ANY organization by id. The request lands as a REQUESTED membership of the org's MEMBER group — the group every org is created with, carrying the read-only ORG_USER role — so it grants nothing until someone holding `admin.groups.members.add` IN THAT organization approves it (`POST /api/org-admin/{orgId}/join-requests/{userId}/approve`), and then only reading the org, its users and its groups. The DAL takes the requester from the caller's own session (the route forwards it); nothing in the body names a user. A pending invitation or an existing membership is left as it is and reported in `status` (INVITED — accept it from your invitations; ACTIVE — already a member). An organization whose signup the platform has not approved takes no requests.\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: { orgId*: string }"
      }
    },
    "required": [
      "body"
    ]
  },
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": true,
    "idempotentHint": false,
    "openWorldHint": false
  }
}