Skip to content

Add first-party Apple mobile MCP integration - #251

Closed
jfrolich wants to merge 1 commit into
mainfrom
feature/apple-mobile-mcp-v2
Closed

Add first-party Apple mobile MCP integration#251
jfrolich wants to merge 1 commit into
mainfrom
feature/apple-mobile-mcp-v2

Conversation

@jfrolich

@jfrolich jfrolich commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add the maintained @tellahq/opensession-apple-mobile workspace package and stable opensession apple-mobile-mcp stdio entry point
  • keep credential-free build tools separate from user-restricted release tools, including enforced allowedUsers protection for apple-release, project-root boundaries, protected credential paths, and authenticated commit-bound release plans
  • ship the Apple mobile skill, setup guide, examples, Connections labels, and a Library catalog entry
  • document xtool's development-only distribution, Apple SDK licensing concerns on Linux, the macOS/Xcode release requirement, and the absence of App Review or public-release actions

Verification

  • bun test packages/integrations/apple-mobile packages/core/opensession-server/src/server/connections-security.test.ts packages/core/opensession-server/src/server/plugins.test.ts packages/core/opensession-server/src/server/routes/connections.test.ts (50 pass)
  • bun run typecheck
  • bun run lint
  • bun run format:check
  • bun scripts/check-module-side-effects.ts

Created by this Assistant session

@jfrolich jfrolich self-assigned this Aug 30, 2026
@open-session-os-tella-dev

open-session-os-tella-dev Bot commented Aug 30, 2026

Copy link
Copy Markdown

🤖 OS review · request changes · confidence 2/5

Safe once the release authorization and commit-binding issues below are fixed. The integration adds the intended build/release MCP surfaces, but the release allowlist can be bypassed by renaming the connection, and execution can sign or upload code that no longer matches the approved commit.
3 inline comments below.

💡 Labels: os-auto-fix — I fix these and push until CI passes · os-adversarial — deeper two-pass review · os-simplify — quality cleanup pass.
Reviewed 65009ae · GPT-5.6 Sol · earlier reviews collapse above · open session

🔁 Not merge-ready and no live session owns this branch — add the os-auto-fix label and I'll fix the findings automatically.

@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
opensession Ready Ready Preview Aug 30, 2026 12:55pm

@open-session-os-tella-dev open-session-os-tella-dev Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OS review · 65009ae


/** Credentialed first-party release tools must never become fleet-wide. */
export function requiresAllowedUsers(name: string): boolean {
return name.toLowerCase() === "apple-release";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 P1 — Release authorization is bypassed by renaming the MCP connection

The restriction identifies the credentialed capability solely by its operator-selected name. A valid POST /api/connections/mcp can add {name: "ios-release", command: "opensession", args: ["apple-mobile-mcp", "--mode", "release"], env: {...}} without allowedUsers; requiresAllowedUsers returns false, and filterMcpServers consequently exposes those credentialed release tools to every interactive session. Enforce this from the entry's command/arguments rather than its name, including the package binary entry point, and apply the same fail-closed check when resolving runtime configuration so hand-edited configs cannot bypass it.

planId: string,
confirmation: string,
) {
const { plan, config } = await loadPlan(projectDir, planId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 P1 — The approved commit is checked before, not during, the release build

loadPlan verifies the worktree commit and cleanliness once, then executePlan archives directly from that mutable worktree without another source check. For example, an IDE or concurrent session can edit Sources/App.swift after line 57 returns but before xcodebuild starts at line 93; the modified source is then signed and potentially uploaded while the result still reports the approved plan.commit. That breaks the advertised commit-bound approval guarantee. Materialize the planned commit in a private immutable checkout and build from it, rather than executing the signed commands against the caller's live worktree.

const realParent = realpathSync(parent);
if (!isWithin(projectDir, realParent))
throw new Error(`Output parent escapes project: ${input}`);
return unresolved;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 P2 — Existing output-directory symlinks escape the project boundary

The mustExist: false path validates only the output path's parent. If .build/apple-mobile already exists as a symlink to /Users/operator/protected, that parent is the in-project .build, so the helper returns the unresolved symlink and plan/output creation writes outside the allowed project. This is the exact mode used for release.artifactDirectory. Resolve and boundary-check unresolved itself when it already exists; only use the nearest-parent logic for paths that do not yet exist.

Suggested change
return unresolved;
if (existsSync(unresolved)) {
const candidate = realpathSync(unresolved);
if (!isWithin(projectDir, candidate))
throw new Error(`Output path escapes project: ${input}`);
return candidate;
}
return unresolved;

@jfrolich

Copy link
Copy Markdown
Contributor Author

Superseded by #252, which adds the requested Settings → Integrations setup flow on top of the first-party integration.

@jfrolich jfrolich closed this Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant