cadence-mcp
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., "@cadence-mcpLet's practise for a backend role focused on PostgreSQL and API design."
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.
cadence-mcp
An MCP server that lets an AI assistant run a cadence practice interview: start one, get the next question, submit the user's answer, have it scored. The two actions that cannot be undone — scoring, which closes the interview and spends its budget, and deleting it — are confirmed by a person, not by the model.
You Let's practise for a backend role. PostgreSQL and API design.
Claude start_interview → ask_next_question
"Walk me through a system you've shipped that had real users on it…"
You (your answer, in your words)
Claude submit_answer → ask_next_question → …
You That's enough, score me.
Claude finish_interview
┌ Finish the "Backend Engineer" interview and have it scored? This closes
│ it for good, and scoring is charged to its budget ($0.0019 of $0.5000 used).
└ [x] Go ahead
Scorecard — overall 68/100 …Tools
Tool | What it does | Asks first |
| The account's interviews, newest first, with status and cost | — |
| A new interview for a role, seniority and up to six focus areas | — |
| Streams the interviewer's next question and returns it whole | — |
| Records the user's answer to the last question | — |
| Transcript and, once finished, the scorecard | — |
| Spend against the interview's guardrail | — |
| What the interviewer's own tools did before each question, as records | — |
| Closes the interview and scores it | yes |
| Deletes the interview and its scorecard, permanently | yes |
Inputs are validated against the same limits cadence enforces (a role title of
2–160 characters, at most six focus areas, an answer of up to 8000 characters
that is not blank, a UUID for the ID), so a bad call fails before it costs a
round trip — and an ID like ../../auth/me never becomes part of a URL.
Related MCP server: Interview Prep MCP Agent
Configuration
Variable | |
| Where cadence runs. |
| The cadence account the assistant acts as. Use one made for this. |
| Optional. Path of the audit log; |
Claude Desktop — claude_desktop_config.json:
{
"mcpServers": {
"cadence": {
"command": "node",
"args": ["/absolute/path/to/cadence-mcp/src/server.js"],
"env": {
"CADENCE_API_URL": "http://localhost:8000",
"CADENCE_EMAIL": "you@example.com",
"CADENCE_PASSWORD": "…"
}
}
}
}Claude Code:
claude mcp add cadence \
-e CADENCE_API_URL=http://localhost:8000 \
-e CADENCE_EMAIL=you@example.com \
-e CADENCE_PASSWORD='…' \
-- node /absolute/path/to/cadence-mcp/src/server.jscadence itself runs with docker compose up and no API key at all: a scripted
interviewer takes the same code paths, which is enough to try everything here.
Decisions worth defending
A person confirms, and the fallback says what it proves
An assistant that can call delete_interview can call it by mistake, and a
model that has been told "ask the user first" can decide the user already
agreed. So the server asks, through MCP elicitation: the client shows the
person a dialog, and only an explicit "yes" from that dialog lets the call
through. A decline or a dismissed dialog is a no, and is recorded as
declined.
Not every client supports elicitation. There, the tool refuses and says why,
and only goes ahead when called again with confirm: true. That is weaker,
and the code does not pretend otherwise: it proves the model was shown the
consequences, not that a person agreed. In that mode the human gate is the
client's own per-tool approval prompt, which is why both risky tools carry
honest annotations (destructiveHint on delete) for clients that use them to
decide when to ask.
Finishing an interview that is already scored asks nothing: cadence returns the stored scorecard, nothing is charged and nothing irreversible is left to do.
Refresh tokens rotate, so refreshing is single-flight
cadence issues a new refresh token on every refresh and the old one stops working the moment it is used. When an access token expires, every call in flight gets a 401 at once. If each refreshed on its own, the first would win and the rest would present a token that was already spent. Here they all wait for one rotation; a call that finds the token already rotated retries with the new one instead of rotating again. If the refresh itself is refused, the server logs in again with the configured account. Tokens live in memory only.
A retry after a 401 is safe even for submit_answer: cadence checks the token
in a dependency that runs before the handler, so a 401 means nothing was
written.
The question comes back whole, and from done
cadence streams the question as server-sent events, token by token; an MCP tool
returns one result. The client reads the stream to the end and returns the text
from the done event — the question exactly as cadence stored it — rather than
its own concatenation of the tokens. The SSE parser is cadence's front-end
parser, ported line for line with its tests, because the bug that parser was
written to fix (CRLF line endings never matching "\n\n", so no event is ever
emitted) is not one to rediscover in a second client of the same API. The
stream also has a hard timeout and a size limit: a question that never ends is
not a question.
The audit log, and the bug it found
Every tool call appends one JSON line — tool, outcome (ok, error,
declined), arguments, duration and a request ID. The same ID goes to cadence
as X-Request-ID, so one call can be followed into the API's logs. Answers are
recorded as their length, never their text: an audit trail needs to show that
an answer was submitted, not what a person said in an interview.
Following those IDs into cadence's logs is how a cadence bug turned up: every
access-log line said "request_id": "-", because the ID was reset one
statement before the line that exists to carry it. The response header was
right; nothing compared the two. Fixed in cadence,
with the test extended to check the log line as well as the header.
The interviewer's tool calls come back as records
cadence's interviewer calls its own tools before each question — check what the
interview has covered, read the rubric for a dimension, flag an answer to come
back to — and cadence keeps every call in its own table. get_tool_calls reads
that audit.
Most of what it returns the application computed. One value it did not: a flagged follow-up's topic is text the model wrote after reading the candidate's answer. So every argument and result is passed on as one JSON value on one line, cut at 300 characters with the original length shown, under a header that calls them data, not instructions. A topic with a newline in it cannot turn into a line of its own that reads like an instruction; there is a test that tries.
stdout is the protocol
Desktop clients start this server over stdio, so stdout carries MCP messages and nothing else. Every diagnostic goes to stderr, and the startup check runs before the transport opens: a missing variable is one sentence on stderr and exit code 1, not a malformed message the client cannot explain. There is a test for exactly that.
The assistant relays the interview; it does not sit it
The server's instructions and the tool descriptions say it plainly: show each question as returned, submit the user's own answer, never answer on the user's behalf or polish the answer first. A scorecard of the model's answers would be worthless, and the tools are where that rule can be stated to every client at once.
Tests
70 tests, no network: the tools run through the real MCP protocol (the SDK's
client, over a linked in-memory transport) against a fake cadence on a local
socket that implements the parts of the contract a client depends on —
status codes, FastAPI's error bodies, refresh-token rotation, Retry-After,
and an SSE stream that can be told to arrive one character at a time, with CRLF,
behind a keep-alive, cut off, or with an error event.
The fake is only as good as its fidelity, so the whole flow was also run
against the real cadence backend with tools/e2e.mjs: the server started as a
real process over stdio, a full interview, both confirmations, the 409 and the
404. Run it before trusting a change to either side.
npm ci
npm test # the suite
npm run check # tsc --strict over the JavaScript
node tools/contagem.js # the count above is checked, not typedLicense
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
AI interview practice and career preparation with user-controlled guidance.
AI voice interviewer: create roles, screen CVs, schedule interviews, read scored reports.
Run AI interviews, simulated personas and coaching sessions on JobMojito.
Run in-product voice interviews with AI agents and analyze source-linked evidence.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceIntelligent interview assistant that parses resumes, generates interview questions, records conversations, and produces evaluation reports for technical interviews.9-
- AlicenseAqualityDmaintenanceEnables interview preparation by analyzing resumes and job descriptions, generating role-specific questions, and evaluating answers using MCP tools integrated with an OpenAI agent.5MIT
- AlicenseNot gradedqualityBmaintenanceLets assistants manage private, locally transcribed meeting and interview recordings: start/stop sessions, list and search transcripts, retrieve paginated transcript text, add notes/tags, and export recordings.MIT

herdr-mcp-serverofficial
AlicenseNot gradedqualityCmaintenanceEnables a chat or voice assistant to drive coding agents running in herdr: it can start an agent on a task, list and watch sessions started anywhere, send follow-ups, answer an agent's questions and approve or refuse its permission prompts. Long-running work is reported back through webhook callbacks so the conversation can continue without blocking.MIT