feat(astrolabe): add Nextcloud PHP app for MCP server management
Adds a native Nextcloud app "Astroglobe" that provides: - Personal settings: OAuth authorization for background MCP access - Admin settings: Server status and vector sync monitoring - API endpoints for MCP server communication The app uses PKCE OAuth flow to obtain tokens for the MCP server, enabling features like background vector sync per ADR-018. Includes: - PHP app structure (controllers, services, settings) - Vue.js frontend components - Docker compose mount configuration - Installation hook for development testing - ADR-018 documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use OCP\Util;
|
||||
|
||||
Util::addScript(OCA\Astroglobe\AppInfo\Application::APP_ID, OCA\Astroglobe\AppInfo\Application::APP_ID . '-main');
|
||||
|
||||
?>
|
||||
|
||||
<div id="astroglobe"></div>
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin settings template for MCP Server UI.
|
||||
*
|
||||
* Displays server status, vector sync metrics, configuration,
|
||||
* and provides administrative controls.
|
||||
*
|
||||
* @var array $_ Template parameters
|
||||
* @var array $_['serverStatus'] Server status from API
|
||||
* @var array $_['vectorSyncStatus'] Vector sync metrics from API
|
||||
* @var string $_['serverUrl'] Configured MCP server URL
|
||||
* @var bool $_['apiKeyConfigured'] Whether API key is set in config.php
|
||||
* @var bool $_['vectorSyncEnabled'] Whether vector sync is enabled
|
||||
*/
|
||||
|
||||
script('astroglobe', 'astroglobe-adminSettings');
|
||||
style('astroglobe', 'astroglobe-settings');
|
||||
?>
|
||||
|
||||
<div id="mcp-admin-settings" class="section">
|
||||
<h2><?php p($l->t('MCP Server Administration')); ?></h2>
|
||||
|
||||
<div class="mcp-settings-info">
|
||||
<p><?php p($l->t('Monitor and configure the Nextcloud MCP (Model Context Protocol) Server.')); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Status -->
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Configuration')); ?></h3>
|
||||
<table class="mcp-info-table">
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Server URL')); ?></strong></td>
|
||||
<td>
|
||||
<?php if (!empty($_['serverUrl'])): ?>
|
||||
<code><?php p($_['serverUrl']); ?></code>
|
||||
<?php else: ?>
|
||||
<span class="error"><?php p($l->t('Not configured')); ?></span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('API Key')); ?></strong></td>
|
||||
<td>
|
||||
<?php if ($_['apiKeyConfigured']): ?>
|
||||
<span class="badge badge-success">
|
||||
<span class="icon icon-checkmark-white"></span>
|
||||
<?php p($l->t('Configured')); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span class="badge badge-warning">
|
||||
<span class="icon icon-alert"></span>
|
||||
<?php p($l->t('Not configured')); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php if (empty($_['serverUrl']) || !$_['apiKeyConfigured']): ?>
|
||||
<div class="notecard notecard-warning">
|
||||
<p><strong><?php p($l->t('Configuration Required')); ?></strong></p>
|
||||
<p><?php p($l->t('Add the following to your config.php:')); ?></p>
|
||||
<pre><code>'mcp_server_url' => 'http://localhost:8000',
|
||||
'mcp_server_api_key' => 'your-secret-api-key',</code></pre>
|
||||
<p class="mcp-help-text">
|
||||
<a href="https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/ADR-018-nextcloud-php-app-for-settings-ui.md" target="_blank">
|
||||
<?php p($l->t('See documentation for details')); ?>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Server Status -->
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Server Status')); ?></h3>
|
||||
<table class="mcp-info-table">
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Version')); ?></strong></td>
|
||||
<td><?php p($_['serverStatus']['version'] ?? 'Unknown'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Authentication Mode')); ?></strong></td>
|
||||
<td><code><?php p($_['serverStatus']['auth_mode'] ?? 'Unknown'); ?></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Management API Version')); ?></strong></td>
|
||||
<td><?php p($_['serverStatus']['management_api_version'] ?? 'Unknown'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Uptime')); ?></strong></td>
|
||||
<td>
|
||||
<?php if (isset($_['serverStatus']['uptime_seconds'])): ?>
|
||||
<?php
|
||||
$uptime = $_['serverStatus']['uptime_seconds'];
|
||||
$hours = floor($uptime / 3600);
|
||||
$minutes = floor(($uptime % 3600) / 60);
|
||||
p(sprintf('%d hours, %d minutes', $hours, $minutes));
|
||||
?>
|
||||
<?php else: ?>
|
||||
<?php p($l->t('Unknown')); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Vector Sync')); ?></strong></td>
|
||||
<td>
|
||||
<?php if ($_['vectorSyncEnabled']): ?>
|
||||
<span class="badge badge-success">
|
||||
<span class="icon icon-checkmark-white"></span>
|
||||
<?php p($l->t('Enabled')); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span class="badge badge-neutral">
|
||||
<?php p($l->t('Disabled')); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Vector Sync Metrics -->
|
||||
<?php if ($_['vectorSyncEnabled'] && !isset($_['vectorSyncStatus']['error'])): ?>
|
||||
<div class="mcp-status-card" id="vector-sync-metrics">
|
||||
<h3><?php p($l->t('Vector Sync Metrics')); ?></h3>
|
||||
<table class="mcp-info-table">
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Status')); ?></strong></td>
|
||||
<td>
|
||||
<?php
|
||||
$status = $_['vectorSyncStatus']['status'] ?? 'unknown';
|
||||
$statusClass = $status === 'idle' ? 'success' : ($status === 'syncing' ? 'info' : 'neutral');
|
||||
?>
|
||||
<span class="badge badge-<?php p($statusClass); ?>">
|
||||
<?php p(ucfirst($status)); ?>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Indexed Documents')); ?></strong></td>
|
||||
<td><?php p(number_format($_['vectorSyncStatus']['indexed_documents'] ?? 0)); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Pending Documents')); ?></strong></td>
|
||||
<td><?php p(number_format($_['vectorSyncStatus']['pending_documents'] ?? 0)); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Last Sync')); ?></strong></td>
|
||||
<td><?php p($_['vectorSyncStatus']['last_sync_time'] ?? 'Never'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Processing Rate')); ?></strong></td>
|
||||
<td><?php p(sprintf('%.1f docs/sec', $_['vectorSyncStatus']['documents_per_second'] ?? 0)); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Errors (24h)')); ?></strong></td>
|
||||
<td>
|
||||
<?php
|
||||
$errors = $_['vectorSyncStatus']['errors_24h'] ?? 0;
|
||||
if ($errors > 0): ?>
|
||||
<span class="error"><?php p($errors); ?></span>
|
||||
<?php else: ?>
|
||||
<?php p('0'); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="mcp-help-text">
|
||||
<?php p($l->t('Metrics are updated in real-time. Refresh the page to see latest values.')); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php elseif ($_['vectorSyncEnabled']): ?>
|
||||
<div class="mcp-status-card mcp-error">
|
||||
<h3><?php p($l->t('Vector Sync Metrics')); ?></h3>
|
||||
<div class="notecard notecard-error">
|
||||
<p><?php p($l->t('Failed to retrieve vector sync status:')); ?></p>
|
||||
<p><code><?php p($_['vectorSyncStatus']['error'] ?? 'Unknown error'); ?></code></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Additional Features -->
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Features')); ?></h3>
|
||||
<ul class="mcp-feature-list">
|
||||
<li>
|
||||
<span class="icon icon-user"></span>
|
||||
<strong><?php p($l->t('User Settings')); ?></strong>
|
||||
<p><?php p($l->t('Users can manage their MCP server connections in Personal Settings.')); ?></p>
|
||||
</li>
|
||||
<?php if ($_['vectorSyncEnabled']): ?>
|
||||
<li>
|
||||
<span class="icon icon-search"></span>
|
||||
<strong><?php p($l->t('Vector Visualization')); ?></strong>
|
||||
<p><?php p($l->t('Interactive semantic search interface with 2D PCA visualization.')); ?></p>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<li>
|
||||
<span class="icon icon-link"></span>
|
||||
<strong><?php p($l->t('MCP Protocol')); ?></strong>
|
||||
<p><?php p($l->t('Full support for MCP sampling, elicitation, and bidirectional streaming.')); ?></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Documentation -->
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Documentation')); ?></h3>
|
||||
<ul class="mcp-links">
|
||||
<li>
|
||||
<a href="https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/ADR-018-nextcloud-php-app-for-settings-ui.md" target="_blank">
|
||||
<?php p($l->t('Architecture Decision Record (ADR-018)')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/configuration.md" target="_blank">
|
||||
<?php p($l->t('Configuration Guide')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/cbcoutinho/nextcloud-mcp-server" target="_blank">
|
||||
<?php p($l->t('GitHub Repository')); ?>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Error template for MCP Server UI settings.
|
||||
*
|
||||
* Displayed when the MCP server cannot be reached or returns an error.
|
||||
*
|
||||
* @var array $_ Template parameters
|
||||
* @var string $_['error'] Error title
|
||||
* @var string $_['details'] Error details/message
|
||||
* @var string $_['server_url'] Configured server URL (optional)
|
||||
* @var string $_['help_text'] Additional help text (optional)
|
||||
*/
|
||||
|
||||
style('astroglobe', 'astroglobe-settings');
|
||||
?>
|
||||
|
||||
<div class="mcp-settings-error">
|
||||
<div class="notecard notecard-error">
|
||||
<h3>
|
||||
<span class="icon icon-error"></span>
|
||||
<?php p($_['error'] ?? 'Error'); ?>
|
||||
</h3>
|
||||
|
||||
<?php if (isset($_['details'])): ?>
|
||||
<p><strong><?php p($l->t('Details:')); ?></strong></p>
|
||||
<p><code><?php p($_['details']); ?></code></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_['server_url'])): ?>
|
||||
<p><strong><?php p($l->t('Server URL:')); ?></strong></p>
|
||||
<p><code><?php p($_['server_url']); ?></code></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_['help_text'])): ?>
|
||||
<p class="mcp-help-text"><?php p($_['help_text']); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h4><?php p($l->t('Troubleshooting Steps:')); ?></h4>
|
||||
<ol>
|
||||
<li><?php p($l->t('Verify the MCP server is running and accessible')); ?></li>
|
||||
<li><?php p($l->t('Check that mcp_server_url in config.php is correct')); ?></li>
|
||||
<li><?php p($l->t('Ensure mcp_server_api_key matches the server configuration')); ?></li>
|
||||
<li><?php p($l->t('Check firewall rules and network connectivity')); ?></li>
|
||||
<li><?php p($l->t('Review MCP server logs for errors')); ?></li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/ADR-018-nextcloud-php-app-for-settings-ui.md" target="_blank" class="button">
|
||||
<?php p($l->t('View Documentation')); ?>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/**
|
||||
* OAuth authorization required template.
|
||||
*
|
||||
* Shown when user needs to authorize Nextcloud to access MCP server.
|
||||
* Implements OAuth 2.0 Authorization Code flow with PKCE.
|
||||
*
|
||||
* @var array $_ Template parameters
|
||||
* @var string $_['oauth_url'] URL to initiate OAuth flow
|
||||
* @var string $_['server_url'] MCP server base URL
|
||||
* @var bool $_['has_expired'] Whether token exists but is expired
|
||||
* @var string|null $_['error_message'] Optional error message to display
|
||||
*/
|
||||
|
||||
use OCP\Util;
|
||||
|
||||
Util::addStyle('astroglobe', 'astroglobe-settings');
|
||||
?>
|
||||
|
||||
<div id="mcp-personal-settings">
|
||||
<div class="mcp-settings-info">
|
||||
<p><?php p($l->t('Configure your personal MCP Server integration.')); ?></p>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_['error_message'])): ?>
|
||||
<div class="mcp-status-card mcp-error">
|
||||
<h3>
|
||||
<span class="icon icon-error"></span>
|
||||
<?php p($l->t('Session Expired')); ?>
|
||||
</h3>
|
||||
<p><?php p($_['error_message']); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="mcp-status-card">
|
||||
<h3>
|
||||
<span class="icon icon-password"></span>
|
||||
<?php p($l->t('Authorization Required')); ?>
|
||||
</h3>
|
||||
|
||||
<?php if (isset($_['has_expired']) && $_['has_expired']): ?>
|
||||
<p>
|
||||
<?php p($l->t('Your MCP server access has expired. Please sign in again to continue using MCP features.')); ?>
|
||||
</p>
|
||||
<?php else: ?>
|
||||
<p>
|
||||
<?php p($l->t('To access MCP server features, you need to authorize Nextcloud to connect to your MCP server on your behalf.')); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<p>
|
||||
<strong><?php p($l->t('What happens next?')); ?></strong>
|
||||
</p>
|
||||
|
||||
<ol class="mcp-help-text">
|
||||
<li><?php p($l->t('You will be redirected to your identity provider')); ?></li>
|
||||
<li><?php p($l->t('Sign in with your credentials')); ?></li>
|
||||
<li><?php p($l->t('Authorize Nextcloud to access the MCP server')); ?></li>
|
||||
<li><?php p($l->t('You will be redirected back to this page')); ?></li>
|
||||
</ol>
|
||||
|
||||
<h4><?php p($l->t('Permissions Requested')); ?></h4>
|
||||
|
||||
<ul class="mcp-feature-list">
|
||||
<li>
|
||||
<span class="icon icon-info"></span>
|
||||
<div>
|
||||
<strong><?php p($l->t('Profile Information')); ?></strong>
|
||||
<p><?php p($l->t('Basic profile information (user ID, email) for identification')); ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-files"></span>
|
||||
<div>
|
||||
<strong><?php p($l->t('Read Access')); ?></strong>
|
||||
<p><?php p($l->t('View your Notes, Calendar, Files, and other Nextcloud data')); ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-rename"></span>
|
||||
<div>
|
||||
<strong><?php p($l->t('Write Access')); ?></strong>
|
||||
<p><?php p($l->t('Create and modify Notes, Calendar events, Files, and other Nextcloud data')); ?></p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<a href="<?php p($_['oauth_url']); ?>" class="button primary">
|
||||
<span class="icon icon-play"></span>
|
||||
<?php if (isset($_['has_expired']) && $_['has_expired']): ?>
|
||||
<?php p($l->t('Sign In Again')); ?>
|
||||
<?php else: ?>
|
||||
<?php p($l->t('Authorize Access')); ?>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p class="mcp-help-text" style="margin-top: 16px;">
|
||||
<?php p($l->t('By authorizing, you allow Nextcloud to access the MCP server at:')); ?>
|
||||
<br>
|
||||
<code><?php p($_['server_url']); ?></code>
|
||||
</p>
|
||||
|
||||
<p class="mcp-help-text">
|
||||
<?php p($l->t('You can revoke this access at any time from this settings page.')); ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mcp-status-card">
|
||||
<h3>
|
||||
<span class="icon icon-info"></span>
|
||||
<?php p($l->t('About MCP Server')); ?>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<?php p($l->t('The Model Context Protocol (MCP) server provides AI assistants with access to your Nextcloud data.')); ?>
|
||||
</p>
|
||||
|
||||
<p class="mcp-help-text">
|
||||
<?php p($l->t('Once authorized, you can use AI tools like Claude Desktop to interact with your Notes, Calendar, Files, and more through natural language.')); ?>
|
||||
</p>
|
||||
|
||||
<ul class="mcp-links">
|
||||
<li>
|
||||
<a href="https://github.com/cbcoutinho/nextcloud-mcp-server" target="_blank" rel="noopener noreferrer">
|
||||
<span class="icon icon-external"></span>
|
||||
<?php p($l->t('MCP Server Documentation')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://modelcontextprotocol.io" target="_blank" rel="noopener noreferrer">
|
||||
<span class="icon icon-external"></span>
|
||||
<?php p($l->t('Learn about Model Context Protocol')); ?>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
/**
|
||||
* Personal settings template for MCP Server UI.
|
||||
*
|
||||
* Displays user session information, background access status,
|
||||
* and provides controls for managing MCP server integration.
|
||||
*
|
||||
* @var array $_ Template parameters
|
||||
* @var string $_['userId'] Current user ID
|
||||
* @var array $_['serverStatus'] Server status from API
|
||||
* @var array $_['session'] User session details from API
|
||||
* @var bool $_['vectorSyncEnabled'] Whether vector sync is enabled
|
||||
* @var bool $_['backgroundAccessGranted'] Whether user has granted background access
|
||||
* @var string $_['serverUrl'] MCP server URL
|
||||
*/
|
||||
|
||||
// Get URL generator from Nextcloud's service container
|
||||
$urlGenerator = \OC::$server->getURLGenerator();
|
||||
|
||||
script('astroglobe', 'astroglobe-personalSettings');
|
||||
style('astroglobe', 'astroglobe-settings');
|
||||
?>
|
||||
|
||||
<div id="mcp-personal-settings" class="section">
|
||||
<h2><?php p($l->t('MCP Server')); ?></h2>
|
||||
|
||||
<div class="mcp-settings-info">
|
||||
<p><?php p($l->t('Manage your connection to the Nextcloud MCP (Model Context Protocol) Server.')); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Server Connection Status -->
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Server Connection')); ?></h3>
|
||||
<table class="mcp-info-table">
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Server URL')); ?></strong></td>
|
||||
<td><code><?php p($_['serverUrl']); ?></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Server Version')); ?></strong></td>
|
||||
<td><?php p($_['serverStatus']['version'] ?? 'Unknown'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Auth Mode')); ?></strong></td>
|
||||
<td><?php p($_['serverStatus']['auth_mode'] ?? 'Unknown'); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Session Information -->
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Session Information')); ?></h3>
|
||||
<table class="mcp-info-table">
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('User ID')); ?></strong></td>
|
||||
<td><code><?php p($_['userId']); ?></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Background Access')); ?></strong></td>
|
||||
<td>
|
||||
<?php if ($_['backgroundAccessGranted']): ?>
|
||||
<span class="badge badge-success">
|
||||
<span class="icon icon-checkmark-white"></span>
|
||||
<?php p($l->t('Granted')); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span class="badge badge-neutral">
|
||||
<?php p($l->t('Not Granted')); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php if (!$_['backgroundAccessGranted']): ?>
|
||||
<div class="mcp-grant-section">
|
||||
<p class="mcp-help-text">
|
||||
<?php p($l->t('Background access allows the MCP server to sync your documents in the background for semantic search. Without it, your documents will not be indexed.')); ?>
|
||||
</p>
|
||||
<a href="<?php p($_['serverUrl']); ?>/oauth/login?next=<?php p(urlencode($urlGenerator->getAbsoluteURL($urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'astroglobe'])))); ?>" class="button primary" id="mcp-grant-button">
|
||||
<span class="icon icon-confirm"></span>
|
||||
<?php p($l->t('Grant Background Access')); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($_['backgroundAccessGranted'] && isset($_['session']['background_access_details'])): ?>
|
||||
<div class="mcp-background-details">
|
||||
<h4><?php p($l->t('Background Access Details')); ?></h4>
|
||||
<table class="mcp-info-table">
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Flow Type')); ?></strong></td>
|
||||
<td><?php p($_['session']['background_access_details']['flow_type'] ?? 'N/A'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Provisioned At')); ?></strong></td>
|
||||
<td><?php p($_['session']['background_access_details']['provisioned_at'] ?? 'N/A'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Token Audience')); ?></strong></td>
|
||||
<td><?php p($_['session']['background_access_details']['token_audience'] ?? 'N/A'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?php p($l->t('Scopes')); ?></strong></td>
|
||||
<td><code style="font-size: 11px;"><?php p($_['session']['background_access_details']['scopes'] ?? 'N/A'); ?></code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="mcp-revoke-section">
|
||||
<form method="post" action="<?php p($urlGenerator->linkToRoute('astroglobe.api.revokeAccess')); ?>" id="mcp-revoke-form">
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']); ?>">
|
||||
<button type="submit" class="button warning" id="mcp-revoke-button">
|
||||
<span class="icon icon-delete"></span>
|
||||
<?php p($l->t('Revoke Background Access')); ?>
|
||||
</button>
|
||||
<p class="mcp-help-text">
|
||||
<?php p($l->t('This will delete the refresh token and prevent background operations from running on your behalf.')); ?>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Identity Provider Profile -->
|
||||
<?php if (isset($_['session']['idp_profile'])): ?>
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Identity Provider Profile')); ?></h3>
|
||||
<table class="mcp-info-table">
|
||||
<?php foreach ($_['session']['idp_profile'] as $key => $value): ?>
|
||||
<tr>
|
||||
<td><strong><?php p(ucfirst(str_replace('_', ' ', $key))); ?></strong></td>
|
||||
<td>
|
||||
<?php if (is_array($value)): ?>
|
||||
<?php p(implode(', ', $value)); ?>
|
||||
<?php else: ?>
|
||||
<?php p((string)$value); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Vector Sync Features -->
|
||||
<?php if ($_['vectorSyncEnabled']): ?>
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Semantic Search')); ?></h3>
|
||||
<p><?php p($l->t('Search your indexed content using semantic similarity. Find documents by meaning, not just keywords.')); ?></p>
|
||||
<a href="<?php p($urlGenerator->linkToRoute('astroglobe.page.index')); ?>" class="button primary">
|
||||
<span class="icon icon-search"></span>
|
||||
<?php p($l->t('Open MCP Server UI')); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="mcp-status-card mcp-disabled">
|
||||
<h3><?php p($l->t('Semantic Search')); ?></h3>
|
||||
<p class="mcp-help-text">
|
||||
<?php p($l->t('Vector sync is not enabled on the MCP server. Contact your administrator to enable this feature.')); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- OAuth Connection Management -->
|
||||
<div class="mcp-status-card">
|
||||
<h3><?php p($l->t('Connection Management')); ?></h3>
|
||||
<p><?php p($l->t('You are currently connected to the MCP server via OAuth.')); ?></p>
|
||||
|
||||
<div class="mcp-revoke-section">
|
||||
<form method="post" action="<?php p($urlGenerator->linkToRoute('astroglobe.oauth.disconnect')); ?>" id="mcp-disconnect-form">
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']); ?>">
|
||||
<button type="submit" class="button warning" id="mcp-disconnect-button">
|
||||
<span class="icon icon-close"></span>
|
||||
<?php p($l->t('Disconnect from MCP Server')); ?>
|
||||
</button>
|
||||
<p class="mcp-help-text">
|
||||
<?php p($l->t('This will remove your OAuth connection to the MCP server. You will need to authorize access again to use MCP features.')); ?>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Confirm revoke and disconnect actions
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const revokeForm = document.getElementById('mcp-revoke-form');
|
||||
if (revokeForm) {
|
||||
revokeForm.addEventListener('submit', function(e) {
|
||||
if (!confirm('<?php p($l->t('Are you sure you want to revoke background access? This action cannot be undone.')); ?>')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const disconnectForm = document.getElementById('mcp-disconnect-form');
|
||||
if (disconnectForm) {
|
||||
disconnectForm.addEventListener('submit', function(e) {
|
||||
if (!confirm('<?php p($l->t('Are you sure you want to disconnect from the MCP server? You will need to authorize access again.')); ?>')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user