Skip to main content
Glama

campaignstack_send_message

Destructive

Ask CampaignStack to send one message into a LinkedIn conversation the owner's connected account is already part of, optionally with attachments given as public URLs. Takes a conversationRef { platform, id } from campaignstack_get_conversations. Read the thread with campaignstack_get_conversations using ids and include.messages first. If the last message is the owner's and the other person has not answered since, do not send: say so, and send only if the user confirms they want to follow up again. This reaches a real person. Before calling it, tell the user exactly who it goes to and read the wording back to them, and wait for an explicit yes. The send is dispatched asynchronously and the response carries a messageEntityUrn; campaignstack_get_conversations reports delivery. Pass sendAt to hold the message and send it later instead of now; it is cancelled if the other person replies first, so read the wording and the time back and wait for a yes. campaignstack_get_conversations with include.scheduledMessages lists pending ones; campaignstack_edit_conversations cancels or edits one. One person per call. There is no bulk form, and calling this in a loop over a list is not the supported way to reach a list: add the leads with campaignstack_edit_lead_list and run a workflow over it with campaignstack_trigger_workflow, which paces the sends and applies the review step the workspace configured. Business hours do not apply. A message past the account's daily message limit is still sent, and the result carries a warning to pass on to the user. A paused account, or messaging LinkedIn has challenged, refuses the send.

Input Schema

NameRequiredDescriptionDefault
textYes
sendAtNoISO 8601 with a UTC offset. Omit to send now. With it, the message is held and sent at that time instead (1 minute to 180 days out) - cancelled automatically if the other person replies first. Read the wording and the time back to the user and wait for a yes before calling this with sendAt set.
attachmentsNoUp to 5 files to attach (images or documents). Downloaded server-side and validated against the LinkedIn attachment policy.
workspaceIdNoWorkspace ID. Omit it when this connection reaches one workspace: a workspace key (cs_) is bound to its own, and a user key (csu_) or connected app whose person belongs to exactly one workspace defaults to that one. Required only when the person belongs to several; the error then lists them, and campaignstack_whoami reports them too.
idempotencyKeyNoOptional. A key you choose for this one send. Calling again with the same key returns the send already made instead of sending twice (use it when a call timed out); a key reused for a different send is refused. Without a key, the same words to the same person within a few minutes are refused as a repeat.
conversationRefYes

Output Schema

NameRequiredDescriptionDefault
sendAtNo
statusNo
warningNo
messageEntityUrnNo
scheduledMessageIdNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changed
    • removedInput schema / properties / dangerouslyBypassSafetySystem
      Removed value: -{
      -  "description": "Deprecated name for overrideOwnLimits. Use overrideOwnLimits.",
      -  "type": "boolean"
      -}
    • addedInput schema / properties / idempotencyKey
      Added value: +{
      +  "description": "Optional. A key you choose for this one send. Calling again with the same key returns the send already made instead of sending twice (use it when a call timed out); a key reused for a different send is refused. Without a key, the same words to the same person within a few minutes are refused as a repeat.",
      +  "maxLength": 128,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • removedInput schema / properties / overrideOwnLimits
      Removed value: -{
      -  "description": "Tells CampaignStack to skip its OWN protective pacing for this one call: the daily budget, the weekly cap, the business-hours window, the account status check and the risk pause. These are limits CampaignStack sets to keep the account healthy. They are not LinkedIn's controls, and nothing here touches, negotiates with or works around anything LinkedIn enforces. LinkedIn's own measured ceiling is a separate check that is never overridable, and neither is a pause the account's owner set. Default false, and it should stay false. Setting it true voids the safety guarantee: from that call on, CampaignStack can no longer promise the pacing that keeps the account out of trouble, and the risk of a restriction sits with the owner. Every use is recorded in the workspace audit log. Ask the owner in plain words and get an explicit yes first. A refusal from the safety system is that system working, not a fault to route around: report the reason and let the person decide, and never retry the same send with this set.",
      -  "type": "boolean"
      -}
    • addedOutput schema / properties / warning
      Added value: +{
      +  "anyOf": [
      +    {
      +      "anyOf": [
      +        {
      +          "not": {}
      +        },
      +        {
      +          "type": "string"
      +        }
      +      ]
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
  2. Changed3 schema fields changed
    • addedInput schema / properties / sendAt
      Added value: +{
      +  "description": "ISO 8601 with a UTC offset. Omit to send now. With it, the message is held and sent at that time instead (1 minute to 180 days out) - cancelled automatically if the other person replies first. Read the wording and the time back to the user and wait for a yes before calling this with sendAt set.",
      +  "format": "date-time",
      +  "type": "string"
      +}
    • addedOutput schema / properties / scheduledMessageId
      Added value: +{
      +  "anyOf": [
      +    {
      +      "anyOf": [
      +        {
      +          "not": {}
      +        },
      +        {
      +          "type": "string"
      +        }
      +      ]
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • addedOutput schema / properties / sendAt
      Added value: +{
      +  "anyOf": [
      +    {
      +      "anyOf": [
      +        {
      +          "not": {}
      +        },
      +        {
      +          "type": "string"
      +        }
      +      ]
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
  3. Changed1 schema field changed
    • addedInput schema / properties / workspaceId
      Added value: +{
      +  "description": "Workspace ID. Omit it when this connection reaches one workspace: a workspace key (cs_) is bound to its own, and a user key (csu_) or connected app whose person belongs to exactly one workspace defaults to that one. Required only when the person belongs to several; the error then lists them, and campaignstack_whoami reports them too.",
      +  "type": "string"
      +}
  4. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": true,
      +  "properties": {
      +    "messageEntityUrn": {
      +      "anyOf": [
      +        {
      +          "anyOf": [
      +            {
      +              "not": {}
      +            },
      +            {
      +              "type": "string"
      +            }
      +          ]
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "status": {
      +      "anyOf": [
      +        {
      +          "anyOf": [
      +            {
      +              "not": {}
      +            },
      +            {
      +              "type": "string"
      +            }
      +          ]
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    }
      +  },
      +  "type": "object"
      +}
  5. Changed3 schema fields changed
    • removedInput schema / properties / dangerouslyBypassSafetySystem / default
      Removed value: -false
    • addedInput schema / properties / dangerouslyBypassSafetySystem / description
      Added value: +"Deprecated name for overrideOwnLimits. Use overrideOwnLimits."
    • addedInput schema / properties / overrideOwnLimits
      Added value: +{
      +  "description": "Tells CampaignStack to skip its OWN protective pacing for this one call: the daily budget, the weekly cap, the business-hours window, the account status check and the risk pause. These are limits CampaignStack sets to keep the account healthy. They are not LinkedIn's controls, and nothing here touches, negotiates with or works around anything LinkedIn enforces. LinkedIn's own measured ceiling is a separate check that is never overridable, and neither is a pause the account's owner set. Default false, and it should stay false. Setting it true voids the safety guarantee: from that call on, CampaignStack can no longer promise the pacing that keeps the account out of trouble, and the risk of a restriction sits with the owner. Every use is recorded in the workspace audit log. Ask the owner in plain words and get an explicit yes first. A refusal from the safety system is that system working, not a fault to route around: report the reason and let the person decide, and never retry the same send with this set.",
      +  "type": "boolean"
      +}
  6. First observed

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations: it discloses asynchronous dispatch with a messageEntityUrn, delivery confirmation via get_conversations, that a message past the daily limit still sends with a warning to pass on, that paused or LinkedIn-challenged accounts refuse the send, that business hours do not apply, and that sendAt is auto-cancelled if the other party replies first. The human-in-the-loop confirmation requirement is spelled out.

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 the core action and constraint, and nearly every sentence carries operational weight (safety gating, bulk alternative, failure modes). However it is long and repeats the 'read the wording back and wait for a yes' instruction twice (once generally, once for sendAt), which is mild redundancy rather than waste.

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?

An output schema exists so return values need not be explained, yet the description still notes the messageEntityUrn and delivery reporting. Combined with prerequisites, refusal conditions, scheduling semantics, and the supported bulk path, an agent has everything needed to call this correctly and safely.

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

Parameters3/5

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

Schema description coverage is moderate (67%) and the schema already documents sendAt, attachments, workspaceId, and idempotencyKey in detail. The description's main added value is telling the agent where conversationRef comes from (campaignstack_get_conversations), but for the other parameters it largely restates the schema, so the baseline 3 is appropriate.

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?

States a precise verb and resource: send one message into a LinkedIn conversation the owner is already part of, and immediately scopes it with 'One person per call. There is no bulk form.' This distinguishes it from siblings like campaignstack_send_connection_request, campaignstack_send_inmail, and campaignstack_craft_message without opening any schema.

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?

Explicitly covers when to use (conversationRef from get_conversations, read the thread with include.messages first), when NOT to send (last message is the owner's with no reply since), and the correct alternative for bulk outreach (edit_lead_list + trigger_workflow, which paces sends and applies the configured review). It also routes cancellation/edits to edit_conversations and pending messages to include.scheduledMessages.

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