{"id":"ed85f1a8-3360-46b7-9217-541b2c809d56","slug":"tedyno-tessera","kind":"mcp","name":"Tessera","summary":"A fast, native database client for macOS — PostgreSQL, MySQL, MariaDB and SQLite. Swift and SwiftUI, no Electron.","owner":"tedyno","repoUrl":"https://github.com/tedyno/Tessera","license":"GPL-3.0","licenseTier":"strong-copyleft","trust":"community","stars":2,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-07-18T22:49:41.000Z","addedAt":"2026-10-21T09:20:59.578Z","logoUrl":"https://avatars.githubusercontent.com/u/31020031?u=0753802d8de3a58033c8e3828af81d8b33355c58&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["databases"],"tags":["database","database-client","database-gui","macos","mariadb","mysql","postgresql","sql"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-27T00:11:45.833Z","sample":false,"url":"https://conduits.dev/tools/tedyno-tessera","language":"Swift","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Tessera\n\n[![CI](https://github.com/tedyno/Tessera/actions/workflows/ci.yml/badge.svg)](https://github.com/tedyno/Tessera/actions/workflows/ci.yml)\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)\n![Platform: macOS 26+](https://img.shields.io/badge/platform-macOS%2026%2B-lightgrey)\n\nA fast, native database client for macOS. No Electron, no webview, no JavaScript —\npure Swift and SwiftUI. Built for PostgreSQL, MySQL, MariaDB, SQLite and Redis, with\nsecure credential storage and SSH tunnelling.\n\nThe name is the Latin word for a single tile of a mosaic: one cell of a data grid, from\nwhich the whole picture is assembled.\n\n> **Status:** under active development and usable day to day, but expect rough edges.\n\n## Features\n\n- **PostgreSQL, MySQL, MariaDB, SQLite and Redis** through one interface, with several connections\n  live at once — staging and production side by side. Each tab is bound to its own session,\n  labelled with its connection and a live status dot, and a per-tab picker points it at any\n  connection. SQLite needs no server at all: point a connection at a file (or a new path —\n  the file is created on first connect).\n- **Redis** gets its own primitives instead of a SQL facade: the console is a redis-cli\n  (⌘↩ runs the line under the cursor, replies render into the grid — HGETALL as\n  field/value pairs, ZRANGE WITHSCORES as member/score), and connecting opens a key\n  browser — SCAN with a MATCH pattern, key/type/TTL pages with Load more, double-click\n  opens a key with its type's read command, ⌫ deletes keys behind a confirmation.\n- **Split-pane tiling** — drag a tab onto a pane's edge to split the workspace four ways,\n  drop it on another pane's tab bar to move it there, drag the dividers to resize, and close\n  a whole pane with its tabs. Tabs reorder within a pane by drag. The whole layout persists\n  across launches.\n- **Window themes** — choose a backdrop from a grid of live gradient swatches (the Monokai\n  Pro filters plus Catppuccin, Tokyo Night, Dracula, Nord, Gruvbox, Rosé Pine, One Dark) and\n  a light / dark / system appearance. The whole app follows the theme — sheets, sidebar,\n  results header — and the Dock icon changes with it.\n- **Connection organizer** — nest connections in folders, colour-code them, mark the\n  dangerous ones read-only, and connect / disconnect / reconnect / re-introspect from the\n  sidebar (with a live green status dot).\n- **Schema browser** and a **global search** (double-Shift) across every connection's\n  schemas, tables and columns.\n- **SQL console** with syntax highlighting, Tab-to-complete autocompletion (schema-aware),\n  run-statement-at-cursor, server-side cancellation (`pg_cancel_backend` / `KILL QUERY`),\n  and running a `.sql` file statement by statement.\n- **Editable results grid** — edit, insert, duplicate and delete rows; changes are staged,\n  listed with per-row discard, reviewable as SQL, and committed together. Multi-cell\n  selection, copy/paste, and column auto-fit.\n- **Table view** separate from the console, with a completing WHERE filter, sortable\n  headers, an adjustable row limit, paging (\"Load more\") and total row counts.\n- **Schema editing** — add, rename, retype and drop columns, indexes and tables, with the\n  generated DDL shown before it runs.\n- **Export** a table, a schema or the whole database through `pg_dump` / `mysqldump` /\n  `mariadb-dump` — with\n  structure/data, DROP/CREATE options, INSERT-statement or custom format, and **gzip** so\n  you can send it straight on. The binary is matched to the server's major version. A\n  configurable default export folder (Downloads) with timestamped filenames, and\n  **reveal-in-Finder after export**.\n- **Import / restore** dumps through `psql` / `pg_restore` / `mysql` / `mariadb`. (SQLite has\n  no dump pipeline — the database *is* a file; Tessera offers Reveal in Finder instead.)\n- **Export query results** to CSV or JSON.\n- **SSH tunnelling** with password or key authentication (OpenSSH ed25519 and RSA keys).\n- **Secrets stay in the Keychain** — never in a config file, never in the organizer JSON.\n- **Built-in MCP server** — optionally let an AI assistant inspect your schema and run\n  queries, gated by per-connection read/write permissions. See below.\n- **Localized** — English and Czech.\n\n## Requirements\n\nmacOS 26 or later, on Apple silicon or Intel. Building requires Xcode 26 or later.\n\n## Download\n\nThrough [Homebrew](https://brew.sh):\n\n```sh\nbrew tap tedyno/tessera\nbrew trust tedyno/tessera\nbrew install --cask tessera\n```\n\nThe middle step is not a formality Homebrew invented for Tessera: since version 6 it refuses\nto load a cask from a third-party tap until you say you trust it. Tessera cannot live in the\nofficial `homebrew/cask` tap, which from 2026-09-01 accepts only notarized apps — see\n[Installing](#installing) below.\n\nOr grab the latest **[`Tessera.dmg` from Releases](https://github.com/tedyno/Tessera/releases/latest)**,\nopen it, and drag Tessera to your Applications folder. The DMG is a universal build (Apple\nsilicon and Intel).\n\nFrom 0.20.0 on, Tessera **keeps itself up to date** — it checks for new versions and offers\nto install them, and you can trigger a check anytime from **Tessera ▸ Check for Updates…**.\nEvery update is verified against a signature (Sparkle / EdDSA) before it is installed, so it\nis safe even though the app isn't notarized.\n\n## Installing\n\nThe build is **not notarized**, because notarization requires a paid Apple Developer account\nand this is an open-source project without one. macOS will therefore refuse to open it on the\nfirst try, reporting that it cannot be checked for malicious software.\n\nTo open it anyway, launch it once, dismiss the warning, then go to **System Settings ▸\nPrivacy & Security**, scroll to the security section, and click **Open Anyway**. (The old\nright-click → *Open* shortcut no longer works; Apple removed that bypass in macOS 15.)\n\nAlternatively, strip the quarantine flag from the terminal:\n\n```sh\nxattr -dr com.apple.quarantine /Applications/Tessera.app\n```\n\nIf overriding Gatekeeper makes you uncomfortable — reasonably so — build it from source\ninstead, and the question never comes up.\n\n## Building from source\n\n```sh\ngit clone https://github.com/tedyno/Tessera.git\ncd Tessera\nopen Tessera.xcodeproj   # then ⌘R\n```\n\nOr from the command line:\n\n```sh\nxcodebuild -project Tessera.xcodeproj -scheme Tessera -destination 'platform=macOS' build\n```\n\nThe portable core is a local Swift package and builds and tests on its own:\n\n```sh\ncd TesseraCore && swift build && swift test\n```\n\n### Stop the Keychain re-asking on every build\n\nBy default local builds are **ad-hoc** signed, which gives the app a different identity each\ntime, so the Keychain treats every build as a new application and re-asks permission for each\nstored connection password. To give the app a stable identity, create a self-signed code\nsigning certificate once:\n\n```sh\nScripts/make-signing-cert.sh\n```\n\nIt writes an untracked `Config/Local.xcconfig` pointing the build at the certificate. Rebuild,\nthen click **Always Allow** on the Keychain prompt once per connection — because the signature\nis now stable, it won't ask again. (This does not get you past Gatekeeper; that still needs a\npaid Developer ID and notarization.)\n\n## MCP server\n\nTessera can act as a [Model Context Protocol](https://modelcontextprotocol.io) server, so an\nassistant (Claude Code, Codex, or any MCP client) can inspect your schema and run queries for you.\n\nIt is **off by default**, and access is layered so that nothing happens by accident:\n\n1. A master switch in **Settings ▸ MCP**, off until you turn it on.\n2. Per connection, separate **read** and **write** permissions — a connection is invisible to\n   MCP until you grant read.\n3. Every write, export and import asks for confirmation, showing the exact SQL or file.\n4. A connection marked read-only can never be granted write access.\n\nThe server binds to `127.0.0.1` only, requires a bearer token, and refuses any request\ncarrying an `Origin` header, so a web page cannot drive it. Passwords are never exposed over\nMCP, and MCP cannot choose where an export is written. **Query ▸ MCP Activity** shows a live\nlog of everything a client has done.\n\n### Letting the safe tools run without a prompt\n\nGranting a connection read access in Tessera does not stop your assistant asking before\nevery call — that decision belongs to the client, which knows nothing about Tessera's own\npermissions. Settings ▸ MCP therefore generates the snippet for the client you pick: a\n`config.toml` block for Codex, plain `mcpServers` JSON for anything else, and for Claude\nCode the `claude mcp add` command — after which you allow the rule `mcp__tessera` in\n`/permissions`.\n\nTo make that safe, the tools describe themselves:\n\n- Reads, and exports into your export folder, are annotated `readOnlyHint` — Codex's\n  `writes` approval mode and editors such as VS Code run these unattended.\n- Anything that can overwrite data is annotated `destructiveHint`, and additionally\n  carries Anthropic's `requiresUserInteraction`, which makes Claude Code prompt for it on\n  **every** call — even in auto and bypass modes, and even if you allowed the whole\n  `tessera` server. That covers `import_dump`, `delete_connection` and\n  `update_connection`.\n- `run_query` is not marked that way, because it is also how an assistant runs an ordinary\n  `SELECT`. Its writes are gated by Tessera's own approval sheet instead.\n\nAnnotations are hints, not guarantees — the real limits are the ones enforced above, and\nthey hold whatever a client makes of the hints.\n\nNone of that is obvious to the assistant, which sees only that its calls keep being\nrefused. Settings ▸ MCP therefore has a second Copy button, **Assistant notes**: a short\nbriefing you paste into the conversation when it gets stuck. It says that the client\ngates tool calls separately from Tessera, that a hidden connection is hidden on purpose,\nand that the fix is the `mcp__tessera` rule — so the assistant stops sending you back to\nre-check permissions you already granted.\n\nIt is a button rather than the protocol's `instructions` field on purpose. Clients re-send\nthat field as context on *every* turn, and this is a first-run problem most sessions never\nhit — pasted by hand it costs nothing until it helps.\n\n## Architecture\n\nTwo layers, strictly separated:\n\n```\nTessera.xcodeproj      # macOS app target (SwiftUI)\nTessera/               # app sources (UI layer)\nTesseraCore/           # local Swift Package — portable core, no SwiftUI\n  Sources/DBKit/           # models + protocols (no networking dependencies)\n  Sources/DBPersistence/   # organizer and profile persistence (JSON)\n  Sources/DBDriverPostgres/\n  Sources/DBDriverMySQL/   # also serves MariaDB (same wire protocol)\n  Sources/DBDriverSQLite/  # system libsqlite3, no dependencies\n  Sources/DBDriverRedis/   # hand-rolled RESP2 client over SwiftNIO\n  Sources/DBTunnel/        # SSH local port forwarding\n  Sources/DBSecurity/      # Keychain wrapper\n  Sources/DBMCPServer/     # MCP HTTP transport\n```\n\n`TesseraCore` deliberately knows nothing about SwiftUI; the drivers depend on `DBKit`, never\nthe other way round. The UI talks to the core purely through `DBKit` protocols, injected as\ndependencies.\n\n**Tech stack:** Swift 6 (strict concurrency), SwiftUI, PostgresNIO, MySQLNIO, the system\nSQLite3 C library, a hand-rolled RESP2 Redis client on SwiftNIO, Citadel (swift-nio-ssh),\nSecurity.framework.\n\n## Contributing\n\nIssues and pull requests are welcome. Two things to know before you open one:\n\n- All repository content is in **English** — code, comments, commit messages, docs. The app\n  UI is localized separately through `Tessera/Localizable.xcstrings`.\n- Every user-facing string must be localizable; never hand a bare `String` to the UI.\n\n[`CONTRIBUTING.md`](CONTRIBUTING.md) has the rest: how the two layers are separated, why\nnon-trivial logic belongs in `TesseraCore` with tests, and how to add a translation. Security\nissues go through [`SECURITY.md`](SECURITY.md), privately rather than in a public issue.\n\n## License\n\nCopyright (C) 2026 David Vaníček\n\nTessera is free software: you can redistribute it and modify it under the terms of the\n**GNU General Public License, version 3**, as published by the Free Software Foundation.\nSee [`LICENSE`](LICENSE) for the full text.\n\nIt is distributed in the hope that it will be useful, but **without any warranty** — without\neven the implied warranty of merchantability or fitness for a particular purpose.\n\nThird-party components and their notices are listed in\n[`THIRD-PARTY-LICENSES.md`](THIRD-PARTY-LICENSES.md).\n\n## Releasing\n\nMaintainers only:\n\n```sh\nScripts/make-release.sh 0.1.0            # build, sign, package into dist/\nScripts/make-release.sh 0.1.0 --publish  # ...and create the GitHub release\n```\n\nThe release is signed locally rather than in CI: the certificate is what every user's\nKeychain trusts, so it never leaves the maintainer's machine. The script refuses to package\nan ad-hoc signed build, because releasing one would reset every user's stored passwords.\n"}