Phone a Friend
For when your agent would rather ask than guess.
A small MCP server you run yourself. Your AI agent asks people questions, they answer through a link in the browser, and the agent reads the answers when it gets back to the work.
Your agent, over MCP
ask_questions({ questions: [{ text: "Should guest checkout ask for a phone number?" }] }) // later… list_answers()
Pat, in the browser
Should guest checkout ask for a phone number?
Only if they pick delivery. Couriers need it, nobody else does.
Pat Example · 4 min ago
How it works
Agents are great until they hit a question only a person can answer. Then they either guess, or someone ends up playing postman, copying questions out to people and answers back in. This gives the agent somewhere to ask directly, without anyone sitting in the chat waiting.
The agent asks
It opens a session, attaches the docs or screenshots it's asking about, posts its questions and makes a share link.
People answer
Anyone with the link types their name once and answers, or says they don't know. No account, no app to install.
The agent follows up
Next time it checks, it reads the answers, asks follow-ups in the same thread, and accepts or closes each question.
Get started
You need Docker, and an MCP client such as Claude Code or VS Code with GitHub Copilot.
- 1
Run the container
Everything it keeps (the database, screenshots and its cookie secret) lives in the
feedback-datavolume, so you can stop, upgrade and restart it without losing anything.docker run -d --name feedback -p 8080:8080 -v feedback-data:/data \ ghcr.io/nickmza/curly-octo-journey:latest
Check it's up with
curl http://localhost:8080/healthz. - 2
Create a project and an API key
A project groups an agent's sessions, and its API key is what the agent connects with. The key is shown once.
docker exec feedback feedback create-project --name "My team" # Created project "My team" (3dd9…) # API key (shown once, store it safely): afk_…
If you'd rather click: start the container with
ADMIN_KEYset to 16 or more random characters and open/admin, or turn on sign-in (below) so people create their own projects. - 3
Connect your agent
The MCP endpoint is
/mcpover Streamable HTTP, with the API key as a bearer token. For Claude Code:claude mcp add --transport http feedback http://localhost:8080/mcp \ --header "Authorization: Bearer afk_…"
For VS Code with GitHub Copilot, add this to
.vscode/mcp.json. VS Code asks for the key the first time the server starts and stores it securely, so it stays out of git. Then switch Copilot Chat to Agent mode and start thefeedbackserver.{ "inputs": [ { "type": "promptString", "id": "feedback-api-key", "description": "Phone a Friend API key (afk_…)", "password": true } ], "servers": { "feedback": { "type": "http", "url": "http://localhost:8080/mcp", "headers": { "Authorization": "Bearer ${input:feedback-api-key}" } } } }Clients that only start local (stdio) servers can reach it through mcp-remote:
{ "mcpServers": { "feedback": { "command": "npx", "args": ["mcp-remote", "http://localhost:8080/mcp", "--allow-http", "--header", "Authorization: Bearer afk_…"] } } } - 4
Ask something
Talk to the agent in plain words and it picks the tools. For example:
Use the feedback tools to ask me whether the setup steps in the README are clear, and what's missing. Then give me the share link.
Open the link it gives you, type your name, and answer.
- 5
Put it where your people can reach it
Reviewers open share links in their own browser, so the server has to be reachable from their machines.
localhostis fine for trying it on your own. For a team, run it on a shared host, or behind a reverse proxy or a tunnel, and setPUBLIC_URLto that address, since share links are built from it. With anhttps://address the reviewer cookie is marked Secure too.docker run -d --name feedback -p 8080:8080 -v feedback-data:/data \ -e PUBLIC_URL=https://feedback.example.com \ ghcr.io/nickmza/curly-octo-journey:latest
Optional: let people sign in
Point it at Keycloak or any OpenID Connect provider (Entra ID, Google, Auth0, Authentik, Zitadel) and anyone who can sign in can create and manage their own projects on My projects. Answering questions never needs a sign-in.
- Find your provider's issuer URL: the
issuervalue at<issuer>/.well-known/openid-configuration, for examplehttps://keycloak.example.com/realms/acme. Copy it exactly; the app checks it character for character. - Register a web application (in Keycloak: an OpenID Connect client with Client authentication on and only Standard flow ticked). Set the redirect URI to
<PUBLIC_URL>/auth/callbackand the post-logout redirect URI to<PUBLIC_URL>/. - Optionally require PKCE with
S256. The app always sends it. - Copy the client secret and start the container with sign-in on:
docker run -d --name feedback -p 8080:8080 -v feedback-data:/data \ -e PUBLIC_URL=https://feedback.example.com \ -e OIDC_ISSUER=https://keycloak.example.com/realms/acme \ -e OIDC_CLIENT_ID=phone-a-friend \ -e OIDC_CLIENT_SECRET=<the secret> \ ghcr.io/nickmza/curly-octo-journey:latest
To check it, open <PUBLIC_URL>/api/account: it should say "signInEnabled":true, and a Sign in button appears at the top right. If the provider uses a certificate from your company's own CA, mount its root certificate and set NODE_EXTRA_CA_CERTS to its path. Behind a proxy, add the provider's domain to NO_PROXY. docker logs feedback says why a sign-in failed.
What else is in the box
Screenshots both ways
The agent can show a screenshot with a question, and reviewers can attach one to an answer. Images are re-encoded, which strips location data.
Webhooks
New links, questions and replies post a small JSON message you can route to Teams, Slack, Zapier or your own code.
Reviewer threads
Reviewers can raise their own questions, ideas and bugs. The agent sees them but never acts on them by itself.
One SQLite file
No database to run. Rate limits on links and replies, and a strict Content-Security-Policy, are on by default.
The agent's tools:
create_sessionattach_docsask_questionscreate_share_linkrevoke_share_linklist_sessionsget_sessionlist_answersget_screenshotpost_followupaccept_answerclose_questionarchive_sessionI built this because I got tired of playing postman between my agents and everyone else. Here's how that went.
Free to use, at your own risk. It comes with no warranty and no promise of support.