diff --git a/.gitignore b/.gitignore
index fda4de3..bf7f363 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,32 +31,5 @@ playground.xcworkspace
.build/
-# CocoaPods
-#
-# We recommend against adding the Pods directory to your .gitignore. However
-# you should judge for yourself, the pros and cons are mentioned at:
-# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
-#
-# Pods/
-#
-# Add this line if you want to avoid checking in source code from the Xcode workspace
-# *.xcworkspace
-
-# Carthage
-#
-# Add this line if you want to avoid checking in source code from Carthage dependencies.
-# Carthage/Checkouts
-
-Carthage/Build/
-
-# fastlane
-#
-# It is recommended to not store the screenshots in the git repo.
-# Instead, use fastlane to re-generate the screenshots whenever they are needed.
-# For more information about the recommended setup visit:
-# https://docs.fastlane.tools/best-practices/source-control/#source-control
-
-fastlane/report.xml
-fastlane/Preview.html
-fastlane/screenshots/**/*.png
-fastlane/test_output
\ No newline at end of file
+# Release artifacts
+dist/
diff --git a/App/Info.plist b/App/Info.plist
index 8a6c508..57abec8 100644
--- a/App/Info.plist
+++ b/App/Info.plist
@@ -8,10 +8,6 @@
_mcp._tcp
- NSCalendarsFullAccessUsageDescription
- ${PRODUCT_NAME} needs access to provide event information to the MCP server.
- NSRemindersFullAccessUsageDescription
- ${PRODUCT_NAME} needs access to provide reminders information to the MCP server.
SUEnableInstallerLauncherService
SUFeedURL
diff --git a/Scripts/release.sh b/Scripts/release.sh
new file mode 100755
index 0000000..07f56a1
--- /dev/null
+++ b/Scripts/release.sh
@@ -0,0 +1,471 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+APP_NAME="${APP_NAME:-iMCP}"
+APP_BUNDLE="${APP_BUNDLE:-${APP_NAME}.app}"
+KEYCHAIN_PROFILE="${KEYCHAIN_PROFILE:-}"
+VERSION="${VERSION:-}"
+BUILD_NUMBER="${BUILD_NUMBER:-}"
+SCHEME="${SCHEME:-iMCP}"
+CONFIGURATION="${CONFIGURATION:-Release}"
+DESTINATION="${DESTINATION:-platform=macOS}"
+PROJECT_FILE="${PROJECT_FILE:-${APP_NAME}.xcodeproj/project.pbxproj}"
+DIST_DIR="${DIST_DIR:-dist}"
+ARCHIVE_PATH="${ARCHIVE_PATH:-${DIST_DIR}/${APP_NAME}.xcarchive}"
+EXPORT_DIR="${EXPORT_DIR:-${DIST_DIR}/export}"
+EXPORT_OPTIONS_PLIST="${EXPORT_OPTIONS_PLIST:-${DIST_DIR}/export-options.plist}"
+TEAM_ID="${TEAM_ID:-}"
+SIGNING_CERTIFICATE="${SIGNING_CERTIFICATE:-Developer ID Application}"
+BUNDLE_ID="${BUNDLE_ID:-}"
+PROVISIONING_PROFILE_NAME="${PROVISIONING_PROFILE_NAME:-}"
+PROVISIONING_PROFILE_UUID="${PROVISIONING_PROFILE_UUID:-}"
+
+# Derived artifact names for notarization/release steps.
+NOTARY_ZIP="${DIST_DIR}/${APP_NAME}-notarize.zip"
+
+print_usage() {
+ cat <<'EOF'
+Usage: Scripts/release.sh [command]
+
+Commands:
+ all Build check, bump, archive, export, package, notarize, staple, commit/tag, release, upload (default)
+ check Quick release build check
+ bump Bump version/build numbers
+ archive Create an Xcode archive for direct distribution
+ export Export a Developer ID signed app from the archive
+ profiles List installed provisioning profiles
+ package Create the release zip from the app bundle
+ notarize Submit the app bundle for notarization
+ staple Staple the notarization ticket to the app bundle
+ commit Commit version bump and create release tag
+ release Create a GitHub release (no assets)
+ upload Upload the release asset to GitHub
+ help Show this help
+
+Environment:
+ APP_NAME App name (default: iMCP)
+ APP_BUNDLE App bundle path (default: ${APP_NAME}.app)
+ KEYCHAIN_PROFILE Required for notarize
+ VERSION Required for bumping, commit, release, and upload
+ BUILD_NUMBER Optional; used when bumping build number
+ SCHEME Xcode scheme for build check (default: iMCP)
+ CONFIGURATION Build configuration for build check (default: Release)
+ DESTINATION Build destination for build check (default: platform=macOS)
+ PROJECT_FILE Xcode project file (default: ${APP_NAME}.xcodeproj/project.pbxproj)
+ DIST_DIR Output directory for artifacts (default: dist)
+ ARCHIVE_PATH Archive path (default: dist/${APP_NAME}.xcarchive)
+ EXPORT_DIR Export path for the signed app (default: dist/export)
+ EXPORT_OPTIONS_PLIST Export options plist path (default: dist/export-options.plist)
+ TEAM_ID Team ID for Developer ID signing (optional)
+ SIGNING_CERTIFICATE Signing certificate (default: Developer ID Application)
+ BUNDLE_ID Bundle identifier for export profiles (optional)
+ PROVISIONING_PROFILE_NAME Provisioning profile name for export (optional)
+ PROVISIONING_PROFILE_UUID Provisioning profile UUID for export (optional)
+EOF
+}
+
+# If APP_BUNDLE isn't explicit, derive the built app path from Xcode settings.
+resolve_app_bundle() {
+ resolve_exported_app || true
+ if [[ -d "${APP_BUNDLE}" ]]; then
+ return 0
+ fi
+
+ local built_products_dir=""
+ local full_product_name=""
+
+ built_products_dir="$(xcodebuild -quiet -scheme "${SCHEME}" -configuration "${CONFIGURATION}" -destination "${DESTINATION}" -showBuildSettings | awk -F ' = ' '/BUILT_PRODUCTS_DIR/ {print $2; exit}')"
+ full_product_name="$(xcodebuild -quiet -scheme "${SCHEME}" -configuration "${CONFIGURATION}" -destination "${DESTINATION}" -showBuildSettings | awk -F ' = ' '/FULL_PRODUCT_NAME/ {print $2; exit}')"
+
+ if [[ -n "${built_products_dir}" && -n "${full_product_name}" ]]; then
+ local candidate="${built_products_dir}/${full_product_name}"
+ if [[ -d "${candidate}" ]]; then
+ APP_BUNDLE="${candidate}"
+ fi
+ fi
+}
+
+require_app_bundle() {
+ resolve_app_bundle
+ if [[ ! -d "${APP_BUNDLE}" ]]; then
+ echo "Missing app bundle: ${APP_BUNDLE}" >&2
+ exit 1
+ fi
+}
+
+require_keychain_profile() {
+ if [[ -z "${KEYCHAIN_PROFILE}" ]]; then
+ echo "Missing keychain profile. Set KEYCHAIN_PROFILE." >&2
+ exit 1
+ fi
+}
+
+require_version() {
+ if [[ -z "${VERSION}" ]]; then
+ echo "VERSION is required for releases." >&2
+ exit 1
+ fi
+}
+
+require_clean_tree() {
+ if ! git diff --quiet || ! git diff --cached --quiet; then
+ echo "Working tree is dirty. Commit or stash changes first." >&2
+ exit 1
+ fi
+}
+
+ensure_dist_dir() {
+ mkdir -p "${DIST_DIR}"
+}
+
+resolve_bundle_id() {
+ if [[ -n "${BUNDLE_ID}" ]]; then
+ return 0
+ fi
+ if [[ ! -f "${PROJECT_FILE}" ]]; then
+ return 1
+ fi
+ while IFS= read -r line; do
+ if [[ "${line}" == *"PRODUCT_BUNDLE_IDENTIFIER ="* && "${line}" != *"imcp-server"* ]]; then
+ BUNDLE_ID="${line#*PRODUCT_BUNDLE_IDENTIFIER = }"
+ BUNDLE_ID="${BUNDLE_ID%;}"
+ return 0
+ fi
+ done < "${PROJECT_FILE}"
+ return 1
+}
+
+list_profiles() {
+ local profiles_dir
+ local found_dir="0"
+ local profile tmp_plist name uuid team weatherkit app_id
+ local profiles_dirs=(
+ "${HOME}/Library/MobileDevice/Provisioning Profiles"
+ "${HOME}/Library/Developer/Xcode/UserData/Provisioning Profiles"
+ )
+ resolve_bundle_id || true
+
+ for profiles_dir in "${profiles_dirs[@]}"; do
+ if [[ ! -d "${profiles_dir}" ]]; then
+ continue
+ fi
+ found_dir="1"
+ for profile in "${profiles_dir}"/*.mobileprovision "${profiles_dir}"/*.provisionprofile; do
+ if [[ ! -f "${profile}" ]]; then
+ continue
+ fi
+ tmp_plist="$(mktemp)"
+ if ! security cms -D -i "${profile}" > "${tmp_plist}" 2>/dev/null; then
+ rm -f "${tmp_plist}"
+ continue
+ fi
+ name="$("/usr/libexec/PlistBuddy" -c "Print Name" "${tmp_plist}" 2>/dev/null || true)"
+ uuid="$("/usr/libexec/PlistBuddy" -c "Print UUID" "${tmp_plist}" 2>/dev/null || true)"
+ team="$("/usr/libexec/PlistBuddy" -c "Print TeamIdentifier:0" "${tmp_plist}" 2>/dev/null || true)"
+ weatherkit="$("/usr/libexec/PlistBuddy" -c "Print Entitlements:com.apple.developer.weatherkit" "${tmp_plist}" 2>/dev/null || true)"
+ app_id="$("/usr/libexec/PlistBuddy" -c "Print Entitlements:com.apple.application-identifier" "${tmp_plist}" 2>/dev/null || true)"
+ rm -f "${tmp_plist}"
+ if [[ -n "${BUNDLE_ID}" && -n "${app_id}" ]]; then
+ if [[ "${app_id}" != *".${BUNDLE_ID}" && "${app_id}" != "${BUNDLE_ID}" ]]; then
+ continue
+ fi
+ fi
+ printf '%s\n' "Name: ${name}"
+ printf '%s\n' "UUID: ${uuid}"
+ printf '%s\n' "Team: ${team}"
+ if [[ -n "${app_id}" ]]; then
+ printf '%s\n' "App ID: ${app_id}"
+ fi
+ if [[ -n "${weatherkit}" ]]; then
+ printf '%s\n' "WeatherKit: ${weatherkit}"
+ fi
+ printf '%s\n\n' "File: ${profile}"
+ done
+ done
+
+ if [[ "${found_dir}" != "1" ]]; then
+ echo "No provisioning profiles directory found at expected locations:" >&2
+ echo " ${profiles_dirs[0]}" >&2
+ echo " ${profiles_dirs[1]}" >&2
+ exit 1
+ fi
+}
+
+resolve_exported_app() {
+ local candidate
+ for candidate in "${EXPORT_DIR}"/*.app "${EXPORT_DIR}"/Applications/*.app "${EXPORT_DIR}"/Products/Applications/*.app; do
+ if [[ -d "${candidate}" ]]; then
+ APP_BUNDLE="${candidate}"
+ return 0
+ fi
+ done
+ return 1
+}
+
+release_zip() {
+ require_version
+ printf '%s/%s-%s.zip' "${DIST_DIR}" "${APP_NAME}" "${VERSION}"
+}
+
+cleanup() {
+ rm -f "${NOTARY_ZIP}"
+}
+
+trap cleanup EXIT
+
+bump_version() {
+ require_version
+ if [[ ! -f "${PROJECT_FILE}" ]]; then
+ echo "Missing project file: ${PROJECT_FILE}" >&2
+ exit 1
+ fi
+ local resolved_build_number="${BUILD_NUMBER}"
+ if [[ -z "${resolved_build_number}" ]]; then
+ # Find the current build number and increment it if not provided.
+ resolved_build_number="0"
+ while IFS= read -r line; do
+ if [[ "${line}" =~ CURRENT_PROJECT_VERSION\ =\ ([0-9]+)\; ]]; then
+ resolved_build_number="${BASH_REMATCH[1]}"
+ break
+ fi
+ done < "${PROJECT_FILE}"
+ resolved_build_number="$((resolved_build_number + 1))"
+ fi
+
+ echo "Setting MARKETING_VERSION to ${VERSION}"
+ echo "Setting CURRENT_PROJECT_VERSION to ${resolved_build_number}"
+ # Replace both version fields in the project file without agvtool.
+ local tmp_file
+ tmp_file="$(mktemp)"
+ while IFS= read -r line; do
+ if [[ "${line}" == *"MARKETING_VERSION ="* ]]; then
+ printf '%s\n' "${line%%MARKETING_VERSION = *}MARKETING_VERSION = ${VERSION};" >> "${tmp_file}"
+ elif [[ "${line}" == *"CURRENT_PROJECT_VERSION ="* ]]; then
+ printf '%s\n' "${line%%CURRENT_PROJECT_VERSION = *}CURRENT_PROJECT_VERSION = ${resolved_build_number};" >> "${tmp_file}"
+ else
+ printf '%s\n' "${line}" >> "${tmp_file}"
+ fi
+ done < "${PROJECT_FILE}"
+ mv "${tmp_file}" "${PROJECT_FILE}"
+}
+
+build_zip() {
+ local source_bundle="$1"
+ local output_zip="$2"
+ ensure_dist_dir
+ echo "Creating zip: ${output_zip}"
+ ditto -c -k --keepParent "${source_bundle}" "${output_zip}"
+}
+
+build_check() {
+ echo "Checking release build (scheme: ${SCHEME}, configuration: ${CONFIGURATION})"
+ xcodebuild -quiet -scheme "${SCHEME}" -configuration "${CONFIGURATION}" -destination "${DESTINATION}" build
+ resolve_app_bundle
+}
+
+archive_app() {
+ ensure_dist_dir
+ echo "Archiving app to ${ARCHIVE_PATH}"
+ xcodebuild -quiet -scheme "${SCHEME}" -configuration "${CONFIGURATION}" -destination "generic/platform=macOS" archive -archivePath "${ARCHIVE_PATH}"
+}
+
+write_export_options() {
+ ensure_dist_dir
+ local tmp_file
+ tmp_file="$(mktemp)"
+ cat > "${tmp_file}" <
+
+
+
+ method
+ developer-id
+ signingStyle
+ manual
+ signingCertificate
+ ${SIGNING_CERTIFICATE}
+EOF
+ local profile_value=""
+ if [[ -n "${PROVISIONING_PROFILE_UUID}" ]]; then
+ profile_value="${PROVISIONING_PROFILE_UUID}"
+ elif [[ -n "${PROVISIONING_PROFILE_NAME}" ]]; then
+ profile_value="${PROVISIONING_PROFILE_NAME}"
+ fi
+ if [[ -n "${profile_value}" ]]; then
+ if ! resolve_bundle_id; then
+ echo "BUNDLE_ID is required when using provisioning profiles." >&2
+ exit 1
+ fi
+ cat >> "${tmp_file}" <provisioningProfiles
+
+ ${BUNDLE_ID}
+ ${profile_value}
+
+EOF
+ fi
+ if [[ -n "${TEAM_ID}" ]]; then
+ cat >> "${tmp_file}" <teamID
+ ${TEAM_ID}
+EOF
+ fi
+ cat >> "${tmp_file}" <<'EOF'
+
+
+EOF
+ mv "${tmp_file}" "${EXPORT_OPTIONS_PLIST}"
+}
+
+export_app() {
+ write_export_options
+ echo "Exporting Developer ID app to ${EXPORT_DIR}"
+ xcodebuild -quiet -exportArchive -archivePath "${ARCHIVE_PATH}" -exportPath "${EXPORT_DIR}" -exportOptionsPlist "${EXPORT_OPTIONS_PLIST}"
+ resolve_app_bundle
+}
+
+notarize() {
+ require_app_bundle
+ require_keychain_profile
+ ensure_dist_dir
+ echo "Zipping for notarization: ${NOTARY_ZIP}"
+ ditto -c -k --keepParent "${APP_BUNDLE}" "${NOTARY_ZIP}"
+ echo "Submitting to notarization"
+ xcrun notarytool submit "${NOTARY_ZIP}" --wait --keychain-profile="${KEYCHAIN_PROFILE}"
+}
+
+staple() {
+ require_app_bundle
+ echo "Stapling notarization ticket"
+ xcrun stapler staple "${APP_BUNDLE}"
+}
+
+package_release() {
+ require_app_bundle
+ local release_zip_path
+ release_zip_path="$(release_zip)"
+ build_zip "${APP_BUNDLE}" "${release_zip_path}"
+ shasum -a 256 "${release_zip_path}" > "${release_zip_path}.sha256"
+ echo "Done: ${release_zip_path}"
+}
+
+validate_staple() {
+ require_app_bundle
+ echo "Validating stapled ticket"
+ xcrun stapler validate "${APP_BUNDLE}"
+}
+
+commit_and_tag() {
+ require_version
+ local release_zip_path
+ release_zip_path="$(release_zip)"
+ if [[ ! -f "${release_zip_path}" ]]; then
+ echo "Missing release asset: ${release_zip_path}" >&2
+ exit 1
+ fi
+ # Ensure the stapled build exists before tagging a release.
+ validate_staple
+ if git rev-parse --verify "refs/tags/${VERSION}" >/dev/null 2>&1; then
+ echo "Tag already exists: ${VERSION}" >&2
+ exit 1
+ fi
+ echo "Committing version bump"
+ git add -A
+ if git diff --cached --quiet; then
+ echo "No changes to commit."
+ else
+ git commit -m "Release ${VERSION}"
+ fi
+ echo "Tagging release ${VERSION}"
+ git tag -a "${VERSION}" -m "Release ${VERSION}"
+}
+
+create_release() {
+ require_version
+ echo "Creating GitHub release ${VERSION}"
+ gh release create "${VERSION}" --generate-notes
+}
+
+upload_asset() {
+ require_version
+ local release_zip_path
+ release_zip_path="$(release_zip)"
+ if [[ ! -f "${release_zip_path}" ]]; then
+ echo "Missing release asset: ${release_zip_path}" >&2
+ exit 1
+ fi
+ echo "Uploading release asset ${release_zip_path}"
+ gh release upload "${VERSION}" "${release_zip_path}" --clobber
+ gh release view --web "${VERSION}"
+}
+
+all() {
+ # Full release flow with strict gating at each step.
+ build_check
+ require_clean_tree
+ bump_version
+ archive_app
+ export_app
+ package_release
+ notarize
+ staple
+ commit_and_tag
+ create_release
+ upload_asset
+}
+
+release() {
+ create_release
+}
+
+upload() {
+ upload_asset
+}
+
+COMMAND="${1:-all}"
+case "${COMMAND}" in
+ all)
+ all
+ ;;
+ check)
+ build_check
+ ;;
+ bump)
+ bump_version
+ ;;
+ archive)
+ archive_app
+ ;;
+ export)
+ export_app
+ ;;
+ profiles)
+ list_profiles
+ ;;
+ package)
+ package_release
+ ;;
+ notarize)
+ notarize
+ ;;
+ staple)
+ staple
+ ;;
+ commit)
+ commit_and_tag
+ ;;
+ release)
+ release
+ ;;
+ upload)
+ upload
+ ;;
+ help|-h|--help)
+ print_usage
+ ;;
+ *)
+ echo "Unknown command: ${COMMAND}" >&2
+ print_usage >&2
+ exit 1
+ ;;
+esac
diff --git a/iMCP.xcodeproj/project.pbxproj b/iMCP.xcodeproj/project.pbxproj
index 4d877ed..56b8a8e 100644
--- a/iMCP.xcodeproj/project.pbxproj
+++ b/iMCP.xcodeproj/project.pbxproj
@@ -396,7 +396,7 @@
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 8;
+ CURRENT_PROJECT_VERSION = 9;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
ENABLE_APP_SANDBOX = YES;
@@ -415,13 +415,15 @@
INFOPLIST_KEY_CFBundleDisplayName = iMCP;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
INFOPLIST_KEY_LSUIElement = YES;
- INFOPLIST_KEY_NSCameraUsageDescription = "${PRODUCT_NAME} needs access to the camera to take pictures for the MCP server.";
- INFOPLIST_KEY_NSContactsUsageDescription = "${PRODUCT_NAME} needs access to provide contact information to the MCP server.";
- INFOPLIST_KEY_NSHumanReadableCopyright = "© 2025 Loopwork Limited. All rights reserved.";
- INFOPLIST_KEY_NSLocalNetworkUsageDescription = "${PRODUCT_NAME} uses the local network to connect to the MCP server.";
- INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "${PRODUCT_NAME} needs access to provide location information to the MCP server.";
- INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "${PRODUCT_NAME} needs access to provide location information to the MCP server.";
- INFOPLIST_KEY_NSMicrophoneUsageDescription = "${PRODUCT_NAME} needs access to the microphone to record audio for the MCP server.";
+ INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "iMCP needs access to provide event information to the MCP server.";
+ INFOPLIST_KEY_NSCameraUsageDescription = "iMCP needs access to the camera to take pictures for the MCP server.";
+ INFOPLIST_KEY_NSContactsUsageDescription = "iMCP needs access to provide contact information to the MCP server.";
+ INFOPLIST_KEY_NSHumanReadableCopyright = "© 2026 dododo, LLC. All rights reserved.";
+ INFOPLIST_KEY_NSLocalNetworkUsageDescription = "iMCP uses the local network to connect to the MCP server.";
+ INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "iMCP needs access to provide location information to the MCP server.";
+ INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "iMCP needs access to provide location information to the MCP server.";
+ INFOPLIST_KEY_NSMicrophoneUsageDescription = "iMCP needs access to the microphone to record audio for the MCP server.";
+ INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "iMCP needs access to provide reminders information to the MCP server.";
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
@@ -436,8 +438,8 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 15.1;
- MARKETING_VERSION = 1.3.0;
- PRODUCT_BUNDLE_IDENTIFIER = com.loopwork.iMCP;
+ MARKETING_VERSION = 1.3.1;
+ PRODUCT_BUNDLE_IDENTIFIER = co.dododo.iMCP;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = auto;
@@ -458,9 +460,9 @@
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
+ CURRENT_PROJECT_VERSION = 9;
DEAD_CODE_STRIPPING = YES;
- DEVELOPMENT_TEAM = "";
+ DEVELOPMENT_TEAM = TTY35UM57S;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
@@ -481,13 +483,15 @@
INFOPLIST_KEY_CFBundleDisplayName = iMCP;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
INFOPLIST_KEY_LSUIElement = YES;
- INFOPLIST_KEY_NSCameraUsageDescription = "${PRODUCT_NAME} needs access to the camera to take pictures for the MCP server.";
- INFOPLIST_KEY_NSContactsUsageDescription = "${PRODUCT_NAME} needs access to provide contact information to the MCP server.";
- INFOPLIST_KEY_NSHumanReadableCopyright = "© 2025 Loopwork Limited. All rights reserved.";
- INFOPLIST_KEY_NSLocalNetworkUsageDescription = "${PRODUCT_NAME} uses the local network to connect to the MCP server.";
- INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "${PRODUCT_NAME} needs access to provide location information to the MCP server.";
- INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "${PRODUCT_NAME} needs access to provide location information to the MCP server.";
- INFOPLIST_KEY_NSMicrophoneUsageDescription = "${PRODUCT_NAME} needs access to the microphone to record audio for the MCP server.";
+ INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "iMCP needs access to provide event information to the MCP server.";
+ INFOPLIST_KEY_NSCameraUsageDescription = "iMCP needs access to the camera to take pictures for the MCP server.";
+ INFOPLIST_KEY_NSContactsUsageDescription = "iMCP needs access to provide contact information to the MCP server.";
+ INFOPLIST_KEY_NSHumanReadableCopyright = "© 2026 dododo, LLC. All rights reserved.";
+ INFOPLIST_KEY_NSLocalNetworkUsageDescription = "iMCP uses the local network to connect to the MCP server.";
+ INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "iMCP needs access to provide location information to the MCP server.";
+ INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "iMCP needs access to provide location information to the MCP server.";
+ INFOPLIST_KEY_NSMicrophoneUsageDescription = "iMCP needs access to the microphone to record audio for the MCP server.";
+ INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "iMCP needs access to provide reminders information to the MCP server.";
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
@@ -502,11 +506,10 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 15.1;
- MARKETING_VERSION = 1.3.0;
- PRODUCT_BUNDLE_IDENTIFIER = com.loopwork.iMCP;
+ MARKETING_VERSION = 1.3.1;
+ PRODUCT_BUNDLE_IDENTIFIER = co.dododo.iMCP;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
- "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "iMCP Developer Build Provision Profile";
SDKROOT = auto;
SUPPORTED_PLATFORMS = macosx;
SUPPORTS_MACCATALYST = NO;