Building MCP Servers & Clients: interview questions
- Source
- From the RAG & Agents Engineering course
- By
- Sourav Banerjee
- Last updated
- 2 Nov 2026
Production questions of the kind asked in applied AI engineering interviews.
1. Larkspur's assistant moved from held sessions to MultiServerMCPClient.get_tools() to simplify the code. Since then the handbook server's in-memory embedding cache never hits, and p95 latency has doubled. What happened?
What a strong answer covers:
get_tools()inlangchain-mcp-adapters0.3.2 opens a new session for each tool call, and over stdio each session is a new server process, so the cache dies with every call- Confirms it from the wire, not the code: count
initializerequests and server process starts per tool call (one each, against zero with held sessions) - Fixes the client by holding sessions,
async with client.session("handbook")andload_mcp_tools(session), or moves the server to HTTP, where the process outlives the session - Moves the cache out of process memory if it must survive restarts anyway, and adds a check on the setup cost per call to the latency dashboard
2. The status server runs as three replicas behind a load balancer, with stateful Streamable HTTP. Some tool calls fail with 404 "Session not found". What is going on, and what do you change?
What a strong answer covers:
- A stateful session lives in the memory of the replica that answered
initialize; a request with thatmcp-session-idrouted to another replica gets 404, and the client must initialize again - Two fixes: sticky routing on the
mcp-session-idheader, orstateless_http=Trueso any replica can answer any request - Stateless costs: no server-to-client stream, so the server cannot push notifications between requests, and nothing per session survives; fine for a search tool that keeps no state
- Also checks the idle timeout (1,800 seconds by default in SDK 1.30.0) and the 10,000-session cap, since both end sessions the client still believes in
3. How would you monitor the MCP layer of the assistant in production, separately from the model?
What a strong answer covers:
- Logs per tool call: server name, transport, session id, latency split into session setup and the call itself
- Tracks the ratio of
initializerequests totools/callrequests; it should be near zero with held sessions, and a jump to one means a client started opening sessions per call - Counts HTTP status codes per server (202 on SSE, 404 for lost sessions, 406 from clients sending the wrong
Acceptheader) with middleware like the lab's recorder - Alerts when a server's
tools/listchanges, because the model's routing depends on the names and descriptions it lists
4. At startup the status server's container fails to pull. With MultiServerMCPClient, the assistant does not start at all, though the handbook is fine. With the hand-built client from project 02, it starts with handbook tools only. Which behaviour do you want, and how do you get it?
What a strong answer covers:
get_tools()loads every server withasyncio.gather, so one failed server raises and no tools load; project 02 wraps each server in its owntryand keeps going- Decides per server: a support assistant can answer handbook questions without status, so start degraded, but say so in the system prompt and in the UI
- Loads servers one by one with
get_tools(server_name=...)or per-server sessions, records which failed, and retries them in the background - Tests it: a golden question per server, run with each server down, checking the assistant says it cannot reach status instead of guessing
5. A teammate deploys the SSE project's server on a VM to share it with the support team. It binds 0.0.0.0:8081 and offers run_command. What do you flag before it goes live?
What a strong answer covers:
- Anyone who reaches the port can open a session and run any shell command:
shell=True, no authentication, no timeout (the stdio version at least has 30 seconds) - The README promises command validation the code does not have, and the app is built by hand from
SseServerTransportwith no security settings, so DNS-rebinding protection is off - Replaces the shell with narrow tools (
search_handbook, notrun_command), binds to localhost behind an authenticating proxy, and runs the process in a container with a read-only file system - Moves to Streamable HTTP with FastMCP's own app, so host and origin checks come with the server, and adds the server to the team's security review like any other API