XcodeBuildMCP is an MCP server exposing Xcode / Swift workflows as tools and resources.
Stack: TypeScript · Node.js · plugin-based auto-discovery (src/mcp/tools, src/mcp/resources).
For full details see README.md and docs/ARCHITECTURE.md.
- No hard-coded secrets, tokens or DSNs.
- All shell commands must flow through
CommandExecutorwith validated arguments (no directchild_processcalls). - Paths must be sanitised via helpers in
src/utils/validation.ts. - Sentry breadcrumbs / logs must NOT include user PII.
| Rule | Quick diff heuristic |
|---|---|
| Dependency injection only | New child_process | fs import ⇒ critical |
| Handler / Logic split | handler > 20 LOC or contains branching ⇒ critical |
| Plugin auto-registration | Manual registerTool(...) / registerResource(...) ⇒ critical |
Positive pattern skeleton:
// src/mcp/tools/foo-bar.ts
export async function fooBarLogic(
params: FooBarParams,
exec: CommandExecutor = getDefaultCommandExecutor(),
fs: FileSystemExecutor = getDefaultFileSystemExecutor(),
) {
// ...
}
export const handler = (p: FooBarParams) => fooBarLogic(p);- External-boundary rule: Use
createMockExecutor/createMockFileSystemExecutorfor command execution and filesystem side effects. - Internal mocking is allowed:
vi.mock,vi.fn,vi.spyOn, and.mock*are acceptable for internal modules/collaborators. - Each tool must have tests covering happy-path and at least one failure path.
- Avoid the
anytype unless justified with an inline comment.
docs/TOOLS.mdmust exactly mirror the structure ofsrc/mcp/tools/**(exclude__tests__and*-shared). Diff heuristic: if a PR adds/removes a tool but does not changedocs/TOOLS.md⇒ warning.- Update public docs when CLI parameters or tool names change.
| Anti-pattern | Preferred approach |
|---|---|
Complex logic in handler |
Move to *Logic function |
| Re-implementing logging | Use src/utils/logger.ts |
Direct fs / child_process usage |
Inject FileSystemExecutor / CommandExecutor |
| Chained re-exports | Export directly from source |
- External-boundary violations: confirm tests use injected executors/filesystem for external side effects.
- DI compliance: search for direct
child_process/fsimports outside approved patterns. - Docs accuracy: compare
docs/TOOLS.mdagainstsrc/mcp/tools/**. - Style: ensure ESLint and Prettier pass (
npm run lint,npm run format:check).
Happy reviewing 🚀