Skip to main content
Glama

Create person

well_create_person

Create a new person (contact) in the current workspace.

Use this tool when the user asks to add, create, or register a new contact, employee, or person.

REQUIRED: first_name OPTIONAL: last_name, job_title, email, phone, company_id, address, copy_from_person_id

One call saves the person with their email, their phone, their company and their postal address. Never call well_add_contact_channel after it for the same email, phone or address.

  • address: { address_line1, postal_code, city, country } as the person gave it. A person of the workspace with the same full name who holds that address, with the same postal code or city, is that person: the call returns them with created false and creates no one.

  • copy_from_person_id: the person_id of a person read in another workspace of the user. The call copies that person's last name, job title, email, phone and address into this workspace; the values you pass win.

  • phone: E.164 (+33612345678). Spaces, dots, dashes and brackets are removed before the check, so a number copied from a contact card ("+33 6 11 22 33 44") is saved as it reads. When the number has no country code or is incomplete, ask the person for the full number before you call this tool.

  • company_id: the id of a company of the workspace, found with a read first. When no company of the workspace is the one the person names, create it first with well_create_company, then pass the id it returns: one order from the person saves the person and their company. Use only an id a read or a create returned; never pick a company because its name looks alike.

A contact card the person shares reaches you as their message, with its name, company, phone and email lines:

  • With an order to add or save it ("Add this supplier"), it is a complete order: save the person at once with every field of the card (create the company first when the workspace does not hold it), then read back what was saved. Ask nothing.

  • With no order, write nothing: offer to save it as one numbered choice. Several cards get one numbered line each, so the person picks by number.

Returns { success: true, person_id, full_name, created, company_name, email, phone, address, saved_fields } on success, or { success: false, error } on failure. created is false when the person already existed: say they are already in Well, never that they were saved. company_name, email, phone and address are those the person holds after the call; null means the person does not hold it. saved_fields lists those of company_name, email, phone and address this call wrote: on a person who already existed, only those fields were saved. When created is null, the call could not read the person back: a null company_name or address is unknown, not absent, so never say it was not saved.

Input Schema

NameRequiredDescriptionDefault
emailNoEmail address (optional)
phoneNoPhone number in E.164, like +33612345678 (optional)
addressNoThe person's postal address (optional); with the name, it finds the person already held
job_titleNoJob title
last_nameNoLast name (optional)
company_idNoId of the company the person works at, from a read or from well_create_company (optional)
first_nameYesFirst name (required)
workspace_idNoTarget workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which.
conversation_idNoThe conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation.
idempotency_keyNoOptional client-supplied key. A retried write with the same key returns the original result instead of re-applying the operation.
workspace_scopeNoRestrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace.
copy_from_person_idNoperson_id of a person read in another workspace of the user, whose values the call copies (optional)

Output Schema

NameRequiredDescriptionDefault
codeNo
emailNo
errorNo
phoneNo
addressNo
createdNo
successYes
full_nameNo
person_idNo
reply_linesNo
company_nameNo
saved_fieldsNo
conversation_idNoThe conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation.
near_candidatesNo
newly_connectedNoTools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: "<name> is connected.". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later.
conversation_id_noteNoPresent only when the server opened a fresh lane, stating that no choice recorded earlier was read.
conversation_id_sourceNoWhere the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened.
near_candidates_truncatedNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed17 schema fields changed
    • addedInput schema / properties / address
      Added value: +{
      +  "description": "The person's postal address (optional); with the name, it finds the person already held",
      +  "properties": {
      +    "address_line1": {
      +      "description": "Street line with its number",
      +      "maxLength": 255,
      +      "type": "string"
      +    },
      +    "address_line2": {
      +      "maxLength": 255,
      +      "type": "string"
      +    },
      +    "city": {
      +      "maxLength": 255,
      +      "type": "string"
      +    },
      +    "country": {
      +      "description": "2-letter country code",
      +      "maxLength": 2,
      +      "type": "string"
      +    },
      +    "postal_code": {
      +      "maxLength": 255,
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "address_line1"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / copy_from_person_id
      Added value: +{
      +  "description": "person_id of a person read in another workspace of the user, whose values the call copies (optional)",
      +  "format": "uuid",
      +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      +  "type": "string"
      +}
    • changedInput schema / properties / email / pattern
      Previous value: -"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"New value: +"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
    • addedOutput schema / properties / address
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / code
      Added value: +{
      +  "type": "string"
      +}
    • removedOutput schema / properties / company_name / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / company_name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / created / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / created / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
    • removedOutput schema / properties / email / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / email / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • addedOutput schema / properties / near_candidates
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "company_id": {
      +        "type": "string"
      +      },
      +      "name": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "company_id",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / near_candidates_truncated
      Added value: +{
      +  "type": "boolean"
      +}
    • removedOutput schema / properties / phone / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / phone / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • addedOutput schema / properties / reply_lines
      Added value: +{
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / saved_fields / items / enum
      Previous value: -[
      -  "company_name",
      -  "email",
      -  "phone"
      -]New value: +[
      +  "company_name",
      +  "email",
      +  "phone",
      +  "address"
      +]
  2. Changed1 schema field changed
    • addedOutput schema / properties / saved_fields
      Added value: +{
      +  "items": {
      +    "enum": [
      +      "company_name",
      +      "email",
      +      "phone"
      +    ],
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  3. Changed1 schema field changed
    • changedInput schema / properties / company_id / description
      Previous value: -"Id of an existing company the person works at (optional)"New value: +"Id of the company the person works at, from a read or from well_create_company (optional)"
  4. Changed9 schema fields changed
    • addedInput schema / properties / company_id
      Added value: +{
      +  "description": "Id of an existing company the person works at (optional)",
      +  "format": "uuid",
      +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      +  "type": "string"
      +}
    • addedInput schema / properties / email / description
      Added value: +"Email address (optional)"
    • addedInput schema / properties / email / maxLength
      Added value: +320
    • addedInput schema / properties / phone / description
      Added value: +"Phone number in E.164, like +33612345678 (optional)"
    • addedInput schema / properties / phone / pattern
      Added value: +"^\\+[1-9]\\d{1,14}$"
    • addedOutput schema / properties / company_name
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • addedOutput schema / properties / created
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "boolean"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • addedOutput schema / properties / email
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • addedOutput schema / properties / phone
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
  5. Changed1 schema field changed
    • changedOutput schema / properties / newly_connected / description
      Previous value: -"Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. Start the reply with one line per entry, in the person's language: \"<name> is connected.\". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later."New value: +"Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: \"<name> is connected.\". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later."
  6. Changed1 schema field changed
    • addedInput schema / properties / workspace_scope
      Added value: +{
      +  "description": "Restrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace.",
      +  "enum": [
      +    "family"
      +  ],
      +  "type": "string"
      +}
  7. Changed1 schema field changed
    • addedOutput schema / properties / newly_connected
      Added value: +{
      +  "description": "Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. Start the reply with one line per entry, in the person's language: \"<name> is connected.\". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "name": {
      +        "type": "string"
      +      },
      +      "service_id": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "service_id"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  8. Changed4 schema fields changed
    • addedInput schema / properties / conversation_id
      Added value: +{
      +  "description": "The conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / conversation_id
      Added value: +{
      +  "description": "The conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / conversation_id_note
      Added value: +{
      +  "description": "Present only when the server opened a fresh lane, stating that no choice recorded earlier was read.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / conversation_id_source
      Added value: +{
      +  "description": "Where the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened.",
      +  "enum": [
      +    "host_meta",
      +    "argument",
      +    "minted"
      +  ],
      +  "type": "string"
      +}
  9. Changed2 schema fields changed
    • addedInput schema / properties / job_title / maxLength
      Added value: +100
    • changedInput schema / properties / last_name / anyOf
      Previous value: -[
      -  {
      -    "maxLength": 100,
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "maxLength": 255,
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  10. Changed1 schema field changed
    • removedInput schema / properties / job_title / maxLength
      Removed value: -200
  11. Changed1 schema field changed
    • changedInput schema / properties / workspace_id / description
      Previous value: -"Target workspace. Omit to use the only authorized workspace, or (for read tools) to query all authorized workspaces grouped by workspace. Required for write tools when the token authorizes more than one workspace."New value: +"Target workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which."
  12. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=false): it discloses the dedup behavior (a matching name+address returns created=false and creates nobody), phone normalization rules, the copy_from_person_id merge precedence ('the values you pass win'), the read-before-create requirement for company_id, and the null-created ambiguity on read-back.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then a REQUIRED/OPTIONAL roster, then per-field rules, then the contact-card policy, then the return contract — a sensible ordering. Slightly long, and the REQUIRED/OPTIONAL roster restates schema facts an agent already has.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite an output schema existing, the description adds the operational meaning of created/created-null and saved_fields that an agent must not misreport to the user. For a 12-param write tool with nested address and dedup side effects, nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description earns more: it explains the address object's role in identity matching, the E.164 normalization and the ask-for-full-number rule, and the exact semantics of copy_from_person_id and company_id sourcing. It does not explain workspace_id, conversation_id, idempotency_key, or workspace_scope, which the schema carries alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: 'Create a new person (contact) in the current workspace.' The sibling landscape is huge, and the description pre-empts the most confusable ones by ruling out well_add_contact_channel and pointing to well_create_company for the company path.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit trigger conditions ('when the user asks to add, create, or register a new contact, employee, or person') plus explicit prohibitions ('Never call well_add_contact_channel after it for the same email, phone or address') and a differentiated policy for a shared contact card with vs. without an explicit save order.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources