面试题库
共 328 题,当前筛选 2 题。
课程全部30 天从前端工程师到 Agent 工程师5 天提示词工程零基础Claude 高效使用:从对话到 Claude CodeCodex 与 OpenAI Agents SDK 高效使用7 天 MCP:把工具接进任何 Agent7 天 Agent Skills:把经验做成可复用能力5 天上下文工程14 天 RAG:从检索到可信回答14 天用 Agent 搭一条 AI 短剧生产线
7 天 MCP:把工具接进任何 Agent
D3 resources 与 prompts:URI 模板、变更通知、进度与日志、分页,以及客户端能力
MCP 的分页游标为什么必须是不透明的?如果客户端去解析它,会出什么问题?Why must MCP pagination cursors be opaque, and what breaks if a client parses them?
国内高频海外高频进阶#pagination#api-design分析过程 · 先想清楚再作答
- 这题表面考规范条文,实际考「有没有做过带分页的对外接口」。只背出「规范说不透明」拿不到分,要能说出解析之后具体哪一步会崩。
- 拆法:先问游标里到底装的是什么。服务端可以装偏移量、主键、时间戳、甚至一段加密状态,而且**换实现时它随时会变**。客户端一旦按某种格式解析,服务端从偏移量换成主键那天,所有客户端一起挂——这是把服务端的内部实现变成了公开契约。
- 第二个坑是伪造。客户端自己造一个 offset:9999 递给服务端,等于绕过了服务端对翻页范围的控制;如果游标里编了权限或过滤条件,伪造它就是一次越权。
- 第三个坑最阴:把空字符串当成结束。规范写死了只有 nextCursor **缺失**才代表没有下一页,空串是完全合法的游标。判错的表现是最后一页数据被静默丢掉,而且不报错,测试也很难发现。
- 结论:客户端对游标只允许做一个判断——nextCursor 在不在。页大小同理不得假设固定值,服务端随时可以改。非法游标服务端应当回 -32602,而不是静默返回第一页,否则客户端会陷进死循环。
- 可预期的追问:那服务端这边有什么坑?偏移量式游标要求列表顺序稳定,中途插入一条会让后面全部错位,所以要么先排序、要么把游标编成上一条的主键。
How to reason about it · think before answering
- It looks like a spec-recitation question but really tests whether you have shipped a paginated public API. Quoting the rule earns nothing; naming the concrete failure does.
- Start from what a cursor holds. A server may encode an offset, a primary key, a timestamp, or encrypted state, and it may change that at any time. A client that parses one format breaks everywhere the day the server switches, because parsing turned an internal detail into a public contract.
- Second failure is forgery. A client that fabricates offset:9999 bypasses the server's control over paging range, and if the cursor encodes filters or permissions, forging it is a privilege escalation.
- Third and nastiest: treating an empty string as the end. The spec is explicit that only a missing nextCursor ends the sequence; an empty string is a valid cursor. Getting this wrong silently drops the last page with no error, which tests rarely catch.
- Conclusion: a client may make exactly one judgment about a cursor — whether nextCursor is present. Page size likewise must not be assumed fixed. Servers should reject invalid cursors with -32602 rather than silently returning page one, which would loop the client forever.
- Likely follow-up: what bites the server side? Offset cursors require a stable ordering, since an insertion shifts everything after it, so either sort first or encode the last item's key instead.
答题要点
- 游标内容是服务端的内部实现,解析它等于把实现细节变成公开契约,服务端换实现时客户端全挂
- 伪造游标可以绕过服务端对翻页范围的控制,游标里若编了过滤或权限条件就是越权
- 只有 nextCursor 缺失才代表结束,空字符串是合法游标,判错会静默丢掉最后一页
- 页大小由服务端决定不得假设固定,非法游标服务端应回 -32602 而不是静默回第一页
Key points
- Cursor contents are server internals; parsing them turns an implementation detail into a public contract that breaks on any change
- Forged cursors bypass server-side paging control, and become privilege escalation if the cursor encodes filters or permissions
- Only a missing nextCursor ends the sequence — an empty string is valid, and getting it wrong silently drops the last page
- Page size is server-decided and must not be assumed fixed; invalid cursors should return -32602 rather than silently resetting
D4 远程 MCP:Streamable HTTP 绑定、无状态模型与请求元数据、OAuth 2.1 授权、容器部署
2026-07-28 去掉了协议级会话。那一个需要跨调用保存状态的远程服务端——比如购物车、数据库事务——应该怎么设计?The 2026-07-28 revision removed protocol-level sessions. How should a remote server that needs cross-call state — a shopping cart, a database transaction — be designed?
国内高频海外高频进阶#statelessness#api-design分析过程 · 先想清楚再作答
- 这题在筛「有没有把无状态当成设计约束」。答「用 Mcp-Session-Id 头」的当场出局,那个头这一版已经删了;答「存在服务端内存里按连接查」的同样出局,因为客户端根本不保证复用连接。
- 先给结构:状态必须由客户端携带,服务端只认请求里带来的东西。落地成两种形态——一是服务端铸造的显式句柄,创建工具返回一个 id,后续调用把它当普通工具参数传回来;二是签过名的不透明状态串,比如多轮请求里的 requestState,服务端把上下文签进去,重试时原样收回。
- 两者的差别在于「谁存数据」:句柄背后的购物车内容还是存在服务端的库里,句柄只是主键;requestState 是把上下文本身编码进字符串,服务端零存储。前者适合长期存在的业务对象,后者适合一次交互内的续接。
- 结论:不管哪种,服务端内存里都不为某个客户端留东西,所以任何副本都能处理任何请求,扩容不需要粘性路由——这正是这次改动想换来的东西。
- 安全是必须主动补的一句:句柄是名字不是凭证。要用安全随机数生成、绑定到已认证的主体(按 user_id 加 handle 做键)、设过期时间,并且每次调用重新校验调用者身份。规范明确写了服务端不得把持有句柄当成身份认证。requestState 同理,它经客户端转手,是攻击者可控输入,必须 HMAC 或 AEAD 验签,并把主体、原请求标识、短过期签进去。
- 可预期的追问:多副本时 requestState 怎么办?答案是所有副本共享签名密钥即可,这仍然是无状态的——状态在客户端手里,副本只负责验签。追问二可能是「怎么保证一次性」,答案是签名只能缩小重放窗口,真要单次消费得自己在服务端加一层消费记录。
How to reason about it · think before answering
- The screen is whether you treat statelessness as a design constraint. Answering 'use Mcp-Session-Id' fails immediately — that header was removed. So does 'keep it in server memory keyed by connection', since clients are not required to reuse connections.
- Give the structure first: state must travel with the client, and the server trusts only what arrives in the request. Two concrete shapes — a server-minted explicit handle returned by a creation tool and passed back as an ordinary tool argument, or a signed opaque blob like the requestState used by multi round-trip requests.
- The difference is who stores the data. A handle is just a primary key into server-side storage; a requestState encodes the context itself, so the server stores nothing. Handles suit long-lived business objects, requestState suits continuing a single interaction.
- Conclusion: either way the server keeps nothing per client in memory, so any replica can serve any request and scaling needs no sticky routing — which is exactly what the change was buying.
- Volunteer the security half: a handle is a name, not a credential. Generate it from a secure random source, bind it server-side to the authenticated principal (key storage as user id plus handle), expire it, and re-authorize on every call — the spec says possession of a handle must not be treated as authentication. requestState passes through the client, so it is attacker-controlled input and must be integrity-protected with HMAC or AEAD, carrying the principal, an originating-request identifier, and a short expiry.
- Likely follow-up: what about requestState across replicas? Share the signing key; it is still stateless because the state lives with the client and replicas only verify. A second follow-up is single use — signing bounds the replay window but does not guarantee one-time consumption, which needs a server-side redemption record.
答题要点
- 状态必须由客户端携带:服务端铸造显式句柄,作为普通工具参数在后续调用里传回
- 一次交互内的续接可以用签名的不透明状态串,服务端零存储,多副本共享签名密钥即可
- 句柄不是凭证:安全随机生成、绑定已认证主体、设过期,每次调用重新鉴权
- 收益是任何副本能处理任何请求,扩容不需要粘性路由,重启后重发即可
Key points
- State travels with the client: the server mints an explicit handle that later calls pass back as an ordinary tool argument
- Within one interaction, a signed opaque blob works with zero server storage; replicas just share the signing key
- A handle is not a credential: securely random, bound to the authenticated principal, expiring, re-authorized on every call
- The payoff is that any replica serves any request, so scaling needs no sticky routing and retries are cheap