Skip to content

Conversation

@pull
Copy link

@pull pull bot commented Jan 13, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

barthap and others added 3 commits January 13, 2026 07:43
# Why

#42093 (comment)

# How

- Remove expo-blob autolinking exclusion
- Add missing `AesCryptoModule` on Android

# Test Plan

- [x] Run NCL in Expo Go on Android
  - [x] Confirm Blob works
  - [x] Confirm Crypto works
- [x] Run NCL in Expo Go on iOS
  - [x] Confirm Blob works
  - [x] Confirm Crypto works
# Why

To keep parity with core RN `<Image />` which does support PSD previews.

On iOS, `UIImage` natively supports PSD / 8BIM images (it's part of the
[Image I/O
framework](https://developer.apple.com/documentation/imageio/8bim-image-properties)).
Core RN image passes through data to UIImage directly, but SDWebImage
does not.

# How

Added a passthrough SDWebImage coder, that verifies magic bytes* and
passes the data to `UIImage`.

_*There are probably more compatible formats than PSD (I guess RAW?) so
in the future we can extend this coder to support them. However, I
haven't found a simple reliable way of finding all of them. Too loose
checks might result in potentially overriding other dedicated SDWebImage
coders (= degraded perf)._

# Test Plan

- ✅ bare-expo NCL - added sample image to the formats screen

---------

Co-authored-by: Tomasz Sapeta <tsapeta@expo.dev>
# Why

CLI extensions are already supported by the CLI, where any expo package
can expose tools that will be available in the CLI "more tools" menu.

These commands are suitable as MCP tools as well, since they follow a
fixed schema for input/output.

# How

This PR implements support for exposing a command in a cli extension as
an MCP tool.

An example of a cli extension configuration for the
`expo-background-task` package (`expo-modules.config.json`)

```json
{
  ...
  "devtools": {
    "cliExtensions": {
      "description": "Expo: manage background tasks",
      "commands": [
        { "name": "fail", "title": "Show error with regular log", "environments": [ "cli", "mcp" ] },
        { "name": "fail++", "title": "Show error with error log", "environments": [ "cli", "mcp" ] },
        { "name": "fail--", "title": "Throw error", "environments": [ "cli", "mcp" ] },
        { "name": "test", "title": "Succeed with output", "environments": [ "cli", "mcp" ] },
        { "name": "test++", "title": "Succeed with error output", "environments": [ "cli", "mcp" ] },
        { "name": "json", "title": "Succeed with JSON error output", "environments": [ "cli", "mcp" ] },
        { "name": "json--", "title": "Succeed with JSON error output", "environments": [ "cli", "mcp" ] }
      ],
      "entryPoint": "testing.js"
    }
  }
}
```

The file `testing.js` should be placed at the root of the
`expo-background-task`:

```js
console.log('Starting to test expo-background-task');
setTimeout(() => {
  if (process.argv[2] === 'fail') {
    console.log('Testing expo-background-task failed');
    process.exit(1);
  } else if (process.argv[2] === 'fail++') {
    console.error('Testing expo-background-task failed');
    process.exit(1);
  } else if (process.argv[2] === 'fail--') {
    throw new Error('Testing expo-background-task failed');
  } else if (process.argv[2] === 'test') {
    console.log('Finished testing expo-background-task');
  } else if (process.argv[2] === 'params') {
    console.log('Params provided:', process.argv[3]);
  } else if (process.argv[2] === 'json') {
    console.log(
      JSON.stringify([
        { type: 'text', text: 'This is an info text', level: 'info' },
        { type: 'text', text: 'This is a warning', level: 'warning' },
        { type: 'text', text: 'This is an error', level: 'error' },
        { type: 'text', text: 'This is a link', level: 'info', url: 'https://example.com' },
        { type: 'image', url: 'https://picsum.photos/200/300', text: 'Example image' },
      ])
    );
  } else if (process.argv[2] === 'json--') {
    console.error(
      JSON.stringify([
        { type: 'text', text: 'This is an info text', level: 'info' },
        { type: 'text', text: 'This is a warning', level: 'warning' },
        { type: 'text', text: 'This is an error', level: 'error' },
        { type: 'image', url: 'https://picsum.photos/200/300', text: 'Example image' },
      ])
    );
    process.exit(1);
  } else {
    console.error('Finished testing expo-background-task');
  }
}, 1250);
```

# Test Plan

- Add the above files to `expo-background-task`
- Install the `expo-mcp` package in BareExpo
- Restart the cli with `EXPO_UNSTABLE_MCP_SERVER=1 nexpo start`
- Start a new agent chat in VSCode
- Run the command `Execute the command "json--" for the mcp tool
expo-background-task`
- Verify that the agent asks if it is ok to run the command in a message
similar to: "I'll execute the "json--" command for the
expo-background-task MCP tool."
- Press "Allow"
- Verify that the output is something like the following:



# Checklist

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [x] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).

---------

Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
@pull pull bot locked and limited conversation to collaborators Jan 13, 2026
@pull pull bot added the ⤵️ pull label Jan 13, 2026
@pull pull bot merged commit 0075c66 into code:main Jan 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants