> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Connect AI agents to the Tally MCP server

The Tally MCP connector routes your AI agent's tool calls to Tally's own MCP server through Scalekit. Each user signs in to Tally once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 26 tools.

**Authentication:** OAuth 2.1/DCR
**Categories:** Productivity, Automation
**Tools:** 26: 9 read, 17 write, 0 destructive
**Users sign in with:** OAuth
**OAuth app:** Scalekit's or your own
**Built by:** Vendor MCP
**Try it:** [Playground in the Scalekit dashboard](https://app.scalekit.com/ws/signup?sk_intent=playground&provider=TALLYMCP)

## What you can do

- **Build forms**: create new forms and add, move, or remove questions, blocks, and pages
- **Add conditional logic**: create or update conditional logic rules on questions and blocks, and set which fields are required
- **Style forms**: apply brand colors, fonts, and images from a website, or update layout and custom CSS
- **Configure and publish**: update submission limits, notifications, and redirects, then save and publish the form
- **Read submissions and insights**: fetch form responses and track views, completions, and conversion rate

## Setup

1. ### Install the SDK

   **Node.js**

   ```bash
   npm install @scalekit-sdk/node dotenv
   ```

   **Python**

   ```bash
   pip install scalekit-sdk-python python-dotenv
   ```

2. ### Set your credentials

   Add your Scalekit credentials to your `.env` file. Find values in **[app.scalekit.com](https://app.scalekit.com)** > **Developers** > **API Credentials**.

   ```sh title=".env"
   SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
   SCALEKIT_CLIENT_ID=<your-client-id>
   SCALEKIT_CLIENT_SECRET=<your-client-secret>
   ```

3. ### Create the Tally MCP connection

   In **AgentKit > Connections**, create a Tally MCP connection. The name you give it is the `connection_name` your code passes. See [Configure connections](/agentkit/connections/).

   Scalekit credentials are available for Tally MCP server, so you don't need to register an OAuth app.

4. ### Authorize a user and make your first call

   **Node.js** (`quickstart.mts`)

   ```typescript
   import { ScalekitClient } from '@scalekit-sdk/node'
   import 'dotenv/config'
   import { createInterface } from 'node:readline/promises'

   const scalekit = new ScalekitClient(
     process.env.SCALEKIT_ENVIRONMENT_URL,
     process.env.SCALEKIT_CLIENT_ID,
     process.env.SCALEKIT_CLIENT_SECRET,
   )
   const actions = scalekit.actions

   const connector = 'tallymcp'
   const identifier = 'user_123'

   // Generate an authorization link for the user
   const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
   console.log('Authorize Tally MCP:', link)
   const rl = createInterface({ input: process.stdin, output: process.stdout })
   await rl.question('Press Enter after authorizing...')
   rl.close()

   // Make your first call
   const result = await actions.executeTool({
     connector,
     identifier,
     toolName: 'tallymcp_inspect_custom_css',
     toolInput: {},
   })
   console.log(result)
   ```

   ```bash
   npx tsx quickstart.mts
   ```

   **Python** (`quickstart.py`)

   ```python
   import os
   from scalekit import ScalekitClient
   from dotenv import load_dotenv
   load_dotenv()

   scalekit_client = ScalekitClient(
       env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
       client_id=os.getenv("SCALEKIT_CLIENT_ID"),
       client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
   )
   actions = scalekit_client.actions

   connection_name = "tallymcp"
   identifier = "user_123"

   # Generate an authorization link for the user
   link_response = actions.get_authorization_link(
       connection_name=connection_name,
       identifier=identifier,
   )
   print("Authorize Tally MCP:", link_response.link)
   input("Press Enter after authorizing...")

   # Make your first call
   result = actions.execute_tool(
       tool_input={},
       tool_name="tallymcp_inspect_custom_css",
       connection_name=connection_name,
       identifier=identifier,
   )
   print(result)
   ```

   ```bash
   python quickstart.py
   ```

   Each user signs in once. See [Authorize a user](/agentkit/tools/authorize/) for the full flow and statuses.

## Tools

Pass the exact name to `execute_tool`, with an input like each tool's example. To ask for a tool that's missing, use the [request form](https://scalekitsupport.portal.usepylon.com/forms/request-a-connector-tool).

**Node.js**

```typescript
const result = await actions.executeTool({
  toolName: 'tallymcp_extract_brand',
  toolInput: {
    url: '<url>',
  },
  connector: 'tallymcp',
  identifier: 'user_123',
})
```

**Python**

```python
result = actions.execute_tool(
    tool_name="tallymcp_extract_brand",
    tool_input={
        "url": "<url>",
    },
    connection_name="tallymcp",
    identifier="user_123",
)
```

`result.data` is the app's response as JSON, and `result.execution_id` (`executionId` in Node.js) is the ID of the call.

### `tallymcp_extract_brand`

Extract Brand · Read-only

Extract brand colors, fonts, and images from a website URL to apply to the form.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `url` (`string`, required): No description.

Example input: `{"url":"<url>"}`

### `tallymcp_fetch_insights`

Fetch Insights · Read-only

Fetch analytics metrics for a form such as views, completions, and conversion rate.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `formId` (`string`, required): No description.
- `period` (`string`, required): No description. One of: `today`, `yesterday`, `24h`, `7d`, `30d`, `3m`, `6m`, `12m`, `all`.
- `include` (`array`, optional): No description.

Example input: `{"formId":"<formId>","period":"today"}`

### `tallymcp_fetch_submissions`

Fetch Submissions · Read-only

Retrieve paginated form submissions with question labels and response values.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `formId` (`string`, required): No description.
- `filter` (`object`, optional): No description.
- `limit` (`number`, optional): No description. Default: `50`.
- `page` (`number`, optional): No description. Default: `1`.

Example input: `{"formId":"<formId>"}`

### `tallymcp_inspect_custom_css`

Inspect Custom Css · Read-only

Return the current custom CSS and available CSS selectors for the form.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `tallymcp_list_blocks`

List Blocks · Read-only

Retrieve the current form structure as a block ledger showing all blocks with their UUIDs and types.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `tallymcp_list_forms`

List Forms · Read-only

List forms the user has access to, with optional filtering and pagination.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `filter` (`object`, optional): No description.
- `limit` (`number`, optional): No description. Default: `50`.
- `page` (`number`, optional): No description. Default: `1`.

Example input: `{}`

### `tallymcp_list_workspaces`

List Workspaces · Read-only

List all workspaces the user can access.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `tallymcp_load_form`

Load Form · Read-only

Load an existing form by ID to prepare it for editing.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `formId` (`string`, required): No description.

Example input: `{"formId":"<formId>"}`

### `tallymcp_search_documentation`

Search Documentation · Read-only

Answer-only search of the Tally Help Center for explicit documentation or product-knowledge questions: how Tally works, whether a capability exists, supported features, limits, or docs links. Never use as a preflight for form edits. Never use for commands that change the current form, including adding or creating blocks, configuring fields, setting defaults, updating settings, adding calculated fields, styling, moving, removing, formatting, or applying logic.

Read only: yes. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `query` (`string`, required): No description.
- `topK` (`number`, optional): No description.

Example input: `{"query":"<query>"}`

### `tallymcp_apply_logic`

Apply Logic · Write

Create or update conditional logic rules on form blocks using DSL syntax.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `operations` (`array`, required): No description.

Example input: `{"operations":[]}`

### `tallymcp_configure_blocks`

Configure Blocks · Write

Update block properties such as visibility, required state, and other settings.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `updates` (`array`, required): No description.

Example input: `{"updates":[]}`

### `tallymcp_create_blocks`

Create Blocks · Write

Add new question blocks or content blocks to the current form.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `groups` (`array`, required): No description.

Example input: `{"groups":[]}`

### `tallymcp_create_new_form`

Create New Form · Write

Create a new blank form with the specified title and optional branding.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `title` (`string`, required): No description.
- `coverImageUrl` (`string`, optional): No description.
- `logoUrl` (`string`, optional): No description.
- `submitButtonText` (`string`, optional): No description.
- `workspaceId` (`string`, optional): No description.

Example input: `{"title":"<title>"}`

### `tallymcp_move_blocks`

Move Blocks · Write

Move one or more blocks to a new position in the form.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `blockUuids` (`array`, required): No description.
- `insertAfterBlockUuid` (`string`, required): No description.

Example input: `{"blockUuids":[],"insertAfterBlockUuid":"<insertAfterBlockUuid>"}`

### `tallymcp_remove_blocks`

Remove Blocks · Write

Remove specific blocks from the form by their UUIDs.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `blockUuids` (`array`, required): No description.

Example input: `{"blockUuids":[]}`

### `tallymcp_remove_pages`

Remove Pages · Write

Remove entire pages from the form by page number.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `pageNumbers` (`array`, required): No description.

Example input: `{"pageNumbers":[]}`

### `tallymcp_remove_questions`

Remove Questions · Write

Remove entire questions from the form by their UUIDs.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `questionUuids` (`array`, required): No description.

Example input: `{"questionUuids":[]}`

### `tallymcp_reposition_pages`

Reposition Pages · Write

Move, swap, or reorder pages using a command (move, swap, reorder).

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `command` (`string`, required): No description. One of: `move`, `swap`, `reorder`.
- `currentPageNumber` (`number`, optional): No description.
- `newPageNumber` (`number`, optional): No description.
- `order` (`array`, optional): No description.
- `pageNumberA` (`number`, optional): No description.
- `pageNumberB` (`number`, optional): No description.

Example input: `{"command":"move"}`

### `tallymcp_reposition_questions`

Reposition Questions · Write

Move or swap questions using a command (move, swap).

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `command` (`string`, required): No description. One of: `move`, `swap`.
- `afterBlockUuid` (`string`, optional): No description.
- `questionUuidA` (`string`, optional): No description.
- `questionUuidB` (`string`, optional): No description.
- `questionUuids` (`array`, optional): No description.

Example input: `{"command":"move"}`

### `tallymcp_save_form`

Save Form · Write

Save the current form changes and optionally publish or unpublish the form.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `formId` (`string`, optional): No description.
- `status` (`string`, optional): No description. One of: `DRAFT`, `PUBLISHED`. Default: `PUBLISHED`.

Example input: `{}`

### `tallymcp_set_column_layout`

Set Column Layout · Write

Organize blocks into a side-by-side column layout.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `layout` (`string`, required): No description.

Example input: `{"layout":"<layout>"}`

### `tallymcp_set_form_title`

Set Form Title · Write

Set or update the form title that appears at the top of the form.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `title` (`string`, required): No description.

Example input: `{"title":"<title>"}`

### `tallymcp_update_custom_css`

Update Custom Css · Write

Apply custom CSS to the form as a last-resort override for styling not supported by update_styling.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `css` (`string`, required): No description.
- `reason` (`string`, required): No description.

Example input: `{"css":"<css>","reason":"<reason>"}`

### `tallymcp_update_settings`

Update Settings · Write

Update form settings including submission limits, notifications, redirects, and metadata.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `closeAt` (`string`, optional): No description.
- `closeMessage` (`string`, optional): No description.
- `direction` (`string`, optional): No description. One of: `ltr`, `rtl`.
- `hasPartialSubmissions` (`boolean`, optional): No description.
- `hasProgressBar` (`boolean`, optional): No description.
- `isClosed` (`boolean`, optional): No description.
- `language` (`string`, optional): No description. One of: `af`, `ar`, `sq`, `bn`, `bg`, `ca`, `zh-CN`, `zh-TW`, `hr`, `cs`, `da`, `nl`, `en`, `et`, `eu`, `fo`, `fa`, `fil`, `fi`, `fr`, `ka`, `de`, `kl`, `el`, `he`, `hi`, `hu`, `is`, `id`, `ga`, `it`, `ja`, `ko`, `lv`, `lt`, `no`, `ms`, `mk`, `pl`, `pt`, `pt-BR`, `ro`, `ru`, `sr`, `si`, `sk`, `sl`, `es`, `es-MX`, `sv`, `ta`, `th`, `tr`, `uk`, `uz`, `vi`, `yo`.
- `metaDescription` (`string`, optional): No description.
- `metaImageUrl` (`string`, optional): No description.
- `metaSiteFaviconUrl` (`string`, optional): No description.
- `metaSiteName` (`string`, optional): No description.
- `metaTitle` (`string`, optional): No description.
- `pageAutoJump` (`boolean`, optional): No description.
- `password` (`string`, optional): No description.
- `redirectOnCompletionUrl` (`string`, optional): No description.
- `respondentEmail` (`string`, optional): No description.
- `saveForLater` (`boolean`, optional): No description.
- `selfEmail` (`string`, optional): No description.
- `submissionsDataRetention` (`string`, optional): No description.
- `submissionsLimit` (`string`, optional): No description.
- `uniqueSubmissionKey` (`string`, optional): No description.
- `verifyEmail` (`string`, optional): No description.

Example input: `{}`

### `tallymcp_update_styling`

Update Styling · Write

Update form appearance and advanced styling in a single call.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `advanced` (`object`, optional): No description.
- `appearance` (`object`, optional): No description.

Example input: `{}`

### `tallymcp_update_text`

Update Text · Write

Update the HTML text content of blocks in the form.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `updates` (`array`, required): No description.

Example input: `{"updates":[]}`

## Related

Other Productivity connectors ([all 103](/agentkit/connectors/?category=productivity)):

- [Slack](/agentkit/connectors/slack/): Scalekit connector, OAuth, 96 tools
- [Microsoft 365](/agentkit/connectors/microsoft365/): Scalekit connector, OAuth, 317 tools
- [Notion](/agentkit/connectors/notion/): Scalekit connector, OAuth, 51 tools


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
