parley-mcp
OfficialBundles the Lucide icon set as data (with version and licence) so the conversation UI can render message reactions, files and other icons; exposes an icon(name) and fileIcon(name) helper that applications can reuse for their own buttons.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@parley-mcptell the person the build passed and ask them to review the staging link"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Clavarium Parley
A bridge between a command-line agent and a screen of its own.
A command-line agent lives in a terminal. Whoever does not read a terminal cannot talk with it. Parley gives the agent seven verbs, as a command and as an MCP server, and gives an application a small library that shows the exchange as a conversation, on any screen.
It is part of the Clavarium family and needs nothing of Clavarium: any application, any agent that can run a command.
The seven verbs
The agent runs | To |
| say where it is, what it did, in Markdown; a long text with its short version |
| ask, with or without choices ( |
| point to a file it made; several at once, each with its title: |
| say in one line what it is doing now, at each new step |
| read what was written to it, answers and attached files included, each message with its id (what a card or a reply points to), and its questions still open |
| close a question the person answered another way |
| the end of the exchange, both sides (or |
| say where it is |
| how to work with the person, in a few lines, for an agent that forgot |
parley --help says all of it to the agent. The same seven verbs are an MCP
server (parley-mcp, or node server/parley-mcp.mjs --dir FOLDER) for an
agent that is given it that way; both write the same files.
An agent may also work long without a word. Its TOOL can say it acts:
parley pulse in its hooks at each action, parley pulse --end when its turn
ends (with Claude Code: PreToolUse, UserPromptSubmit; Stop, Notification). Nothing is
posted and nothing printed; the screen says "Working…" while it beats, and
"stopped at 14:32" once its turn ended. parley pulse --end --stop-check in
Claude Code's Stop hook asks it once, when it stops while its chat still says
it works, to say where it is.
A picture the person attaches can be drawn on before it is sent (a tap on it,
then a finger or the mouse), with a note about it alone: the agent receives
the picture as drawn (photo-annotated.png) and the note under its path.
Nothing waits: the agent posts, and is told in one line when a message arrived. See docs/protocol.md.
Related MCP server: beacon
Parley announces, the application decides
Event, to | Carries | An application may |
| the message, how many the agent has not read | type |
| the message | show it |
| the question and its choices | show buttons, ring a phone |
| the path, and how to open it ( | show a link, or say it is not in a shared folder |
|
| show it; ring a phone on |
| one line: what it is doing now | show it while it works; nothing more |
| the reaction, and whether the set says it wakes ( | tell the agent now, later, or with the next message |
| with a keep folder: the lines kept that changed or went in the bridge folder, or were slipped in | nothing: the screen says it; alert someone, or log it |
Action | Does |
| writes what the person said ( |
| puts a reaction of the set on a message of the agent, or takes it back ( |
| the exchange: messages, open questions, status, steps (states and what it did, in order), files, unread |
| a part of it: the end, the page before, or only what changed since a cursor; the questions open, the status and the counts stay the whole thread's (see the protocol) |
| the whole thread searched, newest first |
| the text that asks an agent to use Parley, in English, saying the person's language |
Parley types nothing anywhere. WAKE (You have a new message: run "parley read".) and the invitation are texts an application uses as they
are, changes, or does not use.
The pieces
Piece | File | What it is |
The agent's side |
| the seven verbs, as an MCP server and as a command; no dependency |
The application's side |
| reads and writes the files, cleans what the agent wrote, announces events |
The screen |
| the exchange in two views, simple and detailed; no framework |
The words |
| one dictionary per language |
The icons |
| the Lucide icons used, as data, with their version and licence (ISC; MIT for those of Feather); |
Use it
import { install, Parley, WAKE, texts } from 'clavarium-parley/host';
install('/path/to/work/.parley'); // the folder, once
const parley = new Parley('/path/to/work/.parley', {
on: (event) => { /* person-wrote: get WAKE to the agent, your way; agent-asked: alert, or not */ },
reach: (path) => (path.startsWith('/work/') ? path : null), // what the person can open
keep: '/path/to/state/chat-copy', // optional: your own copy of the thread, out of the agent's reach
});
parley.listen();
typeInTheAgentsTerminal(parley.invite('fr', { install: 'npm install -g /path/to/clavarium-parley-0.10.0.tgz', shared: '/work' }));and in a page:
import { mount } from 'clavarium-parley/ui';
mount(element, { load, send, words: texts('fr', operatorsOwn), open, terminal, view: 'simple',
voice: yourDictation, replies: yourReadyAnswers });The agent can write in its folder, the person's lines too. Given keep, a
folder of its own that the agent cannot reach, the application's side keeps
every line there as it reads it (the person's as it writes them), shows that
copy, and notes any line kept that changed or went in the bridge folder:
the screen says "History changed here: original shown" where it happened.
See the protocol.
The command is installed from the archive npm pack makes, by the
application or by the agent: npm install -g clavarium-parley-0.10.0.tgz,
then parley --help. Installing it runs no script of its own. It finds
its folder as git finds a repository: the nearest .parley from where it
stands, or --dir, or $PARLEY_DIR.
The screen
Two views of one exchange, and a person picks one:
Simple | Detailed | |
Messages | the agent's across a reading column, rendered from Markdown; the person's in bubbles on the right, each with a sign of where it is (sent, read, worked on; handled: no sign); the time on hover, or a long press | the same, each with its time, every sign |
Long messages | the short version first, or folded after about twelve lines; its IMPORTANT box in sight | unfolded |
While it works | one line, moving: what it does now; gone when its next message comes; what came before it one click away | the same line, and every step of this turn above it |
Steps it went through | folded into the message they led to: a click on it opens them ("5 steps" is said with its time) | unfolded between the messages, each with its time and state |
Where it is | when it waits for the person: once, at the end of the thread, until they write; done: once, quietly, while it is the last thing that happened | the same; at the top, what it does now, or the state it said when the end does not say it; on the side, what it does now and its machine ( |
Its newest message | never folded nor cut: nothing seems left below it | unfolded |
Reactions | on its messages: a button on hover (always there on a touch screen, in its corner), or a right click; a long press selects the text; eight, each with its word | the same |
Pictures | in their place, their title under them; several shown at once, one gallery; large: grown out of the thumbnail, zoomed, a strip of the others, closed with a tap; "Media and files" in the menu | the same, with each file's name |
Files | the ones the person can open, by name | every one, with its path; one that cannot be opened is said so |
Its terminal | a way to it |
In both, the day is said when it changes, and the time when long passed between two messages, as a chat does.
The box, and the slots an application fills
Parley draws the box; what it holds that Parley cannot know, the application gives it. Without a slot, nothing of it is shown.
Slot | The application gives | The box shows |
|
| the reactions on its messages |
| the name said above its messages (default: the dictionary's neutral word), the tool, small, in the detailed view | |
| milliseconds: once the agent read the person's newest message and posted nothing since, "Received, thinking..." after the first (default | |
|
| a button beside Send; what is said goes into the box; while it listens, the box itself says what it does (its placeholder, and a small label on its frame), so that nothing on the screen moves; Send pressed while a phrase is still being written sends it once written |
| the device's choice, kept by the application | "send by itself when I stop talking", in the small menu of settings beside the view (only with |
|
| ready answers above the box: |
|
| Enter sends with a keyboard ( |
| true on a touch screen (default: any coarse pointer) | the box is never focused by the page, only by a finger: the keyboard never comes up by itself, and a tap on a button of the box leaves it open |
|
| what opens over the thread (the large picture, the media, the reactions, the search, the menu) takes a step of the history, and Back closes the one on top, as on a phone; |
| a name for this thread (the application's conversation, say) | what is being written in the box is kept on this device as it is typed, and found again when the thread is shown again (another one looked at meanwhile, the page reloaded); sent, it is let go |
|
| a card on a tap on a person of a family or a zone of a picture: its label, its line, that button, "Talk about it" |
|
| formulas, |
|
| a button beside the box picks files; they are shown above it until sent; on Send each is uploaded, then the message goes with them (files alone are a message); in the thread, by name in the person's bubble |
|
| the end of the thread; "Earlier messages" at its top brings the page before, the reader kept where they were; each look asks only what changed |
|
| the search looks in the whole thread; a message found further back opens at its place |
handle.reveal(id) shows one message, the application's way to point to it
(a card that links to it): its id, or its first 8 characters or more, as
parley read shows it. Older than what is shown, the pages before it are
brought until it is there; then the thread scrolls to it and marks it a
moment. It resolves true when shown, false when no message has that id.
Lines of the application -- what happened around the agent, such as its
machine short of memory -- are given with the messages (from: "system") and
shown as grey lines across the thread with their time and buttons, which call
the application's act(id, line); words of its text may be buttons too
(links, a commit it names). See the protocol.
When the agent asks with choices, they are answered in its message, or in
the person's own words ("Other answer…", under them); with --pick-many,
each is a box to tick, then Send, and the agent reads those ticked; asked
together (--group), they are one card, a step each, a summary, one Send; once
that message has scrolled away (or a keyboard took the room), the same
choices come first above the box, never twice on the screen. Every size is
in em and rem: the page's text size is the box's.
A panel beside the thread
A list the application keeps -- its tasks, its batches, what the agent may start -- shown on the right of the thread. Parley does not know where it comes from: it shows items, and hands a tick or a click back to the application.
const chat = mount(element, { load, send, words,
side: { title: 'Batches', items, tick: (id, on) => save(id, on), open: (id) => showCard(id),
folded: kept[name] ?? false, onFold: (folded) => { kept[name] = folded; } } });
chat.side = { ...sameSlots, items: newer }; // given again when the list changed; null: no panel
| The application gives | The panel shows |
| the list's name | above the list, and on the bar's button (its title) |
|
| each by its title; under it its |
| resolves once kept, refuses with a reason | a box to tick on each item not done ( |
| opens the item where the application shows it | its title is a button |
|
| its state in colour |
| a number (default: the items not done; | on the bar's button |
|
| one button under the list ("Start the list") |
| its first state; the person's choice, for the application to keep (per conversation, say); |
Wide (PANEL_PX, 860 pixels of the chat, and more), the panel is a column of
its own on the right, from the bar to the box; the thread and the box keep
theirs. Narrow, it never squeezes the thread: the bar's button opens it as a
sheet over the thread, closed by Back, Escape, its own button or a tap
elsewhere. panelOf(side) is the same list as plain data, as it will be
shown.
Words
What an agent reads (the help, the MCP descriptions, the invitation, the
wake line) is English only; the invitation tells it the person's language.
What a person reads comes from a dictionary per language, chosen by lang;
a missing word is the English one. An application may pass its own
dictionary, whole or partial, which replaces any word whatever it says:
texts(lang, own). Every word is put on the page as text, never as markup.
A language is added with one file.
What was tried, and what was not
Tried for real, once, with the MCP server (version 0.1): an agent (OpenCode,
on hosted open models) in its own machine; an application (Clavarium)
showing the exchange. Invited, the agent said it was ready through tell in
19 seconds; told a message arrived, it read it, did the job, and asked a
question with two choices through ask; answered with one touch on the
page, it read the answer and went on.
Tried for real with version 0.2 (OpenCode, on hosted open models): the
parley command installed by the agent from its archive, tell, ask,
show and status, an answer given ten minutes later, and the two views in
a real page.
Not tried yet with a real agent: the panel beside the thread (tested here and in an application's own end-to-end runs, the screen checked in a browser, wide and on an emulated phone); a part of the thread (read({ last | days | before | since }),
search(), "Earlier messages", parley read --last and --before; tested here
and in an application's own end-to-end runs, on threads of 600 and 1,000
messages); questions asked together (--group), choices to tick (--pick-many, many) and "Other answer…" (tested here, the screen checked in a browser); version 0.10 -- Back closing what is open over the thread (tested here, and in an application's own end-to-end runs); "Received, thinking..." and "No answer yet" (tested here); version 0.8 -- several files shown at once with their titles, reactions, dictated messages, done said once, the media of a thread, the viewer, the side of the detailed view (tested here and in an application's own end-to-end runs, the screen checked on a real thread replayed); Markdown, short versions, close and the signs of each message (version 0.7, tested here and in an application's own end-to-end runs, the screen checked on a real thread replayed); doing and the line of what it does now
(version 0.3, tested here with stand-ins); the box's slots (version 0.4:
dictation, ready answers, the keyboard of a phone), tested in an
application's own end-to-end runs with a recorded voice and an emulated
phone, not yet by a person on a real phone; files attached by the person,
lines of the application and read --all (version 0.5), tested here and in an
application's own end-to-end runs, not yet with a real agent; any agent but OpenCode; an answer
coming hours later; a mirror between two agents.
Licence
MIT. See LICENSE.
Working on Parley
After cloning, wire the repository's hooks once: npm run hooks (it sets
core.hooksPath to hooks in this clone). It is a script of its own, never
run by an install: installing the package changes no git configuration.
npm run check fails while the hooks are not wired.
This server cannot be deployed
Maintenance
Related MCP Connectors
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
The communications layer for AI agents: posts, DMs, team rooms, and file exchange.
Give any AI agent a way to ask a person — for approval, a decision, an answer or a review.
Persistent memory, hybrid search and a goal graph for AI agents, over stdio or remote HTTP.
Related MCP Servers
- AlicenseAqualityFmaintenanceEnables AI assistants like Claude to interact with humans through intuitive GUI dialogs, supporting text input, choices, confirmations, and information displays.633 PyPI163MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to communicate with humans using notify and ask semantics, supporting session management and blocking or non-blocking messages.11 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to list and read existing ChatGPT conversations and send messages into them, retrieving the assistant's reply through ChatGPT Desktop's native bridge. It works without cookies, UI automation, or an OpenAI API key.1Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to exchange messages and hold threaded conversations across local and remote gateways, with human approval, signed A2A interoperability, and relayed CLI execution.MIT