内容
# 索引存储MCP
为Xcode项目提供语义代码导航功能的MCP服务器。代理可以按名称查找符号,按USR查找定义和引用,跟踪协议一致性和重写,以及获取文件的结构大纲——与Xcode通过Cmd+Click和Find Usages提供的导航相同。
基于苹果的[IndexStoreDB](https://github.com/swiftlang/indexstore-db)库,该库读取Xcode在构建过程中生成的索引数据。
## 何时使用
- **大型代码库**,`grep`返回太多噪声。按USR查找符号是精确的——不会从注释、字符串或类似命名的符号中匹配错误。
- **重构**——在更改类型或接口之前,找到所有协议一致性、方法重写和扩展。`relatedOccurrences`在一个调用中回答“什么会中断?”。
- **导航陌生代码**——代理可以跟踪调用图,并在定义和引用之间跳转,就像开发人员在Xcode中使用Cmd+Click一样,而不是猜测文件结构。
- **减少上下文窗口使用**——`symbolsInFile`返回结构大纲(名称、类型、行号),无需读取整个源文件。对于大型文件,这保持了代理的上下文聚焦。
- **跨依赖导航**——索引包括项目Swift包依赖中的符号,而不仅仅是您自己的源文件。
对于小型项目,`grep`和文件读取通常足够快。当项目规模和复杂性增长时,此MCP会带来回报。
## 先决条件
- **macOS 14+**
- **Xcode**已安装(提供`libIndexStore.dylib`)
- 目标项目必须在Xcode中至少构建一次,以便索引存储存在于DerivedData中
## 设置
### 构建
```sh
git clone https://github.com/hpatel-lincoln/swift-index-store-mcp.git
cd swift-index-store-mcp
swift build -c release
```
二进制文件位于克隆目录内的`.build/release/IndexStoreMCP`。
### 配置您的MCP客户端
<details>
<summary><strong>Claude Code</strong></summary>
```sh
claude mcp add index-store-mcp /path/to/swift-index-store-mcp/.build/release/IndexStoreMCP
```
</details>
<details>
<summary><strong>Claude Desktop / Cursor / other MCP clients</strong></summary>
将以下内容添加到您的MCP配置文件中:
```json
{
"mcpServers": {
"index-store-mcp": {
"command": "/path/to/swift-index-store-mcp/.build/release/IndexStoreMCP"
}
}
}
```
</details>
### 配置您的代理
添加MCP服务器使工具可用,但代理通常会默认为`grep`,除非另有指示。添加以下内容到您的项目的`CLAUDE.md`(或等效的代理指令文件)中,以鼓励代理使用索引:
```markdown
## Xcode 导航(index-store-mcp)
该项目已配置index-store-mcp服务器。在处理Swift/Objective-C源文件时,请使用它进行代码导航,而不是grep。
### 何时使用
- 查找符号的定义、引用或调用位置
- 跟踪协议一致性、方法重写或扩展
- 获取文件的结构大纲,然后再阅读它
- 区分具有通用名称的符号(例如,init、configure、handle)
- 确定符号的类型或种类(类、协议、枚举、方法、属性)
- 导航到包依赖中定义的符号
### 工作流程
1. 调用`loadIndex`,并在会话开始时传入工作区/项目路径
2. 使用`searchSymbol`(精确名称,首选)或`searchSymbolPattern`(模糊/部分, 使用较长的模式减少噪声)查找USR
3. 使用`getOccurrences`或`relatedOccurrences`,并传入USR查找所有使用位置
4. 当您正在阅读文件并需要特定位置的USR时,使用`symbolAtPosition`
5. 使用`symbolsInFile`获取文件的结构,而无需读取完整源代码
6. 在构建后调用`refreshIndex`以获取更改
```
## 工具(由代理调用)
### loadIndex
必须先调用。加载项目的Xcode索引。
```
workspacePath: "/path/to/MyApp.xcworkspace"
```
接受`.xcworkspace`、`.xcodeproj`或一个裸目录(对于在Xcode中打开的Swift包)。
### searchSymbol
按源代码中出现的确切名称查找符号。返回一个或多个USR(统一符号解析),唯一标识符号。
```
name: "viewDidLoad"
```
### searchSymbolPattern
模糊搜索时,您只知道部分名称。支持子序列匹配——`mvc`找到`MyViewController`,`vdl`找到`viewDidLoad`。
```
pattern: "mvc"
```
### symbolAtPosition
返回特定文件位置的符号。比`searchSymbol`更精确,当名称不明确时(例如`init`)。
```
file: "/path/to/MyFile.swift", line: 42, column: 10
```
### getOccurrences
给定USR,返回该符号定义、引用或调用的每个位置。支持角色过滤(`definition`、`reference`、`call`等)。
```
usr: "s:13MyApp0A14ViewControllerC"
```
### relatedOccurrences
查找结构关系:协议一致性、方法重写、类型扩展。在重构协议或基类之前至关重要。
```
usr: "s:13MyApp0A8ProtocolP"
```
### symbolsInFile
返回文件中定义的所有符号的结构大纲——名称、类型、USR和行号。
```
file: "/path/to/MyFile.swift"
```
### refreshIndex
在构建后轮询索引更改。调用此操作时,查询结果可能已过时。
## 典型的代理工作流程
```
loadIndex(workspacePath: "/path/to/MyApp.xcworkspace")
→ "索引已加载"
searchSymbol(name: "AppDelegate")
→ [{ usr: "s:5MyApp0A8DelegateC", kind: "class", location: "AppDelegate.swift:3" }]
getOccurrences(usr: "s:5MyApp0A8DelegateC", roles: ["reference"])
→ [{ file: "main.swift", line: 12, role: "reference" }, ...]
symbolsInFile(file: "/path/to/AppDelegate.swift")
→ [{ name: "AppDelegate", kind: "class", line: 3 },
{ name: "application(_:didFinishLaunchingWithOptions:)", kind: "instanceMethod", line: 5 }, ...]
```
## 工作原理
当Xcode构建项目时,编译器将符号索引数据写入`DerivedData/Index.noindex/DataStore`。IndexStoreMCP通过IndexStoreDB读取这些数据,并通过stdio传输在[Model Context Protocol](https://modelcontextprotocol.io)上公开。
服务器通过检查以下内容自动发现DerivedData:
1. Xcode偏好中的自定义DerivedData位置
2. 工作区旁边的一个`DerivedData`文件夹(相对模式)
3. 默认的`~/Library/Developer/Xcode/DerivedData`
系统框架符号(UIKit、Foundation等)默认过滤掉。传递`includeSystem: true`到任何工具以包含它们。
## 测试
参见[TESTING.md](TESTING.md)。
## 许可证
IndexStoreMCP在MIT许可证下发布。详情请参见[LICENSE](LICENSE)。