Topic 8: Module 1 milestone and interview questions
Project Milestone
After this module your copy of notes-assistant should contain:
notes-assistant/
requirements.txt
notes/ 8 sample notes (unchanged)
notes_assistant/
__init__.py
store.py NoteStore: read in full in Part B
llm.py chat() for groq / gemini / ollama: read in full in Part B
examples/
m01_store_tour.py NoteStore in use, including errors and create() in a temp folder
m01_native_tools.py native function calling with a hand-written schema (--offline for the scripted stand-in)
m01_first_server.py first MCP server: one search_notes tool over NoteStore (stdio or --http PORT)
m01_first_client.py Client in memory and over stdio
m01_broken_stdio.py a deliberately broken launch, for diagnosis practice
m01_wire.sh raw JSON-RPC over Streamable HTTP with curl
m01_versions.py the same server through server/discover and the legacy handshake
m01_lab.py the Module LabCode explained
- In simple words: a checklist of what should exist on disk now.
- What happens: the
notes_assistantpackage already contains later files too (server.py,host.py, and others) because the repository ships the finished project; you have now read and used the two that every later module imports. Everything new in this module lives inexamples/. - Comes out: you can verify the milestone with
PYTHONPATH=. python examples/m01_lab.py; if it printsall three transports agree: True, your store, server, and client all work over every transport.
The key design decisions to carry forward: business logic in store.py with no MCP imports; one chat() helper so the provider is an environment variable; tool schemas generated from type hints rather than written by hand; and tool names that match the final design (search_notes now, create_note in Module 3).
Interview Questions
1. What problem does MCP solve, in one sentence and one number? It turns N x M custom integrations between AI applications and tool systems into N + M implementations of one protocol. For 4 hosts and 6 tool systems that is 24 adapters versus 10 implementations; the saving grows with scale because multiplication outpaces addition.
2. If every LLM API already supports function calling, why do we need MCP? Function calling is how a model asks to use a tool; it says nothing about where tool definitions come from or who runs them. MCP standardises that outer layer: discovering tools from a separate server and executing calls there, across languages and processes. Hosts still use native function calling underneath, converting MCP tool definitions into the provider's format.
3. Explain host, client, and server, and why there is one client per server. The host is the user-facing AI application; it owns the model, UI, and consent decisions. A client is a connector inside the host that talks to exactly one server. A server exposes tools, resources, and prompts. One client per server isolates servers from each other (one cannot see another's traffic or the whole conversation) and contains failures to one connection.
4. What is the difference between a tool, a resource, and a prompt? They differ by who is in control. Tools are model-controlled functions the model decides to call. Resources are application-controlled content identified by URIs that the host or user chooses to attach. Prompts are user-controlled templates the user invokes, such as slash commands. Choose by asking who should decide.
5. Walk through a tools/call request in the 2026-07-28 revision over Streamable HTTP. A POST to the single MCP endpoint with a JSON-RPC 2.0 body: jsonrpc, an id, method: "tools/call", and params holding name, arguments, and a _meta envelope with io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. Headers include MCP-Protocol-Version, Mcp-Method: tools/call, and Mcp-Name equal to the tool name. The response echoes the id and carries content, optional structuredContent, isError, and resultType.
6. A tool call fails. When does the client get a JSON-RPC error and when does it get isError: true? Protocol problems (malformed request, missing _meta, mismatched headers, unknown method, unsupported version) produce a JSON-RPC error object. Problems inside the tool, including unknown tool names and validation failures the model could fix, produce a normal result with isError: true and the message in content, so the model can read it and try again.
7. What changed in the 2026-07-28 revision, and why does it matter for deployment? MCP became stateless: the initialize handshake and protocol sessions were removed, every request carries its version and capabilities in _meta, server/discover became the discovery call, and server-initiated requests were replaced by Multi Round-Trip Requests. Because no request depends on a session held by one replica, servers can scale horizontally behind an ordinary load balancer.
8. Sampling and roots are deprecated. What do you use instead? Instead of sampling, the server calls an LLM provider API directly when it needs a model. Instead of roots, pass directories or files through tool parameters, resource URIs, or server configuration (for example an environment variable like NOTES_DIR). Both still work during a deprecation window of at least twelve months under SEP-2577 and SEP-2596, but new code should not adopt them.
9. Your stdio server "does nothing" and the client reports Connection closed. How do you debug it? Read the server's stderr first: a stdio server's stdout is the protocol channel, so tracebacks and logs appear on stderr, which the SDK forwards. The usual causes are an import error, a missing environment variable (stdio children do not inherit your environment unless you pass env), a wrong working directory, or something printing non-protocol text to stdout.
10. When would you not use MCP? When nothing is shared: one script with one or two functions (use native function calling), service-to-service calls with no model (REST or gRPC), deterministic pipelines (plain code), bulk data movement (return links, not bytes), sub-millisecond hot paths (in-process calls), or delegating whole goals to another reasoning agent (an agent-to-agent protocol such as A2A).
11. How do you keep up with protocol changes? Read each revision's changelog and the deprecated features registry, watch SEP pull requests in the accepted and in-review states in the specification repository, and read your SDK's release notes and migration guide. Keep business logic separate from protocol code so upgrades touch only the thin server layer.
Other Tools and Providers
| Category | Used in this module | Alternatives | When to consider them |
|---|---|---|---|
| MCP SDK | Python SDK mcp==2.2.0 (MCPServer, Client) | Official SDKs for TypeScript, Java, Kotlin, C#, Go, Rust, Swift, Ruby, and PHP | Your host or server is written in another language; all interoperate over the same protocol |
| LLM provider | Groq (default), Gemini, Ollama through chat() | OpenAI, Anthropic, Mistral, OpenRouter, LM Studio, vLLM (most offer OpenAI-compatible endpoints or native tool calling) | You already pay for one, need a specific model, or must self-host; an OpenAI-compatible endpoint plugs into PROVIDERS with one new entry |
| MCP hosts to try your server in | The lab host you build in Module 6 | Claude Desktop and Claude Code, VS Code with GitHub Copilot, Cursor, and other MCP-enabled apps | You want to use the notes server from a polished UI; each takes a small config entry naming the command or URL |
| Interactive debugging | curl and small scripts | MCP Inspector (mcp dev with the cli extra, or npx @modelcontextprotocol/inspector) | You want to click through tools, resources, and prompts; Module 5 uses it |
| Integration style | MCP | Native function calling, REST/OpenAPI, gRPC, A2A for agent-to-agent | See the decision tables in A.4 and A.5 |
| Search backend | Keyword scoring in NoteStore.search | SQLite FTS5, a vector database with embeddings, a hosted search service | Thousands of notes, or questions phrased very differently from the notes' wording; keep the same search_notes tool contract and swap the store |
Coming Up in Module 2
You have now seen MCP messages on the wire, but only the happy path of two methods. Module 2, Protocol Architecture and Transports, opens the protocol up: requests, responses, notifications, and error codes in full; stateless discovery with server/discover and how it replaced the legacy initialize handshake and sessions; capability and version negotiation; pagination, progress, cancellation, and completions; and the two transports in depth, including stdio's subprocess model, Streamable HTTP's headers and SSE streaming, origin validation against DNS rebinding, and how to migrate off the deprecated HTTP+SSE transport. You will keep using the same notes server, now watching every byte it sends.