Skip to content
217 changes: 217 additions & 0 deletions app/lib/pages/settings/developer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:omi/backend/http/api/conversations.dart';
import 'package:omi/backend/preferences.dart';
import 'package:omi/backend/schema/conversation.dart';
import 'package:omi/env/env.dart';
import 'package:omi/pages/settings/widgets/create_mcp_api_key_dialog.dart';
import 'package:omi/pages/settings/widgets/mcp_api_key_list_item.dart';
import 'package:omi/pages/settings/widgets/developer_api_keys_section.dart';
Expand Down Expand Up @@ -260,6 +261,51 @@ class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
);
}

Widget _buildMcpConfigRow(String label, String value) {
return GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(text: value));
AppSnackbar.showSnackbar('$label copied');
},
child: Row(
children: [
Expanded(
flex: 2,
child: Text(
label,
style: TextStyle(color: Colors.grey.shade500, fontSize: 13),
),
),
Expanded(
flex: 3,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
decoration: BoxDecoration(
color: const Color(0xFF0D0D0D),
borderRadius: BorderRadius.circular(6),
),
child: Row(
children: [
Expanded(
child: Text(
value,
style: const TextStyle(
color: Colors.white,
fontFamily: 'Ubuntu Mono',
fontSize: 13,
),
),
),
FaIcon(FontAwesomeIcons.copy, color: Colors.grey.shade600, size: 11),
],
),
),
),
],
),
);
}

Widget _buildApiKeysList(BuildContext context) {
return Consumer<McpProvider>(
builder: (context, provider, child) {
Expand Down Expand Up @@ -973,6 +1019,177 @@ class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
),
),

const SizedBox(height: 24),

// MCP Server Section
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFF1C1C1E),
borderRadius: BorderRadius.circular(14),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: const Color(0xFF2A2A2E),
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: FaIcon(FontAwesomeIcons.server, color: Colors.grey.shade400, size: 16),
),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'MCP Server',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 2),
Text(
'Connect AI assistants to your data',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 13,
),
),
],
),
),
],
),
const SizedBox(height: 20),

// Server URL
Text(
'Server URL',
style: TextStyle(color: Colors.grey.shade400, fontSize: 12, fontWeight: FontWeight.w600),
),
const SizedBox(height: 8),
Builder(
builder: (context) {
final mcpUrl = '${Env.apiBaseUrl}v1/mcp/sse';
return GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(text: mcpUrl));
AppSnackbar.showSnackbar('URL copied');
},
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
decoration: BoxDecoration(
color: const Color(0xFF0D0D0D),
borderRadius: BorderRadius.circular(10),
border: Border.all(color: const Color(0xFF2A2A2E), width: 1),
),
child: Row(
children: [
Expanded(
child: Text(
mcpUrl,
style: const TextStyle(
color: Colors.white,
fontFamily: 'Ubuntu Mono',
fontSize: 13,
),
),
),
const SizedBox(width: 8),
FaIcon(FontAwesomeIcons.copy, color: Colors.grey.shade500, size: 14),
],
),
),
);
},
),

const SizedBox(height: 20),
Divider(color: Colors.grey.shade800, height: 1),
const SizedBox(height: 20),

// API Key Auth Section
Text(
'API Key Auth',
style: TextStyle(color: Colors.grey.shade400, fontSize: 12, fontWeight: FontWeight.w600),
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
flex: 2,
child: Text(
'Header',
style: TextStyle(color: Colors.grey.shade500, fontSize: 13),
),
),
Expanded(
flex: 3,
child: Text(
'Authorization: Bearer <key>',
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 12,
fontFamily: 'Ubuntu Mono',
),
),
),
],
),

const SizedBox(height: 20),
Divider(color: Colors.grey.shade800, height: 1),
const SizedBox(height: 20),

// OAuth Section
Text(
'OAuth',
style: TextStyle(color: Colors.grey.shade400, fontSize: 12, fontWeight: FontWeight.w600),
),
const SizedBox(height: 12),

// Client ID
_buildMcpConfigRow('Client ID', 'omi'),
const SizedBox(height: 8),

// Client Secret hint
Row(
children: [
Expanded(
flex: 2,
child: Text(
'Client Secret',
style: TextStyle(color: Colors.grey.shade500, fontSize: 13),
),
),
Expanded(
flex: 3,
child: Text(
'Use your MCP API key',
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 13,
fontStyle: FontStyle.italic,
),
),
),
],
),
],
),
),

const SizedBox(height: 32),

// Webhooks Section
Expand Down
2 changes: 2 additions & 0 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
conversations,
memories,
mcp,
mcp_sse,
oauth,
auth,
action_items,
Expand Down Expand Up @@ -77,6 +78,7 @@

app.include_router(payment.router)
app.include_router(mcp.router)
app.include_router(mcp_sse.router)
app.include_router(developer.router)
app.include_router(imports.router)

Expand Down
Loading