Skip to main content
Glama
thenavidm

Senja MCP Server

by thenavidm

Senja MCP Server & CLI

npm CI License YouTube X LinkedIn

Senja MCP server and CLI for Codex and AI agents. 12 shared tools for current testimonials and invites, isolated private projects, exact reviewed tasks and bounded exports.

One package supplies both task CLI commands and local MCP tools, with a bundled Claude Desktop extension. Built and maintained by Navid Moazzez. Full setup is on navid.me.

This native terminal illustrates shipped tool names; it is not a recording of real customer messages. Use a private intended-project API key. Account features and email delivery remain subject to Senja. Official hosted MCP already supports search, links and invites; our local task workflows and limits are compared below.

Two ways to use it

Command line

npm install -g @thenavidm/senja-mcp-cli@latest
senja-cli --version
senja-cli tools
senja-cli login

MCP server, for your AI app

codex mcp add senja -- npx -y @thenavidm/senja-mcp-cli@latest

Configure private credentials in the client/runtime before native requests. Ask it to find the relevant existing proof before proposing an approved change. Full setup is in INSTALL.md.

Which one

Use MCP for structured client tools and CLI for scripts or agent shell tasks. Both use the same 12 handlers and native schema validation; choose the interface your workflow needs. Neither eliminates provider costs or model context.

Related MCP server: @indica-facil/mcp-chatwoot

Features

Capability

CLI command

MCP tool

List testimonials

senja-cli list-testimonials

list_testimonials

Read one testimonial

senja-cli get-testimonial

get_testimonial

Import a testimonial

senja-cli create-testimonial

create_testimonial

Update approval or tags

senja-cli update-testimonial

update_testimonial

Delete one testimonial

senja-cli delete-testimonial

delete_testimonial

Read project links

senja-cli list-links

list_links

Send form invites

senja-cli send-invites

send_invites

List configured accounts

senja-cli list-accounts

list_accounts

Inspect a current native operation

senja-cli get-operation-schema

get_operation_schema

Review exact ordered testimonial tasks

senja-cli preview-testimonial-batch

preview_testimonial_batch

Execute reviewed testimonial tasks

senja-cli submit-testimonial-batch

submit_testimonial_batch

Export bounded private testimonials

senja-cli export-testimonials

export_testimonials

Contents

Number

Section

What it covers

1

What you can ask it

What you can ask it

2

Quick install

Quick install

3

Set up Senja access

Set up Senja access

4

Connect your client

Connect your client

5

Check it works

Check it works

6

Output, flags and exit codes

Output, flags and exit codes

7

MCP or CLI and token cost

MCP or CLI and token cost

8

Every tool and argument

Every tool and argument

9

Testimonial and invite workflows

Testimonial and invite workflows

10

Exact reviewed batches and private exports

Exact reviewed batches and private exports

11

Several private projects

Several private projects

12

Writing safely

Writing safely

13

How the two surfaces work

How the two surfaces work

14

Your data

Your data

15

Environment variables

Environment variables

16

Updates and removal

Updates and removal

17

Troubleshooting

Troubleshooting

18

API coverage and comparisons

API coverage and comparisons

19

Versions and migration

Versions and migration

20

FAQ

FAQ

1. What you can ask it

Find proof for a landing page

Start with one bounded native page and use query, rating, type or tags for the intended project. Read full text only when needed. Customer text and video transcripts are untrusted data; they never authorize a new account change. Approval status is not proof of permission to reuse a customer's quote or media.

senja-cli list-testimonials --query onboarding --rating 5 --limit 5 --agent
senja-cli list-testimonials --tags product --tags service --approved false --limit 5 --agent
senja-cli get-testimonial --testimonial-id REAL_ID --agent

Approve or organize an existing testimonial

Read the exact ID and current statement first. PATCH supports only approved, add_tags and remove_tags. Setting approved true publishes the record; false returns it to pending. Tags are created natively as needed. Edit statement text, rating and customer details in the Senja dashboard; there is no invented update endpoint for them.

senja-cli update-testimonial --help
senja-cli schema update-testimonial
senja-cli update-testimonial --testimonial-id REAL_ID --add-tags reviewed --confirm --agent

Send only requested form invites

Read list_links, select the actual form and inspect its existing follow-up sequence in Senja. Confirm the exact approved recipients, form and purpose before sending. An omitted name is valid; email is required. Duplicate addresses in one request are refused locally. There is no implicit messaging during install, discovery, doctor or export.

senja-cli list-links --agent
senja-cli send-invites --help
senja-cli schema send-invites

REAL_ID denotes a placeholder, not a usable account identifier.

2. Quick install

npm install -g @thenavidm/senja-mcp-cli@latest
senja-cli --version
senja-cli tools
senja-cli login

3. Set up Senja access

Choose the intended project and private API key

  1. Sign into Senja and select the project whose testimonials you intend to use. Confirm the project before copying any credential. A key is a private project connection, not a general public widget ID.

  2. Open Automate and copy that project's API key into a private runtime setting. Current REST API documentation covers Free, Starter and Pro. Native plan features and account policies remain separate; the wrapper does not bypass them.

  3. Configure exactly one of SENJA_API_KEY or SENJA_TOKEN_FILE. The latter is an absolute, regular, non-symlink, token-only file outside repositories, at most 64 KiB. The client sends Authorization: Bearer; do not prefix the setting with Bearer or use your login password.

  4. On macOS/Linux restrict the file to your owner with mode 0600 and its parent directory to your owner. On Windows restrict file and parent-directory ACLs separately. POSIX modes do not establish Windows privacy. Each server runtime must be able to read its own file; a GUI, Docker or remote host does not inherit a different terminal's environment automatically.

  5. Run senja-cli doctor for local configuration. When you deliberately want an authenticated read, run doctor --network: it requests GET /testimonials?limit=1 and prints count/verification metadata, not customer records. This proves one project read, not ownership, permission for every endpoint, successful email delivery or an approved mutation.

The package does not load .env files, import browser cookies, create keys, connect OAuth or rotate credentials. login prints these setup instructions only. Keep resolved secrets out of code, screenshots, public issues, version control and AI prompts.

Project profiles and revocation

SENJA_ACCOUNTS is a private JSON array of unique {name,api_key,token_file} profiles. Use one credential method per profile. SENJA_DEFAULT_ACCOUNT selects the default label and --account selects an exact label. An incomplete named profile never inherits a global key, another project or an official hosted session after a missing credential or 401/403.

list_accounts returns labels/default/auth/source only, without keys, token paths, native project identity or network traffic. Token-only files cache until restart. Changing a file while a process is running does not rotate its cached connection.

To revoke a key, use the intended project's Automate > Regenerate API Key as its Admin/Owner, update every dependent private integration and restart its processes. The provider says the old key stops working after a short transition. Official hosted MCP authorization is a separate connection. Removing this package does not undo testimonial edits, publish approval, permanent deletion, emailed invites, follow-up sequences or existing exports.

Effects and local limits

There is no universal provider quota invented here. Local spacing defaults to 250 ms and request timeout 30 seconds; other processes share native project quotas. Bodies cap at 1 MiB and responses at 5 MiB. No automatic retry, redirect following or media download occurs. A failed write can have an unknown outcome; inspect native state before any explicit repeat.

send_invites uses a real forms[].id from list_links and that form's existing email/follow-up sequence. It is not a local draft, arbitrary email editor or test-send command. Its local 100-recipient cap is not a documented native quota. Receipt sent/skipped values do not prove delivered messages or consent. Only send to the actual approved recipients and purpose.

4. Connect your client

Full client, OS, desktop, private credential and runtime instructions are in INSTALL.md.

Codex

Codex is the current validation priority. Private token paths must exist in the process or remote environment where the server runs.

codex mcp add senja -- npx -y @thenavidm/senja-mcp-cli@latest
codex mcp list

Account credentials must reach the server through private environment settings. codex mcp add --env NAME=value stores values in your local config, so never commit that config or put secrets in a shared command. In TOML, the equivalent server is:

[mcp_servers.senja]
command = "npx"
args = ["-y", "@thenavidm/senja-mcp-cli@latest"]
env_vars = ["SENJA_API_KEY", "SENJA_TOKEN_FILE", "SENJA_ACCOUNTS", "SENJA_DEFAULT_ACCOUNT", "SENJA_READ_ONLY", "SENJA_ALLOW_DESTRUCTIVE"]

env_vars forwards those names from the environment available to Codex. If that environment does not contain them, configure private env settings locally. Codex can also call the CLI directly with SKILL.md and --agent output.

Claude Code

For a user-scoped connection, after privately configuring credentials:

claude mcp add --scope user senja -- npx -y @thenavidm/senja-mcp-cli@latest
claude mcp list

Use the client's private local environment settings for the account variable if they are not inherited. Claude's -e NAME=value registration option writes values into its config; only use it locally through your secret manager, with no shared command transcript. Never place credentials in a project .mcp.json. Reconnect and ask Claude to verify credentials.

Alternatively install the CLI, make SKILL.md available to Claude, and use shell commands. Registering both surfaces is optional.

Claude Desktop

Install the .mcpb extension

  1. Download senja-2.0.0.mcpb from GitHub Releases.

  2. In a supported Claude Desktop build, open Settings > Extensions > Advanced settings > Install Extension… and select it.

  3. Enter a private project API key in the sensitive setting, OR an absolute private token-only file path. Leave the unused method empty. Requests use Authorization: Bearer. Named profiles require private manual runtime settings.

  4. Enable read-only if you want only the 6 read operations. Reconnect and verify the intended project with one deliberate read.

The bundle includes production dependencies and no credentials. Use a regular private token-only file if you prefer file-based credentials. The manifest requires Node 22 or newer from a compatible host. Organization policy may restrict custom extensions. Manual bundle updates require installing the new version; no automatic directory updates are promised. GUI installation remains unverified separately from archive/protocol checks.

Manual config

Open Settings > Developer > Edit Config, or use your platform's config file:

OS

Typical config path

macOS

~/Library/Application Support/Claude/claude_desktop_config.json

Windows

%APPDATA%\Claude\claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json; confirm the location through Edit Config in your installed build

{
  "mcpServers": {
    "senja": {
      "command": "npx",
      "args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
      "env": {
        "SENJA_API_KEY": "YOUR_PRIVATE_API_KEY",
        "SENJA_TOKEN_FILE": ""
      }
    }
  }
}

Replace the placeholders only in your private file. Merge the server entry into an existing mcpServers object instead of replacing other integrations. Fully quit and reopen Claude Desktop. Do not enable an extension and a manual entry with the same name; choose one route.

If a Windows launcher cannot execute npx directly, use "command": "cmd" with "args": ["/c", "npx", "-y", "@thenavidm/senja-mcp-cli@latest"]. An absolute node executable and installed dist/index.js path also avoids launcher/PATH problems.

Cursor

Use private user settings at ~/.cursor/mcp.json, or Settings > Tools & MCP. Cursor documents environment interpolation and envFile support.

{
  "mcpServers": {
    "senja": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
      "env": {
        "SENJA_API_KEY": "${env:SENJA_API_KEY}",
        "SENJA_TOKEN_FILE": "${env:SENJA_TOKEN_FILE}"
      }
    }
  }
}

The environment values must exist for the Cursor process. If you use envFile, keep that file private and outside version control. A project's .cursor/mcp.json must not contain actual credentials. Reconnect the server after saving.

VS Code and Copilot

Use MCP: Open User Configuration. VS Code uses servers and secure inputs, rather than a mcpServers root:

{
  "inputs": [
    {"type": "promptString", "id": "senja-api-token", "description": "Senja API key (leave empty for a private token file)", "password": true},
    {"type": "promptString", "id": "senja-token-file", "description": "Optional private token-file path (leave empty for API key)"}
  ],
  "servers": {
    "senja": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
      "env": {
        "SENJA_API_KEY": "${input:senja-api-token}",
        "SENJA_TOKEN_FILE": "${input:senja-token-file}"
      }
    }
  }
}

Start Senja through the MCP controls, approve trust if prompted, and enter credentials in the private input prompts. Workspace .vscode/mcp.json may contain this placeholder-only structure, but never resolved secret values. Remote development runs the server in the selected remote environment, so local file paths refer to that environment.

Windsurf

Open Cascade's MCP settings or edit the private user file ~/.codeium/windsurf/mcp_config.json. Use the Claude Desktop manual mcpServers block above with your locally configured env values. See Windsurf's current MCP documentation. Restart or reconnect Senja in Cascade; project files must not contain secrets.

Zed

Open Settings > AI > MCP Servers > Add Server > Add Local Server, or your user settings file. Zed uses context_servers:

{
  "context_servers": {
    "senja": {
      "command": "npx",
      "args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
      "env": {
        "SENJA_API_KEY": "YOUR_PRIVATE_API_KEY",
        "SENJA_TOKEN_FILE": ""
      }
    }
  }
}

Enter actual values only in private user settings. Check the active-server indicator before prompting. Do not wrap command and args inside a nested command object from older Zed examples.

Gemini CLI

Merge the Claude Desktop manual mcpServers block into your private ~/.gemini/settings.json. Configure the private credential values locally, then restart Gemini CLI and inspect /mcp. See Gemini CLI's MCP configuration. Its project settings must not contain real credentials. You can instead use the CLI from an agent shell.

Other local stdio clients use the same command and arguments, adapted to their config format. A client that only accepts a remote MCP URL cannot connect directly: this package does not ship a public HTTP listener. ChatGPT's remote connector setup is not a substitute for local stdio installation.

Docker

Build locally from the reviewed source; no prebuilt registry image is claimed:

git clone https://github.com/thenavidm/senja-mcp-cli.git
cd senja-mcp-cli
docker build -t senja-mcp-cli .
docker run --rm -i -e SENJA_API_KEY senja-mcp-cli

Cline and other local MCP clients

Use the client's Add MCP server flow with command npx, arguments -y and @thenavidm/senja-mcp-cli@latest, stdio transport, and private local SENJA_API_KEY or SENJA_TOKEN_FILE settings. UI names depend on the installed client. Reconnect and discover tools before an account call. Browser-only clients need a remote HTTPS connector; use Senja's official server rather than this local stdio command.

5. Check it works

senja-cli --version
senja-cli tools
senja-cli list-accounts --agent
senja-cli doctor
senja-cli doctor --network
senja-cli list-testimonials --limit 1 --agent --select total,testimonials.id

Only the final two commands intentionally contact Senja. The one-item example may return a private ID; use doctor --network if you only need verification metadata. Never create, approve, delete or email a testimonial merely to test installation. Fixtures/protocol discovery, actual provider outcomes, desktop GUI installation and completed Codex usage measurements are distinct checks.

6. Output, flags and exit codes

senja-cli tools --agent
senja-cli list-testimonials --limit 5 --agent --select total,testimonials.id
senja-cli schema send-invites

--agent requests JSON/compact/no-input/no-color/yes formatting, not confirmation. Repeated array flags collect tags; one --recipients or --tasks flag contains one JSON object. Whole native bodies use payload or an absolute regular non-symlink payload_file capped1MiB. Do not mix body methods.

Exit

Meaning

0

Success

2

Usage, invalid native input or refused effect

3

Not found

4

Authentication/permission

5

Native API error

7

Rate limited

10

Missing/invalid private configuration

7. MCP or CLI and token cost

MCP clients can load all schemas, defer discovery, or load selected schemas; the mode changes input overhead. CLI use still needs command/schema discovery and model-readable results. --agent and --select can reduce formatting/output for an appropriate task, but do not prove smaller total cost.

Codex is the current verification client. No completed matched provider task/token comparison has been measured for this release. Record actual model/client/package versions, dates, loading settings, prompt/result sizes, successful equivalent outcomes and API usage before publishing numbers. Do not estimate tokens from characters or reuse another client's measurements. Installed skills may incur recurring listing and one-time reading costs, and caching changes billed cost separately from token counts.

8. Every tool and argument

list_testimonials

Read one native page with exact current search, tag, approval, language and date/rating filters.

Argument

Type

Required

Meaning and constraints

sort

string

Optional

Native sort field; direction uses order. {"enum": ["date", "rating"]}

order

string

Optional

{"enum": ["asc", "desc"]}

approved

boolean

Optional

Exact native/schema value

rating

integer

Optional

{"minimum": 1, "maximum": 5}

type

string

Optional

{"enum": ["text", "video"]}

integration

string

Optional

{"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}

tags

array

Optional

{"maxItems": 100}

query

string

Optional

Native full-text search, including customer name/email; output may contain personal data.

lang

string

Optional

Native ISO 639 language selector.

limit

integer

Optional

Native page size. total counts only the current page. {"minimum": 1, "maximum": 1000}

page

integer

Optional

{"minimum": 1}

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

senja-cli list-testimonials --help
senja-cli schema list-testimonials
{
  "type": "object",
  "properties": {
    "sort": {
      "type": "string",
      "enum": [
        "date",
        "rating"
      ],
      "description": "Native sort field; direction uses order."
    },
    "order": {
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    },
    "approved": {
      "type": "boolean"
    },
    "rating": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "type": {
      "type": "string",
      "enum": [
        "text",
        "video"
      ]
    },
    "integration": {
      "type": "string",
      "enum": [
        "twitter",
        "product_hunt",
        "google",
        "facebook",
        "reddit",
        "capterra",
        "g2",
        "linkedin",
        "app_store",
        "trustpilot",
        "shopify",
        "play_store",
        "yelp",
        "slack",
        "discord",
        "apple_podcasts",
        "telegram",
        "whatsapp",
        "instagram",
        "youtube",
        "tiktok",
        "appsumo",
        "amazon",
        "zillow",
        "udemy",
        "chrome_web_store",
        "airbnb",
        "skillshare",
        "realtor",
        "sourceforge",
        "whop",
        "wordpress",
        "fiverr",
        "homestars",
        "web_page"
      ]
    },
    "tags": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "string",
        "minLength": 1,
        "description": "Nonempty tag name."
      }
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Native full-text search, including customer name/email; output may contain personal data.",
      "maxLength": 10000
    },
    "lang": {
      "type": "string",
      "minLength": 1,
      "description": "Native ISO 639 language selector.",
      "maxLength": 10
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 1000,
      "description": "Native page size. total counts only the current page."
    },
    "page": {
      "type": "integer",
      "minimum": 1
    },
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    }
  },
  "required": [],
  "additionalProperties": false
}

Native request: GET /testimonials. No native JSON body.

{
  "name": "list_testimonials",
  "method": "GET",
  "path": "/testimonials",
  "title": "List testimonials",
  "description": "Read one native page with exact current search, tag, approval, language and date/rating filters.",
  "group": "testimonials",
  "risk": "read",
  "params": [
    {
      "name": "sort",
      "key": "sort",
      "schema": {
        "type": "string",
        "enum": [
          "date",
          "rating"
        ],
        "description": "Native sort field; direction uses order."
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "order",
      "key": "order",
      "schema": {
        "type": "string",
        "enum": [
          "asc",
          "desc"
        ]
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "approved",
      "key": "approved",
      "schema": {
        "type": "boolean"
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "rating",
      "key": "rating",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 5
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "type",
      "key": "type",
      "schema": {
        "type": "string",
        "enum": [
          "text",
          "video"
        ]
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "integration",
      "key": "integration",
      "schema": {
        "type": "string",
        "enum": [
          "twitter",
          "product_hunt",
          "google",
          "facebook",
          "reddit",
          "capterra",
          "g2",
          "linkedin",
          "app_store",
          "trustpilot",
          "shopify",
          "play_store",
          "yelp",
          "slack",
          "discord",
          "apple_podcasts",
          "telegram",
          "whatsapp",
          "instagram",
          "youtube",
          "tiktok",
          "appsumo",
          "amazon",
          "zillow",
          "udemy",
          "chrome_web_store",
          "airbnb",
          "skillshare",
          "realtor",
          "sourceforge",
          "whop",
          "wordpress",
          "fiverr",
          "homestars",
          "web_page"
        ]
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "tags",
      "key": "tags",
      "schema": {
        "type": "array",
        "maxItems": 100,
        "items": {
          "type": "string",
          "minLength": 1,
          "description": "Nonempty tag name."
        }
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "query",
      "key": "query",
      "schema": {
        "type": "string",
        "minLength": 1,
        "description": "Native full-text search, including customer name/email; output may contain personal data.",
        "maxLength": 10000
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "lang",
      "key": "lang",
      "schema": {
        "type": "string",
        "minLength": 1,
        "description": "Native ISO 639 language selector.",
        "maxLength": 10
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "limit",
      "key": "limit",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 1000,
        "description": "Native page size. total counts only the current page."
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    },
    {
      "name": "page",
      "key": "page",
      "schema": {
        "type": "integer",
        "minimum": 1
      },
      "in": "query",
      "required": false,
      "style": "form",
      "explode": true
    }
  ],
  "bodySchema": null,
  "bodyRequired": false,
  "privateOutput": false
}

get_testimonial

Read one exact testimonial, including native video metadata and public/dashboard links.

Argument

Type

Required

Meaning and constraints

testimonial_id

string

Required

Exact testimonial ID. No slash, traversal or arbitrary URL.

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

senja-cli get-testimonial --help
senja-cli schema get-testimonial
{
  "type": "object",
  "properties": {
    "testimonial_id": {
      "type": "string",
      "minLength": 1,
      "description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
    },
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    }
  },
  "required": [
    "testimonial_id"
  ],
  "additionalProperties": false
}

Native request: GET /testimonials/{testimonial_id}. No native JSON body.

{
  "name": "get_testimonial",
  "method": "GET",
  "path": "/testimonials/{testimonial_id}",
  "title": "Read one testimonial",
  "description": "Read one exact testimonial, including native video metadata and public/dashboard links.",
  "group": "testimonials",
  "risk": "read",
  "params": [
    {
      "name": "testimonial_id",
      "key": "testimonial_id",
      "schema": {
        "type": "string",
        "minLength": 1,
        "description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
      },
      "in": "path",
      "required": true,
      "style": "form",
      "explode": true
    }
  ],
  "bodySchema": null,
  "bodyRequired": false,
  "privateOutput": false
}

create_testimonial

Create one text/video testimonial from an authorized existing customer statement. Explicit approval is required.

Argument

Type

Required

Meaning and constraints

title

string

Optional

Exact native/schema value

text

string

Optional

Exact native/schema value

customer_name

string

Optional

Exact native/schema value

customer_company

string

Optional

Exact native/schema value

customer_tagline

string

Optional

Exact native/schema value

customer_username

string

Optional

Exact native/schema value

form_id

string

Optional

Exact native/schema value

url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

thumbnail_url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

customer_avatar

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

customer_company_logo

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

customer_url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

video_url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

type

string

Optional

{"enum": ["text", "video"]}

customer_email

string

Optional

{"format": "email"}

rating

integer

Optional

{"minimum": 1, "maximum": 5}

date

string

Optional

{"format": "date-time"}

approved

boolean

Optional

Explicitly true publishes the testimonial; false keeps it pending.

integration

string

Optional

{"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}

tags

array

Optional

{"maxItems": 100}

media

array

Optional

{"maxItems": 100}

media[].alt

string

Optional

Exact native/schema value

media[].url

string

Required

{"format": "uri"}

media[].type

string

Required

{"enum": ["image", "video"]}

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

confirm

boolean

Optional

Must be true for the requested mutation or exclusive private output file.

payload

object

Optional

Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.

payload.title

string

Optional

Exact native/schema value

payload.text

string

Optional

Exact native/schema value

payload.customer_name

string

Required

Exact native/schema value

payload.customer_company

string

Optional

Exact native/schema value

payload.customer_tagline

string

Optional

Exact native/schema value

payload.customer_username

string

Optional

Exact native/schema value

payload.form_id

string

Optional

Exact native/schema value

payload.url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

payload.thumbnail_url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

payload.customer_avatar

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

payload.customer_company_logo

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

payload.customer_url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

payload.video_url

string

Optional

HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}

payload.type

string

Required

{"enum": ["text", "video"]}

payload.customer_email

string

Optional

{"format": "email"}

payload.rating

integer

Optional

{"minimum": 1, "maximum": 5}

payload.date

string

Optional

{"format": "date-time"}

payload.approved

boolean

Optional

Explicitly true publishes the testimonial; false keeps it pending.

payload.integration

string

Optional

{"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}

payload.tags

array

Optional

{"maxItems": 100}

payload.media

array

Optional

{"maxItems": 100}

payload.media[].alt

string

Optional

Exact native/schema value

payload.media[].url

string

Required

{"format": "uri"}

payload.media[].type

string

Required

{"enum": ["image", "video"]}

payload_file

string

Optional

Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.

senja-cli create-testimonial --help
senja-cli schema create-testimonial
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "minLength": 1,
      "description": ""
    },
    "text": {
      "type": "string",
      "minLength": 1,
      "description": ""
    },
    "customer_name": {
      "type": "string",
      "minLength": 1,
      "description": ""
    },
    "customer_company": {
      "type": "string",
      "minLength": 1,
      "description": ""
    },
    "customer_tagline": {
      "type": "string",
      "minLength": 1,
      "description": ""
    },
    "customer_username": {
      "type": "string",
      "minLength": 1,
      "description": ""
    },
    "form_id": {
      "type": "string",
      "minLength": 1,
      "description": ""
    },
    "url": {
      "type": "string",
      "minLength": 1,
      "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
      "format": "uri"
    },
    "thumbnail_url": {
      "type": "string",
      "minLength": 1,
      "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
      "format": "uri"
    },
    "customer_avatar": {
      "type": "string",
      "minLength": 1,
      "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
      "format": "uri"
    },
    "customer_company_logo": {
      "type": "string",
      "minLength": 1,
      "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
      "format": "uri"
    },
    "customer_url": {
      "type": "string",
      "minLength": 1,
      "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
      "format": "uri"
    },
    "video_url": {
      "type": "string",
      "minLength": 1,
      "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
      "format": "uri"
    },
    "type": {
      "type": "string",
      "enum": [
        "text",
        "video"
      ]
    },
    "customer_email": {
      "type": "string",
      "minLength": 1,
      "description": "",
      "format": "email"
    },
    "rating": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "date": {
      "type": "string",
      "minLength": 1,
      "description": "",
      "format": "date-time"
    },
    "approved": {
      "type": "boolean",
      "description": "Explicitly true publishes the testimonial; false keeps it pending."
    },
    "integration": {
      "type": "string",
      "enum": [
        "twitter",
        "product_hunt",
        "google",
        "facebook",
        "reddit",
        "capterra",
        "g2",
        "linkedin",
        "app_store",
        "trustpilot",
        "shopify",
        "play_store",
        "yelp",
        "slack",
        "discord",
        "apple_podcasts",
        "telegram",
        "whatsapp",
        "instagram",
        "youtube",
        "tiktok",
        "appsumo",
        "amazon",
        "zillow",
        "udemy",
        "chrome_web_store",
        "airbnb",
        "skillshare",
        "realtor",
        "sourceforge",
        "whop",
        "wordpress",
        "fiverr",
        "homestars",
        "web_page"
      ]
    },
    "tags": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "string",
        "minLength": 1,
        "description": "Nonempty tag name."
      }
    },
    "media": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "object",
        "properties": {
          "alt": {
            "type": "string",
            "minLength": 1,
            "description": ""
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "description": "",
            "format": "uri"
          },
          "type": {
            "type": "string",
            "enum": [
              "image",
              "video"
            ]
          }
        },
        "required": [
          "url",
          "type"
        ],
        "additionalProperties": false
      }
    },
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    },
    "confirm": {
      "type": "boolean",
      "description": "Must be true for the requested mutation or exclusive private output file."
    },
    "payload": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "description": ""
        },
        "text": {
          "type": "string",
          "minLength": 1,
          "description": ""
        },
        "customer_name": {
          "type": "string",
          "minLength": 1,
          "description": ""
        },
        "customer_company": {
          "type": "string",
          "minLength": 1,
          "description": ""
        },
        "customer_tagline": {
          "type": "string",
          "minLength": 1,
          "description": ""
        },
        "customer_username": {
          "type": "string",
          "minLength": 1,
          "description": ""
        },
        "form_id": {
          "type": "string",
          "minLength": 1,
          "description": ""
        },
        "url": {
          "type": "string",
          "minLength": 1,
          "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
          "format": "uri"
        },
        "thumbnail_url": {
          "type": "string",
          "minLength": 1,
          "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
          "format": "uri"
        },
        "customer_avatar": {
          "type": "string",
          "minLength": 1,
          "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
          "format": "uri"
        },
        "customer_company_logo": {
          "type": "string",
          "minLength": 1,
          "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
          "format": "uri"
        },
        "customer_url": {
          "type": "string",
          "minLength": 1,
          "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
          "format": "uri"
        },
        "video_url": {
          "type": "string",
          "minLength": 1,
          "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
          "format": "uri"
        },
        "type": {
          "type": "string",
          "enum": [
            "text",
            "video"
          ]
        },
        "customer_email": {
          "type": "string",
          "minLength": 1,
          "description": "",
          "format": "email"
        },
        "rating": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5
        },
        "date": {
          "type": "string",
          "minLength": 1,
          "description": "",
          "format": "date-time"
        },
        "approved": {
          "type": "boolean",
          "description": "Explicitly true publishes the testimonial; false keeps it pending."
        },
        "integration": {
          "type": "string",
          "enum": [
            "twitter",
            "product_hunt",
            "google",
            "facebook",
            "reddit",
            "capterra",
            "g2",
            "linkedin",
            "app_store",
            "trustpilot",
            "shopify",
            "play_store",
            "yelp",
            "slack",
            "discord",
            "apple_podcasts",
            "telegram",
            "whatsapp",
            "instagram",
            "youtube",
            "tiktok",
            "appsumo",
            "amazon",
            "zillow",
            "udemy",
            "chrome_web_store",
            "airbnb",
            "skillshare",
            "realtor",
            "sourceforge",
            "whop",
            "wordpress",
            "fiverr",
            "homestars",
            "web_page"
          ]
        },
        "tags": {
          "type": "array",
          "maxItems": 100,
          "items": {
            "type": "string",
            "minLength": 1,
            "description": "Nonempty tag name."
          }
        },
        "media": {
          "type": "array",
          "maxItems": 100,
          "items": {
            "type": "object",
            "properties": {
              "alt": {
                "type": "string",
                "minLength": 1,
                "description": ""
              },
              "url": {
                "type": "string",
                "minLength": 1,
                "description": "",
                "format": "uri"
              },
              "type": {
                "type": "string",
                "enum": [
                  "image",
                  "video"
                ]
              }
            },
            "required": [
              "url",
              "type"
            ],
            "additionalProperties": false
          }
        }
      },
      "required": [
        "type",
        "customer_name"
      ],
      "additionalProperties": false,
      "description": "Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file."
    },
    "payload_file": {
      "type": "string",
      "minLength": 1,
      "description": "Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags."
    }
  },
  "required": [],
  "additionalProperties": false
}

Native request: POST /testimonials. Provide native body fields OR payload OR payload_file, never mixed. Native body required: type, customer_name

{
  "name": "create_testimonial",
  "method": "POST",
  "path": "/testimonials",
  "title": "Import a testimonial",
  "description": "Create one text/video testimonial from an authorized existing customer statement. Explicit approval is required.",
  "group": "testimonials",
  "risk": "destructive",
  "params": [],
  "bodySchema": {
    "type": "object",
    "properties": {
      "title": {
        "type": "string",
        "minLength": 1,
        "description": ""
      },
      "text": {
        "type": "string",
        "minLength": 1,
        "description": ""
      },
      "customer_name": {
        "type": "string",
        "minLength": 1,
        "description": ""
      },
      "customer_company": {
        "type": "string",
        "minLength": 1,
        "description": ""
      },
      "customer_tagline": {
        "type": "string",
        "minLength": 1,
        "description": ""
      },
      "customer_username": {
        "type": "string",
        "minLength": 1,
        "description": ""
      },
      "form_id": {
        "type": "string",
        "minLength": 1,
        "description": ""
      },
      "url": {
        "type": "string",
        "minLength": 1,
        "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
        "format": "uri"
      },
      "thumbnail_url": {
        "type": "string",
        "minLength": 1,
        "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
        "format": "uri"
      },
      "customer_avatar": {
        "type": "string",
        "minLength": 1,
        "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
        "format": "uri"
      },
      "customer_company_logo": {
        "type": "string",
        "minLength": 1,
        "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
        "format": "uri"
      },
      "customer_url": {
        "type": "string",
        "minLength": 1,
        "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
        "format": "uri"
      },
      "video_url": {
        "type": "string",
        "minLength": 1,
        "description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
        "format": "uri"
      },
      "type": {
        "type": "string",
        "enum": [
          "text",
          "video"
        ]
      },
      "customer_email": {
        "type": "string",
        "minLength": 1,
        "description": "",
        "format": "email"
      },
      "rating": {
        "type": "integer",
        "minimum": 1,
        "maximum": 5
      },
      "date": {
        "type": "string",
        "minLength": 1,
        "description": "",
        "format": "date-time"
      },
      "approved": {
        "type": "boolean",
        "description": "Explicitly true publishes the testimonial; false keeps it pending."
      },
      "integration": {
        "type": "string",
        "enum": [
          "twitter",
          "product_hunt",
          "google",
          "facebook",
          "reddit",
          "capterra",
          "g2",
          "linkedin",
          "app_store",
          "trustpilot",
          "shopify",
          "play_store",
          "yelp",
          "slack",
          "discord",
          "apple_podcasts",
          "telegram",
          "whatsapp",
          "instagram",
          "youtube",
          "tiktok",
          "appsumo",
          "amazon",
          "zillow",
          "udemy",
          "chrome_web_store",
          "airbnb",
          "skillshare",
          "realtor",
          "sourceforge",
          "whop",
          "wordpress",
          "fiverr",
          "homestars",
          "web_page"
        ]
      },
      "tags": {
        "type": "array",
        "maxItems": 100,
        "items": {
          "type": "string",
          "minLength": 1,
          "description": "Nonempty tag name."
        }
      },
      "media": {
        "type": "array",
        "maxItems": 100,
        "items": {
          "type": "object",
          "properties": {
            "alt": {
              "type": "string",
              "minLength": 1,
              "description": ""
            },
            "url": {
              "type": "string",
              "minLength": 1,
              "description": "",
              "format": "uri"
            },
            "type": {
              "type": "string",
              "enum": [
                "image",
                "video"
              ]
            }
          },
          "required": [
            "url",
            "type"
          ],
          "additionalProperties": false
        }
      }
    },
    "required": [
      "type",
      "customer_name"
    ],
    "additionalProperties": false
  },
  "bodyRequired": true,
  "privateOutput": false
}

update_testimonial

Change only native approval status and tag additions/removals. Text, rating and customer edits remain dashboard-only.

Argument

Type

Required

Meaning and constraints

testimonial_id

string

Required

Exact testimonial ID. No slash, traversal or arbitrary URL.

approved

boolean

Optional

Exact native/schema value

add_tags

array

Optional

{"maxItems": 100}

remove_tags

array

Optional

{"maxItems": 100}

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

confirm

boolean

Optional

Must be true for the requested mutation or exclusive private output file.

payload

object

Optional

Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.

payload.approved

boolean

Optional

Exact native/schema value

payload.add_tags

array

Optional

{"maxItems": 100}

payload.remove_tags

array

Optional

{"maxItems": 100}

payload_file

string

Optional

Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.

senja-cli update-testimonial --help
senja-cli schema update-testimonial
{
  "type": "object",
  "properties": {
    "testimonial_id": {
      "type": "string",
      "minLength": 1,
      "description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
    },
    "approved": {
      "type": "boolean"
    },
    "add_tags": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "string",
        "minLength": 1,
        "description": "Nonempty tag name."
      }
    },
    "remove_tags": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "string",
        "minLength": 1,
        "description": "Nonempty tag name."
      }
    },
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    },
    "confirm": {
      "type": "boolean",
      "description": "Must be true for the requested mutation or exclusive private output file."
    },
    "payload": {
      "type": "object",
      "properties": {
        "approved": {
          "type": "boolean"
        },
        "add_tags": {
          "type": "array",
          "maxItems": 100,
          "items": {
            "type": "string",
            "minLength": 1,
            "description": "Nonempty tag name."
          }
        },
        "remove_tags": {
          "type": "array",
          "maxItems": 100,
          "items": {
            "type": "string",
            "minLength": 1,
            "description": "Nonempty tag name."
          }
        }
      },
      "required": [],
      "additionalProperties": false,
      "description": "Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file."
    },
    "payload_file": {
      "type": "string",
      "minLength": 1,
      "description": "Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags."
    }
  },
  "required": [
    "testimonial_id"
  ],
  "additionalProperties": false
}

Native request: PATCH /testimonials/{testimonial_id}. Provide native body fields OR payload OR payload_file, never mixed. Native body requires at least one approval or nonempty tag change.

{
  "name": "update_testimonial",
  "method": "PATCH",
  "path": "/testimonials/{testimonial_id}",
  "title": "Update approval or tags",
  "description": "Change only native approval status and tag additions/removals. Text, rating and customer edits remain dashboard-only.",
  "group": "testimonials",
  "risk": "destructive",
  "params": [
    {
      "name": "testimonial_id",
      "key": "testimonial_id",
      "schema": {
        "type": "string",
        "minLength": 1,
        "description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
      },
      "in": "path",
      "required": true,
      "style": "form",
      "explode": true
    }
  ],
  "bodySchema": {
    "type": "object",
    "properties": {
      "approved": {
        "type": "boolean"
      },
      "add_tags": {
        "type": "array",
        "maxItems": 100,
        "items": {
          "type": "string",
          "minLength": 1,
          "description": "Nonempty tag name."
        }
      },
      "remove_tags": {
        "type": "array",
        "maxItems": 100,
        "items": {
          "type": "string",
          "minLength": 1,
          "description": "Nonempty tag name."
        }
      }
    },
    "required": [],
    "additionalProperties": false
  },
  "bodyRequired": true,
  "privateOutput": false
}

delete_testimonial

Permanently delete exactly the requested testimonial. Irreversible; confirmation required.

Argument

Type

Required

Meaning and constraints

testimonial_id

string

Required

Exact testimonial ID. No slash, traversal or arbitrary URL.

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

confirm

boolean

Optional

Must be true for the requested mutation or exclusive private output file.

senja-cli delete-testimonial --help
senja-cli schema delete-testimonial
{
  "type": "object",
  "properties": {
    "testimonial_id": {
      "type": "string",
      "minLength": 1,
      "description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
    },
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    },
    "confirm": {
      "type": "boolean",
      "description": "Must be true for the requested mutation or exclusive private output file."
    }
  },
  "required": [
    "testimonial_id"
  ],
  "additionalProperties": false
}

Native request: DELETE /testimonials/{testimonial_id}. No native JSON body.

{
  "name": "delete_testimonial",
  "method": "DELETE",
  "path": "/testimonials/{testimonial_id}",
  "title": "Delete one testimonial",
  "description": "Permanently delete exactly the requested testimonial. Irreversible; confirmation required.",
  "group": "testimonials",
  "risk": "destructive",
  "params": [
    {
      "name": "testimonial_id",
      "key": "testimonial_id",
      "schema": {
        "type": "string",
        "minLength": 1,
        "description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
      },
      "in": "path",
      "required": true,
      "style": "form",
      "explode": true
    }
  ],
  "bodySchema": null,
  "bodyRequired": false,
  "privateOutput": false
}

Read native form, widget, Wall of Love, quick-link, case-study and sizzle-reel groups with their IDs and URLs.

Argument

Type

Required

Meaning and constraints

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

senja-cli list-links --help
senja-cli schema list-links
{
  "type": "object",
  "properties": {
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    }
  },
  "required": [],
  "additionalProperties": false
}

Native request: GET /links. No native JSON body.

{
  "name": "list_links",
  "method": "GET",
  "path": "/links",
  "title": "Read project links",
  "description": "Read native form, widget, Wall of Love, quick-link, case-study and sizzle-reel groups with their IDs and URLs.",
  "group": "project_links",
  "risk": "read",
  "params": [],
  "bodySchema": null,
  "bodyRequired": false,
  "privateOutput": false
}

send_invites

Send email invites using a selected form and its existing follow-up sequence. Local cap100 recipients, not a documented provider quota.

Argument

Type

Required

Meaning and constraints

form_id

string

Optional

Exact forms[].id from list_links.

recipients

array

Optional

{"minItems": 1, "maxItems": 100}

recipients[].email

string

Required

{"format": "email"}

recipients[].name

string

Optional

Exact native/schema value

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

confirm

boolean

Optional

Must be true for the requested mutation or exclusive private output file.

payload

object

Optional

Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.

payload.form_id

string

Required

Exact forms[].id from list_links.

payload.recipients

array

Required

{"minItems": 1, "maxItems": 100}

payload.recipients[].email

string

Required

{"format": "email"}

payload.recipients[].name

string

Optional

Exact native/schema value

payload_file

string

Optional

Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.

senja-cli send-invites --help
senja-cli schema send-invites
{
  "type": "object",
  "properties": {
    "form_id": {
      "type": "string",
      "minLength": 1,
      "description": "Exact forms[].id from list_links."
    },
    "recipients": {
      "type": "array",
      "minItems": 1,
      "maxItems": 100,
      "items": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "minLength": 1,
            "description": "",
            "format": "email"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "description": ""
          }
        },
        "required": [
          "email"
        ],
        "additionalProperties": false
      }
    },
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    },
    "confirm": {
      "type": "boolean",
      "description": "Must be true for the requested mutation or exclusive private output file."
    },
    "payload": {
      "type": "object",
      "properties": {
        "form_id": {
          "type": "string",
          "minLength": 1,
          "description": "Exact forms[].id from list_links."
        },
        "recipients": {
          "type": "array",
          "minItems": 1,
          "maxItems": 100,
          "items": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string",
                "minLength": 1,
                "description": "",
                "format": "email"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "description": ""
              }
            },
            "required": [
              "email"
            ],
            "additionalProperties": false
          }
        }
      },
      "required": [
        "form_id",
        "recipients"
      ],
      "additionalProperties": false,
      "description": "Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file."
    },
    "payload_file": {
      "type": "string",
      "minLength": 1,
      "description": "Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags."
    }
  },
  "required": [],
  "additionalProperties": false
}

Native request: POST /invites. Provide native body fields OR payload OR payload_file, never mixed. Native body required: form_id, recipients

{
  "name": "send_invites",
  "method": "POST",
  "path": "/invites",
  "title": "Send form invites",
  "description": "Send email invites using a selected form and its existing follow-up sequence. Local cap100 recipients, not a documented provider quota.",
  "group": "invites",
  "risk": "destructive",
  "params": [],
  "bodySchema": {
    "type": "object",
    "properties": {
      "form_id": {
        "type": "string",
        "minLength": 1,
        "description": "Exact forms[].id from list_links."
      },
      "recipients": {
        "type": "array",
        "minItems": 1,
        "maxItems": 100,
        "items": {
          "type": "object",
          "properties": {
            "email": {
              "type": "string",
              "minLength": 1,
              "description": "",
              "format": "email"
            },
            "name": {
              "type": "string",
              "minLength": 1,
              "description": ""
            }
          },
          "required": [
            "email"
          ],
          "additionalProperties": false
        }
      }
    },
    "required": [
      "form_id",
      "recipients"
    ],
    "additionalProperties": false
  },
  "bodyRequired": true,
  "privateOutput": false
}

list_accounts

Local profile labels/default/auth method only. No keys, token paths, provider identity or network request.

Argument

Type

Required

Meaning and constraints

senja-cli list-accounts --help
senja-cli schema list-accounts
{
  "type": "object",
  "properties": {},
  "required": [],
  "additionalProperties": false
}

get_operation_schema

Local reviewed method/path/query/body schema and provenance for one native tool. No credentials or provider request.

Argument

Type

Required

Meaning and constraints

operation

string

Required

Exact native tool name, e.g. update_testimonial or send_invites. {"enum": ["list_testimonials", "get_testimonial", "create_testimonial", "update_testimonial", "delete_testimonial", "list_links", "send_invites"]}

senja-cli get-operation-schema --help
senja-cli schema get-operation-schema
{
  "type": "object",
  "properties": {
    "operation": {
      "type": "string",
      "enum": [
        "list_testimonials",
        "get_testimonial",
        "create_testimonial",
        "update_testimonial",
        "delete_testimonial",
        "list_links",
        "send_invites"
      ],
      "description": "Exact native tool name, e.g. update_testimonial or send_invites."
    }
  },
  "required": [
    "operation"
  ],
  "additionalProperties": false
}

preview_testimonial_batch

Local validation and SHA-256 of exact ordered testimonial/import/invite work, selected profile label and reviewed schema. No provider reads, key load, identity check, price or rollback guarantee.

Argument

Type

Required

Meaning and constraints

tasks

array

Required

One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to 100 recipients each; review the exact complete recipient list and existing form follow-up sequence. {"minItems": 1, "maxItems": 20}

tasks[].tool

string

Required

{"enum": ["create_testimonial", "update_testimonial", "delete_testimonial", "send_invites"]}

tasks[].arguments

object

Required

Actual native tool arguments without account, confirm, payload_file or output_file.

account

string

Optional

Exact selected private account profile; binds label, not key ownership.

senja-cli preview-testimonial-batch --help
senja-cli schema preview-testimonial-batch
{
  "type": "object",
  "properties": {
    "tasks": {
      "type": "array",
      "minItems": 1,
      "maxItems": 20,
      "description": "One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to 100 recipients each; review the exact complete recipient list and existing form follow-up sequence.",
      "items": {
        "type": "object",
        "properties": {
          "tool": {
            "type": "string",
            "enum": [
              "create_testimonial",
              "update_testimonial",
              "delete_testimonial",
              "send_invites"
            ]
          },
          "arguments": {
            "type": "object",
            "description": "Actual native tool arguments without account, confirm, payload_file or output_file."
          }
        },
        "required": [
          "tool",
          "arguments"
        ],
        "additionalProperties": false
      }
    },
    "account": {
      "type": "string",
      "description": "Exact selected private account profile; binds label, not key ownership."
    }
  },
  "required": [
    "tasks"
  ],
  "additionalProperties": false
}

submit_testimonial_batch

Confirmed one-to-twenty ordered testimonial/import/invite tasks. Prevalidate all and verify exact hash before first request. Stop on first failure with known results/failed index/unattempted indices; no retries, rollback or implicit continuation.

Argument

Type

Required

Meaning and constraints

tasks

array

Required

One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to 100 recipients each; review the exact complete recipient list and existing form follow-up sequence. {"minItems": 1, "maxItems": 20}

tasks[].tool

string

Required

{"enum": ["create_testimonial", "update_testimonial", "delete_testimonial", "send_invites"]}

tasks[].arguments

object

Required

Actual native tool arguments without account, confirm, payload_file or output_file.

account

string

Optional

Exact selected private account profile; binds label, not key ownership.

confirm

boolean

Optional

Explicit approval for this exact requested ordered batch.

review_sha256

string

Required

Exact preview_testimonial_batch hash for identical requests, profile label, schema and order. {"pattern": "^[a-f0-9]{64}$"}

senja-cli submit-testimonial-batch --help
senja-cli schema submit-testimonial-batch
{
  "type": "object",
  "properties": {
    "tasks": {
      "type": "array",
      "minItems": 1,
      "maxItems": 20,
      "description": "One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to 100 recipients each; review the exact complete recipient list and existing form follow-up sequence.",
      "items": {
        "type": "object",
        "properties": {
          "tool": {
            "type": "string",
            "enum": [
              "create_testimonial",
              "update_testimonial",
              "delete_testimonial",
              "send_invites"
            ]
          },
          "arguments": {
            "type": "object",
            "description": "Actual native tool arguments without account, confirm, payload_file or output_file."
          }
        },
        "required": [
          "tool",
          "arguments"
        ],
        "additionalProperties": false
      }
    },
    "account": {
      "type": "string",
      "description": "Exact selected private account profile; binds label, not key ownership."
    },
    "confirm": {
      "type": "boolean",
      "description": "Explicit approval for this exact requested ordered batch."
    },
    "review_sha256": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$",
      "description": "Exact preview_testimonial_batch hash for identical requests, profile label, schema and order."
    }
  },
  "required": [
    "tasks",
    "review_sha256"
  ],
  "additionalProperties": false
}

export_testimonials

Confirmed paginated GET export to an exclusive new 0600 JSON file. Stop on short native page or local caps. Never downloads media, follows URLs, overwrites files, retries or implies an atomic complete backup.

Argument

Type

Required

Meaning and constraints

sort

string

Optional

Native sort field; direction uses order. {"enum": ["date", "rating"]}

order

string

Optional

{"enum": ["asc", "desc"]}

approved

boolean

Optional

Exact native/schema value

rating

integer

Optional

{"minimum": 1, "maximum": 5}

type

string

Optional

{"enum": ["text", "video"]}

integration

string

Optional

{"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}

tags

array

Optional

{"maxItems": 100}

query

string

Optional

Native full-text search, including customer name/email; output may contain personal data.

lang

string

Optional

Native ISO 639 language selector.

limit

integer

Optional

Native page size. total counts only the current page. {"minimum": 1, "maximum": 1000}

page

integer

Optional

{"minimum": 1}

account

string

Optional

Exact configured private account profile label; not a tenant or provider account ID.

confirm

boolean

Optional

Explicit approval for this exact requested ordered batch.

start_offset

integer

Optional

Resume inside the first requested page using an export receipt offset and identical filters/page size. Provider state may have changed. {"minimum": 0, "maximum": 999}

max_pages

integer

Optional

Local request budget, default 10. {"minimum": 1, "maximum": 100}

max_items

integer

Optional

Local item budget, default 1000. May stop within a page; receipt records an offset. {"minimum": 1, "maximum": 10000}

output_file

string

Required

Absolute new file in an existing private directory. Restrict Windows ACLs separately.

senja-cli export-testimonials --help
senja-cli schema export-testimonials
{
  "type": "object",
  "properties": {
    "sort": {
      "type": "string",
      "enum": [
        "date",
        "rating"
      ],
      "description": "Native sort field; direction uses order."
    },
    "order": {
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    },
    "approved": {
      "type": "boolean"
    },
    "rating": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "type": {
      "type": "string",
      "enum": [
        "text",
        "video"
      ]
    },
    "integration": {
      "type": "string",
      "enum": [
        "twitter",
        "product_hunt",
        "google",
        "facebook",
        "reddit",
        "capterra",
        "g2",
        "linkedin",
        "app_store",
        "trustpilot",
        "shopify",
        "play_store",
        "yelp",
        "slack",
        "discord",
        "apple_podcasts",
        "telegram",
        "whatsapp",
        "instagram",
        "youtube",
        "tiktok",
        "appsumo",
        "amazon",
        "zillow",
        "udemy",
        "chrome_web_store",
        "airbnb",
        "skillshare",
        "realtor",
        "sourceforge",
        "whop",
        "wordpress",
        "fiverr",
        "homestars",
        "web_page"
      ]
    },
    "tags": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "string",
        "minLength": 1,
        "description": "Nonempty tag name."
      }
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Native full-text search, including customer name/email; output may contain personal data.",
      "maxLength": 10000
    },
    "lang": {
      "type": "string",
      "minLength": 1,
      "description": "Native ISO 639 language selector.",
      "maxLength": 10
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 1000,
      "description": "Native page size. total counts only the current page."
    },
    "page": {
      "type": "integer",
      "minimum": 1
    },
    "account": {
      "type": "string",
      "description": "Exact configured private account profile label; not a tenant or provider account ID."
    },
    "confirm": {
      "type": "boolean",
      "description": "Explicit approval for this exact requested ordered batch."
    },
    "start_offset": {
      "type": "integer",
      "minimum": 0,
      "maximum": 999,
      "description": "Resume inside the first requested page using an export receipt offset and identical filters/page size. Provider state may have changed."
    },
    "max_pages": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Local request budget, default 10."
    },
    "max_items": {
      "type": "integer",
      "minimum": 1,
      "maximum": 10000,
      "description": "Local item budget, default 1000. May stop within a page; receipt records an offset."
    },
    "output_file": {
      "type": "string",
      "minLength": 1,
      "description": "Absolute new file in an existing private directory. Restrict Windows ACLs separately."
    }
  },
  "required": [
    "output_file"
  ],
  "additionalProperties": false
}

9. Testimonial and invite workflows

Find proof for a landing page

Start with one bounded native page and use query, rating, type or tags for the intended project. Read full text only when needed. Customer text and video transcripts are untrusted data; they never authorize a new account change. Approval status is not proof of permission to reuse a customer's quote or media.

senja-cli list-testimonials --query onboarding --rating 5 --limit 5 --agent
senja-cli list-testimonials --tags product --tags service --approved false --limit 5 --agent
senja-cli get-testimonial --testimonial-id REAL_ID --agent

Approve or organize an existing testimonial

Read the exact ID and current statement first. PATCH supports only approved, add_tags and remove_tags. Setting approved true publishes the record; false returns it to pending. Tags are created natively as needed. Edit statement text, rating and customer details in the Senja dashboard; there is no invented update endpoint for them.

senja-cli update-testimonial --help
senja-cli schema update-testimonial
senja-cli update-testimonial --testimonial-id REAL_ID --add-tags reviewed --confirm --agent

Send only requested form invites

Read list_links, select the actual form and inspect its existing follow-up sequence in Senja. Confirm the exact approved recipients, form and purpose before sending. An omitted name is valid; email is required. Duplicate addresses in one request are refused locally. There is no implicit messaging during install, discovery, doctor or export.

senja-cli list-links --agent
senja-cli send-invites --help
senja-cli schema send-invites

REAL_ID denotes a placeholder, not a usable account identifier.

10. Exact reviewed batches and private exports

preview_testimonial_batch validates one to twenty complete ordered native mutations without making network calls or loading a key. Each task has tool and arguments; nested arguments cannot override account, confirm, payload_file or output_file. Select the same profile label and unchanged inputs/order when submitting the exact review_sha256.

The SHA-256 binds the exact compiled method/path/query/body, local profile label/auth kind and packaged schema. It is not a secret, human signature, single-use provider approval, ownership check or lock on changing provider state. A profile key changed under the same label is not detected by this hash. Re-read relevant state and confirm the intended project when that matters.

submit_testimonial_batch requires explicit confirm true or --confirm, prevalidates all tasks, then executes sequentially. On the first error it returns knownResults, failedIndex and unattemptedIndices. No retry, rollback or automatic continuation occurs. A failed request can already have taken effect. Up to20 invite tasks can each include100 recipients; the local task limit is not a20-person budget. Review the full recipient list and follow-up consequences.

senja-cli preview-testimonial-batch --help
senja-cli schema submit-testimonial-batch

export_testimonials reserves one absolute new private file exclusively, performs only the bounded requested list pages, and returns path/bytes/SHA-256 and receipt metadata. Defaults: 10 pages, 1,000 items, native page size 100. Local caps: 100 pages, 10,000 items and 5 MiB final JSON. A short native page signals exhaustion within the selected filters at that moment. Native total counts the current page, not the entire project.

When a local cap stops the walk, continuation reports page, offset and limit. Resume with that page, identical filters/page size and start_offset. Page changes can cause shifted records; no atomic snapshot, complete backup or deduplication guarantee is made. A second resume writes a different new file; it never appends to or overwrites the earlier export. Review/de-duplicate native IDs when combining evolving pages.

Failure removes only the file this export newly created. Media URLs and transcript metadata remain JSON data; this package never follows or downloads them. Read-only mode refuses file output too. Restrict parent-directory privacy and Windows ACLs separately.

senja-cli export-testimonials --help
senja-cli schema export-testimonials

11. Several private projects

SENJA_ACCOUNTS is a private JSON array of unique {name,api_key,token_file} profiles. Use one credential method per profile. SENJA_DEFAULT_ACCOUNT selects the default label and --account selects an exact label. An incomplete named profile never inherits a global key, another project or an official hosted session after a missing credential or 401/403.

list_accounts returns labels/default/auth/source only, without keys, token paths, native project identity or network traffic. Token-only files cache until restart. Changing a file while a process is running does not rotate its cached connection.

To revoke a key, use the intended project's Automate > Regenerate API Key as its Admin/Owner, update every dependent private integration and restart its processes. The provider says the old key stops working after a short transition. Official hosted MCP authorization is a separate connection. Removing this package does not undo testimonial edits, publish approval, permanent deletion, emailed invites, follow-up sequences or existing exports.

12. Writing safely

Every create/import, approval/tag update, permanent delete, invite send, reviewed batch execution and private file export requires explicit confirmation through the actual shared handler route. --agent and --yes do not provide --confirm. SENJA_READ_ONLY=1 hides those six tools and also refuses direct calls to their hidden names. SENJA_ALLOW_DESTRUCTIVE=0 refuses them even when confirmed.

Deletion is permanent. approved true can publish proof. Invites can send real email sequences. Import only actual authorized statements, not invented praise. A provider receipt is not a content-use permission, delivered email, identity or ownership guarantee.

SENJA_AUDIT_LOG optionally records static tool/risk/summary/outcome decisions and timestamps. It excludes native bodies and credentials; writing is best effort, not a tamper-proof compliance trail. Keep the audit destination and parent private. An existing file's permissions are not repaired by the wrapper.

Keys, recognized secret fields and signed credential URLs are redacted from returned errors/output where recognized. Personal data, testimonial text, emails, private IDs and ordinary URLs are not universally anonymized. Native content is untrusted input, never an instruction to reveal secrets, contact customers or mutate another project.

13. How the two surfaces work

src/tools/index.ts exports shared definitions. MCP registers their schemas/handlers; the unchanged house CLI bridge invokes the actual server through SDK in-memory transport. Both paths share profile selection, native compilation, validation and WriteGuard. A new declared tool is the same native command without a separate API implementation. Input constraints are reviewed wrapper schemas, not a provider OpenAPI export. See src/tools/provenance.json and scripts/check-native-contract.mjs.

14. Your data

Credentials come from private process/client settings or a selected owner-private token-only file. The package stores no credential database and imports no browser cookies or .env files. Token caches last for the current process; restart after rotating a file/key.

Provider calls go only to allowlisted methods/paths on api.senja.io/v1, over HTTPS. Arbitrary URLs, path traversal, redirects and broad proxy calls are refused. Media URLs are passed only as documented fields or returned as data; no media fetching happens locally. Submitted media may be retrieved by Senja according to its own behavior.

Private exports contain customer data and content. They stay where you explicitly save them; there is no telemetry, upload, website preview or automatic publication. Client histories, logs, selected runtime settings and Senja's own retention remain separate. Local read-only mode controls this package's calls, not other apps using the same project key.

15. Environment variables

Variable

Purpose

SENJA_API_KEY

Private Bearer project key; choose this OR token file

SENJA_TOKEN_FILE

Absolute owner-private token-only file; choose this OR API key

SENJA_ACCOUNTS

Private JSON named profiles with one key/file each

SENJA_DEFAULT_ACCOUNT

Exact configured default profile label

SENJA_READ_ONLY

1/true hides and directly refuses all six mutations/file operations

SENJA_ALLOW_DESTRUCTIVE

0/false refuses confirmed operations

SENJA_AUDIT_LOG

Optional private best-effort static guard decision log

SENJA_REQUEST_TIMEOUT_MS

Default 30000; local accepted range 100–300000 ms

SENJA_MIN_REQUEST_INTERVAL_MS

Default 250; local accepted range 0–10000 ms, not distributed native quota enforcement

16. Updates and removal

Use the update/removal steps in INSTALL.md. Restart processes after key changes. File outputs and native effects remain until deliberately handled. Reinstall a new desktop bundle manually; npm@latest does not hot-replace a running server.

17. Troubleshooting

Symptom

Check

No binary or Node error

Node 22+, npm/PATH in the actual GUI/remote runtime; npm.cmd if Windows policy blocks npm.ps1

Exit10 or unknown profile

Exact profile name and one private key/file; no fallback exists

Unreadable token file

Absolute owner-private regular non-symlink file under 64 KiB; restart after replacing it

401/403

Selected project/key/permissions and revocation; official hosted auth is separate

Old sort/per_page/language rejected

Use sort date/rating, order asc/desc, limit and lang

PATCH edit refused

Only approved/add_tags/remove_tags; use dashboard for text/customer/rating edits

Cannot send or delete

Explicit --confirm and local policy; inspect native permissions and real purpose

Invites skipped

Inspect native sent/skipped receipt and existing form sequence; do not blindly repeat

Export stopped at cap

Inspect page/offset/limit and resume to a different new private file

Existing output file

Choose a new file; never remove/overwrite unrelated data

Review hash mismatch

Preview the exact unchanged order/inputs/profile/schema again

429 or uncertain write result

No automatic retry; inspect native state and available rate-limit guidance

Browser-only client

Use official hosted MCP; local stdio needs a supported server runtime

Desktop GUI blocked

Organization/client support and Node 22 runtime; archive discovery does not prove GUI acceptance

18. API coverage and comparisons

Official hosted MCP

Senja already has official account MCP at https://mcp.senja.io. It searches testimonials, finds proof for a use case, creates testimonials, tags records, retrieves asset links/embeds and sends form invites. Current setup docs include Free, Starter and Pro. Hosted account authorization and client approvals are separate from this local API-key package.

Use the official connector when that native experience fits your task. A dedicated official task CLI was not identified in the provider material reviewed on October 3, 2026; this is not a universal or permanent absence claim. This package does not claim to add invites that the official MCP already supports, expose every Senja UI feature, create Studio graphics or replace native embed editing.

Reviewed community server

andrewconnell/senja-mcp at commit 417445647eac47f94c2d12d9196a68d2e1d22559 exposes three testimonial MCP tools. Its inspected API client already uses Bearer auth, separate sort/order, lang/limit and repeated tag query values. Its package does not declare a standalone task CLI; its create handler has no mandatory confirmation argument. This says nothing about external clients' approval controls.

The reviewed interface describes a data array and paid-plan prerequisite; current provider documentation describes testimonials and current-page total, and covers Free/Starter/Pro. Our request/response fixtures follow current provider fields. Community customer_website is not the current documented customer_url field.

Useful owned workflows and limits

The verified addition is a shared task CLI/local MCP with isolated named project profiles, mandatory mutation/file approval, direct read-only refusal, locally reviewed ordered writes and bounded private paginated export with explicit page/offset continuation. These controls are exercised in fixtures and real protocol/CLI processes. They do not establish overall superiority, authenticated account outcomes or token savings.

Capability

This package

Existing alternatives

Task interface

12 shared MCP tools and task CLI commands

Official hosted MCP and reviewed community stdio MCP

Native public API

Seven reviewed documented endpoints

Official hosted tools may cover different native features

Project credentials

Unique local profiles, no global credential fallback

Official connector authorization stays native

Ordered changes

Exact local hash, prevalidation, stop on failure

Not a provider-state lock or replacement for client approval

Private export

Bounded pages/items/bytes and exclusive JSON file

Not an atomic complete backup, consent registry or media downloader

Task tokens

Actual matched Codex measurement pending

No percentage or zero-total-token claim

19. Versions and migration

Component

Reviewed version

Package/desktop

2.0.0

Native public API

v1; seven endpoints checked 2026-10-03

Community source

417445647eac47f94c2d12d9196a68d2e1d22559

Node

>=22

Historical private MCP

1.0.0; three tools

Matched Codex task/token usage

Pending

Legacy caller

Current contract

Required change

per_page

limit

Use native page-size field

language

lang

Use native language selector

date_asc/date_desc sort

sort date/rating plus order

Send field and direction separately

tags string

tags array

Repeat --tags or use a JSON array

create name/email/headline/company

customer_name/customer_email/customer_tagline/customer_company

Use native fields and required type

avatar_url/company_logo_url

customer_avatar/customer_company_logo

Use native HTTPS fields

url used as customer website

url is source; customer_url is customer website

Choose the actual intended field

Three tools with startup key requirement

12 tools with credential-free discovery and guarded effects

Discover tools before private setup; update scripts for approval

No CLI binary

senja-cli and senja-mcp

Use @thenavidm scope and @latest

CHANGELOG.md records the dated major update. Private legacy history stays private; source publishing starts from a clean verified snapshot, preserving AGPL-3.0.

20. FAQ

Yes. Its hosted connector already searches testimonials, creates proof, retrieves asset links and sends form invites. This package adds a shared terminal/local task interface and the documented local workflows. Use the official option when it fits your needs; the comparison does not claim ours replaces its full native feature set.

The CLI runs the same discovered tools through the same in-memory MCP handlers, input validation and write guard. Scripts can use JSON, field selection and exit codes. A dedicated official task CLI was not identified in the reviewed provider material; that finding is dated, not a permanent absence claim.

Current provider REST and MCP setup documentation includes Free, Starter and Pro. Account restrictions and native feature eligibility remain in Senja. The package is free under AGPL-3.0 and cannot bypass a plan or permission check; do not reuse older community paid-only prerequisites as current facts.

Choose the intended project and open Automate in Senja. Store exactly one key privately in SENJA_API_KEY or an absolute owner-private SENJA_TOKEN_FILE outside repositories. The client uses Bearer authentication. Never paste resolved secrets into README examples, public issues, screenshots or AI chats.

Yes. SENJA_ACCOUNTS supplies unique private named profiles, each with its own key or token file. Select an exact name with --account. Named profiles never inherit global credentials or another project. Labels are local settings and do not prove the provider key owner or project identity.

No. login prints private setup instructions and never makes a request, opens an OAuth flow, generates a key or imports a browser session. doctor without --network checks configuration only. doctor --network deliberately makes one limit=1 testimonial request and prints verification metadata.

The reviewed catalogue includes testimonial list/get/create/PATCH/delete, project links and form invites, plus five local/workflow helpers. This is the current seven-endpoint public REST scope reviewed for this package, not a claim to expose every hosted MCP or Senja UI action.

Native PATCH supports only approval status and tag additions/removals. Text, rating and customer edits belong in the Senja dashboard. create_testimonial uses actual customer_name/type fields for an authorized import; it does not invent a generalized edit API.

Yes, according to current native API documentation; false returns it to pending. These are confirmed account changes. Approval does not establish customer permission to reuse their words or media, and reading a testimonial never authorizes publishing it elsewhere.

Use native query for text/title/customer-field search, repeat --tags for tag names, and use rating/type/integration/approved/lang as appropriate. sort is date or rating and order is asc or desc. The wrapper rejects stale per_page, language and combined date_desc-style sort arguments before network traffic.

No. Native total counts the current returned page. Export stops on a short native page or explicit local caps, recording page/offset/limit continuation. It does not infer a project-wide count from total or promise a consistent snapshot while provider content changes.

Use export_testimonials with explicit confirmation and an absolute new private file. Defaults are10pages and1000items; local maximums are100pages,10000items and5MiB JSON. Resume to a different file using the recorded page/start_offset/limit and unchanged filters. Combine/de-duplicate changing native IDs deliberately; no automatic append or atomic backup is promised.

No. JSON includes native media URLs, transcripts and metadata where returned. The package never follows these URLs or downloads video/image/audio files. Signed credential URLs and known keys are redacted where recognized; other personal/customer content is still private data.

The selected form ID and its existing email/follow-up sequence determine native messages. Use a real forms[].id from list_links and only explicitly approved recipients. The local 100-recipient cap is not a native quota. Native sent/skipped receipts do not prove inbox delivery or consent, and invites also exist in the official MCP.

It prevalidates every complete task and binds exact order/requests/profile label/schema to a local hash before sequential execution. The hash is not a single-use provider token, human signature, provider-state lock, consent record or ownership proof. Reconfirm changing provider state when your task requires it.

Execution stops at the first failure with knownResults, failedIndex and unattemptedIndices. A failed write may already have taken effect and native follow-up emails can continue. There is no retry, rollback or automatic continuation. Inspect native state and receipts before explicitly requesting another action.

No. SENJA_READ_ONLY=1 both hides the six confirmed tools and refuses direct hidden calls through the actual handlers. It also refuses private file exports. SENJA_ALLOW_DESTRUCTIVE=0 disables these effects even when confirmed; --agent and --yes never provide explicit --confirm.

Codex and compatible local stdio clients can register npx -y @thenavidm/senja-mcp-cli@latest. INSTALL.md covers Claude Code/Desktop, Cursor, VS Code/Copilot, Windsurf, Zed, Gemini CLI, Docker and other stdio clients, plus Windows/macOS/Linux runtime notes. Browser-only clients need a remote connector such as the official hosted MCP.

The .mcpb includes production dependencies and asks for private sensitive settings or a token file, but compatible hosts still need a Node 22 runtime and organization support. Install newer bundle versions manually. npx@latest resolves the current registry version when the server is restarted; it does not replace a running process or provide guaranteed background updates.

Actual equivalent successful Codex task/token measurements are pending. MCP loading modes, CLI schema/help discovery, outputs, skills and caching all affect costs. No character-based estimate, universal superiority or zero-total-token claim is published. Proven fixture behavior and actual public artifact checks are listed separately from authenticated outcomes and desktop GUI acceptance.

Questions

Open a secret-free issue. Read CONTRIBUTING.md and SECURITY.md.

About the author

Navid Moazzez is a leading AI business strategist, and the host of the AI Creator Summit, watched by 100,000+ creators. He helps creators and founders master AI and build their own AI Operating System (AI OS) to automate their business and life. He creates useful free tools, MCP servers and CLIs that creators and founders can use in their own workflows.

Links

If this is useful, star the repo and come say hi on X.

Dependencies

Runtime: MCP TypeScript SDK, Ajv and ajv-formats. Development: TypeScript, Vitest, Vite and MCPB. Exact locked versions appear above. Packaging tools are excluded from desktop runtime.

License

Preserves AGPL-3.0 and existing private legacy history. Read THIRD_PARTY_NOTICES.md. Senja service terms and trademarks remain separate.


© 2026 Navid Media. Made with ❤️ by Navid Moazzez.

Available Tools

12 tools
create_testimonialImport a testimonialB
Destructive

Create one text/video testimonial from an authorized existing customer statement. Explicit approval is required.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoHTTPS URL without embedded credentials; provider retrieves media where supported.
dateNo
tagsNo
textNo
typeNo
mediaNo
titleNo
ratingNo
accountNoExact configured private account profile label; not a tenant or provider account ID.
confirmNoMust be true for the requested mutation or exclusive private output file.
form_idNo
payloadNoComplete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.
approvedNoExplicitly true publishes the testimonial; false keeps it pending.
video_urlNoHTTPS URL without embedded credentials; provider retrieves media where supported.
integrationNo
customer_urlNoHTTPS URL without embedded credentials; provider retrieves media where supported.
payload_fileNoAbsolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.
customer_nameNo
thumbnail_urlNoHTTPS URL without embedded credentials; provider retrieves media where supported.
customer_emailNo
customer_avatarNoHTTPS URL without embedded credentials; provider retrieves media where supported.
customer_companyNo
customer_taglineNo
customer_usernameNo
customer_company_logoNoHTTPS URL without embedded credentials; provider retrieves media where supported.

TDQS

B3.1/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, openWorldHint=true, idempotentHint=false, and readOnlyHint=false, so the mutating/non-idempotent nature is covered. The description adds the useful prerequisite that an authorized statement and explicit approval are required, but says nothing about side effects, rate limits, or auth beyond that.

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?

Two tight sentences with the action and the approval precondition front-loaded and no wasted words. It is efficient, though the brevity is under-specification rather than deliberate economy given the tool's complexity.

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

Completeness2/5

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

For a 25-parameter creation tool with nested payload objects, dual input modes, and no output schema, this description is far too thin. It omits required-field guidance (0 required params is ambiguous), how payload and confirm interact, and what the operation returns.

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

Parameters2/5

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

With 25 parameters and only 44% schema description coverage, the description carries a heavy compensation burden, yet it only alludes to the text/video 'type' and the customer statement. It explains nothing about the payload vs payload_file vs flat body-flag modes, confirm, account, integration, or the customer_* fields.

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

Purpose4/5

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

States a specific verb and resource ('Create one text/video testimonial') and adds a scope qualifier ('one', from an authorized existing customer statement) that implicitly distinguishes it from the batch siblings. It does not name an alternative tool, but the single-item scope is clear.

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

Usage Guidelines3/5

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

Gives a precondition ('from an authorized existing customer statement') and 'explicit approval is required', which implies the confirm/approved flags. However, it never names when to use this versus preview_testimonial_batch, submit_testimonial_batch, or update_testimonial, leaving the routing decision to inference.

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

delete_testimonialDelete one testimonialA
Destructive

Permanently delete exactly the requested testimonial. Irreversible; confirmation required.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNoExact configured private account profile label; not a tenant or provider account ID.
confirmNoMust be true for the requested mutation or exclusive private output file.
testimonial_idYesExact testimonial ID. No slash, traversal or arbitrary URL.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is partly covered. The description earns credit by escalating severity with 'Permanently' and 'Irreversible' and by disclosing the confirmation prerequisite, which the annotations do not convey.

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

Conciseness5/5

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

Two short sentences, zero filler, with the destructive nature front-loaded before the confirmation requirement. Every clause carries information.

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?

No output schema exists, but for a destructive single-record delete the description supplies purpose, irreversibility, and the confirmation gate, while annotations carry the safety hints. Nothing essential for correct invocation is missing.

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 100%, so account, confirm, and testimonial_id are already fully documented in the schema. The description adds only the notion that deletion is single-target; it doesn't elaborate on the confirm flag or account-label semantics. Baseline 3 applies.

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

Purpose4/5

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

States a specific verb and resource ('Permanently delete ... testimonial') with a scoping qualifier ('exactly the requested') that distinguishes it from a batch delete. It does not explicitly name a sibling, but among the listed siblings the delete intent is unambiguous.

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

Usage Guidelines3/5

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

The description adds a procedural condition ('confirmation required') that implies when the tool can be invoked, but it never states when to prefer this over update_testimonial or how it interacts with siblings. Usage is implied rather than explicitly guided.

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

export_testimonialsExport bounded private testimonialsA
Destructive

Confirmed paginated GET export to an exclusive new0600 JSON file. Stop on short native page or local caps. Never downloads media, follows URLs, overwrites files, retries or implies an atomic complete backup.

ParametersJSON Schema
NameRequiredDescriptionDefault
langNoNative ISO 639 language selector.
pageNo
sortNoNative sort field; direction uses order.
tagsNo
typeNo
limitNoNative page size. total counts only the current page.
orderNo
queryNoNative full-text search, including customer name/email; output may contain personal data.
ratingNo
accountNoExact configured private account profile label; not a tenant or provider account ID.
confirmNoExplicit approval for this exact requested ordered batch.
approvedNo
max_itemsNoLocal item budget, default1000. May stop within a page; receipt records an offset.
max_pagesNoLocal request budget, default10.
integrationNo
output_fileYesAbsolute new file in an existing private directory. Restrict Windows ACLs separately.
start_offsetNoResume inside the first requested page using an export receipt offset and identical filters/page size. Provider state may have changed.

TDQS

A3.8/5.0
Behavior5/5

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

Annotations already declare readOnly=false, destructive=true, openWorld=true, idempotent=false, but the description goes well beyond them: exclusive file creation with 0600 permissions, no overwriting, no media/URL fetching, no retries, and an explicit warning that the result is not an atomic complete backup. These are exactly the behavioral traits an agent needs before calling a file-writing export.

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?

Three tight sentences with the core action front-loaded and zero filler. It is occasionally over-compressed (bare '0600', 'native page', 'local caps') in a way that costs a little readability, but nothing is wasted.

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

Completeness3/5

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

No output schema exists and there are 17 parameters, so the description carries substantial burden. It thoroughly covers the behavioral envelope and failure/stop semantics, but leaves the confirmation workflow, account/integration scoping, and the shape of the resulting file largely unexplained.

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 coverage is only 59% across 17 parameters, so the description must carry weight. It alludes conceptually to confirm ('Confirmed'), the local caps (max_items/max_pages), and page size ('short native page'), but never clarifies undocumented fields such as approved, account, integration, or start_offset behavior. Partial compensation, not full.

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

Purpose4/5

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

States a concrete verb+resource+artifact: a paginated GET export of testimonials written to an exclusive new 0600 JSON file. An agent can immediately distinguish this from list_testimonials or preview_testimonial_batch. It stops short of naming a sibling to avoid, which keeps it from a 5.

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

Usage Guidelines3/5

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

Gives operational guidance on when to stop (short native page or local caps) and a list of non-goals (no media download, no URL following, no retries, no atomic backup), which implicitly scopes the tool. However it never states when to prefer this over list_testimonials, preview_testimonial_batch, or submit_testimonial_batch, nor the prerequisites implied by 'Confirmed'.

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

get_operation_schemaInspect a current native operationA
Read-onlyIdempotent

Local reviewed method/path/query/body schema and provenance for one native tool. No credentials or provider request.

ParametersJSON Schema
NameRequiredDescriptionDefault
operationYesExact native tool name, e.g. update_testimonial or send_invites.

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, and closed-world. The description adds meaningful context beyond that: it is the 'local reviewed' copy and requires no credentials or provider request, which tells the agent this is a side-effect-free metadata read rather than a live call. It stops short of describing the returned structure.

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

Conciseness5/5

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

Two short, front-loaded sentences with no filler: the first states what is returned, the second removes a likely misassumption (that a call might touch credentials or a provider). Nothing is wasted.

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

Completeness4/5

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

With no output schema, the description does sketch the return content (method/path/query/body schema plus provenance) and rules out auth or network side effects. It does not describe the shape or format of that schema object, leaving a small gap for a 1-parameter introspection tool.

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 100%, with an enumerated list of valid operation names and an example format, so the schema carries the parameter semantics. The description's 'for one native tool' reinforces that the single parameter selects an operation, matching the baseline for a fully documented schema.

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

Purpose4/5

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

States a specific verb (inspect/return) and resource (schema + provenance for one native operation), so an agent can tell this is a metadata lookup rather than an actual operation. It does not explicitly contrast itself with the sibling operation tools (get_testimonial, update_testimonial, etc.), but 'for one native tool' plus the tool name make the distinction inferable.

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

Usage Guidelines2/5

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

There is no explicit when-to-use, when-not-to-use, or alternative guidance. 'Local reviewed ... No credentials or provider request' hints that this is an offline introspection call, but the description never says to call it before invoking a native tool or how it relates to the sibling operations.

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

get_testimonialRead one testimonialB
Read-onlyIdempotent

Read one exact testimonial, including native video metadata and public/dashboard links.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNoExact configured private account profile label; not a tenant or provider account ID.
testimonial_idYesExact testimonial ID. No slash, traversal or arbitrary URL.

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint, so the safety and access profile is covered. The description adds that the read includes native video metadata plus public/dashboard links, which is useful context about what it returns, but says nothing about permissions, error cases, or rate limits.

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

Conciseness5/5

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

A single sentence that front-loads the action and resource and wastes nothing. Appropriately sized for a two-parameter read tool.

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

Completeness3/5

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

With annotations covering safety and schema at 100% coverage, the core is complete. But the description hints at a rich return payload (native video metadata, public/dashboard links) with no output schema, so it stops short of telling the agent what it will receive or when this read is preferable to list_testimonials.

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 100%, so the two parameters are fully documented in the schema itself, including the account label caveat and the traversal guard on testimonial_id. The description adds no param-level meaning, which matches the baseline when the schema does the heavy lifting.

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

Purpose4/5

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

States a specific verb ('Read') and resource ('one exact testimonial') with singular scope, distinguishing it from the sibling list_testimonials. However, it doesn't name or contrast any alternative for retrieving a testimonial by ID, so sibling differentiation is only implicit.

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

Usage Guidelines2/5

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

No when-to-use guidance, no prerequisites, and no mention of alternatives. The description never signals that list_testimonials is for enumeration while this is for a single lookup, leaving the agent to infer routing.

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

list_accountsList configured accountsB
Read-onlyIdempotent

Local profile labels/default/auth method only. No keys, token paths, provider identity or network request.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuine context beyond that: output is limited to local profile labels/defaults/auth method and deliberately excludes keys, token paths, and provider identity, telling the agent the result is safe to surface.

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

Conciseness3/5

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

It is very short (two fragments) and wastes no words, but it is telegraphic and front-loads a qualifier rather than the core action. The terseness borders on under-specification rather than disciplined conciseness.

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

Completeness3/5

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

For a zero-parameter, read-only listing tool with no output schema and strong annotations, the description covers the essential safety and scope facts. However, it never plainly states what the tool does or what the returned list contains beyond field-level exclusions, leaving the purpose inferable only from the title.

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?

The tool takes zero parameters, so there is no parameter semantics for the description to carry. Baseline of 4 applies; nothing is missing on this dimension.

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

Purpose3/5

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

The description never states a verb or resource — it only describes the scope of what is returned ("Local profile labels/default/auth method only"). The title supplies the actual purpose, so the agent can infer this lists local accounts, but the description itself is vague about the action.

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

Usage Guidelines2/5

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

There is no when-to-use guidance and no named alternative among the numerous list_* siblings (list_customers, list_partners, list_domains, etc.). The agent must infer that this tool is for enumerating locally configured account profiles rather than any remote data.

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

list_testimonialsList testimonialsC
Read-onlyIdempotent

Read one native page with exact current search, tag, approval, language and date/rating filters.

ParametersJSON Schema
NameRequiredDescriptionDefault
langNoNative ISO 639 language selector.
pageNo
sortNoNative sort field; direction uses order.
tagsNo
typeNo
limitNoNative page size. total counts only the current page.
orderNo
queryNoNative full-text search, including customer name/email; output may contain personal data.
ratingNo
accountNoExact configured private account profile label; not a tenant or provider account ID.
approvedNo
integrationNo

TDQS

C2.8/5.0
Behavior3/5

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

Annotations cover read-only, idempotent, non-destructive. The description adds one meaningful behavioral note: output may contain personal data (customer name/email), which is genuinely useful. But it does not clarify pagination behavior, total counts, or result limits, leaving meaningful gaps for a 12-param listing tool.

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?

Single sentence, no filler, front-loaded with the core action. It is compact but at the cost of detail; reasonable for its length.

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

Completeness2/5

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

For a 12-parameter tool with no output schema, the description is thin. It doesn't explain return shape (e.g., what 'total counts only the current page' implies), pagination usage, sort/order interaction, or the account/integration filters. It leaves the agent without enough to call it confidently.

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 coverage is 42%, so roughly half the parameters are undocumented in the schema. The description lists filter categories (search, tag, approval, language, date/rating) but doesn't map them to specific parameters or explain semantics like 'exact configured private account profile label.' Baseline 3 is the ceiling given the description doesn't compensate for the coverage gap.

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

Purpose3/5

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

The description says it reads a 'native page' of testimonials and enumerates filter dimensions, but 'one native page' is unusual phrasing that doesn't clearly state whether pagination is supported (the schema has a 'page' param, so it must be). It never explicitly distinguishes from siblings like get_testimonial or export_testimonials.

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

Usage Guidelines2/5

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

No guidance on when to use this versus get_testimonial (single fetch) or export_testimonials (bulk export). The reader must infer that this is the list/browse operation, but nothing is stated.

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

preview_testimonial_batchReview exact ordered testimonial tasksB
Read-onlyIdempotent

Local validation and SHA-256 of exact ordered testimonial/import/invite work, selected profile label and reviewed schema. No provider reads, key load, identity check, price or rollback guarantee.

ParametersJSON Schema
NameRequiredDescriptionDefault
tasksYesOne to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to100 recipients each; review the exact complete recipient list and existing form follow-up sequence.
accountNoExact selected private account profile; binds label, not key ownership.

TDQS

B3.4/5.0
Behavior4/5

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

Annotations already establish readOnly, idempotent, closed-world, non-destructive, so the bar is lower; the description still adds real value by enumerating what is NOT performed (no provider reads, no key load, no identity check, no price, no rollback guarantee). That negative-space disclosure meaningfully bounds what a preview guarantees.

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?

Two tight sentences with no filler, leading with the core operation before the disclaimers. Slightly over-compressed – the SHA-256 and 'reviewed schema' references are opaque without more context.

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

Completeness3/5

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

There is no output schema, so the description arguably should say what a preview yields (the hash, validation result) and how it feeds the submit step, and it does not. It covers the operation's boundaries well but leaves the agent guessing about the return payload and the preview-to-submit workflow.

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 100%, so the schema already documents both parameters, including the enum of sub-tools and the recipient-list caveat on tasks. The description adds only loose echoes ('exact ordered ... work', 'selected profile label') without new syntax or format detail, matching the baseline 3.

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

Purpose4/5

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

States a specific action-and-resource pair: local validation plus SHA-256 hashing of an ordered testimonial/import/invite batch. An agent can grasp it's a dry-run validator, but the phrasing is dense jargon and it never names the sibling it pairs with (submit_testimonial_batch), so differentiation is inferred rather than stated.

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

Usage Guidelines2/5

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

No when-to-use guidance at all, and the obvious alternative submit_testimonial_batch is never mentioned. The 'No provider reads...' clauses hint at preview semantics but stop short of telling the agent when to reach for this versus submitting the batch for real.

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

send_invitesSend form invitesB
Destructive

Send email invites using a selected form and its existing follow-up sequence. Local cap100 recipients, not a documented provider quota.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNoExact configured private account profile label; not a tenant or provider account ID.
confirmNoMust be true for the requested mutation or exclusive private output file.
form_idNoExact forms[].id from list_links.
payloadNoComplete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.
recipientsNo
payload_fileNoAbsolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, openWorldHint=true, and idempotentHint=false, so the safety profile is covered. The description adds useful context that the 100-recipient limit is a local tool cap rather than a provider quota, but it does not disclose that `confirm` must be set, that sending is irreversible, or anything about the follow-up sequence behavior.

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?

Two short sentences with the action front-loaded and no padding. The second sentence's phrasing ("Local cap100 recipients") is slightly clipped but still readable and earns its place by clarifying the limit's origin.

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

Completeness3/5

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

For a destructive, open-world mutation with 6 params (0 required) and no output schema, the description is adequate but thin: it never mentions the required `confirm` flag or that the mutation cannot be undone, leaving that entirely to the schema and annotations. It is callable, but not fully self-explanatory.

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 83%, so the schema already documents `account`, `confirm`, `form_id`, `payload`, and `payload_file` in detail. The description only echoes the recipient cap (maxItems 100) and adds no syntax or format meaning beyond the schema, so the baseline 3 applies.

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

Purpose4/5

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

The description gives a specific verb+resource ("Send email invites") and adds scope detail ("using a selected form and its existing follow-up sequence"). It does not need to differentiate from siblings since none of the listed testimonial/link tools overlap with invite sending, so 4 is appropriate.

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

Usage Guidelines2/5

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

There is no explicit when-to-use or when-not-to-use guidance, and no alternative tool is named. The only contextual note is the recipient cap, which is a constraint rather than usage direction.

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

submit_testimonial_batchExecute reviewed testimonial tasksA
Destructive

Confirmed one-to-twenty ordered testimonial/import/invite tasks. Prevalidate all and verify exact hash before first request. Stop on first failure with known results/failed index/unattempted indices; no retries, rollback or implicit continuation.

ParametersJSON Schema
NameRequiredDescriptionDefault
tasksYesOne to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to100 recipients each; review the exact complete recipient list and existing form follow-up sequence.
accountNoExact selected private account profile; binds label, not key ownership.
confirmNoExplicit approval for this exact requested ordered batch.
review_sha256YesExact preview_testimonial_batch hash for identical requests, profile label, schema and order.

TDQS

A3.9/5.0
Behavior5/5

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

Goes well beyond the annotations (destructiveHint, non-idempotent) by disclosing exact failure semantics: stop on first failure, no retries, no rollback, no implicit continuation, and a return shape of known results plus failed index and unattempted indices. This is precisely the operational knowledge an agent needs before firing a destructive batch.

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?

Three dense sentences, front-loaded with scope and then failure behavior; every clause carries operational weight. The opening is a noun fragment that reads telegraphically, but nothing is padded.

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

Completeness4/5

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

For a destructive, non-idempotent batch tool with no output schema, it covers scope limits, ordering, the confirmation gate, and the failure/return contract. It leaves the hash-mismatch path and interaction with the preview sibling implicit, which is the main remaining gap.

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 coverage is 100%, so the baseline is 3; the schema already documents tasks, account, confirm, and review_sha256. The description reinforces ordering and the pre-request hash gate but adds little syntax or per-parameter meaning beyond what the schema states.

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

Purpose4/5

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

The description names the resource and scope precisely: a confirmed, ordered batch of one-to-twenty testimonial/import/invite tasks, executed with hash verification. It is distinguishable from the preview_testimonial_batch sibling by being the execution stage, though it never names that sibling explicitly.

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

Usage Guidelines3/5

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

Usage is implied rather than stated: 'Confirmed' and 'verify exact hash before first request' suggest the tool must follow a preview/confirm flow, but the description never says to call preview_testimonial_batch first or what to do when the hash mismatches. No explicit when-not or alternative routing is given.

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

update_testimonialUpdate approval or tagsA
Destructive

Change only native approval status and tag additions/removals. Text, rating and customer edits remain dashboard-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNoExact configured private account profile label; not a tenant or provider account ID.
confirmNoMust be true for the requested mutation or exclusive private output file.
payloadNoComplete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.
add_tagsNo
approvedNo
remove_tagsNo
payload_fileNoAbsolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.
testimonial_idYesExact testimonial ID. No slash, traversal or arbitrary URL.

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=false and openWorldHint=true, so the safety profile is covered. The description adds the useful scope constraint that only approval and tags are mutable, but it says nothing about the mandatory confirm flag, whether tag removal is reversible, or auth requirements — context that matters for a destructive mutation.

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

Conciseness5/5

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

Two tight sentences with the mutable scope stated first and the exclusion second. No filler, no restatement of the title.

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

Completeness3/5

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

For a destructive, non-idempotent mutation with a nested payload, mutually exclusive body options and no output schema, the description covers the editable surface but omits the confirm prerequisite and the payload-vs-payload_file exclusivity that an agent must get right to call it successfully.

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 coverage is 63% with 8 parameters, including a nested payload object, confirm, account and payload_file. The description maps conceptually to approved/add_tags/remove_tags but adds no syntax, mutual-exclusivity (payload vs. payload_file vs. flat flags) or identifier-format detail beyond what the schema already documents. Baseline 3 is appropriate.

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

Purpose4/5

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

States a specific mutation scope: approval status plus tag additions/removals, and explicitly excludes text, rating and customer edits. An agent immediately knows the editable surface. It does not name a sibling, but no sibling offers a competing update operation, so the field-level scoping does the differentiating work.

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

Usage Guidelines4/5

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

Gives a clear when-not: text, rating and customer edits are 'dashboard-only,' which tells the agent to route those requests elsewhere. It stops short of giving positive selection criteria (e.g., when to prefer this over batch submission) or noting prerequisites such as the confirm flag.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 12 tool updatesv2.0.0
    • First observedcreate_testimonial
    • First observeddelete_testimonial
    • First observedexport_testimonials
    • First observedget_operation_schema
    • First observedget_testimonial
    • First observedlist_accounts
    • First observedlist_links
    • First observedlist_testimonials
    • First observedpreview_testimonial_batch
    • First observedsend_invites
    • First observedsubmit_testimonial_batch
    • First observedupdate_testimonial

TDQS

A3.6/5.0

Scored across 12 tools

Disambiguation4/5

The CRUD tools for testimonials are clearly distinct, and the batch, export, links, and account tools have different scopes. There is minor potential confusion between list_testimonials and export_testimonials, but the descriptions clarify their distinct purposes.

Naming Consistency5/5

All tools follow a consistent snake_case verb_noun pattern, including multi-word names like get_operation_schema and preview_testimonial_batch. No mixed conventions or vague verbs.

Tool Count5/5

With 12 tools, the set is well-scoped for testimonial management, covering core CRUD, batch operations, export, and auxiliary functions without excessive clutter.

Completeness4/5

The surface covers testimonial CRUD (update is intentionally limited), batch preview/submit, export, links, invites, and account listing. Some gaps exist, such as no direct text/rating edits or invite sequence management, but core workflows are well supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables AI agents to fully automate Appwrite backend operations with 143 tools covering databases, users, storage, functions, messaging, and more. Supports advanced features like GeoJSON attributes, file uploads, function deployment, and bulk operations.
    3 npm
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Exposes the full Chatwoot API as 129 tools for AI assistants, enabling account, contact, conversation, message, inbox, team, report, help center, automation, and custom attribute management, plus exclusive Kanban and scheduled message features.
    9 npm
    MIT
  • F
    license
    B
    quality
    B
    maintenance
    Enables AI agents and clients to discover accounts and channels, read scheduling and analytics data, and manage posts, content items, and templates through 41 GraphQL-backed tools with private credential profiles and confirmation-gated mutations.
    41
    -