feat(ui): land V9 scroll intent, message identity, image cache, lifecycle sampling
Android local-first AI workspace: mobile-first local inference engines, user-configured cloud APIs, model management, and image-generation engines under user control.
MCA is an Android-native, local-first AI workspace for people who want direct control over models, inference backends, and cloud API connections.
The project currently focuses on:
llama.cpp as the compatibility route.MCA does not include model weights or API keys. Users bring their own local models, cloud endpoints, and provider credentials.
Real-device screenshots from the Android app:
| Chat | Workspace | Images | Model recommendations |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Settings | Cloud engines | Local engines | Model market |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Model picker | Local API |
|---|---|
![]() |
![]() |
The Local API screenshot is redacted before publishing.
The lightweight GIF above is generated from real-device screenshots. A higher quality MP4 is available at docs/assets/demo/mca-demo.mp4.
This repository is an active Android app workspace. The chat and model management surfaces are usable, while local image generation is still experimental. A complete model bundle is admitted on every compatible device; its first real native load and graph execution determine compatibility.
Current release status:
v0.3.1 (versionCode 10) is the current release line. It fixes Tavern
preset import and the chat-history deletion boundary, moves generation
presets to model ownership with role-card field overrides, and switches the
project license to Apache-2.0. See the
v0.3.1 release notes for verification and
limitations.v0.3.0 (versionCode 9) is the previous release. It added the local Agent
runtime/workspace, the embedded DSH workspace, the Wan 2.2 video workspace,
MediaTek NPU / Anima and Qwen-Image / GenieX routes, Room v35 with migrations,
and the pinned in-repo Wan engine archive. It remains under the MIT License.
See the v0.3.0 release notes.v0.2.4 (versionCode 8) is the previous stability release and remains on
GitHub Releases.arm64-v8a Android devices.llama.cpp compatibility for existing local models, streaming
generation, stop support, token speed labels, reasoning-content filtering,
and local benchmark support. MNN CPU is the preferred route for recommended
mobile chat bundles; GGUF remains the compatibility route for user-supplied
models and local vision projector workflows.mmproj projector is loaded. Local projector files can be bound from
the local model card, downloaded from a model repository and attached to the
currently loaded main model, or installed as a ModelScope recommendation
bundle such as MiniCPM-V 4.6 Q4 with its matching projector./search?q={query}&limit={max_results} or common q/query/max_results
parameters. Provider endpoints may be self-hosted, but readable page fetching
and direct URL reading block localhost, private LAN, link-local, and reserved
addresses by default for safety. When Jina Search is selected with a
key, MCA can fall back to Jina Reader for public pages whose direct readable
content is too weak, while keeping the same private-network guard. MCA reads multiple
direct URLs, expanded search queries, and fetched page bodies concurrently to
keep live search responsive on mobile networks. Keyword search successes use
a short in-memory local cache to avoid repeating the same provider call within
a brief window; direct URL reads are not cached and API keys are never stored
in cache entries. The search test in Settings
uses the fields currently typed into the form, so users can verify an endpoint
before saving it. The closed-loop self-test records whether MCA produced
provider results, prompt context, source-card data, quality scoring, and local
diagnostics. Settings also includes a no-key public JSON self-check filler so
users can verify the integration path before entering their own provider. MCA
labels this source as Public JSON self-check in the app because it is only a protocol
check with limited coverage, not a general web-search engine; production use
should rely on a trusted or self-hosted search service. Custom JSON endpoints may return a top-level array, an
object containing results, items, data, hits, or organic_results, or nested
variants such as data.results and response.items. It accepts common URL/title fields such as
url, link, href, html_url, story_url, canonical_url, displayLink,
formattedUrl, source.url, title, full_name, story_title, and
source.title, plus summary/body fields such as summary, excerpt, and
pageContent. When smart query expansion creates multiple
searches, MCA keeps successful sources even if one expanded query fails.
Tavily and Jina use Authorization: Bearer <key>; Brave uses
X-Subscription-Token and supports both the Web Search endpoint and the
LLM Context endpoint for AI grounding/RAG-style snippets. Public SearxNG
instances often rate-limit or disable JSON responses, so a self-hosted or
explicitly approved endpoint is recommended for reliable search.
Brave and Tavily official API root URLs are accepted and normalized to their
search paths during preflight and request execution.stable-diffusion.cpp, MNN-Diffusion, QNN/HTP,
LiteRT Qualcomm, and MediaTek NPUG/DLA bridges with progress/cancel hooks and
bundle-aware model registration. QNN, MediaTek, and experimental bundles stay
subject to real native load and graph smoke tests; device names only rank
recommendations and never hide a package. The Wan video engine ships as a
pinned, SHA-verified prebuilt archive inside this repository and is also
reproducible with build-engine.sh.stable-diffusion.cpp engine, model-asset download and verification,
Turbo LoRA, graph editing, and foreground generation. The app pins every
model asset and never bundles Wan weights in the APK.https://hf-mirror.com first, with the official Hugging Face endpoint kept
only as a fallback when the mirror cannot serve the asset.mca.assistant.card schema
and can import common nested character-card data fields into a usable
system prompt./v1/models,
/v1/chat/completions, image and video generation endpoints, capability
discovery, JSON replies, and SSE streaming.Download the latest alpha APK from GitHub Releases. Android may ask you to allow installation from your browser or file manager.
The APK does not include model weights or cloud credentials. After installing:
llama.cpp for compatibility. For local vision, use a multimodal
recommendation bundle such as MiniCPM-V 4.6 Q4, or import a compatible main
GGUF and bind its matching mmproj / projector./res/v1/web/search for normal search or /res/v1/llm/context for
grounding-oriented snippets; Brave/Tavily official root URLs are auto-filled
to the normal search paths. Direct page reading will refuse
localhost, LAN, link-local, and reserved addresses unless a development build
explicitly enables private-network fetching. See
docs/WEB_SEARCH.md for the full configuration,
trigger-mode, source-card, and troubleshooting guide.
Quick source guide: choose Tavily or Brave for the fastest API-key setup,
choose self-hosted SearxNG when privacy and control matter most, choose Jina
when page-body extraction needs help, or choose custom JSON when you operate
your own search gateway.Release APKs are signed by the project maintainer. Debug APKs are not intended for public installation.
Optional live web-search smoke tests for maintainers:
$env:MCA_LIVE_WEB_SEARCH_TEST='true'
.\gradlew :app:testDebugUnitTest --tests com.muyuchat.mca.WebSearchProviderTest.liveDirectUrlSmokeReadsRealWebPageWhenEnabled
$env:MCA_LIVE_SEARXNG_ENDPOINT='https://your-searxng.example'
.\gradlew :app:testDebugUnitTest --tests com.muyuchat.mca.WebSearchProviderTest.liveSearxngSmokeUsesConfiguredEndpointWhenProvided
$env:MCA_LIVE_BRAVE_API_KEY='<key>'
.\gradlew :app:testDebugUnitTest --tests com.muyuchat.mca.WebSearchProviderTest.liveBraveSmokeUsesConfiguredKeyWhenProvided
$env:MCA_LIVE_TAVILY_API_KEY='<key>'
.\gradlew :app:testDebugUnitTest --tests com.muyuchat.mca.WebSearchProviderTest.liveTavilySmokeUsesConfiguredKeyWhenProvided
$env:MCA_LIVE_JINA_API_KEY='<key>'
.\gradlew :app:testDebugUnitTest --tests com.muyuchat.mca.WebSearchProviderTest.liveJinaSmokeUsesConfiguredKeyWhenProvided
$env:MCA_LIVE_CUSTOM_JSON_ENDPOINT='https://hn.algolia.com/api/v1/search'
.\gradlew :app:testDebugUnitTest --tests com.muyuchat.mca.WebSearchProviderTest.liveCustomJsonClosedLoopBuildsPromptSourcesAndDiagnosticsWhenProvided
欢迎加入 MCA 交流群,获取使用教程、模型配置建议,交流本地推理体验,并参与不同设备的真机测试。
1062951314
反馈问题时建议附上 MCA 版本、手机型号、芯片、Android 版本、模型名称、运行后端和错误截图。请勿公开 API Key、访问令牌或包含个人隐私的日志。
如果 MCA 对你有帮助,欢迎扫码自愿赞助。赞助不影响任何功能。
![]() 支付宝 |
![]() 微信支付 |
也可以查看 赞助说明,或在 GitHub 点一个 Star 支持项目。
应用内「设置 → 关于 → 赞助支持」也提供同一组离线赞赏码;国内网络无法打开 GitHub 时可直接扫码。
国内访问:应用内更新检查与 APK/校验文件下载使用 gh-proxy.com 加速,失败时自动回退 GitHub 官方地址。该镜像不渲染仓库网页,赞助页和 Star 仍打开 GitHub 官方页面;国内网络下也可直接使用应用内离线赞赏码。「设置 → 关于 → 怎么点 Star?」提供三步引导。
:app - Android application, navigation, ViewModel, cloud/local providers.:core:native - llama.cpp C++/JNI bridge for GGUF-compatible local chat.:core:sd-native - stable-diffusion.cpp C++/JNI bridge for local image and
Wan video generation; prebuilt/ holds the pinned external engine archive.:core:engine - single-active-generation inference service.:core:inference-contract - shared inference/runtime contracts.:core:modelstore - MNN bundle and GGUF import, manifest, SHA-256, managed
model storage; Room v35 catalog.:core:download - ModelScope parsing, file listing, resumable downloads, and
recommendation catalogs.:core:telemetry, :core:deviceprofile, :core:tuning, :core:benchmark,
:core:advisor - metrics, device profiling, parameter plans, benchmarks, and
local recommendations.:core:agent-contract, :core:agent-runtime - Agent tool/MCP/memory runtime.:core:dsh-contract, :core:dsh-runtime, :core:dsh-platform,
:core:dsh-android-actions, :core:dsh-a11y, :core:dsh-vscreen,
:core:dsh-browser, :core:dsh-maintenance - embedded DSH runtime.:core:video-contract - Wan video request/asset contracts.:core:mediatek-native - MediaTek Neuron / NPUG / DLA adapter and Anima
pipeline contracts.:core:qwenimage21 - Qwen-Image 2.1 runtime bridge.:core:designsystem - shared Compose buttons, dialogs, icons, motion, and
accessibility primitives.:api:local - AIDL service, authenticated loopback REST server, capability
registry, and video generation API.:api:dsh-gateway - DSH OpenAI-compatible gateway.:feature:chat - chat, image generation, and media workspaces.:feature:agent, :feature:agent-workspace - Agent diagnostics and workspace.:feature:dsh-workspace - DSH workspace UI.:feature:video-workspace - Wan video workspace and graph editor.:feature:modelhub - model management UI.:feature:settings - runtime, logs, and local API UI.:benchmark - optional macrobenchmark module (-Pmca.includeBenchmark=true).:core:engine tests with UnsupportedClassVersionError).compileSdk.gradle/libs.versions.toml.The external Wan engine is checked in as a 46.6 MB compressed archive under
core/sd-native/prebuilt/. The unpackWanEngine Gradle task verifies its
SHA-256 pins and extracts the libraries into src/main/jniLibs before
packaging; no LFS or separate download step is required. Model weights are not
in this repository and are downloaded by the user after installation.
Create a local local.properties file or set ANDROID_HOME:
sdk.dir=/path/to/android-sdk
local.properties is ignored by Git.
This repository uses submodules for native inference backends:
git clone --recurse-submodules <repo-url>
cd MuYu-Chat-Agent
If you cloned without submodules:
git submodule update --init --recursive
The complete local/debug APK build contract is documented in
docs/BUILD.md. Use scripts/build.ps1 on Windows; it fixes
the debug build to arm64-v8a,x86_64, requires the QAIRT/QNN SDK, and validates
the packaged native libraries after Gradle finishes.
PowerShell:
$env:JAVA_HOME='<path-to-jdk-21>'
$env:ANDROID_HOME='<path-to-android-sdk>'
$env:MCA_QNN_SDK_ROOT='<path-to-qairt-sdk>'
.\scripts\build.ps1
Bash:
export JAVA_HOME=/path/to/jdk-21
export ANDROID_HOME=/path/to/android-sdk
export MCA_QNN_SDK_ROOT=/path/to/qairt-sdk
./gradlew :app:assembleDebug \
-Pmca.abis=arm64-v8a,x86_64 \
-PmcaQnnSdkRoot="$MCA_QNN_SDK_ROOT" \
-PmcaQnnTypedBindingsRequired=true \
--no-daemon --console=plain
The debug APK is generated under:
app/build/outputs/apk/debug/
MCA's product direction is MNN CPU first, GGUF compatible. Recommended
ModelScope chat models prefer MNN packages when a verified equivalent exists,
while user-supplied GGUF models continue to run through llama.cpp.
MNN chat models are handled as complete engine bundles: config.json,
llm_config.json, llm.mnn, llm.mnn.weight, and tokenizer.txt or
tokenizer.mtok must be present before MCA registers or loads the engine.
core/native builds libmca_native.so for the GGUF-compatible llama.cpp
path and libmca_mnn_native.so for the MNN CPU path. With third_party/llama.cpp
present, the module links the Android CPU backend for existing GGUF models. When
an official MNN Android LLM build is supplied through the Gradle/CMake MNN path
properties, the MNN runner is linked for arm64-v8a; otherwise the MNN JNI
library remains a clear stub so development builds fail loudly instead of
silently pretending to run. MNN OpenCL/GPU is not the default path.
core/sd-native builds libmca_sd_native.so against
third_party/stable-diffusion.cpp. MCA stores its Android-specific patch in:
third_party/patches/stable-diffusion.cpp-mca-android.patch
Gradle applies this patch when needed before the native CMake build.
Local image generation is model-bundle sensitive. Some newer image models need a diffusion model plus VAE/AE and text encoder/LLM components in the same engine directory. Compatibility is decided by the complete bundle contract and the first real native load/graph execution. Unknown devices remain eligible and use the generic compatible path; hardware detection only ranks packages and selects runtime tuning.
See docs/MODEL_COMPATIBILITY.md for the current compatibility matrix covering local MNN/GGUF chat, OpenAI-compatible chat, Anthropic Messages, cloud/local vision chat, OpenAI Images, DashScope Image, custom image paths, and experimental local image bundles.
MCA can expose the currently loaded local chat model through an OpenAI-compatible API for trusted clients.
Use this when you want another app, browser, desktop client, or local tool to talk to the model running on the phone.
Recommended client settings:
| Field | Value |
|---|---|
| Protocol | OpenAI-compatible |
| Same-device Base URL | http://127.0.0.1:11435/v1 |
| Same-LAN Base URL | http://<phone-lan-ip>:11435/v1 |
| API key | Generated inside MCA Settings -> Local API |
| Model | Pick from /v1/models, or enter the returned model id manually |
Supported paths:
GET /healthGET /v1/modelsPOST /v1/chat/completionsGET / for the built-in web chat page with text and image attachment input/v1/chat/completions supports standard JSON responses and stream=true
Server-Sent Events. Same-LAN access requires enabling the in-app "open port"
switch and should only be used on trusted networks.
OpenAI-style image input is accepted for local API requests when the loaded
local model is either a complete MNN multimodal bundle with visual.mnn, or a
multimodal GGUF with a matching mmproj projector, and the native runner
reports vision ready. MCA accepts image parts in Chat Completions messages
and Responses-style input arrays. Image parts may use inline
data:image/...;base64,..., readable local paths, file: URLs, or reachable
http(s) image URLs. Android content:// URIs should be converted to base64
or a readable file before sending through the local HTTP API. /v1/models also
exposes MCA extension fields such as vision_ready and vision_projector for
client-side diagnostics.
MNN multimodal vision uses the same default-open rule in the app and Local API:
on compatible ARM64 devices, image input is available whenever the complete
bundle loads and native reports visionReady=true. Per-device
visionValidated metadata is retained only for compatibility and does not
block image input; device-specific failures are handled as explicit exceptions.
The built-in web chat page can also attach browser-selected images. It sends
them as OpenAI-compatible image_url data URLs, making it a quick local vision
smoke-test surface after a multimodal local model is loaded and vision-ready.
To enable local vision in the app, load a complete MNN multimodal bundle, or
load a multimodal main GGUF and bind its matching mmproj / projector from the
local model card or the same model repository.
For cloud vision, enable "supports image input" only on cloud chat engines whose provider and model documentation confirms multimodal image input.
See PRIVACY.md and docs/PERMISSIONS.md for more detail.
MCA intentionally avoids bundling model weights. Model recommendations and download sources must respect each upstream model's license.
The repository references upstream native projects through submodules:
llama.cpp - MIT License.stable-diffusion.cpp - MIT License.MCA is early-stage and changes quickly. Please read CONTRIBUTING.md before opening issues or pull requests.
MCA is licensed under the Apache License, Version 2.0. See LICENSE and NOTICE. Versions 0.3.0 and earlier remain under the MIT License; third-party components retain their own licenses and notices.