Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
279d95d
feat(integrations): UUID-keyed deep links and external access foundation
datlechin Apr 27, 2026
4c59450
feat(integrations): per-connection external access setting UI
datlechin Apr 27, 2026
a6246bf
docs(integrations): external API documentation and CHANGELOG
datlechin Apr 27, 2026
eb44e89
feat(integrations): tablepro-mcp stdio CLI binary
datlechin Apr 27, 2026
fdca4da
feat(integrations): pairing flow with PKCE-flavored exchange
datlechin Apr 27, 2026
b80c4ab
feat(integrations): Raycast extension
datlechin Apr 27, 2026
54ca4f2
feat(integrations): audit log storage and new MCP tools
datlechin Apr 27, 2026
f8ff86d
docs: fix mintlify parse errors in plugin-registry and ai-assistant
datlechin Apr 27, 2026
9798762
docs(integrations): align with shipped contract
datlechin Apr 27, 2026
06deeb6
feat(extension): align wire shapes with shipped contract
datlechin Apr 27, 2026
1d6237f
docs: fold tablepro://import params into external-api/url-scheme
datlechin Apr 27, 2026
9a98815
docs: rewrite features/mcp as orientation page that links to external…
datlechin Apr 27, 2026
6f5437e
docs: remove stale features/deep-links page, update nav and cards
datlechin Apr 27, 2026
34f79dd
docs: rename cursor-claude to mcp-clients with generic guide and 9 cl…
datlechin Apr 27, 2026
24d8203
docs: surface External API in landing page and features overview
datlechin Apr 27, 2026
e708091
docs: add External Access and external client notes to connection-rel…
datlechin Apr 27, 2026
a149cca
docs: cross-link External API from tabs, query history, and keyboard …
datlechin Apr 27, 2026
243be1d
docs: tighten MCP page lazy-start description and update settings ref…
datlechin Apr 27, 2026
c4b18b8
feat(settings): rename MCP tab to Integrations
datlechin Apr 27, 2026
9b3e8f3
fix(integrations): filter blocked connections from list_connections r…
datlechin Apr 27, 2026
591b5d1
feat(integrations): add date filter params to search_query_history tool
datlechin Apr 27, 2026
95690d2
docs(integrations): align mcp-resources shapes with implementation
datlechin Apr 27, 2026
b532f41
feat(extension): set Raycast author to ngoquocdat and update callback…
datlechin Apr 27, 2026
2be9a25
fix(extension): read connections.json from TablePro support dir not c…
datlechin Apr 28, 2026
aaccdd9
refactor: unify MCP files into TablePro support dir, drop com.TablePr…
datlechin Apr 28, 2026
416bd9f
docs: drop Past breaking changes table from versioning page
datlechin Apr 28, 2026
3f57f33
fix(extension): drop redundant TablePro subtitles from commands
datlechin Apr 28, 2026
aa03287
fix(extension): polish action titles, empty states, and pair form for…
datlechin Apr 28, 2026
ff243bd
refactor(extension): replace useState/useEffect data loading with use…
datlechin Apr 28, 2026
3494507
refactor(extension): adopt useForm and add validation to pair flow
datlechin Apr 28, 2026
42f288f
chore(extension): add discovery keywords and use Action.Open variants…
datlechin Apr 28, 2026
69508e6
chore: remove extensions/ — Raycast extension lives in raycast/extens…
datlechin Apr 28, 2026
13eab63
fix(integrations): use Raycast launchContext format for raycast:// re…
datlechin Apr 28, 2026
2580da9
fix(mcp): drop blocked-connection results from list_recent_tabs and s…
datlechin Apr 28, 2026
f19dab5
fix(mcp): enforce externalAccess readOnly on state-mutating tools
datlechin Apr 28, 2026
8a2ca0a
fix(mcp): push search_query_history allowlist into SQL to avoid post-…
datlechin Apr 28, 2026
8fb9141
docs: drop em dashes from pairing redirect format section
datlechin Apr 28, 2026
614a03a
chore: fix lint errors after rebase onto main
datlechin Apr 30, 2026
af0a5d4
fix(mcp): run auth checks before raising window in focus_query_tab
datlechin Apr 30, 2026
a2d4c29
Merge branch 'main' into feat/raycast-integration
datlechin Apr 30, 2026
a2c09ce
fix(mcp): validate and gate export_data table names against SQL injec…
datlechin Apr 30, 2026
9983008
fix(mcp): allow readOnly tokens to navigate window/tab/focus tools
datlechin Apr 30, 2026
6992614
fix(mcp): filter list_connections by token allowed connection ids
datlechin Apr 30, 2026
c9cbd55
fix(mcp): refuse focus_query_tab on tabs without a connection
datlechin Apr 30, 2026
7def027
fix(mcp): restrict export_data output path to Downloads directory
datlechin Apr 30, 2026
8368530
refactor(mcp): rename history allowlist var to clarify token scope
datlechin Apr 30, 2026
d423c67
style(mcp): remove function comment in MCPAuthGuard
datlechin Apr 30, 2026
80d72a7
test(mcp): add export_data table injection regression tests
datlechin Apr 30, 2026
90b9527
fix(mcp): treat empty allowedConnectionIds set as no-access in list_c…
datlechin Apr 30, 2026
ae3de89
fix(deeplink): support schema-qualified table URL path
datlechin Apr 30, 2026
2810452
fix(mcp): handle OPTIONS preflight on integrations exchange endpoint
datlechin Apr 30, 2026
fd1ee94
fix(mcp): guard pairing approval continuation against double resume
datlechin Apr 30, 2026
96dc93c
fix(deeplink): use restoreOrDefault intent for connect URL to avoid f…
datlechin Apr 30, 2026
c130db0
fix(deeplink): suppress welcome window when handling tablepro URL on …
datlechin Apr 30, 2026
17e8975
fix(launch): skip auto-reconnect when a deeplink is being handled on …
datlechin Apr 30, 2026
c697113
fix(launch): do not close restored windows when handling deeplink (ra…
datlechin Apr 30, 2026
675575c
fix(mcp): dedupe concurrent ai-access approval prompts via in-flight …
datlechin Apr 30, 2026
df17ff4
fix(sidebar): mark sidebar loaded when schema already loaded by sibli…
datlechin Apr 30, 2026
b229880
fix(sidebar): render table list when tables binding has data, regardl…
datlechin Apr 30, 2026
c8d2b7a
fix(deeplink): skip placeholder window when deeplink targets specific…
datlechin Apr 30, 2026
a61013e
fix(sidebar): hydrate session.tables from cached schema provider when…
datlechin Apr 30, 2026
6281a71
fix(schema): hydrate session.tables from provider after loadSchema fetch
datlechin Apr 30, 2026
4f36ba6
fix(deeplink): route openTable into existing window's tab manager ins…
datlechin Apr 30, 2026
2ad0160
fix(mcp): auto-connect session when tool requires driver
datlechin Apr 30, 2026
e6f5231
fix(mcp): activate app before auto-connect so any prompt has a key wi…
datlechin Apr 30, 2026
0a0b71f
fix(mcp): dedupe concurrent auto-connect tasks for same connection
datlechin Apr 30, 2026
afc5e6d
fix(mcp): allow tool meta resolution from disk so auto-connect can ru…
datlechin Apr 30, 2026
77aa01f
fix(mcp): use defer for inFlightConnects cleanup
datlechin Apr 30, 2026
f162f28
refactor: typed lifecycle, single auth gate, imperative window factor…
datlechin May 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- External API for Raycast, Cursor, Claude Desktop, and other MCP clients: URL scheme, stdio MCP transport, pairing flow, activity log
- UUID-keyed deep links: `tablepro://connect/<uuid>`, `.../table/<name>`, `.../query?sql=...`, `tablepro://integrations/pair?...`, `tablepro://integrations/start-mcp`
- stdio MCP transport via bundled `tablepro-mcp` CLI at `Contents/MacOS/tablepro-mcp`. Reads handshake file, no token needed
- Per-connection `External Access` setting (`blocked`, `readOnly`, `readWrite`). Defaults to `readOnly`. Bounds token reach via `MIN(token.scope, connection.externalAccess)`
- Pairing flow with PKCE code exchange. One-click token issuance for Raycast and other extensions
- Activity log at `~/Library/Application Support/TablePro/mcp-audit.db`. Viewable in Settings > Integrations > Activity Log. 90-day retention
- New MCP tools: `list_recent_tabs`, `search_query_history`, `open_connection_window`, `open_table_tab`, `focus_query_tab`
- PostgreSQL ICU collation provider in Create Database (PG 15+). Provider picker is added when the server reports PG 15 or newer. ICU locale list comes from `pg_collation`. SQL emission is version-aware: PG 16+ uses unified `LOCALE`, PG 15 uses `ICU_LOCALE` with `LC_COLLATE 'C' LC_CTYPE 'C'`.
- Connection URL parsing: SSH `user:password@host` split, `safeModeLevel` from TablePlus URLs, case-insensitive query params
- Connection URL export: SSH password, Redis database index, MongoDB auth params (`authSource`, `authMechanism`, `replicaSet`), and multi-host
Expand All @@ -25,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- MCP server lazy-starts on first external request. Manual enable in Settings is no longer required
- Settings tab renamed from "MCP" to "Integrations" with new sections for connected clients, activity log, and pairing
- Storage and sync singletons accept dependencies via init for test isolation, matching Apple's URLSession and UserDefaults convention. Production callers using `.shared` are unchanged. `SQLFavoriteStorage` is now an actor so its first access no longer blocks the main thread on SQLite setup.
- Create Database dialog is now driver-driven. Each driver discovers its own valid options (PostgreSQL queries `pg_collation` and `pg_database`, MySQL/MariaDB query `information_schema.character_sets`/`collations`). The hardcoded macOS-flavored locale list is gone. Engines that don't support creation hide the Create button instead of failing on click.
- Introduced TableRows, Row, and Delta value types in TablePro/Models/Query/ as the foundation for the data grid row model rewrite. No callers migrated yet (Phase C.1 of the DataGrid refactor).
Expand Down Expand Up @@ -64,6 +73,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Data grid cell focus ring redraws when the user toggles Light or Dark mode mid-session, picking up the system's appearance-aware focus indicator color
- Data grid keeps sortedIDs and cachedRowCount paired by calling updateCache() immediately after the SwiftUI bridge writes new sortedIDs to the coordinator, removing a window where the cached count and the sort permutation could disagree
- Display formats memoized per tab on MainContentCoordinator keyed by schema version, smart-detection setting, and format-overrides version, so ValueDisplayDetector.detect runs once per result schema instead of on every SwiftUI body evaluation
- MCP HTTP router replaced with a route registry. `MCPRouter` now matches paths and methods against a list of `MCPRouteHandler` values; `/mcp` traffic and `/v1/integrations/exchange` traffic each live in their own handler file under `Core/MCP/Routes/`. OPTIONS preflight is handled once at the router level for every path
- `MCPAuthGuard` and `MCPConnectionBridge` route concurrent dedup through a shared `OnceTask` actor (`Core/Concurrency/OnceTask.swift`). Cleanup of in-flight slots happens in `defer` inside the actor, so a cancelled or thrown caller no longer leaves a stale entry behind.

### Removed (BREAKING)

- `tablepro://connect/<name>/...` deep links. Replace with UUID-keyed paths from "Copy Connection Deep Link" in the sidebar context menu. User-saved bookmarks must be regenerated
- MCP server data directory moved from `~/Library/Application Support/com.TablePro/` to `~/Library/Application Support/TablePro/`. Existing tokens, audit log, and handshake files are not migrated. Re-pair Raycast, Cursor, Claude Desktop, and any other external clients after upgrading. Delete the old directory with `rm -rf ~/Library/Application Support/com.TablePro`

### Fixed

Expand All @@ -77,6 +93,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Persist group deletions before firing the sync notification, fixing a race that could re-upload deleted groups via iCloud.
- Persist connection deletions before firing the sync notification, fixing the same race for deleted connections.
- Refuse to generate SQL when the database dialect cannot be resolved, instead of silently emitting unquoted identifiers.
- MCP `execute_query`: strip trailing semicolons before appending `LIMIT/OFFSET`, fixing `syntax error at or near LIMIT` for queries like `select * from t;`.

## [0.36.0] - 2026-04-27

Expand Down
37 changes: 26 additions & 11 deletions TablePro.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

/* Begin PBXBuildFile section */
5A32BBFB2F9D5EAB00BAEB5F /* X509 in Frameworks */ = {isa = PBXBuildFile; productRef = 5A32BBFA2F9D5EAB00BAEB5F /* X509 */; };
5A32BC0B2F9D659100BAEB5F /* mcp-server in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5A32BC002F9D5F1300BAEB5F /* mcp-server */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
5A32BC0B2F9D659100BAEB5F /* tablepro-mcp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5A32BC002F9D5F1300BAEB5F /* tablepro-mcp */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
5A3A69B82F976F38000AC5B2 /* GhosttyTerminal in Frameworks */ = {isa = PBXBuildFile; productRef = 5A3A69B72F976F38000AC5B2 /* GhosttyTerminal */; };
5A3A69BA2F976F38000AC5B2 /* GhosttyTheme in Frameworks */ = {isa = PBXBuildFile; productRef = 5A3A69B92F976F38000AC5B2 /* GhosttyTheme */; };
5A3BE6FC2F97DB0000611C1F /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
Expand Down Expand Up @@ -75,6 +75,13 @@
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
5A32BC0C2F9D659200BAEB5F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5A32BBFF2F9D5F1300BAEB5F;
remoteInfo = "tablepro-mcp";
};
5A860000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
Expand Down Expand Up @@ -219,7 +226,7 @@
dstPath = "";
dstSubfolderSpec = 6;
files = (
5A32BC0B2F9D659100BAEB5F /* mcp-server in CopyFiles */,
5A32BC0B2F9D659100BAEB5F /* tablepro-mcp in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -259,7 +266,7 @@

/* Begin PBXFileReference section */
5A1091C72EF17EDC0055EA7C /* TablePro.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TablePro.app; sourceTree = BUILT_PRODUCTS_DIR; };
5A32BC002F9D5F1300BAEB5F /* mcp-server */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "mcp-server"; sourceTree = BUILT_PRODUCTS_DIR; };
5A32BC002F9D5F1300BAEB5F /* tablepro-mcp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "tablepro-mcp"; sourceTree = BUILT_PRODUCTS_DIR; };
5A3BE6F82F97DA8100611C1F /* LibSQLDriverPlugin.tableplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LibSQLDriverPlugin.tableplugin; sourceTree = BUILT_PRODUCTS_DIR; };
5A860000100000000 /* TableProPluginKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TableProPluginKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5A861000100000000 /* OracleDriver.tableplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OracleDriver.tableplugin; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -311,8 +318,8 @@
5A32BC082F9D5FC900BAEB5F /* Exceptions for "TablePro" folder in "mcp-server" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
MCPBridge/main.swift,
MCPBridge/MCPBridgeProxy.swift,
CLI/main.swift,
CLI/MCPBridgeProxy.swift,
);
target = 5A32BBFF2F9D5F1300BAEB5F /* mcp-server */;
};
Expand Down Expand Up @@ -452,9 +459,9 @@
5AF312BE2F36FF7500E86682 /* Exceptions for "TablePro" folder in "TablePro" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
CLI/main.swift,
CLI/MCPBridgeProxy.swift,
Info.plist,
MCPBridge/main.swift,
MCPBridge/MCPBridgeProxy.swift,
);
target = 5A1091C62EF17EDC0055EA7C /* TablePro */;
};
Expand Down Expand Up @@ -913,7 +920,7 @@
5ABQR00300000000000000A0 /* BigQueryDriverPlugin.tableplugin */,
5AE4F4742F6BC0640097AC5B /* CloudflareD1DriverPlugin.tableplugin */,
5A3BE6F82F97DA8100611C1F /* LibSQLDriverPlugin.tableplugin */,
5A32BC002F9D5F1300BAEB5F /* mcp-server */,
5A32BC002F9D5F1300BAEB5F /* tablepro-mcp */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -994,6 +1001,7 @@
buildRules = (
);
dependencies = (
5A32BC0D2F9D659200BAEB5F /* PBXTargetDependency */,
5A860000C00000000 /* PBXTargetDependency */,
5A861000C00000000 /* PBXTargetDependency */,
5A862000C00000000 /* PBXTargetDependency */,
Expand Down Expand Up @@ -1050,7 +1058,7 @@
packageProductDependencies = (
);
productName = "mcp-server";
productReference = 5A32BC002F9D5F1300BAEB5F /* mcp-server */;
productReference = 5A32BC002F9D5F1300BAEB5F /* tablepro-mcp */;
productType = "com.apple.product-type.tool";
};
5A3BE6F72F97DA8100611C1F /* LibSQLDriverPlugin */ = {
Expand Down Expand Up @@ -2024,6 +2032,11 @@
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
5A32BC0D2F9D659200BAEB5F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A32BBFF2F9D5F1300BAEB5F /* mcp-server */;
targetProxy = 5A32BC0C2F9D659200BAEB5F /* PBXContainerItemProxy */;
};
5A860000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A860000000000000 /* TableProPluginKit */;
Expand Down Expand Up @@ -2402,7 +2415,8 @@
DEVELOPMENT_TEAM = D7HJ5TFYCU;
ENABLE_HARDENED_RUNTIME = YES;
MACOSX_DEPLOYMENT_TARGET = 14.0;
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = "com.TablePro.tablepro-mcp";
PRODUCT_NAME = "tablepro-mcp";
SDKROOT = macosx;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
Expand All @@ -2417,7 +2431,8 @@
DEVELOPMENT_TEAM = D7HJ5TFYCU;
ENABLE_HARDENED_RUNTIME = YES;
MACOSX_DEPLOYMENT_TARGET = 14.0;
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = "com.TablePro.tablepro-mcp";
PRODUCT_NAME = "tablepro-mcp";
SDKROOT = macosx;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
</BuildAction>
<TestAction
buildConfiguration = "Debug"
codeCoverageEnabled = "NO"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
Expand Down
Loading
Loading