A side-by-side look at the Adeu and Human Survey MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Adeu for workplace & productivity work as a local process; choose Human Survey for workplace & productivity as a local process. You can also run both side by side in one mcpServers block.
accept_all_changes, apply_text_revision, diff_docx_files.HUMANSURVEY_API_KEY.login, get_catalog, list_forms.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Workplace & Productivity | Workplace & Productivity |
| Quality signal | 69/100 · Great | 60/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | No auth required | Not declared |
| Pricing | Free | Not declared |
| Required env vars | None listed | HUMANSURVEY_API_KEY |
| Verified owner | Community listing | Community listing |
| GitHub stars | 168 | 1 |
| Directory activity | 3 views 0 installs 0 upvotes | 2 views 0 installs 0 upvotes |
| Tools | 6 | 10 |
| Full listing | View Adeu | View Human Survey |
accept_all_changesAccepts every tracked change in the document, producing a finalized clean document.
remove_comments (boolean, DEFAULT TRUE): also delete every comment. The default is TRUE because this tool's purpose is a distributable clean document, and comments are internal review notes that must not travel to a counterparty. Pass remove_comments=false to accept the tracked changes while KEEPING the comments — use that when the review conversation is still live. Either way the response reports how many comments were deleted and names each one with its author, and comments whose anchored text an accepted deletion consumes are removed regardless, exactly as Word does. [Adeu v3.0.6+df9e00c]apply_text_revisionApplies whole-text revised text to a DOCX document by computing a diff and generating tracked changes. Includes a clean-text verification gate to ensure the applied document matches the supplied text.
`revised_text` must be the complete CLEAN view of the document: read it with `read_docx` (`clean_view=true`, `page='all'`), edit that text, and send ALL of it back. Never CriticMarkup ({++, {--, {>>) — this tool diffs against the clean view, so markup tokens would land in the document as literal prose. Never one page of a paginated extract — everything absent from the text is applied as a tracked deletion.
INTERLOCK: a revision that drops >50% of the characters (>75% for documents under 2000 characters) is refused unless you pass allow_major_deletions=true.
If the applied document's clean text does not then match `revised_text`, NOTHING is written to output_path: a diagnostic copy is kept at <name>.unverified.docx and the call fails. output_path defaults to <name>_redlined.docx; an existing _redlined/_processed artifact is revised in place. [Adeu v3.0.6+df9e00c]diff_docx_filesCompares two DOCX files and returns a compact `@@ Word Patch @@` diff — Adeu's token-level, sub-word patch format — of their text content. Useful for analyzing differences between versions before editing. [Adeu v3.0.6+df9e00c]finalize_documentPrepares a document for external distribution or e-signature. Note: in this zero-dependency environment, protection_mode='encrypt' is unsupported and falls back to a native read-only lock; export_pdf and password are ignored. [Adeu v3.0.6+df9e00c]process_document_batchApplies a batch of edits and review actions to a DOCX.
Batches apply SEQUENTIALLY: each change validates against state from prior changes. Valid changes apply when others fail (salvage default): response LEADS with `PARTIAL: applied K of N` listing unapplied changes. Pass partial=false for all-or-nothing.
Each item in `changes` needs a `type`:
1. 'modify': search-and-replace. `target_text` must match uniquely (`match_mode`:'strict', default) — add context or set `match_mode`:'first'/'all'. Set `regex`:true for regex matching (groups in `new_text` as $1, $2…). `new_text` supports Markdown: '#'–'######' headings, '**bold**', '_italic_', '\n\n' paragraph split. Omit it (with a comment) to annotate without changing text; empty string deletes. Never write CriticMarkup manually — use `comment`.
• EMPTY CELLS: blank cells carry `{#cell:<id>}` anchors — set `target_text` to the anchor and value in `new_text`. Pipes are display separators.
2. 'accept'/'reject': finalize or revert a tracked change by `target_id` (e.g. 'Chg:12').
3. 'reply': reply to a comment by `target_id` (e.g. 'Com:5') with `text`.
4. 'set_field': fill a form field — `field` is its 'CC:<N>' id, tag or alias, `value` the text; list via `read_docx` `mode`:'fields'. Checkboxes take true/false, dates YYYY-MM-DD, dropdowns a listed option. Dual-writes bound stores. A locked/protected control refuses and names the override permitting it.
5. 'insert_row': add table row — `target_text` anchors on an existing row's text, `cells` holds cell values (left-to-right), `position` is 'above'/'below' (default below). 'delete_row': remove row matching `target_text`. Disk mode only.
ID VOLATILITY: 'Chg:N'/'Com:N' ids shift between states — call `read_docx` before accept/reject/reply; never reuse ids from earlier turns.
`author_name` sets Track Changes attribution; defaults to 'Adeu AI (TS)' when omitted. [Adeu v3.0.6+df9e00c]read_docxReads a DOCX file. Returns text with inline CriticMarkup for Tracked Changes and Comments: {++inserted++}, {--deleted--}, {==highlighted==}{>>comment<<}. Set clean_view=True for the finalized 'Accepted' text without markup.
Modes:
- 'full' (default): paginated body content. Use page=N to navigate.
- 'outline': heading map only — start here for large docs to plan targeted reads. Defaults to L1-L2 headings; pass outline_max_level=3-6 to see deeper structure.
- 'appendix': defined terms, anchors, and cross-reference targets. Consult before editing legal/technical docs to avoid breaking references.
- 'changes' (mode='changes'): a ledger of every tracked change and comment (id, type, author, page, snippet) — start here for review work instead of reading pages. Filter with changes_author, page, and changes_offset.
- 'fields' (mode='fields'): a ledger of every content control (ordinal, class, alias/tag, location, lock/binding state, current value) — start here to discover fillable fields. Paginate with fields_offset; `page` and `search_query` do not apply.
`page`: a positive integer (1-indexed, default 1), a page RANGE like '2-6' (returns up to 8 pages in one call, then names the next range), or 'all'. Pages are synthetic length-based chunks sized for LLM consumption, NOT printed Word pages. In mode='full', page='all' returns the whole body with no page chrome; oversized documents are refused with an outline and a bounded-read recipe unless force=true. With `search_query`, `page` instead restricts matches to that page (default: search all pages). [Adeu v3.0.6+df9e00c]loginSign in with an email address and store an API key on this machine. Called with only an email, it mails a six-digit code and returns nothing usable — the code has to come from the person, out of their inbox. Called with the email and that code, it stores a key at ~/.humansurvey/credentials and reports where it was written. The key itself is never printed. Signing in and signing up are the same act: an address that has never been used gets an account.get_catalogList the platforms HumanSurvey knows: the slug to use as catalog_slug, the display label, and which class of channel it is. These are the named channels a respondent can be shown — TikTok, ChatGPT, LinkedIn, Reddit and so on — plus the descriptive options that have no brand behind them, like "a friend or colleague told me". No API key needed.list_formsList the forms on this account: id, name, respondent URL, whether it is active or paused, whether it has been configured with questions yet, and how many responses it has collected.get_formRead one form: its settings, and the question configuration currently shown to respondents — every question, every candidate, and the order mode. Returns the configuration as JSON, because that is the exact shape a configuration write takes.create_formCreate a form and return its id, its respondent URL, and the iframe and postMessage listener to embed that URL in a host page. The form has no questions yet and shows nothing to respondents until it is configured. allowed_origins restricts which sites may embed it; leaving it empty allows any site, which means any site can spend this account’s response quota.configure_formSet the questions and candidates a form shows. Replaces the whole configuration and stores it as a new immutable version, so responses already collected keep describing the list they were actually shown. Re-sending an identical configuration reuses the existing version rather than making another.
A form is one single-select question, optionally expanding into a second. Give a candidate an `expands` naming another question to reveal it when that candidate is picked — that is how "TikTok" becomes "which account".
Candidate ids must be stable keys that survive a rename. Using a handle as an id splits that creator’s history in two the day they change it.
Set catalog_slug to take a candidate’s label and logo from the platform catalog. Order defaults to "rotate", which randomizes per respondent and is what makes the reported shares unbiased; "fixed" keeps your order and accepts that earlier options get picked more often for being earlier.get_attributionWhat respondents said, aggregated. Reports, per question, how many completed responses named each candidate out of how many answered that question, the unresolved answers in the same list, how often a follow-up question failed to find an answer, and revenue where conversion events have been recorded.
Computed fresh on every call, including any mappings made since — so a rollup of a past window can legitimately change between two reads.list_unresolvedThe answers respondents typed instead of picking from the list, grouped by the exact text and ordered by how often it was typed. Reports the spelling variants seen, when each was first and last typed, and whether a mapping already covers it.
These are verbatim words. Two texts that read alike may be different people, and a text may name somebody who is not on the candidate list at all.remapRecord that a specific typed answer means a specific candidate. It applies to every response already carrying that text as well as every future one, so numbers reported for past windows change.
The original text is never altered and a mapping can be revoked, but a report may already have been read. Only map a text whose meaning is established — a text that merely resembles a candidate’s name is not evidence that it is that candidate.
One live mapping per text per question.revoke_remapStop a mapping from applying. The typed answers it covered return to the unresolved list — in past windows as well as future ones, because rollups join mappings when they are read rather than when they are made. Numbers already reported for those windows will therefore change.
Nothing is deleted: the mapping is marked revoked and kept, so a report produced while it was live can still be explained. Revoking an already-revoked mapping is not an error and does not move the time it stopped applying.
Mapping ids appear beside any text that is already mapped in the free-text listing, and in the confirmation given when a mapping is created.Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"adeu": {
"command": "npx",
"args": [
"-y",
"@adeu/mcp-server"
]
}
}
}
{
"mcpServers": {
"sunsiyuan-human-survey": {
"command": "npx",
"args": [
"-y",
"humansurvey-mcp"
],
"env": {
"HUMANSURVEY_API_KEY": "YOUR_HUMANSURVEY_API_KEY_HERE"
}
}
}
}