Perlance connector reference
The master for everything Claude and people need to use Perlance from Claude. The docs site at https://docs.perlanceai.com (the reference and the setup kit) and the app's "Connect Claude" card are built from this file, and npm test fails if it and the live service disagree (tests/connector-doc.test.ts). Change the code and this file together.
1. The address
Paste this into Claude as a custom connector:
https://api.perlanceai.com/mcp
Signing in. The first time Claude uses the connector, it opens a Perlance sign-in page. Choose Google and sign in with your work Google account, the one your Perlance admin added. You do this once per Claude account; Claude renews the sign-in by itself. Perlance never sees your password.
Being refused. Every refusal comes back as a sentence that says what is wrong and who can fix it. Claude should read it to you as given. Refusals about your account (not part of any organisation, removed, domain not allowed, suspended) are fixed by your Perlance admin. Refusals about a role (no route, not the lead, a stale save) are fixed by doing what the sentence says, or by the lead of the node. "Something went wrong inside Perlance" means the service failed: try again, and tell your Perlance admin if it keeps happening.
Refusals any action can give, in the service's words (names in braces are filled in):
- "Perlance cannot use the email address in your sign-in ({email}). Ask your Perlance admin for help."
- "{email} is signed in but is not part of any Perlance organisation. Ask your Perlance admin to add this email."
- "Your Perlance organisation is not set up correctly. Tell your Perlance admin."
- "This Perlance service serves a different organisation, not {org}. Use your own organisation's address."
- "Perlance is suspended for {org}. Tell your Perlance admin."
- "Email addresses at {domain} are not allowed in {org}. Ask your Perlance admin."
- "{email} is not an active member of {org}. Ask your Perlance admin."
- "That request is not complete: {what is missing}." Claude sent an input the action does not take, or left one out.
- "Something went wrong inside Perlance. Try again in a moment; if it keeps happening, tell your Perlance admin."
**Refusals any action after open_seat can give** (they all carry seatId and session):
- "There is no such seat in {org}." The seat id is wrong, or the seat is archived.
- "You have no route into this seat. Ask the owner of its node to assign you." You are no longer assigned to it.
- "That session handle is not yours, or is not for this seat. Open the seat again with open_seat." One handle works for one person on one seat (R-19).
2. The actions
Fifteen, in the order Claude meets them. Every action runs the same five checks (who, which org, which person, may they, do it and record it), and every change is recorded by the service with who and when (R-11).
whoami
For: checking which account Perlance has signed you in as.
Inputs
None.
Returns
The email address, as text.
Refusals
Only the ones any action can give.
Rules
Read only. Nothing is recorded.
my_seats
For: the start of every chat. Lists the roles you hold, so you can choose one to open.
Inputs
None.
Returns
own: one entry per role you hold, with seatId, role, node, lead (true for a node's lead role), state (needs you, at risk or calm), reason (one line), openItems (how many items are open for it) and needsPerson (what the role needs a person for, or null). visitable: other roles you may open, empty until the four routes are built.
Refusals
Only the ones any action can give.
Rules
Read only. A role's state is worked out at the time of asking from its open items and the organisation's thresholds.
open_seat
For: opening one role for this chat. Read everything it returns before doing anything else.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The role to open, from my_seats. |
Returns
In this order: session (the handle every later action needs); seat (role, node, nodeId, lead); nodeContexts (the shared contexts from the root down to this role's node, each with its four parts, marker and age in days); yourNodeContext (lead roles only: how old the node's context is and who saved it); workingRules (section 3); brief (the Role Brief and its links); context (this role's private working context, its marker and word count); state; openItems and waitingOn (one-line summaries); board (lead roles only: the roles directly beneath, with states and counts); skillDocs; history (how many earlier context versions and log entries exist); warnings (an earlier session never logged, a context or node context over its limit).
Refusals
- "There is no such seat in {org}."
- "You have no route into this seat. Ask the owner of its node to assign you."
Rules
Checks your route into the role (R-13) and starts a session, which is recorded. One role per chat. Never returns any other role's private context.
save_context
For: saving this role's private working context whenever something meaningful changes.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
marker | integer | yes | The context's marker from open_seat or the last save. |
currentState | string | yes | Where the work stands. |
inProgress | string | yes | What is under way. |
decisions | string | yes | Decisions made, with dates. |
openQuestions | string | yes | What is still open. |
condensing | object {note: string} | no | When the save shortens the context: a one-line note of what was condensed. |
Returns
The new marker and the wordCount.
Refusals
- "Someone saved this seat since you last read it. Nothing of yours was saved: merge your changes into the latest context and save again with its marker." It comes with
latest(the context now, and its marker) andyourUnsavedContext. Merge, and save again with the new marker.
Rules
Version-checked in one step (R-09): a stale marker never overwrites. The earlier version is always kept (R-10).
save_node_context
For: a node's lead writing the shared context everyone in and beneath the node reads.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role: the node's lead role. |
session | string | yes | The handle from open_seat. |
nodeId | string | yes | The node, which must be the open role's own node. |
marker | integer | yes | The node context's marker from open_seat or the last save. |
currentState | string | yes | Where the group's work stands. |
inProgress | string | yes | What is under way. |
decisions | string | yes | Decisions that affect the group. |
openQuestions | string | yes | What is still open for the group. |
condensing | object {note: string} | no | When the save shortens the context: a one-line note. |
Returns
marker, wordCount, overLimit (over 600 words) and warning (or null).
Refusals
- "Only a node's lead role writes its node context, and {role} is not a lead role. Tell the lead of {node} instead."
- "This session's role leads {node}, so it can write only that node's context."
- "Someone saved the node context of {node} since you last read it. Nothing of yours was saved: merge your changes into the latest and save again with its marker." With
latest.
Rules
Lead roles only, own node only. Version-checked like save_context; every version kept. Over 600 words the save succeeds and is flagged.
log_session
For: the end of every chat. What was done and what is next.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
done | string | yes | What was done in this session. |
next | string | yes | What is next. May be empty. |
Returns
logged: true.
Refusals
- "This session is already logged. Each session gets one log entry."
Rules
One log entry per session, add-only (R-10). It also stops the warning about your earlier unlogged sessions on this role. A session that saved without a log is flagged to the next person who opens the role.
send_down
For: a lead sending an instruction, or a note, to a role beneath its node.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role: a lead role. |
session | string | yes | The handle from open_seat. |
to | string | yes | The role it is for, beneath this node, at any depth. |
kind | one of instruction, note | no | Instruction unless said. |
summary | string | yes | One line, shown in lists. |
body | string | yes | The full text, read only with read_item. |
links | url[] | no | Google Drive or other links. |
priority | one of high, normal, low | no | Normal unless said. |
due | date | no | YYYY-MM-DD. |
partOf | string | no | An open instruction for this role that this one is a part of. |
Returns
itemId and path (the roles it travels through).
Refusals
- "send_down carries instructions and notes. Raise questions and blockers up with raise_up."
- "Only a lead instructs, and {role} is not a lead role. Send a note or a question with add_note instead."
- "{role} is not beneath {your role}. Work goes down only to roles beneath you."
- "{role} is in {node}, not yours. Work moves across nodes through the leads: raise it to {your lead}, who can pass it on."
- "There is no such role in {org}."
- "partOf must be an open item for this role."
Rules
Only leads instruct. Both roles keep the item; every lead in between sees it on their board. Recorded, add-only events (R-10).
raise_up
For: a question or a blocker for the lead above, or any lead higher up.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
to | string | no | A lead role above. Your own lead unless said. |
kind | one of question, blocker | yes | A blocker turns the lead's role to "needs you". |
summary | string | yes | One line. |
body | string | yes | The full text. |
links | url[] | no | Links. |
priority | one of high, normal, low | no | Normal unless said. |
due | date | no | YYYY-MM-DD. |
Returns
itemId, to (the role it went to) and path.
Refusals
- "raise_up carries questions and blockers. Send instructions and notes down with send_down."
- "{role} has no role above it, so there is nobody to raise this to."
- "{role} is beneath {your role}. Raise goes up; send it down with send_down."
- "{role} is a peer, not above you. Ask a peer with add_note."
- "{role} is in {node}, not yours. Work moves across nodes through the leads: raise it to {your lead}, who can pass it on."
- "There is no such role in {org}."
Rules
A question always has an owner. The answer comes back along the recorded path.
add_note
For: a note to a peer in the same node, to the lead above, or to a role beneath; or a question to a peer.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
to | string | yes | The role it is for. |
kind | one of note, question | no | Note unless said. A question only to a peer. |
summary | string | yes | One line. |
body | string | yes | The full text. |
links | url[] | no | Links. |
Returns
itemId and path.
Refusals
- "add_note carries notes and questions, never instructions. Only a lead instructs, with send_down."
- "Raise a question to a role above you with raise_up."
- "Questions go up or across. To ask a role beneath you, send it a note or an instruction."
- "{role} is in {node}, not yours. Work moves across nodes through the leads: raise it to {your lead}, who can pass it on."
- "There is no such role in {org}."
Rules
Never an instruction. Across nodes only through the leads.
read_item
For: one item's full text and history, when you work on it. Lists only ever show one-line summaries.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
itemId | string | yes | The item, from openItems or waitingOn. |
Returns
The item's summary, kind, status, priority, due date, from, to, path, what it answers or is part of, its full text and links, and its events (who did what, when).
Refusals
- "There is no such item for this role." The item is not for, from or through this role.
Rules
Read only. Bodies are fetched one at a time, never in lists. Becomes look_up with kind item when look_up is built (phase 4).
complete_item
For: finishing an instruction, a note or a result that is for this role.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
itemId | string | yes | The item. |
summary | string | no | One line for the result. "Done: ..." unless said. |
result | string | no | What was done. Needed for an instruction: it goes back to the sender. |
Returns
itemId and resultItemId (the result sent back, or null).
Refusals
- "There is no such item for this role."
- "This is a {question or blocker}: answer it with answer_item."
- "Say what was done: complete_item needs a result for an instruction, which goes back to the sender."
- "This item is already {completed, cancelled or answered}."
Rules
The result returns to the sender along the path the instruction came. Nothing is overwritten; the change is an add-only event (R-10).
cancel_item
For: the sender withdrawing an item, with every unfinished part split from it.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role: the one that sent the item. |
session | string | yes | The handle from open_seat. |
itemId | string | yes | The item. |
reason | string | no | Why. |
Returns
cancelled (the item and its unfinished parts) and kept (parts already finished).
Refusals
- "Only the role that sent an item can cancel it."
- "There is no such item for this role."
- "This item is already {completed, cancelled or answered}."
Rules
Finished parts stay finished. Every cancellation is an add-only event.
answer_item
For: answering a question or a blocker that is for this role.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
itemId | string | yes | The question or blocker. |
summary | string | no | One line for the answer. "Answer: ..." unless said. |
answer | string | yes | The answer. |
Returns
itemId, resultItemId (the answer sent back) and path.
Refusals
- "There is no such item for this role."
- "Only questions and blockers are answered. Complete this {kind} with complete_item."
- "This item is already {completed, cancelled or answered}."
Rules
The answer returns to the asker along the recorded path, through every role it passed.
pass_up
For: passing a question or blocker for this role one more level up.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
itemId | string | yes | The question or blocker. |
to | string | no | A lead role above. The next one up unless said. |
note | string | no | Why it is passed up. |
Returns
itemId, to and path.
Refusals
- "There is no such item for this role."
- "Only questions and blockers are passed up."
- "{role} has no role above it to pass this to."
- "{role} is not above {your role}. Pass up goes only to a lead above you."
- "This item is already {completed, cancelled or answered}."
Rules
The item's owner moves up; the answer still comes back down the same path.
flag_needs_person
For: marking that this role needs a person (a sign-off, an access, a decision only a human can give), or clearing that mark.
Inputs
| Input | Type | Required | What it is |
|---|---|---|---|
seatId | string | yes | The open role. |
session | string | yes | The handle from open_seat. |
what | string | no | What is needed. Needed unless clearing. |
from | string | no | From whom. Needed unless clearing. |
clear | true | no | Clears the mark. |
Returns
needsPerson (what and from whom, or null once cleared).
Refusals
- "That request is not complete: say what is needed and from whom, or clear the flag."
Rules
Marks only the open role (R-19). A flagged role shows as "needs you".
3. The working rules
open_seat returns the organisation's working rules from its settings. New organisations start with this text, and Threadwell Labs was given it on 2026-10-15:
Work this role as its holder would. Read the shared contexts and the brief before acting. Save the context when something meaningful changes and before any long step. Keep the private context under the word limit; condense it when warned and mark the save as condensing. Log the session before stopping. Raise blockers up rather than guessing. If you lead this node, promote decisions, dates and client facts to the node context.
4. The Claude setup kit
On its own page: the setup kit.
5. Change log
| Date | What changed | Reconnect? |
|---|---|---|
| 2026-10-15 | First version: fifteen actions (whoami through flag_needs_person, with read_item from PR-018), the default working rules, the setup kit. | No |
| 2026-10-15 | The pages move to https://docs.perlanceai.com (PR-023); the project instructions and the starting file say what open_seat and add_note actually do. People who already pasted the instructions or added the starting file should replace them. | No |