Skip to content

Documentation

Use Kicklace from Claude

What connecting Claude to a workspace gives you, in the words the screen uses: what to ask it, the two ways to connect, what it can and cannot do, and where to read back everything it did. It never sends an email, never deletes a record, and never puts anybody on a list without the words they agreed to.

Settings → Claude is the screen a customer connects their own AI from (#145, #166). Since #228 it opens on what you could ask it — the eight asks in §3 — because that is the only frame on the screen that answers "why would I?", and an address answers "how?", which is a question nobody has until they want the thing above. Then the two ways in (sign in from Claude, or take a key), then what Claude can do, then what it did. This file is where those words are agreed and reviewed; the protocol behind the screen — the JSON-RPC shapes, the OAuth endpoints, the errors, the two kinds of key — is docs/mcp.md.

The screen is src/app/app/[slug]/settings/claude/page.tsx with src/components/settings/claude-recipes.tsx, claude-connect.tsx, claude-tools.tsx and claude-log.tsx, in that order. Its tab sits in Get set up, right after Your website, because connecting Claude is hookup work of the same kind — and Your website's own "Let your AI do it" frame links here, since a founder who has connected Claude can ask it to set the site up rather than paste anything.

1. Use Kicklace from Claude

Claude can look people up, read a person's whole story, run a report, add notes and follow-ups, put someone on a list with the words they agreed to, and draft an email for you to send. It never sends anything and never deletes anything, and everything it does is written down below, in your name.

The frame's own line is "Add Kicklace to Claude and sign in. Nothing is copied, and you can disconnect it here at any time."

Sign in from Claude (#166)

First inside the frame, because it is what most people want and it copies nothing:

Open Claude, go to Settings → Connectors → Add custom connector, and paste this address. Claude sends you back here to sign in, you pick this workspace, and that is the whole of it.

"Settings → Connectors → Add custom connector" is the name of a menu inside Claude, which is why the word connector survives here and nowhere else on the screen (#228).

The address is the same <url> as below: appBaseUrl() + "/api/mcp". The connector registers itself, sends the person to Kicklace's own sign-in, and shows them the consent screen at /connect/authorize:

Let Claude use Kicklace as you? · Signed in as michael@example.com · It will work in WoodWright, as you. — with a workspace picker when they are in more than one, "You are not in any workspace yet" when they are in none, the four things it will be able to do, the two it will not, and Allow / Deny.

What comes back is that member's, in that one workspace: an access token that lasts an hour and a refresh token that rotates. Connected apps on the settings screen lists one row per sign-in — the app's name, the workspace, the day, when it was last used — with a two-step Disconnect that revokes the whole sign-in, so the app stops at its next call rather than at the end of the hour.

Or connect with a key

Claude Code, and some other apps, ask for a key instead of sending you here to sign in. One button makes one of your own; it is shown once.

Any member may press it: the key carries that member's user id, the door acts as them, and Claude can do exactly what they can do with their own hands and nothing more. That is also why the keys listed under it are the signed-in member's own and not the workspace's, and why the two-step Disconnect refuses a key that is not theirs.

The key is sk_live_… with the purpose claude, stored as a SHA-256 hash the moment it is made, so the panel below is the only time it exists in readable form. The screen says so: "This key is shown once. If you lose it, disconnect and connect again."

What each connection knows about (#195)

Every row in both lists — a Connected app and a key — carries one quiet line saying what that client believes Kicklace can do, because a client reads tools/list once and keeps it, and the door cannot push it a new one. It is drawn from tools_listed on the key or on the grant, against the registry the "What Claude can do" frame below reads, so a row can never name a tool that is not there.

Claude read the tool list 2 h ago and has 17 of the 62 tools. It does not know about find_records, describe_website, create_record and 10 more. In the Claude desktop app, switch this connector off and on in the Code tab's list of connected MCP servers; in claude.ai, remove the connector and add it again. A key-based client re-reads the list when it starts.

That is the real sentence for a connection made before the setup round of 2026-09-08, when the door held seventeen tools.

At most three tools are named and the rest are counted; a name the client still holds that Kicklace has since taken away is said as well ("It still lists old_tool, which Kicklace no longer has"). A client with everything reads, in the quiet grey the "last used" line is drawn in:

Has all 62 tools; read 2 h ago.

A connection that has never read the list — a key minted before this landed, or one nothing has used yet — says nothing at all. docs/mcp.md has why listChanged is false and when each client reads the list.

The three snippets

<url> is appBaseUrl() + "/api/mcp" — the screen prints the deployment's own address, so a local one says http://localhost:3111/api/mcp and production says https://www.kicklace.com/api/mcp. <key> is the key just minted.

Claude Code. One line, no shell continuation in it: a backslash and a newline are not the same thing in every shell, and this is meant to be pasted, not read.

claude mcp add --transport http kicklace <url> --header "Authorization: Bearer <key>"

Claude Desktop. Put this in claude_desktop_config.json and start Claude Desktop again.

{
  "mcpServers": {
    "kicklace": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "<url>",
        "--header",
        "Authorization: Bearer <key>"
      ]
    }
  }
}

On macOS that file is ~/Library/Application Support/Claude/claude_desktop_config.json; on Windows it is %APPDATA%\Claude\claude_desktop_config.json. mcp-remote is a small bridge, for a client that still wants a key on disk; it runs on the customer's own machine and passes the key straight to Kicklace. Claude Desktop's own connector list does not need it — it takes the address and signs in, which is the frame above this one.

Any other app that takes a key. An address and one line of authorization. Nothing else to set up. (Streamable HTTP, one header, for whoever is wiring it.)

<url>
Authorization: Bearer <key>

2. What Claude can do

The tools are read from the registry itself (TOOLS in src/lib/mcp/tools/index.ts), so the screen can never promise a tool that is not there; before the tools land it says "The tools arrive with the next deploy." Reads come first, under Looking things up ("Changes nothing. A key made for one of your own servers may do this much and no more"), then Making changes ("Each one is written on the record in your name"). Each row is the tool's name in words, its real name in mono, and the first sentence of the description the model is given. toolWords in claude-tools.tsx holds the words:

Tool On the screen Tool On the screen
list_approvals See what is waiting for you send_broadcast Ask to send an email to a list
describe_workspace Look around your workspace send_email Ask to email one person
find_people Find people delete_record Ask to delete a record
get_person Open a person delete_list Ask to remove a list
search Search everything delete_template Ask to delete a template
search_activity Search the activity delete_object Ask to delete an object
list_followups List follow-ups remove_field Ask to remove a field
run_report Run a report remove_member Ask to remove a member
find_records Find organizations and deals revoke_key Ask to revoke a key
describe_website Check your website hookup disconnect_integration Ask to disconnect an integration
export_record Get a record's export link merge_records Ask to merge two records
create_list Make a list
update_list Change a list
update_automation Change an automation
activate_automation Switch an automation on
pause_automation Pause an automation
rename_stage Rename a stage
reorder_stages Reorder a pipeline's stages
remove_stage Remove a stage
rename_field Rename a field
rename_object Rename an object
remove_chart Take a chart off a dashboard
resize_chart Resize a chart
create_dashboard Make a dashboard
rename_view Rename a view
create_record Add an organization or a deal
save_report Keep a report as a chart
create_view Save a view
add_stage Add a stage
create_pipeline Make a pipeline
add_field Add a field
create_template Write an email template
update_template Change an email template
allow_site Connect a website address
set_timezone Set the timezone
set_workspace Change the workspace's settings
invite_member Invite somebody
change_role Change what a member may do
add_many_to_list Put people on a list
remove_many_from_list Take people off a list
import_rows Import rows
add_note Add a note
create_followup Make a follow-up
complete_followup Complete a follow-up
create_person Add a person
update_person Update a person
add_to_list Put someone on a list
remove_from_list Take someone off a list
move_stage Move a record's stage
draft_broadcast Draft an email
propose_automation Propose an automation
install_blueprint Install a starter

Then the four rules, which are the reason the screen exists at all:

  • It never sends email. It writes a draft and hands you the link; a person presses send.
  • It never deletes. No record, no note, no consent record goes because Claude asked.
  • It never puts anyone on a list without the words they agreed to. The sentence is stored on the subscription, as the proof it always is.
  • Everything is in your name. A note, a stage move, a follow-up — the timeline says "<member> via Claude", and the call is on the log below.

Setting the whole thing up in one call (#222)

install_blueprint is the same button Settings → Setup has: one of Kicklace's starters — the SaaS starter, the Waitlist starter, Release notes — written into the workspace as a list with the words people agree to, the emails, and the automations, all paused. "Set this workspace up like a SaaS product" is one call rather than a dozen, and every automation still waits for a person to read it and switch it on. Anything it could not write comes back as a sentence saying what to connect first; installing again afterwards adds only what is missing. docs/blueprints.md says what each starter holds.

3. Things to ask Claude

The first frame on the screen (#168, moved to the top by #228; src/components/settings/claude-recipes.tsx, whose RECIPES is the same list): eight one-line asks with a Copy beside each, and under each the one clause that says what happens in Kicklace — and, where the ask leans on something outside Kicklace, what has to be connected in Claude for it to work. The frame's meta says to swap the list and stage names for the workspace's own — and, while nothing is connected yet, that this is "what Claude can do with your workspace once you connect it, below". None of them sends anything.

Ask What it does
"Who joined the waitlist this week, and what did they say?" Reads the people and their notes. Nothing changes.
"Add everyone who emailed me this week to Kicklace, with a note on what they wanted" Adds a person and writes one note for each, in your name. Needs Gmail connected in Claude.
"Put the people in this CSV on Product updates with the words they agreed to" Puts each one on the list with that sentence stored word for word. Without it, Claude is refused.
"Draft a welcome to the macOS waitlist for me to send" Writes the draft and gives you the link. Claude never sends.
"Read this LinkedIn profile and add them as a person" Adds one person with what the page says, and a note saying where it came from. Needs Claude's browser.
"Every Monday, brief me on the waitlist" Reads and sums up. Nothing changes. Needs Claude's scheduled tasks.
"Who downloaded but never activated?" Runs a report over your own stages and answers with the count.
"Write an automation that welcomes anyone who joins a list" Claude writes it against your own stages, lists and templates, and saves it as a draft. You read it and turn it on yourself.
"Put visits by week on my dashboard, and save a view of everyone still at Subscriber" Adds the chart to your dashboard and the view to Contacts, both live. Nothing is removed.

Each one is answered by tools that already exist — find_people and get_person, create_person and add_note, add_to_list, draft_broadcast, run_report, propose_automation, save_report and create_view — so the frame | "Set up a Product updates list and write the welcome email for it" | Makes the list with the sentence people will agree to, stored word for word, and saves the email as a template. Nothing is sent. |

Each one is answered by tools that already exist — find_people and get_person, create_person and add_note, add_to_list, draft_broadcast, run_report, propose_automation, create_list and create_template — so the frame never asks for something the door cannot do. The two that name a Claude connector and the one that names Claude's browser say so on the line, because that part is Claude's side of the hookup and not Kicklace's: Kicklace connects to Claude, and Claude connects to the rest. That is also the framing the site's own "Connect what you already use" scene keeps (#168): a tool is shown as reachable through Claude, never as a Kicklace integration.

4. What Claude did

The last twenty rows of agent_calls (src/lib/data/agent-calls.ts), newest first: when, who — the member whose key it was, or the label on a server key, or "No longer connected" for a key that has since been revoked — the tool in the same words, the tool's own one-line summary, and the outcome as Ok, Refused beside its code, or Error. A write carries a small "change" tag. Under the table, one sentence: "34 calls in 30 days, 6 of them changes, 2 refused. Lines older than 30 days are deleted." Empty, it says: "Nothing yet. Connect Claude and ask it something."

A row holds no argument, no address and no words of a note — only the summary the tool wrote — so the whole workspace can read it.

Since #212 a row also says which door the call came through. One made by Ask Kicklace inside the app carries in the app under the member's name; everything else came through a connector or a key and says nothing extra, because that is what every row was until the box existed.

Your questions (#212)

Above the log, and yours only: what you asked Ask Kicklace inside the app, the answer, and how many calls it made, for thirty days.

"who joined the waitlist this week?" — Four people joined since Monday… · 2 h ago · 2 calls: look around your workspace, find people

Empty, it says "Nothing yet. Press ⌘J anywhere, or Ask on a record." A question is a person's own, so nobody else's are listed here; the calls those questions made are in the table below, where the whole workspace can read them. docs/ask.md is the whole of it — the shortcut, the rules, what it costs, and what happens when it wants to send something.

5. Approvals: what Claude asks for (#211)

Claude can look people up, write things down and set a workspace up on its own. Sending an email, deleting something, removing a member, revoking a key and disconnecting an integration are the acts it has to ask for — a sent email cannot be recalled, a deleted record cannot be restored, and a revoked key breaks somebody's server. Those are proposals, and they land on Approvals in the sidebar, under Tasks, with a count of what is waiting.

The two frames on the page:

Waiting for you"Approve one and it runs now, in your name. Reject one and nothing happens at all." Every row is the one sentence a person decides on ("Send “Still on the waitlist” to 33 people on Waitlist"), a line saying who asked and through what and when it runs out, and the two buttons. Approve on a send or a delete asks a second time, in a dialog that repeats the sentence and says what it does; everything else is one click. A member who is not an owner or an admin reads the row and is told "Only owners and admins can decide a proposal." Empty, the frame says:

Nothing waiting. Claude can look people up, write things down and set this workspace up on its own. Sending an email, deleting something, removing a member, revoking a key and disconnecting an integration are the acts it has to ask for — they land here.

Decided — what was approved, rejected, or left until it ran out, newest first, with what happened ("Sent to 33 people.") or the sentence the app refused it with, and a link to whatever the act touched.

A proposal's own page (/app/<workspace>/approvals/<id>) is where the notification lands: the sentence as the page's title, What happens if you approve in plain words, the same two buttons, and the proposal's facts beside it — asked, through, by, expires, and its reference.

The notification. Every owner and admin hears about it once, in the bell and in the Slack channel if one is connected: "Claude wants to send “Still on the waitlist” to 33 people on Waitlist", with "Nothing has happened yet. Approve or reject it by Sep 15." under it. There is no second notification when it is decided — the page says.

Seven days. A proposal nobody decides runs out, and the worker marks it. Nothing expired can be approved.

Whose name it is in. The act runs through the app's own data layer, exactly as the screen would run it, and where it lands on a timeline the row says "Michael Fall, proposed by Claude" — the member who approved it first, and where the idea came from second.