Skip to main content
Glama
config.py8.31 kB
#!/usr/bin/env python # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai __license__ = 'GPL v3' __copyright__ = '2025, Miguel Iglesias' __docformat__ = 'restructuredtext en' from calibre.utils.config import JSONConfig from calibre.utils.localization import _ from qt.core import ( QWidget, QFormLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QFileDialog, QVBoxLayout, QGroupBox, QComboBox, QCheckBox, ) from .providers import ( ensure_model_prefs, get_selected_model, list_enabled_providers, set_selected_model, describe_provider, ) # This is where all preferences for this plugin will be stored. # Name is global, so keep it reasonably unique. prefs = JSONConfig('plugins/mcp_server_recherche') # New settings for MCP server / AI prefs.defaults['server_host'] = '127.0.0.1' prefs.defaults['server_port'] = '8765' prefs.defaults['library_path'] = '' # Use current calibre library when empty prefs.defaults['api_key'] = '' # Optional AI key (e.g. OpenAI) prefs.defaults['models'] = {} prefs.defaults['selected_model'] = {} ensure_model_prefs(prefs) class MCPServerRechercheConfigWidget(QWidget): """Preference widget for MCP Server Recherche plugin.""" def __init__(self): QWidget.__init__(self) layout = QVBoxLayout(self) # Connection settings ------------------------------------------------ server_group = QGroupBox(_('MCP Server Einstellungen'), self) server_form = QFormLayout(server_group) server_group.setLayout(server_form) layout.addWidget(server_group) # Server host self.host_edit = QLineEdit(self) self.host_edit.setText(prefs['server_host']) server_form.addRow(_('Server-Host:'), self.host_edit) # Server port self.port_edit = QLineEdit(self) self.port_edit.setText(prefs['server_port']) server_form.addRow(_('Server-Port:'), self.port_edit) # Library path + browse button lib_row = QHBoxLayout() self.library_edit = QLineEdit(self) self.library_edit.setText(prefs['library_path']) browse_btn = QPushButton(_('Auswahl'), self) browse_btn.clicked.connect(self.choose_library) lib_row.addWidget(self.library_edit) lib_row.addWidget(browse_btn) server_form.addRow(_('Calibre-Bibliothek:'), lib_row) # Info label info = QLabel( _( 'Host/Port konfigurieren spaeter den MCP WebSocket-Server.\n' 'Der Bibliothekspfad ueberschreibt optional die aktuelle Calibre-Bibliothek.' ), self, ) server_form.addRow(info) # AI provider settings ---------------------------------------------- provider_group = QGroupBox(_('AI Provider'), self) provider_layout = QVBoxLayout(provider_group) layout.addWidget(provider_group) self.provider_combo = QComboBox(self) self.provider_combo.currentIndexChanged.connect(self._provider_changed) provider_layout.addWidget(self.provider_combo) form = QFormLayout() provider_layout.addLayout(form) self.provider_enabled = QCheckBox(_('Provider aktiviert'), self) form.addRow('', self.provider_enabled) self.display_name_edit = QLineEdit(self) form.addRow(_('Anzeige-Name:'), self.display_name_edit) self.base_url_edit = QLineEdit(self) form.addRow(_('Base URL:'), self.base_url_edit) self.endpoint_edit = QLineEdit(self) form.addRow(_('Chat Endpoint:'), self.endpoint_edit) self.model_edit = QLineEdit(self) form.addRow(_('Standardmodell:'), self.model_edit) self.api_key_edit = QLineEdit(self) self.api_key_edit.setEchoMode(QLineEdit.Password) form.addRow(_('API Key:'), self.api_key_edit) self.temperature_edit = QLineEdit(self) form.addRow(_('Temperatur:'), self.temperature_edit) selection_row = QHBoxLayout() self.selected_provider_label = QLabel(_('Kein Provider'), self) self.selected_model_label = QLabel('', self) selection_row.addWidget(QLabel(_('Aktiv:'), self)) selection_row.addWidget(self.selected_provider_label) selection_row.addSpacing(8) selection_row.addWidget(self.selected_model_label) choose_btn = QPushButton(_('Standard setzen'), self) choose_btn.clicked.connect(self.choose_model) selection_row.addWidget(choose_btn) provider_layout.addLayout(selection_row) self._load_providers() self._update_selection_labels() def choose_library(self): """Select calibre library root directory.""" path = QFileDialog.getExistingDirectory( self, _('Calibre-Bibliothek auswaehlen'), self.library_edit.text() or '', ) if path: self.library_edit.setText(path) def save_settings(self): """Persist user changes to JSONConfig.""" prefs['server_host'] = self.host_edit.text().strip() or '127.0.0.1' prefs['server_port'] = self.port_edit.text().strip() or '8765' prefs['library_path'] = self.library_edit.text().strip() self._persist_provider_settings() self._update_selection_labels() # ------------------------------------------------------------------ AI helpers def _load_providers(self): self._models = ensure_model_prefs(prefs) self.provider_combo.blockSignals(True) self.provider_combo.clear() for key, cfg in self._models.items(): self.provider_combo.addItem(describe_provider(cfg), key) self.provider_combo.blockSignals(False) self._provider_changed(self.provider_combo.currentIndex()) def _provider_changed(self, index: int): provider_key = self.provider_combo.itemData(index) cfg = self._models.get(provider_key, {}) self.provider_enabled.setChecked(bool(cfg.get('enabled'))) self.display_name_edit.setText(cfg.get('display_name', '')) self.base_url_edit.setText(cfg.get('base_url', '')) self.endpoint_edit.setText(cfg.get('chat_endpoint', '')) self.model_edit.setText(cfg.get('model', '')) self.api_key_edit.setText(cfg.get('api_key', '')) self.temperature_edit.setText(str(cfg.get('temperature', ''))) def _persist_provider_settings(self): index = self.provider_combo.currentIndex() provider_key = self.provider_combo.itemData(index) if not provider_key: return cfg = self._models.setdefault(provider_key, {}) cfg['enabled'] = self.provider_enabled.isChecked() cfg['display_name'] = self.display_name_edit.text().strip() cfg['base_url'] = self.base_url_edit.text().strip() cfg['chat_endpoint'] = self.endpoint_edit.text().strip() cfg['model'] = self.model_edit.text().strip() cfg['api_key'] = self.api_key_edit.text().strip() try: cfg['temperature'] = float(self.temperature_edit.text().strip()) except ValueError: cfg['temperature'] = 0.4 prefs['models'] = self._models def choose_model(self): models = ensure_model_prefs(prefs) enabled = list_enabled_providers(models) if not enabled: self.selected_provider_label.setText(_('Kein aktiver Provider')) self.selected_model_label.setText('') return key = self.provider_combo.itemData(self.provider_combo.currentIndex()) if key not in enabled: key = next(iter(enabled.keys())) model_name = enabled[key].get('model', '') set_selected_model(prefs, key, model_name) self._update_selection_labels() def _update_selection_labels(self): selected = get_selected_model(prefs) models = ensure_model_prefs(prefs) cfg = models.get(selected.get('provider')) if not cfg: self.selected_provider_label.setText(_('Kein Provider')) self.selected_model_label.setText('') return self.selected_provider_label.setText(describe_provider(cfg)) self.selected_model_label.setText(selected.get('model') or '')

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Miguel0888/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server