mirror of
https://github.com/aaronsb/obsidian-mcp-plugin.git
synced 2026-07-22 06:45:14 +00:00
feat: Add HTTPS port conflict detection and auto-increment
- Apply same port conflict detection logic to HTTPS that HTTP uses - Automatically increment HTTPS port if 3443 is in use - Add port availability checking in settings UI for HTTPS port - Update README with comprehensive HTTPS/TLS configuration docs - Document manual JSON configuration for self-signed certificates
This commit is contained in:
parent
958ea6a3b7
commit
bcf0f2d4ab
2 changed files with 110 additions and 12 deletions
68
README.md
68
README.md
|
|
@ -170,6 +170,8 @@ Once this plugin is approved and available in the Obsidian Community Plugins dir
|
|||
### Claude Desktop / Other Clients
|
||||
|
||||
**Option 1: Direct HTTP Transport** (if your client supports it)
|
||||
|
||||
For HTTP (default):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
|
|
@ -183,6 +185,21 @@ Once this plugin is approved and available in the Obsidian Community Plugins dir
|
|||
}
|
||||
```
|
||||
|
||||
For HTTPS (requires proper certificate trust):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"obsidian": {
|
||||
"transport": {
|
||||
"type": "http",
|
||||
"url": "https://localhost:3443/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Note: Direct HTTPS transport may not work with self-signed certificates. Use Option 2 with mcp-remote for HTTPS.
|
||||
|
||||
**Option 2: Via mcp-remote** (recommended for Claude Desktop)
|
||||
|
||||
Since Claude Desktop might not support streaming HTTP transport yet, use mcp-remote:
|
||||
|
|
@ -205,6 +222,57 @@ Once this plugin is approved and available in the Obsidian Community Plugins dir
|
|||
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
||||
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
||||
|
||||
### HTTPS/TLS Configuration (v0.9.0+)
|
||||
|
||||
The plugin supports secure HTTPS connections with automatic self-signed certificate generation:
|
||||
|
||||
1. **Enable HTTPS in Plugin Settings**:
|
||||
- Go to plugin settings in Obsidian
|
||||
- Find "HTTPS/TLS Settings" section
|
||||
- Toggle "Enable HTTPS Server"
|
||||
- Default HTTPS port is 3443 (configurable)
|
||||
- Certificates are auto-generated on first launch
|
||||
|
||||
2. **Configure Claude Code / MCP Client**:
|
||||
|
||||
Since most MCP clients don't trust self-signed certificates by default, you'll need to use `mcp-remote` with environment variables:
|
||||
|
||||
**Manual JSON Configuration Required**:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"obsidian-vault-name": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"mcp-remote",
|
||||
"https://localhost:3443/mcp",
|
||||
"--header",
|
||||
"Authorization: Bearer YOUR_API_KEY_HERE"
|
||||
],
|
||||
"env": {
|
||||
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important Notes**:
|
||||
- Replace `YOUR_API_KEY_HERE` with your actual API key from plugin settings
|
||||
- The `env` section with `NODE_TLS_REJECT_UNAUTHORIZED` is required for self-signed certificates
|
||||
- Command-line tools like `claude mcp add` don't support environment variables, so manual JSON editing is required
|
||||
- Edit your configuration file directly at the locations listed above
|
||||
|
||||
3. **Certificate Storage**:
|
||||
- Auto-generated certificates are stored in: `.obsidian/plugins/semantic-vault-mcp/certificates/`
|
||||
- Certificate paths will auto-populate in settings after generation
|
||||
- Certificates are valid for 1 year and include localhost/127.0.0.1 SANs
|
||||
|
||||
4. **Security Considerations**:
|
||||
- Self-signed certificates are suitable for local development
|
||||
- For production use, consider using proper certificates from a CA
|
||||
- The `NODE_TLS_REJECT_UNAUTHORIZED=0` setting disables certificate validation - use only for local connections
|
||||
|
||||
### Concurrent Sessions for Agent Swarms (v0.5.8+)
|
||||
|
||||
Enable multiple AI agents to work with your vault simultaneously without blocking each other:
|
||||
|
|
|
|||
54
src/main.ts
54
src/main.ts
|
|
@ -152,44 +152,49 @@ export default class ObsidianMCPPlugin extends Plugin {
|
|||
|
||||
async startMCPServer(): Promise<void> {
|
||||
try {
|
||||
// Determine which port to check based on whether HTTPS is enabled
|
||||
const isHttps = this.settings.httpsEnabled && this.settings.certificateConfig?.enabled;
|
||||
const portToUse = isHttps ? this.settings.httpsPort : this.settings.httpPort;
|
||||
const protocol = isHttps ? 'HTTPS' : 'HTTP';
|
||||
|
||||
// Check for port conflicts and auto-switch if needed
|
||||
if (this.settings.autoDetectPortConflicts) {
|
||||
const status = await this.checkPortConflict(this.settings.httpPort);
|
||||
const status = await this.checkPortConflict(portToUse);
|
||||
if (status === 'in-use') {
|
||||
const suggestedPort = await this.findAvailablePort(this.settings.httpPort);
|
||||
const suggestedPort = await this.findAvailablePort(portToUse);
|
||||
|
||||
if (suggestedPort === 0) {
|
||||
// All alternate ports are busy
|
||||
const portsChecked = `${this.settings.httpPort}, ${this.settings.httpPort + 1}, ${this.settings.httpPort + 2}, ${this.settings.httpPort + 3}`;
|
||||
const portsChecked = `${portToUse}, ${portToUse + 1}, ${portToUse + 2}, ${portToUse + 3}`;
|
||||
Debug.error(`❌ Failed to find available port after 3 attempts. Ports checked: ${portsChecked}`);
|
||||
Debug.error('Please check for other applications using these ports or firewall/security software blocking access.');
|
||||
new Notice(`Cannot start MCP server: Ports ${this.settings.httpPort}-${this.settings.httpPort + 3} are all in use. Check console for details.`);
|
||||
new Notice(`Cannot start MCP server: Ports ${portToUse}-${portToUse + 3} are all in use. Check console for details.`);
|
||||
this.updateStatusBar();
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.log(`⚠️ Port ${this.settings.httpPort} is in use, switching to port ${suggestedPort}`);
|
||||
new Notice(`Port ${this.settings.httpPort} is in use. Switching to port ${suggestedPort}`);
|
||||
Debug.log(`⚠️ ${protocol} Port ${portToUse} is in use, switching to port ${suggestedPort}`);
|
||||
new Notice(`${protocol} Port ${portToUse} is in use. Switching to port ${suggestedPort}`);
|
||||
|
||||
// Temporarily use the suggested port for this session
|
||||
this.mcpServer = new MCPHttpServer(this.app, suggestedPort, this);
|
||||
await this.mcpServer.start();
|
||||
this.updateStatusBar();
|
||||
Debug.log(`✅ MCP server started on alternate port ${suggestedPort}`);
|
||||
Debug.log(`✅ MCP server started on alternate ${protocol} port ${suggestedPort}`);
|
||||
if (this.settings.showConnectionStatus) {
|
||||
new Notice(`MCP server started on port ${suggestedPort} (default port was in use)`);
|
||||
new Notice(`MCP server started on ${protocol} port ${suggestedPort} (default port was in use)`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.log(`🚀 Starting MCP server on port ${this.settings.httpPort}...`);
|
||||
this.mcpServer = new MCPHttpServer(this.app, this.settings.httpPort, this);
|
||||
Debug.log(`🚀 Starting MCP server on ${protocol} port ${portToUse}...`);
|
||||
this.mcpServer = new MCPHttpServer(this.app, portToUse, this);
|
||||
await this.mcpServer.start();
|
||||
this.updateStatusBar();
|
||||
Debug.log('✅ MCP server started successfully');
|
||||
if (this.settings.showConnectionStatus) {
|
||||
new Notice(`MCP server started on port ${this.settings.httpPort}`);
|
||||
new Notice(`MCP server started on ${protocol} port ${portToUse}`);
|
||||
}
|
||||
} catch (error) {
|
||||
Debug.error('❌ Failed to start MCP server:', error);
|
||||
|
|
@ -678,7 +683,7 @@ class MCPSettingTab extends PluginSettingTab {
|
|||
}));
|
||||
|
||||
if (this.plugin.settings.httpsEnabled) {
|
||||
new Setting(containerEl)
|
||||
const httpsPortSetting = new Setting(containerEl)
|
||||
.setName('HTTPS Port')
|
||||
.setDesc('Port for HTTPS MCP server (default: 3443)')
|
||||
.addText(text => text
|
||||
|
|
@ -689,9 +694,14 @@ class MCPSettingTab extends PluginSettingTab {
|
|||
if (!isNaN(port) && port > 0 && port < 65536) {
|
||||
this.plugin.settings.httpsPort = port;
|
||||
await this.plugin.saveSettings();
|
||||
// Check port availability for HTTPS
|
||||
this.checkHttpsPortAvailability(port, httpsPortSetting);
|
||||
}
|
||||
}));
|
||||
|
||||
// Check HTTPS port availability on load
|
||||
this.checkHttpsPortAvailability(this.plugin.settings.httpsPort, httpsPortSetting);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Auto-generate Certificate')
|
||||
.setDesc('Automatically generate a self-signed certificate if none exists')
|
||||
|
|
@ -1393,6 +1403,26 @@ class MCPSettingTab extends PluginSettingTab {
|
|||
setting.setDesc('Port for HTTP MCP server (default: 3001)');
|
||||
}
|
||||
}
|
||||
|
||||
private async checkHttpsPortAvailability(port: number, setting: Setting): Promise<void> {
|
||||
if (!this.plugin.settings.autoDetectPortConflicts) return;
|
||||
|
||||
const status = await this.plugin.checkPortConflict(port);
|
||||
|
||||
switch (status) {
|
||||
case 'available':
|
||||
setting.setDesc(`Port for HTTPS MCP server (default: 3443) ✅ Available`);
|
||||
break;
|
||||
case 'this-server':
|
||||
setting.setDesc(`Port for HTTPS MCP server (default: 3443) 🟢 This server`);
|
||||
break;
|
||||
case 'in-use':
|
||||
setting.setDesc(`Port for HTTPS MCP server (default: 3443) ⚠️ Port ${port} in use`);
|
||||
break;
|
||||
default:
|
||||
setting.setDesc('Port for HTTPS MCP server (default: 3443)');
|
||||
}
|
||||
}
|
||||
|
||||
refreshConnectionStatus(): void {
|
||||
// Simply refresh the entire settings display to ensure accurate data
|
||||
|
|
|
|||
Loading…
Reference in a new issue