SmartSurvey MCP server
An MCP server that lets MCP clients read (and optionally, when writes are enabled, act on) a SmartSurvey account: surveys and their designs, responses, exports and survey folders.
whoami — confirm the account user the API key belongs to (name, email, type, survey count) and the region/base URL in use.
list_surveys — surveys with title, nickname, open/closed status, response count and dates; supports paging,
page,sort_byandmax_results.get_survey — one survey's counts, theme and settings; with
detail=truethe full design: variables, translations, every page with questions, answer choices/scores and logic flags.list_responses — a survey's responses with every page, question and answer; filter by
since,until,completed_only,filter_id,tracking_link_id,unique_id, plus labels and translation.get_response — one full response, including Organisation Hierarchy entity fields when present.
list_exports — a survey's exports/reports (name, type, status, size, dates, API download URL); metadata only, files are never downloaded.
list_survey_folders — the survey folders on the account.
Optional write tools (only with
SMARTSURVEY_ALLOW_WRITES=true) — open_survey, close_survey (destructive: closes all tracking links), and send_invitation_to_one (email or SMS an existing invitation to one recipient).Privacy by default — respondent identifiers withheld and emails/phones redacted in titles, design text and answers;
include_contact_details=truereveals them as stored.Safe paging and validation — whole API pages with
page_size/next_page/continuation notes; IDs andsince/untilvalues are validated locally before any API call, with retries/backoff for 429 and gateway errors.
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., "@SmartSurvey MCP server which surveys are open and how many responses do they have?"
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.
SmartSurvey MCP server
An MCP server that lets Claude, ChatGPT and other MCP clients work with a SmartSurvey account: surveys and their designs, responses, exports and survey folders, and (when enabled) opening or closing a survey and sending an invitation to one person. It is built from SmartSurvey's public API documentation and the OpenAPI definitions it publishes, one per reference page, on docs.smartsurvey.io.
Once it's connected, someone on the account can ask things like:
"Which of our surveys are open, and how many responses does each have?"
"Show me the questions in the customer satisfaction survey."
"What did people write in the comments box since 1 September? Anything about waiting times?"
"Pull response 301 with the respondent's details so I can follow up."
"Is last night's raw-data export ready?"
With writes enabled: "Close the summer party survey." / "Send the CSAT invitation to Sam Evans at sam.evans@example.com."
Tools
Tool | What it does | API calls |
| The account user the API key belongs to (name, email, type, survey count) and the base URL in use. |
|
| Surveys with title, nickname, status, response count and dates, in whole API pages up to |
|
| One survey with page/question counts, theme and settings. With |
|
| Responses to a survey with every page, question and answer, in whole API pages up to |
|
| One response in full, including Organisation Hierarchy entity fields when present. |
|
| Exports (reports) of a survey: name, type, status, size, dates and the API download URL. Metadata only; files are never downloaded. |
|
| Survey folders on the account. |
|
| Opens a survey (the API opens only the default tracking link). Writes only. |
|
| Closes a survey and, per the API, all of its tracking links. Writes only, marked destructive. |
|
| Emails or texts an existing invitation to one named recipient. The spec calls this a premium endpoint. Writes only. |
|
Not covered on purpose: contact lists and contacts, API keys, account users, permissions, tracking links, page and question writes, survey creation, copying and deletion, response inserts and deletes, export downloads and deletes, file library, themes, webhooks, and the multi-recipient invitation send.
Related MCP server: WebAsk MCP
Setup
Requires Node 18 or later.
npm install
npm run buildYou need an API key from SmartSurvey (My Account > API Keys > Add New API Key). A key has an API token and a token secret. The API authenticates with HTTP Basic: the token is the username and the secret the password, as the Getting Started guide states ("Username" is the API Token, "Password" is the Token Secret; not the SmartSurvey login).
Use the region you sign in to: app.smartsurvey.co.uk or app.smartsurvey.com is the default (api.smartsurvey.io), app-eu.smartsurvey.com is eu (api-eu.smartsurvey.io), app-us.smartsurvey.com is us (api-us.smartsurvey.io).
Claude Desktop: add this to claude_desktop_config.json:
{
"mcpServers": {
"smartsurvey": {
"command": "node",
"args": ["/absolute/path/to/smartsurvey-mcp/dist/index.js"],
"env": { "SMARTSURVEY_API_TOKEN": "your-token", "SMARTSURVEY_API_SECRET": "your-secret" }
}
}
}Claude Code:
claude mcp add smartsurvey -e SMARTSURVEY_API_TOKEN=your-token -e SMARTSURVEY_API_SECRET=your-secret -- node /absolute/path/to/smartsurvey-mcp/dist/index.jsVariable | Required | Meaning |
| yes | The API token, sent as the HTTP Basic username. |
| yes | The token secret, sent as the HTTP Basic password. |
| no |
|
| no |
|
| no | Overrides the region's host, e.g. |
Safety defaults
Read-only unless
SMARTSURVEY_ALLOW_WRITES=true. Read tools carry the MCPreadOnlyHintannotation;close_surveyis marked destructive because the API closes every tracking link andopen_surveyafterwards reopens only the default one.Survey responses are third-party data. By default a response's
contact_name,contact_email,unique_id,ip_address,user_agent,saved_name,saved_email, and the two links that open the respondent's answers for editing (edit_url,saved_continue_url) are not returned; the value of any survey variable, contact-list column or entity field whose name looks like contact data (email, phone, mobile, name, address, postcode, date of birth, IP, NHS or passport number and the like, whether written asEmail Address,E-mail,home_address,customerName,dateOfBirthornhsnumber) is replaced by a placeholder; and in every other free-text field (answers, choice/row/column labels, question and page titles, variable values,entry_url,referer_url,entity_name) email addresses are replaced with[email redacted]and phone-number-like sequences with[phone redacted].include_contact_details=trueonlist_responsesorget_responsereturns all of it as stored. The phone match is a heuristic: it covers international numbers written with+or00(including the+44 (0)7700 …form), UK numbers with a bracketed area code such as(020) 7946 0958, and UK-style0…numbers of 9 to 11 digits with spaces, dots or hyphens between groups. Other digit strings that happen to start with0(an order number, say) are redacted too, and so is a hyphenated reference that starts with0and holds 9 to 11 digits (0-123-45678-9); numeric IDs, timestamps, page paths such as9001,9002and references that start with another digit or letter, such asPO-0001-000123, are left alone. The same redaction is applied to SmartSurvey's own error messages before they are passed on.Survey titles and nicknames, folder titles and the survey design (
get_survey: page titles and descriptions, question and choice text, variable labels) are the account holder's own content, but they get the same email and phone redaction by default, so that a question such as "Email us at …" reads the same inget_surveyand inlist_responses.include_contact_details=trueonlist_surveys,get_surveyorlist_survey_foldersreturns them as stored. Variable names (URL parameter names such asemail) and survey URLs are never altered.whoamireturns the key owner's own email.List tools return whole API pages, never part of one. The page size sent is
min(100, max_results), and a call stops before a page that could take it pastmax_results, socountcan be belowmax_results(the API may also return fewer rows per page than asked; the docs say visibility rules can filter items out). The result carriespage_size,next_pageand anotesaying to call again with that page and the samemax_results: page numbers only line up for one page size, so changingmax_resultson a continuation would renumber the pages. Cutting a page in the middle and pointing at the page after it would silently skip the rest of that page; this server does not do that.Export download links are the API's own
/downloadendpoints, which need the same credentials; the server returns them as metadata and never fetches a file.IDs are checked before any call is made: every ID in the spec is a positive int32, so anything else (
abc,0,-5,1.5,2147483648,../account-user) is refused locally.since/untiltake a Unix timestamp in seconds between 2000-01-01 and 2100-01-01, or an ISO 8601 date or date-time (2026-09-01,2026-09-01T00:00:00,2026-09-01T00:00:00+01:00; a missing zone means UTC, never the machine's local time). Anything else is refused locally with a message saying what is accepted, rather than guessed:2026is not sent as the Unix timestamp 2026 (33 minutes past the epoch), a millisecond timestamp such as1756000000000is not sent as seconds, and12/08/2026is not read as either 8 December or 12 August.send_invitation_to_onerefuses locally when neither an email nor a mobile number is given, or when bothentity_idandentity_unique_idare given (the spec says to supply one or the other).SmartSurvey does not document a rate limit anywhere in its Getting Started guide or reference pages (the only "429" in the spec is a generic HTTP status enum). Requests are spaced 250 ms apart (about four per second). A 429 is retried at most twice for any method, including
POST …/sendone, on the assumption that a rate-limited request was not processed (see Status). The retry waits forRetry-After(whole or fractional seconds, or an HTTP-date; 2 s then 4 s when the header is absent or unreadable). Each wait is capped at 10 seconds, so one request waits at most 20 seconds in all; a tool call that makes several requests (pages, lookups) can still run past the MCP client's default 60-second request timeout. Past the cap: if SmartSurvey asks for a longer wait the call gives up at once and the message says how long to wait.502, 503 and 504 are retried the same way for
GETonly; when all three attempts fail the error says the service may be unavailable and to try again in a few minutes, without the gateway's HTML. APOST …/sendoneor aPATCH …/open|closeis never retried after a gateway error, because the request may already have been processed and a retry could email someone twice; the error says what to check before repeating it.A 200 whose body is not JSON (a proxy or a login page in the way) is reported as an error naming
SMARTSURVEY_BASE_URL/SMARTSURVEY_REGION, never as an empty list or an empty survey.Rejected credentials (401) produce a message that says which variables to fix and how the two halves of the key are used; a 403 explains the two documented causes (no permission for that survey, or an endpoint not included in the plan); a 402 on an invitation send says the email balance is insufficient; a 400 passes on SmartSurvey's validation errors field by field.
Tests
npm testThe test suite:
Validates every fixture record against the component schemas in SmartSurvey's published OpenAPI definitions (
AccountUserResponse,SurveyResponse,SurveySingleResponse,SurveyDetailedResponse,Response,DetailedResponse,SurveyExportResponse,SurveyFolderResponse). SmartSurvey publishes one OpenAPI document per reference page;test/assemble-spec.mjsfetches the page index (docs.smartsurvey.io/llms.txt) and every reference page's Markdown version, merges the 89 operations and 115 schemas intospec.jsonon the first run, and refuses to continue if two pages define the same operation or schema differently.Starts a local mock of the API under
/v2that serves those fixtures with the documentedpage/page_sizepagination (thePaginatedList*body fields and the fourX-SS-Pagination-*headers,X-SS-Pagination-PageSizebeing the number of rows requested as Getting Started defines it; surveys are capped at 10 per page and responses at 3 whatever is asked, so that lists span several pages and pages are shorter than requested, while folders and exports honour the requested size), Basic-auth 401s, and 402, 403, 404 and 400 answers in the documentedProblemDetails/ValidationProblemDetailsshapes, and answers the firstGET /survey-folderswith a 429. The mock's list, detail, action and error responses are validated against the response schemas the spec names for each operation and status, and the documented keys of each list response are asserted explicitly (thePaginatedList*schemas mark nothing as required).Starts the built server and drives it over stdio with the official MCP client: 27 checks (29 in the whole suite) covering every tool, tool annotations, page-based pagination stopping at the documented page count (from the body and, when the body lacks the paging fields, at
X-SS-Pagination-Total) and continuing across pages shorter than requested,max_resultssent as the page size and honoured with whole pages only (following the tool's own continuation notes from a first page, and from a later start page, yields every fixture record exactly once, both when the mock caps the page size belowmax_resultsand when it honours it),sort_bysent as a repeated query parameter,translation_idpassed through on the detailed survey endpoint and onget_response, every documentedlist_responsesfilter passed through exactly (since/untilconverted from ISO 8601 with and without a zone to Unix timestamps or passed as given, and refused for a bare year, a millisecond timestamp, a fractional number,12/08/2026,2026-08and an impossible date,completed1 or 0,filter_id,tracking_link_id,unique_id,include_labels,translation_id), redaction of respondent identifiers, edit links, contact-like variables and columns (includingE-mail,fullName,homeAddress,dateOfBirth,phoneNumberandnhsnumber), of emails and phone numbers in answers and URLs, in survey titles, folder titles and the survey design by default (the+44 (0)…, bracketed,00-prefixed, extra-spaced and dot-separated phone forms), and their return on request, entity fields on a detailed response, exports without any download call, the 429 retry waiting forRetry-Afterin the seconds, fractional-seconds and HTTP-date forms, giving up after three attempts on a persistent 429 and at once on aRetry-Afterabove the cap, a 429 onPOST …/sendoneretried once, a 502 retried forGETand never forPOST …/sendoneorPATCH …/close, aGETfailing three times with 503 reported with advice and without the gateway HTML, a 200 with a non-JSON body reported as an error, the write gate with the variable unset and set tofalse, thePOST …/sendonebody validated against the spec'sInvitationRequestContactschema for an email and an SMS recipient, the local refusals, the 402/403/404 messages, SmartSurvey's own error text passed on with contact details redacted and a 400's validation errors listed field by field, ID validation before any call, the 401 message, a badSMARTSURVEY_REGION(with or withoutSMARTSURVEY_BASE_URL) or a missing secret stopping the server at start-up, and that every request usedBasic base64(token:secret)and a documented method and path.
Status
This is a working prototype. It has not yet been run against the live API, because it was built without a SmartSurvey account. The API itself is a paid-plan feature: SmartSurvey's public pricing page (checked September 2026) lists "API & Webhooks" on the Growth plan, Scale includes everything in Growth, and the Basic and Advanced plans do not list it. Everything below is taken from the published documentation and should be confirmed on a real account:
Authentication: that the API token is the Basic username and the token secret the password (Getting Started says so), and the body of a 401 (not documented; the mock answers with
ProblemDetails).Pagination: that
page_indexin list bodies is 1-based like thepageparameter (the server keeps its own page counter and stops when it reachespages, when it has collectedtotalrecords from page 1, or on an empty page;X-SS-Pagination-Totalstands in fortotalwhen the body lacks it, and no page count is derived fromX-SS-Pagination-PageSize, which Getting Started defines as the number of rows requested, not returned); thatpages,totalandpage_sizeare present on every list; that the API honourspage_sizeup to 100 (the mock deliberately serves fewer for surveys and responses; the budget check uses the body'spage_sizewhen present, else the size requested); and what apagepast the end returns (the mock answers 200 with an empty list). A page shorter thanpage_sizeis not treated as the end, because the docs say visibility rules may filter items out.sort_by: the accepted property names are not documented, and neither is the serialisation of the array; the server sends the key once per value (sort_by=title&sort_by=date_created), the OpenAPI default for query arrays.completed: the parameter is documented as "Whether to only include completed responses", integer, default 1. The server sendscompleted=0forcompleted_only=falseand expects partial and disqualified responses back; the exact effect of 0 is not documented.since/until: documented as Unix timestamps filtering "after"/"before" a date/time; which response timestamp they compare against (date_started,date_endedordate_modified) and whether the bounds are inclusive is not documented. The mock comparessincewithdate_startedanduntilwithdate_ended, inclusive.include_labels: Getting Started says labels are not included by default andinclude_labels=trueadds them; the list endpoint's own parameter description says the opposite about size. The server passes the value through explicitly on both endpoints (defaulting totrueso answers carry question and choice text) and does not know which fields disappear without labels.translation_id: defaults to 0 on the survey endpoints and 1 on the response endpoints in the spec; the server only sends it when given.The values of
Response.status(completed,partial,disqualifiedper the Data Types page),SurveyResponse.status("e.g. open or closed") andSurveyExportResponse.status(queued, completed or errored), and the integer enumspresentation_mode,completion_action.action,terminal.response_statusandrandomisation, whose names are not documented and are passed through as numbers.Which respondent fields the live API actually fills (
unique_id,contact_name/contact_emailfor invitation responses,ip_address,user_agent,edit_url,saved_*,entity_*) and whetheredit_urlandsaved_continue_urlreally grant access to the answers, as their names suggest; they are withheld by default either way.PATCH …/openandPATCH …/close: sent with no body and noContent-Type, as the spec defines no request body; theApiBasicResponsecontent and whether a 200 is returned when nothing changed.POST …/sendone: whether the invitation's type (email or SMS) decides which ofemail/mobileis required, whether partial failures come back as a 200 withfailed_contacts(as the schema suggests) or as a 4xx, and the exact 402 and 403 behaviour (the spec documents 402 for an insufficient email balance and describes the endpoint as premium and "not available on all plans").A 429 on
POST …/sendoneis retried on the assumption that a rate-limited request was not processed. SmartSurvey documents no 429 and no rate limit at all, so the 250 ms spacing here is a guess on the polite side.The wording of SmartSurvey's error messages and whether any of them echo request data such as a recipient's email address; the texts here are placeholders, and the server redacts contact details from them regardless.
Whether
GET /surveysincludes surveys owned by sub-users of a master account, and whetherGET /account-userreports the master account or the sub-user the key was created under.Timestamps: the docs say all date-times are UTC ISO 8601 (
YYYY-MM-DDTHH:MM:SSZ); the server passes them through unchanged.
Going to production
This version runs locally over stdio, with the account holder's own API key. For customers to connect from claude.ai or ChatGPT without handling keys, the next step is a remote server (Streamable HTTP) behind OAuth, hosted by SmartSurvey, and then a listing in the Claude and ChatGPT connector directories.
Licence
MIT. Built by Alexandru Dragoș (alexandru.dragos96@gmail.com) with an AI agent (Claude) working under his direction.
Available Tools
7 toolsget_responseGet one responseARead-only
One response with every page, question and answer, plus the Organisation Hierarchy entity fields when the account uses that feature. Respondent identifiers are withheld and emails/phone numbers in answers redacted unless include_contact_details is set.
Inputs: survey_id (required), response_id (required), include_labels, translation_id, +1 more.
get_surveyGet a surveyARead-only
One survey with page and question counts, theme and settings. With detail=true the full design is returned: variables, translations, and every page with its questions, answer choices and logic flags (this is the survey design, not respondents' answers). Emails and phone numbers in the title and in page, question and choice text are redacted unless include_contact_details is set.
Inputs: survey_id (required), detail, translation_id, include_contact_details.
list_exportsList exports of a surveyARead-only
Exports (reports) generated for one survey: name, type, status (queued, completed or errored), file size and type, dates and the API download URL. Metadata only; this server never downloads the files.
Inputs: survey_id (required), page, sort_by, max_results.
list_responsesList responses to a surveyARead-only
Responses to one survey with every page, question and answer. Whole API pages of min(100, max_results) responses are returned, so the count may be below max_results; the note says how to continue. Filters (since, until, completed_only, filter_id, tracking_link_id, unique_id) are passed to the API as documented. Respondent identifiers are withheld and emails/phone numbers in answers redacted unless include_contact_details is set.
Inputs: survey_id (required), page, since, until, +9 more.
list_survey_foldersList survey foldersARead-only
The survey folders on the API key's account (id, type, title). Emails and phone numbers in titles are redacted unless include_contact_details is set.
Inputs: page, sort_by, max_results, include_contact_details.
list_surveysList surveysARead-only
Surveys on this account with title, nickname, status (open or closed), response count and dates, in the order the API returns them. Whole API pages of min(100, max_results) surveys are returned, so the count may be below max_results; the note says how to continue. Emails and phone numbers in titles are redacted unless include_contact_details is set.
Inputs: page, sort_by, max_results, include_contact_details.
whoamiWho owns this API keyARead-only
The SmartSurvey account user the API key belongs to (name, email, user type, number of surveys). Use it to confirm which account and region the server is talking to.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 7 tools
Each tool targets a distinct resource and action: whoami for account, list_surveys/get_survey for surveys, list_responses/get_response for responses, list_exports for exports, and list_survey_folders for folders. No overlapping purposes exist across the set.
Most tools follow a clear snake_case verb_noun pattern (list_surveys, get_survey, list_responses, get_response, list_exports, list_survey_folders). The single-word 'whoami' deviates from this pattern but remains a common, readable exception.
Seven tools is well-scoped for a survey data retrieval server, with each tool earning its place by covering a distinct entity or action. There is no bloat or obvious missing central tool.
The read-only surface covers account info, surveys, responses, exports, and folders, which is useful for data extraction. However, it lacks any create, update, or delete operations (e.g., creating surveys or generating exports) and omits tracking links despite filters referencing them, leaving notable gaps for full lifecycle management.
Maintenance
Related MCP Connectors
Read survey responses and manage contacts, webhooks, teams and organisation users.
Create, edit and publish surveys and AI interviews, then read responses and reports.
Create, edit and publish surveys, then read results from your AI chat.
Build, target, launch and analyse consumer surveys from your AI assistant (Survey Light, 71 tools).
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read an Amiqus ID account—clients, onboarding records and steps, check results, templates, case status counts and webhooks—and, when writes are enabled, create records.9MIT

WebAsk MCPofficial
AlicenseNot gradedqualityBmaintenanceEnables AI assistants to create and validate surveys, distribute them, read and tag responses, and generate reports or exports through a hosted Streamable HTTP MCP endpoint with API-key authentication.MIT- AlicenseNot gradedqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read NewZapp account details, campaign reports, open heatmaps, contact groups and contact counts, and to search contacts with personal data withheld by default; when writes are enabled, it can also create and update contacts.MIT
- AlicenseAqualityCmaintenanceEnables MCP clients such as Claude and ChatGPT to browse an Engaging Networks account: campaign pages, supporter records, transaction and recurring-gift history, supporter fields and questions, and marketing automation statistics. When writes are explicitly enabled, it can also set a supporter's opt-ins, with contact details, payment data and free-text personal data redacted by default.10MIT