\documentclass[a4paper]{article}

% Basic packages
\usepackage[fontset=fandol]{ctex}
\usepackage{amsmath, amssymb}
\usepackage{graphicx}
\usepackage[margin=2.5cm]{geometry}
\usepackage[most]{tcolorbox}
\usepackage{etoolbox}
\usepackage{listings}
\usepackage{hyperref}
\usepackage{booktabs}
\usepackage{subcaption}
\usepackage{float}

% Highlight boxes
\newtcolorbox{knowledgebox}[1]{
    enhanced, colback=blue!5!white, colframe=blue!75!black, colbacktitle=blue!75!black,
    coltitle=white, fonttitle=\bfseries, title=#1, attach boxed title to top left={yshift=-2mm, xshift=2mm},
    boxrule=1pt, sharp corners
}

\newtcolorbox{importantbox}[1]{
    enhanced, colback=yellow!10!white, colframe=yellow!80!black, colbacktitle=yellow!80!black,
    coltitle=black, fonttitle=\bfseries, title=#1, sharp corners
}

\newtcolorbox{warningbox}[1]{
    enhanced, colback=red!5!white, colframe=red!75!black, colbacktitle=red!75!black,
    coltitle=white, fonttitle=\bfseries, title=#1, sharp corners
}

% Listings
\lstset{
    language=Python,
    basicstyle=\ttfamily\small,
    keywordstyle=\color{blue},
    stringstyle=\color{red!60!black},
    commentstyle=\color{green!60!black},
    breaklines=true,
    frame=single,
    numbers=left,
    numberstyle=\tiny\color{gray},
    captionpos=b,
    extendedchars=false
}

% Front-page metadata
\newcommand{\notetitle}{CS146S Week 2: The Anatomy of Coding Agents (MCP)}
\newcommand{\noteauthors}{基于 Mihail Eric 授课内容整理}
\newcommand{\notedate}{2025年10月}
\newcommand{\videochannel}{Stanford CS146S}
\newcommand{\videopublishdate}{Fall 2025}
\newcommand{\videoduration}{2 lectures (Mon + Fri)}
\newcommand{\videourl}{https://themodernsoftware.dev}
\newcommand{\videocoverpath}{}
\newcommand{\repourl}{https://github.com/hqhq1025/ai-course-notes}


% Footer with repo info
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{}
\fancyfoot[C]{\thepage}
\fancyfoot[R]{\footnotesize\color{gray}\href{\repourl}{AI Course Notes}}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}

\begin{document}

\begin{titlepage}
\centering
{\Large 课程笔记\par}
\vspace{1.2cm}
{\huge\bfseries \notetitle\par}
\vspace{0.8cm}
{\large \noteauthors\par}
\vspace{0.3cm}
{\large \notedate\par}
\vspace{1.2cm}

\ifdefempty{\videocoverpath}{
\vspace{3cm}
}{
\includegraphics[width=0.82\textwidth,height=0.45\textheight,keepaspectratio]{\videocoverpath}\par
}

\vfill
\begin{tcolorbox}[width=0.9\textwidth, colback=black!2!white, colframe=black!60, sharp corners]
\textbf{课程}：\videochannel\par
\textbf{学期}：\videopublishdate\par
\textbf{讲次}：\videoduration\par
\textbf{网站}：\href{\videourl}{\nolinkurl{\videourl}}\par
\textbf{项目主页}：\href{\repourl}{\nolinkurl{\repourl}}\par
\end{tcolorbox}
\end{titlepage}

\tableofcontents
\newpage

%% --- 正文内容开始 --- %%

\section{从零构建 Coding Agent}

\subsection{什么是 Coding Agent}

Coding Agent 是一种能够自主执行编程任务的 AI 系统。其核心组件包括：

\begin{itemize}
    \item \textbf{System Prompt}：定义 Agent 的行为和指令
    \item \textbf{User Prompt}：用户的自定义请求
    \item \textbf{Assistant Prompt}：LLM 的响应
    \item \textbf{Tool Set}：Agent 可调用的工具集合
\end{itemize}

\begin{importantbox}{Coding Agent 的核心循环}
一个 Coding Agent 的基本工作流程极其简单：
\begin{enumerate}
    \item 从终端读取用户输入，持续追加到对话历史
    \item 告知 LLM 可用的工具（Read\_file、List\_dir、Edit\_file 等）
    \item LLM 在适当时机请求调用工具
    \item 离线执行工具调用并返回结果
    \item 重复上述过程直到任务完成
\end{enumerate}
\end{importantbox}

\subsection{``秘密武器''：Claude Code 的设计哲学}

深入分析 Claude Code 的底层设计，可以发现几个关键的工程决策：

\begin{enumerate}
    \item \textbf{前置 context 注入}：使用小而精准的 prompt 进行 context 前置加载
    \item \textbf{System reminders 无处不在}：在 system prompt、user prompt、tool calls、tool results 中都插入 \texttt{<system-reminder>} 标签，防止模型在长对话中偏离目标
    \item \textbf{Command prefix extraction}：从用户输入中提取命令前缀，实现快捷操作
    \item \textbf{Subagent 派生}：生成子 Agent 处理特定子任务，避免单个 context 过载
\end{enumerate}

\begin{warningbox}{Context Drift 问题}
在长对话中，LLM 容易``忘记''早期的指令和约束——这被称为 context drift。Claude Code 通过在对话的各个环节反复插入 system reminders 来对抗这一问题。这是一个经过工程验证的关键技巧。
\end{warningbox}

\subsection{本章小结}

构建一个基础 Coding Agent 的技术门槛其实很低——核心就是 LLM + tool calling 的循环。但要构建一个\textbf{可靠}的 Coding Agent，需要大量的工程细节：context 管理、drift 防护、子任务分解等。

\section{Model Context Protocol (MCP)}

\subsection{为什么需要 MCP}

LLM 拥有广泛但\textbf{静态}的世界知识——只有在重训时才会更新。要构建真正自主的系统，需要可靠的方式向 LLM 注入动态数据（天气、股价、最新 API 文档等）。

RAG 和 tool calling 是目前最好的答案。但问题在于：

\begin{knowledgebox}{M $\times$ N 连接器问题}
假设有 $M$ 个 LLM 应用和 $N$ 个第三方工具/API。在 MCP 之前，每个应用需要为每个工具编写独立的集成代码——包括认证、错误处理、速率限制等。这导致了 $M \times N$ 个连接器的维护负担。
\end{knowledgebox}

\subsection{MCP 是什么}

MCP（Model Context Protocol）是 Anthropic 于 2024 年 11 月推出的开放协议，为 LLM 提供了一种\textbf{标准化}的工具暴露格式。

\begin{importantbox}{MCP 的核心价值}
MCP 将工具集成从 $M \times N$ 降低到 $M + N$：
\begin{itemize}
    \item 不需要为每个工具重新实现认证、错误处理、速率限制
    \item 使用 JSON-RPC 强制执行一致的输出格式
    \item 从 Language Server Protocol (LSP) 扩展而来，但支持\textbf{主动的}（proactive）agentic workflow，而非 LSP 的纯反应式模式
\end{itemize}
\end{importantbox}

\subsection{MCP 架构详解}

\subsubsection{核心术语}

\begin{itemize}
    \item \textbf{Host}：宿主应用（如 Cursor、Claude Desktop）
    \item \textbf{MCP Client}：嵌入在 Host 中的库（为每个 Server 维护有状态的 session）
    \item \textbf{MCP Server}：轻量级的工具包装器（wrapper）
    \item \textbf{Tool}：可调用的函数（数据源、API 等）
\end{itemize}

\subsubsection{工作流程}

\begin{enumerate}
    \item Client 调用 \texttt{tools/list} 向 MCP Server 查询：``你能做什么？''
    \item Server 返回 JSON 描述每个工具（名称、摘要、JSON Schema）
    \item Host 将这些 JSON 注入模型的 context
    \item 用户 prompt 触发模型，模型输出结构化的 tool call
    \item MCP Server 执行调用，对话继续
\end{enumerate}

\subsubsection{传输层}

MCP 提供两种传输机制：
\begin{itemize}
    \item \textbf{stdio}：标准输入/输出，适用于本地进程通信
    \item \textbf{SSE}（Server-Sent Events）：适用于远程服务通信
\end{itemize}

\subsection{MCP 的局限性}

\begin{warningbox}{当前 Agent 处理多工具的能力有限}
\begin{itemize}
    \item Agent 在面对大量工具时表现不佳——工具描述会快速消耗 context window
    \item API 设计需要面向 AI 原生（AI-native），而非沿用传统的刚性 API 设计
    \item 复杂的 API 参数和嵌套结构会显著降低工具调用的准确率
\end{itemize}
\end{warningbox}

\subsection{本章小结}

MCP 是 AI 编程工具生态的重要基础设施，通过标准化的协议解决了 LLM 与外部工具集成的 $M \times N$ 问题。理解 MCP 的架构（Host $\rightarrow$ Client $\rightarrow$ Server $\rightarrow$ Tool）和通信流程是构建和使用 AI 编程工具的关键。

\section{从协议到产品：MCP 为什么会成为分水岭}

\subsection{它解决的不只是连接问题，而是生态协作问题}
Week 2 对 MCP 的介绍，很容易被误解为 ``又一个 tool calling 协议''。但课程想强调的更深一层含义是：\textbf{MCP 真正统一的是工具生态的协作边界，而不只是调用语法。} 在没有 MCP 的世界里，每个 Agent 产品都要自己决定认证方式、工具描述格式、错误返回结构和会话状态管理；这使得工具作者和 Agent 产品方都不断重复造轮子。

\begin{importantbox}{MCP 之所以重要，是因为它把工具从项目私有实现变成了生态公共接口}
\begin{itemize}
    \item 对工具提供方来说，写一次 MCP Server，就能被多个 Host/IDE/Agent 复用；
    \item 对 Agent 产品来说，不必为每个工具单独适配 schema、错误格式与权限模型；
    \item 对用户来说，工具切换的成本显著下降，工作流可以跨产品迁移。
\end{itemize}
\end{importantbox}

这和历史上的 LSP 很像。LSP 并没有发明 ``补全'' 或 ``跳转定义''，但它统一了编辑器与语言服务之间的接口，于是整个生态的创新速度被抬高。MCP 对 Agent 工具生态扮演的是类似角色，只不过作用对象从 ``编辑器能力'' 变成了 ``模型可调用的外部能力''。

\subsection{真正困难的部分：协议统一后，设计责任才开始出现}
协议统一并不意味着 Agent 就会自然用好工具。相反，接口一旦标准化，大家更容易看到另一个问题：\textbf{很多现有 API 根本不是为模型使用而设计的。}

\begin{warningbox}{AI-native API 设计不能简单照搬给人类开发者的 API}
\begin{itemize}
    \item 参数过多、嵌套太深、状态切换太隐式，会显著降低模型调用成功率；
    \item 返回结果如果缺少简洁摘要和明确错误原因，模型很难做后续决策；
    \item 工具如果不暴露权限边界和副作用说明，Agent 很容易做出高风险调用。
\end{itemize}
\end{warningbox}

\begin{table}[H]
\centering
\begin{tabular}{p{3.0cm}p{4.2cm}p{4.0cm}}
\toprule
\textbf{设计维度} & \textbf{传统 API 常见做法} & \textbf{AI-native 工具更优做法} \\
\midrule
参数设计 & 参数多、结构深、默认值隐式 & 参数尽量扁平，必要信息显式给出 \\
错误处理 & 面向工程师的长错误栈 & 提供可供模型恢复的结构化错误信息 \\
副作用说明 & 依赖文档阅读理解 & 在工具 schema 中直接说明风险与影响范围 \\
返回结果 & 原始 JSON/对象堆叠 & 同时提供摘要字段和机器可解析字段 \\
\bottomrule
\end{tabular}
\caption{MCP 解决了协议统一问题，但工具本身是否 AI-native 仍决定了可用性上限}
\end{table}

\subsection{本章小结}
MCP 的意义不在于又多了一个协议，而在于它为 Agent 工具生态提供了公共接口。真正的下一步挑战，是让工具本身也从 ``给人类开发者看的 API'' 演化为 ``给模型稳定调用的 AI-native API''。

\section{实践视角：一个可维护 Coding Agent 的三层检查表}

\subsection{最容易被忽略的是会话和上下文治理}
Week 2 前半部分用最小 Coding Agent 展示了 tool loop 的核心结构，后半部分再引入 MCP。把两部分放在一起看，会发现一个更实际的工程问题：\textbf{一个能长期稳定工作的 Coding Agent，关键不只在于会不会调用工具，而在于怎么管理上下文、状态和失败恢复。}

\begin{knowledgebox}{三层检查表}
\begin{enumerate}
    \item \textbf{模型层}：系统提示词是否清楚说明任务、边界和工具使用原则；
    \item \textbf{工具层}：工具 schema 是否稳定、返回结果是否适合下一步推理；
    \item \textbf{会话层}：上下文是否会膨胀、是否有 reminder、失败后如何恢复。
\end{enumerate}
\end{knowledgebox}

这也是为什么课程里会强调 context 前置加载、system reminders 和 subagent 分流。这些看似 ``产品技巧'' 的东西，实际上是在弥补当前模型在长期任务上的脆弱性。Agent 不是只要会调用工具就够了，它还必须能在长时间、多步骤、多文件的工作中保持目标一致性。

\subsection{本章小结}
如果把 Week 2 学到的内容真正带回工程实践，一个可靠的 Coding Agent 至少要同时过三道关：模型是否知道该做什么、工具是否适合模型调用、会话是否有足够的上下文治理能力。这三者缺一不可。

\subsection{什么时候不该把问题简单归结为 ``上一个 MCP Server''}
Week 2 还有一个很值得保留的工程判断：不是所有集成问题都应该第一时间被包装成一个新的 MCP Server。协议标准化会降低接入成本，但它不会自动解决权限设计、任务切分和观测性问题。

\begin{warningbox}{MCP 不是系统设计的替代品}
\begin{itemize}
    \item 如果底层 API 本身不稳定，MCP 只会把不稳定更标准地暴露出来；
    \item 如果任务边界不清晰，模型即便能调用工具，也可能在错误的层面上自动化；
    \item 如果缺少日志、重试和回滚机制，协议统一反而可能放大错误传播范围。
\end{itemize}
\end{warningbox}

这也是为什么课程一边讲协议，一边仍然强调 agent loop、context management 与产品约束。真正可靠的 Coding Agent，从来不是 ``工具越多越好''，而是 ``能在明确边界内稳定完成任务''。

\section{总结与延伸}

Week 2 深入了 Coding Agent 的技术内核。从手动构建一个最小化的 Coding Agent，到理解 MCP 协议如何将工具集成标准化，课程展示了 AI 编程工具``魔法''背后的工程实现。

\subsection{总结表}

\begin{table}[H]
\centering
\begin{tabular}{p{2.8cm}p{4.2cm}p{4.0cm}}
\toprule
\textbf{主题} & \textbf{Week 2 的核心结论} & \textbf{工程含义} \\
\midrule
最小 Agent Loop & LLM + tool call + observation 已能形成基本闭环 & 原理简单，但上下文与错误处理决定可用性 \\
Claude Code 经验 & reminder、context 预载、subagent 分流都很关键 & 产品设计直接影响模型稳定性 \\
MCP 协议 & 工具集成从 $M \times N$ 下降到 $M + N$ & 生态创新可以从私有集成走向公共接口 \\
AI-native Tools & 协议统一后，工具设计本身成为瓶颈 & API 需要更扁平、可恢复、可解释 \\
\bottomrule
\end{tabular}
\caption{Week 2 更像一节 Coding Agent 基础设施设计课，而不只是工具使用课}
\end{table}

\subsection{关键要点}

\begin{itemize}
    \item Coding Agent = LLM + Tool Calling 循环，核心简单但工程细节决定质量
    \item Claude Code 的关键设计：context 前置加载、system reminders 防 drift、subagent 分流
    \item MCP 将 $M \times N$ 集成降为 $M + N$，使用 JSON-RPC 标准化工具描述
    \item MCP 架构：Host $\rightarrow$ Client $\rightarrow$ Server $\rightarrow$ Tool
    \item 当前局限：Agent 处理多工具能力有限，API 需要 AI-native 设计
\end{itemize}

\subsection{拓展阅读}

\begin{itemize}
    \item MCP 官方文档：\url{https://modelcontextprotocol.io}
    \item Anthropic MCP 发布博客：\url{https://www.anthropic.com/news/model-context-protocol}
    \item JSON-RPC 2.0 规范：\url{https://www.jsonrpc.org/specification}
    \item Language Server Protocol：\url{https://microsoft.github.io/language-server-protocol/}
\end{itemize}

%% --- 正文内容结束 --- %%

\end{document}
