Swift code analysis with Periphery - detect unused code and improve code quality
A Model Context Protocol (MCP) server that wraps the Periphery tool, enabling AI assistants to perform Swift code audits and detect unused code in iOS/macOS projects.
Using Homebrew (Recommended):
# 1. Install Periphery
brew install peripheryapp/periphery/periphery
# 2. Install Periphery MCP Server
brew tap zyntx-lab/tap
brew install periphery-mcp-server
# 3. Configure Claude Desktop
# Edit: ~/Library/Application Support/Claude/claude_desktop_config.json
# Add:
# "periphery": {
# "command": "/opt/homebrew/bin/periphery-mcp-server"
# }
# 4. Restart Claude Desktop (Cmd+Q then reopen)
# 5. Test it
# In Claude Desktop: "Check if Periphery is installed"From Source:
# 1. Install Periphery
brew install peripheryapp/periphery/periphery
# 2. Clone and build this server
git clone https://github.com/zyntx-lab/periphery-mcp-server.git
cd periphery-mcp-server
swift build -c release
# 3. Install to system path
sudo cp .build/release/periphery-mcp-server /usr/local/bin/
sudo chmod +x /usr/local/bin/periphery-mcp-server
# 4. Configure Claude Desktop
# Edit: ~/Library/Application Support/Claude/claude_desktop_config.json
# Add:
# "periphery": {
# "command": "/usr/local/bin/periphery-mcp-server"
# }
# 5. Restart Claude Desktop (Cmd+Q then reopen)
# 6. Test it
# In Claude Desktop: "Check if Periphery is installed"brew install peripheryapp/periphery/peripheryOr download from Periphery releases.
# Add the tap
brew tap zyntx-lab/tap
# Install the server
brew install periphery-mcp-server
# Verify installation
which periphery-mcp-server
# Should output: /opt/homebrew/bin/periphery-mcp-serverDownload the latest binary from Releases:
# Download and install
curl -L https://github.com/zyntx-lab/periphery-mcp-server/releases/download/v1.0.0/periphery-mcp-server \
-o /usr/local/bin/periphery-mcp-server
chmod +x /usr/local/bin/periphery-mcp-server
# Verify installation
which periphery-mcp-server
# Should output: /usr/local/bin/periphery-mcp-server# Clone the repository
git clone https://github.com/zyntx-lab/periphery-mcp-server.git
cd periphery-mcp-server
# Build release version
swift build -c release
# Install to system path (requires password)
sudo cp .build/release/periphery-mcp-server /usr/local/bin/
sudo chmod +x /usr/local/bin/periphery-mcp-server
# Verify installation
which periphery-mcp-server
# Should output: /usr/local/bin/periphery-mcp-serverThe server is also available on the MCP Registry. Use your MCP-compatible client to install it directly.
The config file is at: ~/Library/Application Support/Claude/claude_desktop_config.json
If you installed via Homebrew:
{
"mcpServers": {
"periphery": {
"command": "/opt/homebrew/bin/periphery-mcp-server"
}
}
}If you installed to /usr/local/bin:
{
"mcpServers": {
"periphery": {
"command": "/usr/local/bin/periphery-mcp-server"
}
}
}If you're using the build directory directly:
{
"mcpServers": {
"periphery": {
"command": "/FULL/PATH/TO/periphery-mcp-server/.build/release/periphery-mcp-server"
}
}
}If you already have other MCP servers configured:
{
"mcpServers": {
"xcode": {
"command": "node",
"args": ["/path/to/xcode-mcp-server/dist/index.js"]
},
"periphery": {
"command": "/usr/local/bin/periphery-mcp-server"
}
}
}Important: You must completely quit and restart Claude Desktop for changes to take effect.
Cmd+Q or use Claude Desktop → QuitOpen a new conversation in Claude Desktop and try:
"Check if Periphery is installed"
If configured correctly, Claude will use the check_periphery_installed tool and respond with installation status.
Before configuring Claude Desktop, you can test the server with the MCP Inspector:
# Install MCP Inspector (if not already installed)
npm install -g @modelcontextprotocol/inspector
# Test your server
npx @modelcontextprotocol/inspector /usr/local/bin/periphery-mcp-server
# Or if using build directory
npx @modelcontextprotocol/inspector /path/to/periphery-mcp-server/.build/release/periphery-mcp-serverThe Inspector will open in your browser where you can test all tools interactively.
Add to .vscode/mcp.json:
{
"mcpServers": {
"periphery": {
"type": "stdio",
"command": "/usr/local/bin/periphery-mcp-server"
}
}
}Add to .cursor/mcp.json:
{
"mcpServers": {
"periphery": {
"type": "stdio",
"command": "/usr/local/bin/periphery-mcp-server"
}
}
}check_periphery_installedVerify that Periphery CLI is installed and accessible.
Parameters: None
Example Response:
{
"installed": true,
"path": "/usr/local/bin/periphery",
"message": "Periphery is installed and ready"
}get_periphery_versionGet the installed version of Periphery.
Parameters: None
Example Response:
{
"version": "2.18.0",
"raw_output": "2.18.0"
}scan_projectRun a basic Periphery scan on a project.
Parameters:
project_path (required): Path to .xcodeproj or Package.swiftschemes (optional): Build schemes to scan (Xcode only)targets (optional): Specific targets to analyzeformat (optional): Output format: json, xcode, csv, checkstyle (default: json)Example Response:
{
"success": true,
"results": [
{
"kind": "class",
"name": "UnusedClass",
"modifiers": ["public"],
"location": "Sources/MyApp/UnusedClass.swift:10:7"
}
],
"summary": {
"total_unused": 5,
"by_kind": {"class": 2, "function": 3}
}
}scan_with_configRun Periphery scan using a YAML configuration file.
Parameters:
config_path (required): Path to .periphery.yml config fileanalyze_unused_importsFocus specifically on detecting unused imports.
Parameters:
project_path (required): Path to .xcodeproj or Package.swiftschemes (optional): Build schemes to scantargets (optional): Specific targets to analyzefind_redundant_publicIdentify public declarations that could be internal.
Parameters:
project_path (required): Path to .xcodeproj or Package.swiftschemes (optional): Build schemes to scantargets (optional): Specific targets to analyzescan_with_optionsAdvanced scanning with custom Periphery flags.
Parameters:
project_path (required): Path to .xcodeproj or Package.swiftschemes (optional): Build schemes to scantargets (optional): Specific targets to analyzeformat (optional): Output formatretain_public (optional): Retain all public declarationsretain_objc_accessible (optional): Retain @objc declarationsdisable_unused_import_analysis (optional): Disable unused import analysisindex_store_path (optional): Custom index store locationverbose (optional): Enable verbose outputOnce configured, you can have natural conversations with Claude about your code:
Check Installation:
You: "Check if Periphery is installed"
Claude: [Uses check_periphery_installed]
"Yes, Periphery is installed at /usr/local/bin/periphery
Version: 2.18.0"Scan a Project:
You: "Scan my iOS project at ~/Projects/MyApp/MyApp.xcodeproj for unused code"
Claude: [Uses scan_project]
"I found 15 unused declarations in your project:
Classes (5):
- UnusedViewController at MyApp/UnusedViewController.swift:10
- OldDataManager at MyApp/Models/OldDataManager.swift:25
...
Functions (8):
- helperFunction at Utils/Helpers.swift:42
...
Imports (2):
- UIKit in DataModel.swift:1
..."Find Redundant Public:
You: "Check which public declarations could be made internal in ~/Projects/MyFramework"
Claude: [Uses find_redundant_public]
"Found 12 public declarations that are only used internally and could be made internal:
- public class InternalHelper (only used within the framework)
- public func formatDate() (only called from within the module)
..."Analyze Unused Imports:
You: "Find unused imports in my Swift package"
Claude: [Uses analyze_unused_imports]
"Found 8 unused imports that can be safely removed:
- Foundation in Models/User.swift (not using any Foundation APIs)
- Combine in ViewModels/ProfileViewModel.swift (Combine is imported but not used)
..."Create .periphery.yml in your project:
project: MyApp.xcodeproj
schemes:
- MyApp
targets:
- MyApp
- MyAppKit
format: json
retain_public: false
retain_objc_accessible: true
verbose: falseThen use scan_with_config:
You: "Scan my project using the custom config"
Symptoms: Claude doesn't recognize Periphery tools after configuration
Solutions:
Verify config file syntax:
# Check for JSON syntax errors
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | python3 -m json.toolCheck the binary path is correct:
# Test that the binary exists and runs
/usr/local/bin/periphery-mcp-server
# Or your custom path
/path/to/.build/release/periphery-mcp-serverCompletely restart Claude Desktop:
Cmd+Q to quit (not just close the window)Check Claude Desktop logs:
# View logs for errors
tail -f ~/Library/Logs/Claude/mcp*.logIf you get "Periphery is not installed":
brew install peripheryapp/periphery/peripherywhich peripherycheck_periphery_installed tool againIf the Inspector can't connect to the server:
Verify the server runs:
# Server should wait for input, not exit immediately
/usr/local/bin/periphery-mcp-server
# Press Ctrl+C to exitCheck for errors:
# Run with verbose output
/usr/local/bin/periphery-mcp-server 2>&1 | tee server.logUse the absolute path:
npx @modelcontextprotocol/inspector $(which periphery-mcp-server)Default timeout is 5 minutes. For large projects:
scan_with_config with a focused configuration--index-store-path to reuse build artifactsPeriphery requires a compiled project with an index store:
# For Xcode projects
ls /path/to/YourProject.xcodeproj
# For Swift Packages
ls /path/to/Package.swift# Test Periphery directly
periphery scan --project /path/to/YourProject.xcodeproj --schemes YourSchemeIf you get "Permission denied" when running the server:
# Make the binary executable
chmod +x /usr/local/bin/periphery-mcp-server
# Or for build directory
chmod +x .build/release/periphery-mcp-serverThis server uses the CLI approach rather than importing Periphery as a library for maximum stability:
Contributions are welcome! Please:
MIT License - see LICENSE file for details.
This server is available through multiple channels: