Architecture
TablePro is built with:- SwiftUI for the UI layer
- AppKit for low-level macOS integration (windows, menus, native tabs)
- Swift Concurrency (async/await, actors) for all async work
- Native C libraries for database connectivity (linked as static
.afiles)
Design Patterns
MVVM
- Models: structs (value types, Codable)
- ViewModels:
@Observableclasses (Swift 5.9+) - Views: SwiftUI, with AppKit bridging where needed
Protocol-Oriented Drivers
All database connectivity goes through one protocol:DatabaseType.pluginTypeId.
Actor Isolation
Thread-safe shared state uses Swift actors:Dependencies
CodeEditSourceEditor bundles a SwiftLint plugin, which is why
-skipPackagePluginValidation is required for CLI builds.Plugin System
All database drivers are.tableplugin bundles loaded at runtime. This keeps the app binary small and makes adding new databases a matter of dropping in a bundle.
Key files:
Driver Plugins
Built-in plugins ship inside the app bundle. Registry plugins are downloaded on demand from the plugin registry.
Opt-in Plugin Protocols
Plugins can adopt additional protocols beyondPluginDatabaseDriver to expose extra capabilities. These are runtime-cast (as?) by PluginManager, so existing plugins that do not conform keep working without an ABI bump.
A
PluginDefaultSortProvider returns one of:
.useAppDefault(default if the plugin does not conform): apply the user setting (Primary key, First column, or No sorting)..suppress: never auto-sort tables opened with this plugin (useful for NoSQL engines where ORDER BY is not meaningful)..forceColumns([String]): ignore the user setting and sort by the supplied column names (for example MongoDB could force_id).
Key Components
DatabaseManager
Connection pool and lifecycle management. Primary interface between UI and drivers. Handles connect, disconnect, reconnect, and session tracking.ConnectionHealthMonitor
Pings active connections every 30 seconds. Auto-reconnects with exponential backoff on failure.Autocomplete Engine
- CompletionEngine: entry point, produces ranked suggestions
- SQLContextAnalyzer: parses cursor position context (table ref, column ref, keyword)
- SQLSchemaProvider: actor that caches and serves schema data
MCP Layer
The MCP server lives underCore/MCP/ and is split into five horizontal layers. Each layer talks only to the layer below it.
Wire: pure Codable types, no I/O. JSON-RPC 2.0, strict-CRLF HTTP, SSE encoder/decoder.
Transport: HTTP server uses NWListener and binds to 127.0.0.1:<port> by default. The stream endpoints (exchanges, listenerState) are bounded AsyncStreams consumed by MCPServerManager. The bridge’s client-side transport uses URLSession.bytes(for:) for incremental SSE.
Session: MCPSessionStore is an actor that owns session lifecycle. Idle timeout is 15 minutes. Token revocation marks sessions with .tokenRevoked and the SSE stream emits a typed terminate comment so clients can distinguish revoke from network blip.
Protocol: MCPProtocolDispatcher spawns a child Task per inbound exchange, so two concurrent tool calls run in parallel instead of queueing on the dispatcher actor. Per-request cancellation flows through MCPInflightRegistry. Long-running tools emit notifications/progress to clients that pass _meta.progressToken.
Bridge: tablepro-mcp is a 50-line composition root. MCPStdioMessageTransport host-side, MCPStreamableHttpClientTransport upstream. Errors land in os_log and stderr. The host-facing transport writes only validated JsonRpcMessage bytes to stdout.
The server accepts protocol versions 2025-03-26, 2025-06-18, and 2025-11-25. See Versioning for the negotiation rules and the additive-within-major-version stability policy.
Data Flow
Connection
Query Execution
State Management
Directory Structure
TablePro
Core
Database
Plugins
Services
Utilities
Autocomplete
SSH
QuerySupport
Views
Models
ViewModels
Extensions
Theme
Resources
Plugins
TableProPluginKit
MySQLDriverPlugin
PostgreSQLDriverPlugin
SQLiteDriverPlugin
ClickHouseDriverPlugin
MSSQLDriverPlugin
RedisDriverPlugin
...
Libs
TableProTests
scripts
