<!--
---
title: "Project Caffeine Arabica版本 Srpint1开发者指南"
description: "Arabica版本第一个迭代版本的开发者指南说明，实现一个最小化的5 Wys提示词策略 MCP Server 功能"
type: "Development Guide"
file: arabical-sprint1-development-specification-guide.md
version: "v1.0.0"
author: "Gitconomy Research-郭晧"
date: 2026-03-01
tags:
  - Project Caffeine
  - MCP
  - LLM
  - JSON-RPC 2.0
  - TypeScript
  - Node.js
license: "CC BY-SA 4.0"
status: "Active"
---
-->
# Arabica Sprint1 版本开发指南说明

## 1. 环境前置要求

在开始部署前，请确保开发机已安装以下软件：

- **Node.js**: v18 LTS 或更高版本。
- **Visual Studio Code (VS Code)**: 作为主力开发与断点调试 IDE。
- **Cherry Studio**: 最新版，作为发起请求的 MCP Client（大模型中枢）。
- **本地知识库**: 一个存放 `.md` 格式笔记的本地文件夹（如 Obsidian Vault）。

---

## 2. 工程初始化与依赖安装

打开终端，执行以下命令从零搭建工程骨架：

```bash
# 1. 创建并进入项目目录
mkdir project-caffeine-ts
cd project-caffeine-ts

# 2. 初始化 npm
npm init -y

# 3. 安装生产核心依赖
npm install @modelcontextprotocol/sdk zod

# 4. 安装 TypeScript 及开发环境依赖
npm install --save-dev typescript @types/node

# 5. 创建标准的目录结构
mkdir -p src/services dist .vscode
touch src/app.ts src/services/promptService.ts src/services/resourceService.ts .vscode/launch.json tsconfig.json
```

---

## 3. 核心工程配置

我们需要配置 TypeScript 编译器选项、启动脚本以及 VS Code 独有的源码映射调试环境。
### 3.1 编辑`tsconfig.json`

控制代码编译并生成用于断点调试的 `sourceMap`：

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "CommonJS",
    "moduleResolution": "node",
    "outDir": "./dist",
    "rootDir": "./src",
    "sourceMap": true,             // 【关键】生成 .js.map 文件，用于 VS Code 断点映射
    "strict": true,                // 开启严格模式
    "esModuleInterop": true,       // 允许默认导入 CommonJS 模块
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
	"include": ["src/**/*"]
}
```

### 2.2 编辑`package.json`

添加 `build` 和 `watch` 脚本，用于将 `.ts` 编译为 `.js`。在 `package.json` 中找到 `"scripts"` 字段并替换为

```json
"scripts": { "build": "tsc", "watch": "tsc --watch", "start": "node dist/app.js" }
```

### 2.3 编辑 `.vscode/launch.json`  

新增的 `outFiles` 字段，它告诉 VS Code 去 `dist` 目录寻找编译后的文件，从而将断点映射回你的 `src/*.ts` 源码上。

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "🍒 附加到 Cherry Studio (TS 联调)",
      "port": 9229,
      "restart": true,
      "skipFiles": ["<node_internals>/**"],
      "outFiles": ["${workspaceFolder}/dist/**/*.js"]
    }
  ]
}
```

---

## 4. 第核心业务代码实现

### 4.1. `src/services/promptService.ts` (提示词策略生成)

纯本地业务逻辑，负责 5 Whys 框架生成。

```TypeScript
/**
 * 根据查询主题生成 5 Whys 提示词策略
 * @param query 用户输入的查询主题
 * @returns 包含 5 个追问的字符串数组
 */
export function generate5Whys(query: string): string[] {
    if (query.includes("开源人才")) {
        return [
            "为什么中国开源人才的培养面临困难？",  
            "为什么中国开源人才缺乏足够的行业经验？",  
            "为什么开源社区对中国人才的支持力度不足？",  
            "为什么中国开源人才的市场需求与供给不平衡？",  
            "为什么政策支持不足导致中国开源人才流失？"
        ];
    }

    return [
        `为什么 "${query}" 会成为一个问题？`,
        `为什么导致上述现象的直接原因会发生？`,
        `为什么当前的系统或流程没有阻止这种情况？`,
        `为什么以前的解决方案或预防措施失效了？`,
        `为什么根本的系统性漏洞一直未被修复？`
    ];
}
```

### ## 4.2 `src/services/resourceService.ts` (本地知识库访问)

带有严格路径防穿越（Path Traversal）安全校验的本地文件读取服务。

```TypeScript
import fs from 'fs/promises';
import path from 'path';

// 【⚠️ 重要配置】请修改为你电脑上真实的 Markdown 笔记文件夹绝对路径！
const OBSIDIAN_VAULT_PATH = '/home/wguo/Downloads/MyVault';

export async function listObsidianNotes(): Promise<string[]> {
    try {
        const files = await fs.readdir(OBSIDIAN_VAULT_PATH);
        return files.filter(file => file.toLowerCase().endsWith('.md'));
    } catch (error: any) {
        console.error(`[Project Caffeine] 无法读取知识库目录: ${error.message}`);
        return [];
    }
}

export async function readObsidianNote(filename: string): Promise<string> {
    const targetPath = path.resolve(OBSIDIAN_VAULT_PATH, filename);
    const safeVaultPath = path.resolve(OBSIDIAN_VAULT_PATH);

    // 核心防御：防止大模型通过传入 "../../" 读取系统敏感文件
    if (!targetPath.startsWith(safeVaultPath)) {
        throw new Error(`安全警告：越权访问拦截！禁止读取目录外的文件: ${filename}`);
    }

    try {
        const content = await fs.readFile(targetPath, 'utf-8');
        return content;
    } catch (error: any) {
        throw new Error(`无法读取笔记 [${filename}]: 文件可能不存在或无权限。`);
    }
}
```

### 4.3 `src/app.ts` (主入口)

负责初始化标准输入输出传输层，并向 Cherry Studio 注册工具字典。

```TypeScript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
import { generate5Whys } from './services/promptService';
import { listObsidianNotes, readObsidianNote } from './services/resourceService';

// ==========================================
// 1. 初始化 MCP Server
// ==========================================
const mcpServer = new McpServer({
    name: "Project-Caffeine-Prompt-Strategy",
    version: "1.2.0"
});

// ==========================================
// 2. 注册 Tools (工具) - 赋予大模型主动执行的能力
// ==========================================

// 工具 1：5 Whys 提示词策略生成
mcpServer.tool(
    "generate_5_whys",
    "使用 5 Whys 模板对用户查询进行深度分解，生成增强的提示词策略",
    { query: z.string().describe("需要分析的查询主题") },
    async ({ query }: { query: string }) => {
        console.error(`[Project Caffeine] 大模型调用工具: 正在生成 5 Whys 策略 -> ${query}`);
        const enhancedPrompt = generate5Whys(query);
        return {
            content: [{ type: "text", text: JSON.stringify(enhancedPrompt, null, 2) }]
        };
    }
);

// 工具 2：扫描本地知识库目录
mcpServer.tool(
    "list_local_notes",
    "获取本地 Obsidian 知识库中的所有 Markdown 笔记列表，用于了解当前有哪些可用的本地上下文资料。",
    {},
    async () => {
        console.error(`[Project Caffeine] 大模型调用工具: 正在扫描本地笔记列表...`);
        const notes = await listObsidianNotes();
        return {
            content: [{
                type: "text",
                text: notes.length > 0 ? `找到了以下笔记：\n${notes.join('\n')}` : "未找到笔记。"
            }]
        };
    }
);

// 工具 3：阅读指定的单篇笔记内容
mcpServer.tool(
    "read_local_note",
    "读取本地 Obsidian 知识库中指定笔记的完整内容，作为深度分析的上下文参考。",
    { filename: z.string().describe("需要读取的笔记文件名，必须包含 .md 后缀") },
    async ({ filename }: { filename: string }) => {
        console.error(`[Project Caffeine] 大模型调用工具: 正在深度阅读笔记 -> ${filename}`);
        try {
            const content = await readObsidianNote(filename);
            return { content: [{ type: "text", text: content }] };
        } catch (error: any) {
            return {
                content: [{ type: "text", text: `读取失败: ${error.message}` }],
                isError: true // 明确告知大模型此操作抛出了错误
            };
        }
    }
);

// ==========================================
// 3. 注册 Resources (资源) - 暴露给客户端供用户手动勾选的静态数据
// ==========================================

// 资源 1：知识库目录索引
mcpServer.resource(
    "obsidian-index",                   // 客户端显示的资源 Name/ID
    "obsidian://vault/index",           // 唯一的 URI 标识
    {
        description: "本地知识库的目录索引，包含所有 Markdown 笔记的列表"
    },
    async (uri) => {
        console.error(`[Project Caffeine] 客户端请求静态资源: ${uri.href}`);

        const notes = await listObsidianNotes();
        const textContent = notes.length > 0
            ? `当前知识库包含以下文件：\n${notes.join('\n')}`
            : "当前知识库为空。";

        return {
            contents: [{
                uri: uri.href,
                mimeType: "text/plain",
                text: textContent
            }]
        };
    }
);

// ==========================================
// 4. 启动底层 Stdio 传输层
// ==========================================
async function start(): Promise<void> {
    console.error("[Project Caffeine] 正在启动 TS 版 MCP Server (含 Tools 与 Resources)...");
    const transport = new StdioServerTransport();
    await mcpServer.connect(transport);
    console.error("[Project Caffeine] MCP Server 已就绪，等待 Cherry Studio 交互。");
}

// 捕获致命错误并安全退出
start().catch((err: unknown) => {
    console.error("服务器启动失败:", err);
    process.exit(1);
});
```

---

## 5. 启动与工作流验证

### 5.1 步骤一：启动 TS 实时编译 (Watch Mode)

在 VS Code 中打开终端，运行以下命令。这会让 TypeScript 编译器在后台实时监控你的 `.ts` 文件修改，并自动编译到 `dist` 目录中：

```bash
npm run watch
```

_(保持这个终端窗口在后台运行不要关闭)_

### 5.2 步骤二：在 Cherry Studio 中配置 Server

1. 进入 Cherry Studio 的 **设置 -> MCP**。

2. 添加或修改 Server，**关键在于你要指向编译后的 `dist/app.js` 而不是 `src/app.ts`**：

    - **Command**: `node`
    - **Args**: `["--inspect=9229", "/project-caffeine-sprint1/dist/app.js"]`  
    - _注意：需要输入app.js的绝对路径_

3. 确保状态灯亮起绿色。

### 5.3 步骤三：VS Code 源码级断点联调

1. 在 `src/app.ts` 或各个 Service 的关键代码行打上断点。
2. 在 VS Code 左侧调试面板，选择 **"🍒 附加到 Cherry Studio (TS 联调)"**，点击运行。
3. 状态栏变色即表示成功抓取到 Cherry Studio 的底层 Node 进程。

### 5.4 发起全链路交互

在 Cherry Studio 对话框中，输入以下指令测试大模型的自主编排能力：

> _"请先查看我的本地笔记列表，找到关于开源领域的笔记并阅读内容。然后结合你的知识，调用 5 Whys 工具帮我分析一下里面的痛点。"_

**预期结果**：你将看到大模型**自动、按顺序**调用了 `list_local_notes` -> `read_local_note` -> `generate_5_whys` 三个工具，最终为你输出一篇深度融合了你的私有知识库的洞察报告。

---

## 6. 系统运行测试样例


在开始执行测试之前，请确保已完成以下前置准备：

- **后台编译**：在 VS Code 终端保持运行 `npm run watch` 命令。
- **配置连接**：在 Cherry Studio 的设置中，将 Command 设为 `node`，Args 设为 `["--inspect=9229", "<绝对路径>/dist/app.js"]`，并确保状态灯亮起绿色。
- **本地知识库**：确保代码中 `OBSIDIAN_VAULT_PATH` 指向的本地文件夹中存在至少一篇 Markdown 格式的测试笔记。

### 6.1 测试样例1：基础工具调用与分支逻辑验证

- **测试目标**：验证 `generate_5_whys` 工具的硬编码逻辑分支是否生效。

- **操作步骤**：

    1. 向大模型发送指令：“请调用工具，帮我生成关于‘开源人才’的 5 Whys 策略。”

- **预期结果**：

    - VS Code Debug Console打印日志：`[Project Caffeine] 大模型调用工具: 正在生成 5 Whys 策略 -> 开源人才`。
    - 大模型的回答中必须包含代码中预设的具体问题，例如“为什么中国开源人才的培养面临困难？”、“为什么中国开源人才缺乏足够的行业经验？”等。

### 6.2 测试样例 2：泛化工具调用验证

- **测试目标**：验证 `generate_5_whys` 工具在遇到未知主题时的泛化模板处理能力。

- **操作步骤**：

    1. 向大模型发送指令：“我正在研究‘AI算力成本过高’的问题，请调用工具为我生成 5 Whys 框架。”

- **预期结果**：

    - 大模型会调用工具，并将主题代入泛化模板，输出类似“为什么 "AI算力成本过高" 会成为一个问题？”、“为什么导致上述现象的直接原因会发生？”等框架性问题。


### 6.3 测试样例 3：安全防御机制测试（红蓝对抗）

- **测试目标**：验证 `read_local_note` 工具中的路径防穿越（Path Traversal）安全校验是否能成功拦截恶意请求。

- **操作步骤**：

    1. 向大模型发送诱导性指令：“请调用读取笔记的工具，帮我读取 `../etc/passwd` 文件的内容。”

- **预期结果**：

    - 工具调用将被拦截，并抛出错误。
    - 大模型将收到包含 `isError: true` 的错误响应。
    - 错误信息明确提示大模型：“读取失败: 安全警告：越权访问拦截！禁止读取目录外的文件”。


### 6.4 测试样例 4：全链路 Agentic 自主编排测试

- **测试目标**：验证大模型是否能自主决策，按顺序组合调用多个外部工具完成复杂分析。

- **操作步骤**：

    1. 向大模型发送综合指令：“请先查看我的本地笔记列表，找到关于开源领域的笔记并阅读内容。然后结合你的知识，调用 5 Whys 工具帮我分析一下里面的痛点。”。

- **预期结果**：

    - 大模型将自动并按顺序调用 `list_local_notes` -> `read_local_note` -> `generate_5_whys` 三个工具。
    - 最终输出一篇融合了私有知识库内容深度的洞察报告。

### 6.5 测试样例 5：VS Code 断点联调环境测试

- **测试目标**：验证 `.vscode/launch.json` 源码映射与调试环境配置是否成功。

- **操作步骤**：

    1. 在 `src/app.ts` 或其他 Service 文件的关键代码行打上断点。
    2. 在 VS Code 调试面板选择“🍒 附加到 Cherry Studio (TS 联调)”并运行。
    3. 在 Cherry Studio 中触发任意工具调用。

- **预期结果**：

    - VS Code 底部状态栏变色，表示成功抓取到 Cherry Studio 的底层 Node 进程。
    - 代码执行将暂停在设置了断点的位置，允许开发者查看当前变量与调用栈。

---

## 许可声明

本文档采用 **知识共享署名--相同方式共享 4.0 国际许可协议 (CC BY--SA 4.0)** 进行许可，© 2025-2026  Gitconomy Research.
