Uc 是一个 AI 原生 的基于 .NET 10 + WebView2的Windows 桌面浏览器,把 AI 嵌入浏览器的每一个角落。它不是"加了个 AI 聊天的浏览器"——而是把 AI 渗透到浏览体验的每个环节:你浏览、搜索、阅读、翻译、自动化的每一种方式,都有 AI 在背后深度参与。
🤖 AI 能力
AI 聊天侧面板
Ctrl+Shift+A 随时呼出。侧面板打开时,AI 能感知你当前正在看的页面——你可以直接问"这页讲了什么"、"帮我翻译成英文"、"这段代码有什么问题"。
支持多模型切换,一次配置多个提供商,随时换着用:OpenAI、Anthropic、DeepSeek、Google Gemini、OpenRouter、GitHub Models等。
对话历史本地保存修改删除等,支持搜索、重命名、继续对话。API 密钥使用 Windows DPAPI 加密存储,不会明文泄露。
🧠 MCP(模型上下文协议)
Uc 是 首批在浏览器层面原生支持 MCP 协议 的浏览器之一。
通过 MCP,AI 不再只能"说话"——它能调用你本地的工具:读文件、操作命令行、查询数据库、访问浏览器等等——真正帮你完成操作。你在聊天里说一句"帮我查一下这个项目的 Test 覆盖率",AI 就能自己去读代码、跑测试、把结果呈现给你。
- 支持 stdio 传输,可配置任意多个 MCP 服务器
- 自动连接、断线重试、状态管理
- 内置文件系统 MCP 服务
- 管理页面实时查看每个服务器的连接状态和可用工具
- 第三方 MCP 服务器即插即用
🛠️ AI 技能系统(Skills)
技能是告诉 AI "遇到这类任务该怎么做" 的能力模块,用 Markdown + YAML 定义,放在指定目录即可加载。
内置技能:
| 技能 |
一句话 |
explore |
浏览代码库或页面,帮你找到需要的信息 |
review |
审查代码或文本,发现问题和改进点 |
summarize |
总结当前页面或选中文本的核心要点 |
translate |
自动检测语言,中英互译 |
explain |
用简单语言解释选中的复杂内容 |
在聊天中输入 /技能名 即可调用。你也可以自己写技能——管理页面支持创建、编辑、启用、禁用,满足特定工作流。
🖱️ AI 右键菜单
在任何页面上选中文字,右键即用:
- "Ask AI about..." — 把选中内容作为问题发送给 AI
- "Explain..." — 用大白话解释选中的内容
- "Translate..." — 自动检测并翻译
不用离开当前页面,不用复制粘贴,选中即问。
🔍 AI 搜索建议
地址栏输入时,AI 会根据你的浏览历史和上下文生成搜索建议——不是简单的关键词补全,而是真正理解你可能的搜索意图。
📖 AI 阅读总结
阅读模式(Reader Mode)基于 Mozilla Readability 提取文章正文,一键让 AI 生成中文摘要。看长文时不必读完,AI 帮你提炼核心要点。适合资讯阅读、论文浏览、文档速览。
🖥️ 不止是 AI
AI 是核心,但浏览器该有的它都有。
原生广告拦截 — 网络级别的广告和追踪器拦截。内置数千条规则,每个站点可单独开关,实时显示拦截数量。
Chrome 扩展支持 — 直接从 Chrome Web Store 安装扩展。弹窗、侧面板、工具栏图标、徽章——该有的都有,和 Chrome 一致。
全暗色主题 + 无痕模式 — 整站暗色完美,遇到浅色网站可强制变暗。无痕窗口使用完全隔离的临时 Profile,关闭即焚。
标签页内存管理 — 闲置标签页自动经历"冻结 → 挂起 → 回收"三级降级,释放大量内存。点回来时瞬间恢复。播放音频的标签页不会被冻结,也可以手动标记保持唤醒。
数据导入 — 从 Chrome、Brave、Edge、Vivaldi、Opera 等 Chromium 浏览器一键导入书签、密码、Cookie、历史记录。迁移无痛。
日常好用的细节 — 画中画、截图、页面翻译、搜索关键字快捷跳转、恢复关闭标签页、下载管理器、多窗口支持、标签拖拽分离成独立窗口、会话恢复——都不少。
🔑 配置 AI
- 打开设置(
Ctrl+,)
- 进入 AI 配置页面
- 选择提供商,填入 API 密钥
API 密钥使用 Windows DPAPI 加密,存储在本地 SQLite 数据库中。对话历史、模型偏好、MCP 配置同样持久化保存。
自定义模型
Uc 支持兼容 OpenAI API 格式的任意接口。在设置中填入自定义 Endpoint 和模型名称即可接入私有部署或兼容服务。
🔌 MCP(模型上下文协议)
MCP 让 AI 能够调用本地工具。配置方式:
- 打开 MCP 管理页面(
uc://mcp)
- 添加 MCP 服务器配置(名称、命令、参数)
- 服务器自动连接,状态实时显示
- AI 聊天时自动调用可用工具
内置 MCP 服务器:
示例配置:
{
"McpServers": [
{
"Name": "fs",
"Type": "stdio",
"Command": "npx",
"Args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:\\"
],
"AutoStart": true
},
{
"Name": "playwright",
"Type": "stdio",
"Command": "npx",
"Args": [
"-y",
"@playwright/mcp@latest"
],
"AutoStart": true
}
]
}
⌨️ 快捷键
| 快捷键 |
功能 |
Ctrl+Shift+A |
打开/关闭 AI 聊天侧面板 |
Ctrl+, |
打开设置 |
Ctrl+L / Alt+D |
定位到地址栏 |
Ctrl+T |
新建标签页 |
Ctrl+W |
关闭标签页 |
Ctrl+Shift+T |
恢复关闭的标签页 |
Ctrl+Tab |
下一个标签页 |
Ctrl+Shift+Tab |
上一个标签页 |
Ctrl+R / F5 |
刷新 |
F11 |
全屏 |
Ctrl+Shift+N |
新建无痕窗口 |
Ctrl+J |
下载管理 |
Ctrl+H |
历史记录 |
Ctrl+F |
页面内查找 |
Ctrl++ / Ctrl+- |
放大 / 缩小 |
Ctrl+0 |
重置缩放 |
对话管理 (AiChat.cs)
架构:WebView2 双工通信
AI Chat 面板是 WebView2 中加载的本地 HTML 页面,通过 PostWebMessageAsString / WebMessageReceived 与 C# 后端双向通信。
public class AiChat
{
private const string AiChatHost = "uc.ai";
private const string AiChatUrl = "https://uc.ai/ai-chat.html";
private readonly WebView2 _view;
private readonly AppSettings _settings;
private readonly List<AiChatMessage> _messages = new();
private CancellationTokenSource? _streamCts;
private string? _currentSessionId;
private string _currentSessionModel = "";
}
WebMessage 协议 — 20+ 消息类型
OnWebMessageReceived 中按 type 分发:
| type |
方向 |
功能 |
send |
FE→BE |
发送用户消息 |
new |
FE→BE |
新建对话 |
stop |
FE→BE |
中止流式响应 |
edit |
FE→BE |
编辑某轮消息后重跑 |
deleteMessages |
FE→BE |
批量删除消息 |
switchModel |
FE→BE |
切换模型/供应商 |
getModels |
FE→BE |
获取当前模型配置 |
context |
FE→BE |
上报当前浏览页面上下文 |
command |
FE→BE |
触发 MainWindow 快捷键 |
getSkills |
FE→BE |
获取技能列表 |
runSkill |
FE→BE |
运行技能 |
listConversations |
FE→BE |
列出对话列表 |
loadConversation |
FE→BE |
加载历史对话 |
deleteConversation |
FE→BE |
删除对话(移至回收站) |
restoreConversation |
FE→BE |
恢复对话 |
purgeConversation |
FE→BE |
永久删除 |
purgeAll / deleteAllConversations |
FE→BE |
批量操作 |
renameConversation |
FE→BE |
重命名 |
searchConversations |
FE→BE |
全文搜索 |
多轮工具调用循环 — SendMessagesAsync
private async Task SendMessagesAsync(CancellationToken ct)
{
const int maxToolRounds = 5;
for (int round = 0; round < maxToolRounds; round++)
{
var systemPrompt = BuildSystemPrompt();
// 等待 MCP 自动连接(最多 5s 轮询)
if (round == 0)
await WaitForMcpAsync(mcpHost, ct);
var tools = GetMcpToolDefinitions();
await AiService.ChatStreamFullAsync(_messages, tools, chunk =>
{
switch (chunk.Type)
{
case AiStreamChunkType.Text: // → "delta"
case AiStreamChunkType.Reasoning: // → "reasoning"
case AiStreamChunkType.ToolCalls: // 按 index 合并跨 delta 的工具调用
case AiStreamChunkType.Error: // → "error"
}
}, systemPrompt, ct);
// 无工具调用 → 结束
if (!gotToolCalls) break;
// 有工具调用 → 执行并追加结果到 _messages,进入下一轮
var results = await ExecuteToolsAsync(toolCalls);
// 结果以 role="tool" 加入对话,继续循环
}
}
LLM 返回工具调用 → 执行 → 结果送回 LLM → 再次输出,最多 5 轮。
快捷键快捷功能
public async Task RunExplainAsync(string selectedText) { ... }
public async Task RunTranslateAsync(string selectedText) { ... }
public async Task RunSummarizeAsync(string selectedText) { ... }
public async Task RunCustomPromptAsync(string prompt, string selectedText) { ... }
MCP 工具集成
McpClient — stdio 传输层 (Features/McpClient.cs)
每个 MCP 服务器是一个独立子进程,通过 stdin/stdout JSON-RPC 通信。使用 Windows Job Object 保证进程树终止。
public class McpToolInfo
{
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public JsonElement? Schema { get; set; }
}
关键机制:
- 子进程通过
Process + Job Object (JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE) 管理生命周期
- 超时控制:
_callSem 信号量 + CancellationToken + 超时后 Kill 进程
- 自动重连:
_autoRestart 标志,崩溃后自动重启
MCP 工具定义注入
private List<AiToolDef>? GetMcpToolDefinitions()
{
var connected = mcpHost.GetServerViews()
.Where(v => v.Status == "connected" && v.ToolList.Count > 0);
foreach (var sv in connected)
foreach (var t in sv.ToolList)
tools.Add(new AiToolDef
{
Name = $"{sv.Name}__{t.Name}", // server__tool 命名空间
Description = t.Description,
Parameters = t.Schema?.ToString() ?? @"{""type"":""object""}",
});
return tools;
}
工具名以 {server}__{tool} 格式传递给 LLM,执行时拆分回 server 和 tool 名:
var parts = call.Name.Split("__", 2);
var server = parts[0]; var tool = parts[1];
var client = mcpHost.GetClient(server);
var result = await client.CallToolAsync(tool, args);
System Prompt 构建
private string BuildSystemPrompt()
{
var prompt = "You are a helpful AI assistant integrated into the Uc browser...";
// 1. 当前页面上下文
if (!string.IsNullOrEmpty(CurrentPageContext))
prompt += $"\n\nThe user is currently viewing: {CurrentPageContext}";
// 2. 可用 Skills(通过 /skillname 调用)
prompt += "\n## Available Skills";
foreach (var s in allSkills)
prompt += $"\n- **{s.Name}**: {s.Description}";
// 3. 可用 MCP 工具(通过 function calling 调用)
prompt += "\n## Available Tools (via function calling)";
foreach (var t in connectedTools)
prompt += $"\n- `{sv.Name}__{t.Name}`: {t.Description}";
return prompt;
}
对话持久化 (ConversationSession.cs / ConversationStore.cs)
数据结构
public class ConversationSession
{
public string Id { get; set; } = "";
public string? Title { get; set; }
public string Model { get; set; } = "";
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public int TurnCount { get; set; }
public string? Preview { get; set; }
public List<AiChatMessage> Messages { get; set; } = new();
}
public class ConversationSummary
{
public string Id { get; set; } = "";
public string? Title { get; set; }
public string Model { get; set; } = "";
public long CreatedAt { get; set; }
public long UpdatedAt { get; set; }
public int Turns { get; set; }
public string? Preview { get; set; }
public bool IsTrashed { get; set; }
}
存储结构
%APPDATA%\Uc\conversations\
├── conv_abc123.json # 活跃对话
├── conv_def456.json
├── .titles.json # 用户自定义标题(侧边文件)
└── .trash\ # 回收站
└── conv_ghi789.json
SaveAsync 自动更新 Title(取首条 user 消息前 60 字)、Preview(末条 assistant 回复前 120 字)、TurnCount
ReadSummaryAsync 使用 Utf8JsonReader 流式读取,避免全量反序列化
SearchAsync 先匹配元数据,再对未匹配的对话全文搜索消息内容(限 64KB 以内文件)
设置层 — AI 相关配置 (AppSettings.cs)
public class AppSettings
{
// 主开关
public bool AiEnabled { get; set; }
// 所有供应商
public List<AiProviderConfig> AiProviders { get; set; } = new();
// 当前激活的供应商和模型
public string AiActiveProvider { get; set; } = "";
public string AiActiveModel { get; set; } = "";
// Skills & MCP
public List<string> DisabledSkills { get; set; } = new();
public List<string> SkillPaths { get; set; } = new();
public List<McpServerConfig> McpServers { get; set; } = new();
// 便捷方法
public AiProviderConfig? GetActiveProvider() =>
string.IsNullOrEmpty(AiActiveProvider)
? AiProviders.FirstOrDefault()
: GetProvider(AiActiveProvider);
public void SetAiApiKey(string key, string? providerName = null) { ... }
public string? GetAiApiKey(string? providerName = null) { ... }
}
支持从旧版单供应商 JSON 自动迁移到新版多供应商格式。
完整架构图
┌─────────────────────────────────────────────────────┐
│ AiChat (WebView2) │
│ https://uc.ai/ai-chat.html ←→ PostWebMessageAsString │
│ (20+ 消息类型的 JSON 协议) │
└────────────────────┬────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────┐
│ AiService (静态入口) │
│ ChatAsync / ChatStreamFullAsync / SummarizeAsync │
│ ExplainAsync / SuggestAsync / FetchModelsAsync │
│ ResolveProvider (缓存) / InvalidateCache │
└────────────────────┬────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────┐
│ AiProviderResolver.DetectKind() │
│ ApiKind → KnownProviders 匹配 → 域名 → 默认 OpenAI │
└───────┬──────────────────────────┬──────────────────┘
│ │
┌───────▼──────────┐ ┌─────────▼──────────┐
│ OpenAiProvider │ │ AnthropicProvider │
│ /chat/completions│ │ /v1/messages │
│ Bearer Token │ │ x-api-key │
│ 支持工具调用 │ │ 不支持工具调用 │
└───────┬──────────┘ └─────────┬──────────┘
│ │
┌───────▼────────────────────────▼──────────┐
│ AiRetry (3次, 指数退避+抖动) │
│ SseStream (30s 看门狗超时) │
└───────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────┐
│ MCP 工具生态 │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ McpHost │ │ McpClient (stdio) │ │
│ │ 管理多 Server │ │ JSON-RPC 2.0 │ │
│ │ 自动重连 │ │ JobObject 生命周期 │ │
│ └────────┬────────┘ └──────────┬──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ GetMcpToolDefinitions() ExecuteToolsAsync│
│ → AiToolDef[{Name,Schema}] → 执行结果 │
└───────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────┐
│ ConversationStore │
│ JSON 文件存储 / 回收站 / 全文搜索 / 侧边标题 │
│ %APPDATA%\Uc\conversations\ │
└───────────────────────────────────────────────┘
关键设计要点
- 双重流式入口:
ChatStreamAsync(简化版,仅 Text)和 ChatStreamFullAsync(完整版,含 reasoning / tool_calls / usage / error),前者向后兼容。
- Provider 缓存:
AiService.ResolveProvider() 按 provider|model 缓存 IAiProvider 实例,InvalidateCache() 在设置变更后调用。
- 密钥安全:DPAPI (
ProtectedData) 加密存储,绑定 Windows 当前用户。
- SSE 空闲保护:StreamReader 侧 Timer 看门狗,30s 无新行则
Stream.Close() 触发超时异常。
- 重试策略:仅
408 / 429 / 5xx 和 IOException 可重试,OperationCanceledException 不重试。
- 多轮工具调用:
SendMessagesAsync 最多 5 轮循环:LLM 输出 → 解析工具调用 → MCP 执行 → 结果回填 → 继续请求,类似 AutoGPT 的 ReAct 模式。
- MCP 命名空间:工具名以
{server}__{tool} 格式传递,确保跨服务唯一性。
- WebMessage 协议:20+ 种消息类型覆盖完整的对话 CRUD、模型切换、技能/MCP 工具管理。
- 对话存储优化:列表使用
Utf8JsonReader 流式读取避免全量反序列化;全文搜索限 64KB 以内文件。
- 双 prompt 注入:系统提示词包含 Skills(
/skillname 文本命令)和 MCP 工具(function calling 自动调用)两套独立的扩展机制。