Add build dir, prepare package

This commit is contained in:
Peter Steinberger 2025-05-23 05:57:02 +02:00
parent a7970d8de7
commit eab4e5a394
10 changed files with 5808 additions and 31 deletions

109
.gitignore vendored
View file

@ -1,2 +1,109 @@
# macOS
.DS_Store
.DS_Store
.AppleDouble
.LSOverride
Icon
._*
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Node.js / TypeScript
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.npm
.yarn-integrity
*.tsbuildinfo
.eslintcache
.node_repl_history
*.tgz
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# TypeScript
dist/
build/
*.js.map
# Logs
logs/
*.log
pids/
*.pid
*.seed
*.pid.lock
# Testing
coverage/
.nyc_output/
lib-cov/
*.lcov
.grunt
.lock-wscript
# IDEs and editors
.idea/
.vscode/
*.swp
*.swo
*~
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
*.sublime-project
# Swift / Xcode
swift-cli/
peekaboo
.build/
DerivedData/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
Packages/
Package.pins
Package.resolved
.swiftpm/
*.playground
timeline.xctimeline
playground.xcworkspace
# Temporary files
*.tmp
*.temp
.cache/
# OS generated files
Thumbs.db

62
.npmignore Normal file
View file

@ -0,0 +1,62 @@
# Source files
src/
swift-cli/Sources/
swift-cli/Tests/
# Test files
tests/
test_peekaboo.sh
jest.config.cjs
coverage/
*.test.ts
*.test.js
# Development files
.gitignore
.eslintrc*
.prettierrc*
tsconfig.json
.editorconfig
.nvmrc
# IDE and system files
.vscode/
.idea/
.DS_Store
*.swp
*.swo
*~
# Build artifacts
*.tsbuildinfo
.build/
DerivedData/
# Documentation source
docs/
*.md
!README.md
!LICENSE
# CI/CD
.github/
.gitlab-ci.yml
.travis.yml
# Temporary files
*.tmp
*.temp
.cache/
*.log
# Development dependencies
pino-pretty
# Swift build files (except the binary)
swift-cli/Package.swift
swift-cli/Package.resolved
swift-cli/.build/
swift-cli/.swiftpm/
# Keep only the compiled binary
!peekaboo

View file

@ -1,5 +1,12 @@
# Peekaboo MCP Server
![Peekaboo Banner](https://raw.githubusercontent.com/steipete/peekaboo/main/assets/banner.png)
[![npm version](https://badge.fury.io/js/%40steipete%2Fpeekaboo-mcp.svg)](https://www.npmjs.com/package/@steipete/peekaboo-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![macOS](https://img.shields.io/badge/macOS-12.0%2B-blue.svg)](https://www.apple.com/macos/)
[![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
A macOS utility exposed via Node.js MCP server for advanced screen captures, image analysis, and window management.
## 🚀 Installation & Setup
@ -29,17 +36,17 @@ xcode-select --install
```bash
# Install globally for system-wide access
npm install -g peekaboo-mcp
npm install -g @steipete/peekaboo-mcp
# Or install locally in your project
npm install peekaboo-mcp
npm install @steipete/peekaboo-mcp
```
#### Method 2: From Source
```bash
# Clone the repository
git clone https://github.com/yourusername/peekaboo.git
git clone https://github.com/steipete/peekaboo.git
cd peekaboo
# Install Node.js dependencies

33
jest.config.cjs Normal file
View file

@ -0,0 +1,33 @@
/** @type {import('jest').Config} */
module.exports = {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
extensionsToTreatAsEsm: ['.ts'],
transform: {
'^.+\.ts$': ['ts-jest', {
useESM: true,
tsconfig: {
module: 'ESNext',
target: 'es2022',
moduleResolution: 'NodeNext',
allowSyntheticDefaultImports: true,
esModuleInterop: true
}
}]
},
moduleNameMapper: {
'^(\.{1,2}/.*)\.js$': '$1',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
testMatch: [
'**/tests/unit/**/*.test.ts',
'**/tests/integration/**/*.test.ts',
],
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/index.ts'
],
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov', 'html']
};

5408
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

68
package.json Normal file
View file

@ -0,0 +1,68 @@
{
"name": "@steipete/peekaboo-mcp",
"version": "1.0.0-alpha1",
"description": "A macOS utility exposed via Node.js MCP server for advanced screen captures, image analysis, and window management",
"type": "module",
"main": "dist/index.js",
"bin": {
"peekaboo-mcp": "dist/index.js"
},
"files": [
"dist/",
"peekaboo"
],
"scripts": {
"build": "tsc",
"build:swift": "./scripts/build-swift-cli.sh",
"build:all": "npm run build:swift && npm run build",
"start": "node dist/index.js",
"prepublishOnly": "npm run build:all",
"dev": "tsc --watch",
"clean": "rm -rf dist",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:swift": "cd swift-cli && swift test",
"test:integration": "npm run build && npm run test:swift && npm test",
"test:all": "npm run test:integration",
"postinstall": "chmod +x dist/index.js 2>/dev/null || true"
},
"keywords": [
"mcp",
"screen-capture",
"macos",
"ai-analysis",
"image-analysis",
"window-management"
],
"author": "Peter Steinberger <steipete@gmail.com>",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.12.0",
"openai": "^4.0.0",
"pino": "^8.0.0",
"zod": "^3.22.0"
},
"devDependencies": {
"@types/jest": "^29.5.8",
"@types/node": "^20.10.0",
"jest": "^29.7.0",
"pino-pretty": "^10.0.0",
"ts-jest": "^29.1.1",
"typescript": "^5.3.0"
},
"engines": {
"node": ">=18.0.0"
},
"os": [
"darwin"
],
"repository": {
"type": "git",
"url": "https://github.com/steipete/peekaboo.git"
},
"bugs": {
"url": "https://github.com/steipete/peekaboo/issues"
},
"homepage": "https://github.com/steipete/peekaboo#readme"
}

18
scripts/build-swift-cli.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
set -e
echo "Building Swift CLI..."
# Change to swift-cli directory
cd "$(dirname "$0")/../swift-cli"
# Build the Swift CLI in release mode
swift build --configuration release
# Copy the binary to the root directory
cp .build/release/peekaboo ../peekaboo
# Make it executable
chmod +x ../peekaboo
echo "Swift CLI built successfully and copied to ./peekaboo"

View file

@ -0,0 +1,52 @@
#!/bin/bash
set -e # Exit immediately if a command exits with a non-zero status.
PROJECT_ROOT_REL=".." # Relative path to project root from swift-cli
PROJECT_ROOT=$(cd "$(dirname "$0")/$PROJECT_ROOT_REL" && pwd)
SWIFT_PROJECT_PATH="$PROJECT_ROOT/swift-cli"
FINAL_BINARY_NAME="peekaboo"
FINAL_BINARY_PATH="$PROJECT_ROOT/$FINAL_BINARY_NAME"
ARM64_BINARY_TEMP="$PROJECT_ROOT/${FINAL_BINARY_NAME}-arm64"
X86_64_BINARY_TEMP="$PROJECT_ROOT/${FINAL_BINARY_NAME}-x86_64"
# Swift compiler flags for size optimization
# -Osize: Optimize for binary size.
# -wmo: Whole Module Optimization, allows more aggressive optimizations.
# -Xlinker -dead_strip: Remove dead code at the linking stage.
SWIFT_OPTIMIZATION_FLAGS="-Xswiftc -Osize -Xswiftc -wmo -Xlinker -dead_strip -Xlinker -no_uuid"
echo "🧹 Cleaning previous build artifacts..."
(cd "$SWIFT_PROJECT_PATH" && swift package reset) || echo "'swift package reset' encountered an issue, attempting rm -rf..."
rm -rf "$SWIFT_PROJECT_PATH/.build"
rm -f "$ARM64_BINARY_TEMP" "$X86_64_BINARY_TEMP" "$FINAL_BINARY_PATH.tmp"
echo "🏗️ Building for arm64 (Apple Silicon)..."
(cd "$SWIFT_PROJECT_PATH" && swift build --arch arm64 -c release $SWIFT_OPTIMIZATION_FLAGS)
cp "$SWIFT_PROJECT_PATH/.build/arm64-apple-macosx/release/$FINAL_BINARY_NAME" "$ARM64_BINARY_TEMP"
echo "✅ arm64 build complete: $ARM64_BINARY_TEMP"
echo "🏗️ Building for x86_64 (Intel)..."
(cd "$SWIFT_PROJECT_PATH" && swift build --arch x86_64 -c release $SWIFT_OPTIMIZATION_FLAGS)
cp "$SWIFT_PROJECT_PATH/.build/x86_64-apple-macosx/release/$FINAL_BINARY_NAME" "$X86_64_BINARY_TEMP"
echo "✅ x86_64 build complete: $X86_64_BINARY_TEMP"
echo "🔗 Creating universal binary..."
lipo -create -output "$FINAL_BINARY_PATH.tmp" "$ARM64_BINARY_TEMP" "$X86_64_BINARY_TEMP"
echo "🤏 Stripping symbols for further size reduction..."
# -S: Remove debugging symbols
# -x: Remove non-global symbols
strip -Sx "$FINAL_BINARY_PATH.tmp"
# Replace the old binary with the new one
mv "$FINAL_BINARY_PATH.tmp" "$FINAL_BINARY_PATH"
echo "🗑️ Cleaning up temporary architecture-specific binaries..."
rm -f "$ARM64_BINARY_TEMP" "$X86_64_BINARY_TEMP"
echo "🔍 Verifying final universal binary..."
lipo -info "$FINAL_BINARY_PATH"
ls -lh "$FINAL_BINARY_PATH"
echo "🎉 Universal binary '$FINAL_BINARY_PATH' created and optimized successfully!"

View file

@ -38,34 +38,30 @@ initializeSwiftCliPath(packageRootDir);
let hasSentInitialStatus = false;
// Initialize logger
const pinoTransports = [];
const logLevel = process.env.LOG_LEVEL || 'info';
const logFile = path.join(os.tmpdir(), 'peekaboo-mcp.log');
// Default file transport
pinoTransports.push({
level: process.env.LOG_LEVEL || 'info',
target: 'pino/file',
options: {
destination: path.join(os.tmpdir(), 'peekaboo-mcp.log'),
mkdir: true // Ensure the directory exists
}
});
// Conditional console logging for development
if (process.env.PEEKABOO_MCP_CONSOLE_LOGGING === 'true') {
pinoTransports.push({
level: process.env.LOG_LEVEL || 'info', // Or a more verbose level for console e.g. 'debug'
target: 'pino-pretty',
options: {
destination: 2, // stderr
colorize: true, // pino-pretty typically defaults to true if TTY
}
});
}
const logger = pino({
name: 'peekaboo-mcp',
level: process.env.LOG_LEVEL || 'info', // Overall minimum level, transport levels can be more specific
}, pino.multistream(pinoTransports as any)); // Use pino.multistream
// Create logger with file destination by default
const logger = process.env.PEEKABOO_MCP_CONSOLE_LOGGING === 'true'
? pino({
name: 'peekaboo-mcp',
level: logLevel,
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: true,
ignore: 'pid,hostname'
}
}
})
: pino({
name: 'peekaboo-mcp',
level: logLevel
}, pino.destination({
dest: logFile,
sync: false
}));
// Tool context for handlers
const toolContext = { logger };

26
tsconfig.json Normal file
View file

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts"
]
}