Skip to main content
Glama
ulrich-johannes

datastore-mcp

datastore-mcp

A remote MCP (Model Context Protocol) server that gives an AI assistant a persistent key/value state store backed by MariaDB. Deployed as a container on Fly.io, authenticated via OAuth 2.1.

What it stores

A single table (name configurable via DB_TABLE) with columns:

column

meaning

var_name

primary key / variable name

description

short human-readable description

content

the value (LONGTEXT — can be very long)

created

row creation timestamp

last_updated

auto-updated on every change

deleted

soft-delete flag

The server creates this table automatically on startup if it doesn't exist (see migrations/001_init.sql for the equivalent manual DDL).

Related MCP server: Kova Mind MCP Server

MCP tools exposed

  • state_create(var_name, description?, content?) — create a new variable; fails if it already exists (unless it was soft-deleted, in which case it's revived).

  • state_get(var_name) — read a variable's full record.

  • state_update(var_name, description?, content?) — update an existing variable; omitted fields are left unchanged.

  • state_delete(var_name) — soft-delete a variable (sets deleted = 1).

  • state_list(include_deleted?) — list var_name + description for all (non-deleted, by default) variables.

Authentication

The MCP endpoint (/mcp) requires an OAuth 2.1 Bearer token, obtained via a standard authorization-code + PKCE flow with dynamic client registration — the flow modern MCP clients (Claude.ai, Claude Code, etc.) already speak. There is a single set of credentials (OAUTH_USERNAME / OAUTH_PASSWORD) gating the login screen shown during that flow — enter them once when your MCP client connects.

Limitations to be aware of (fine for a personal/single-user tool, not for multi-tenant use):

  • Tokens and pending logins are kept in memory, not persisted — they're lost on redeploy/restart (a well-behaved client just re-runs the OAuth flow), so the app is configured to keep at least one machine always running (see fly.toml) rather than scale-to-zero.

  • Access tokens last 1 hour, but a refresh token is issued and rotated alongside each one, so a client that supports the standard OAuth refresh grant renews its session silently instead of prompting a fresh login.

  • Dynamic client registration is open (any client can register itself), same as most MCP OAuth reference implementations — the actual gate is the username/password login screen.

Local development

cp .env.example .env   # fill in your local MariaDB + a login/password
npm install
npm run dev

Environment variables

See .env.example for the full list:

  • PUBLIC_URL — externally reachable base URL (used to build OAuth issuer/redirect URLs). Must be https:// in production (an http://localhost exemption exists for local dev).

  • PORT — HTTP port to listen on.

  • DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME, DB_TABLE, DB_SSL — MariaDB connection.

  • OAUTH_USERNAME, OAUTH_PASSWORD — credentials for the OAuth login screen.

Deploying to Fly.io

  1. Create the Fly app (one-time, from your machine):

    fly apps create <your-app-name>

    Update the app = "..." line in fly.toml to match.

    Then allocate a public IP so <your-app-name>.fly.dev actually resolves — this isn't something fly.toml can declare, it's a one-time action against the app itself:

    fly ips allocate-v6 -a <your-app-name>
    fly ips allocate-v4 --shared -a <your-app-name>

    (fly launch usually does this automatically; fly apps create alone does not — if you skip this, the hostname returns NXDOMAIN/no DNS record and the service is unreachable even though it's running fine.)

  2. Set secrets (never commit these — use fly secrets, not [env] in fly.toml):

    fly secrets set \
      PUBLIC_URL=https://<your-app-name>.fly.dev \
      DB_HOST=... DB_PORT=3306 DB_USER=... DB_PASSWORD=... DB_NAME=... DB_TABLE=mcp_state \
      DB_SSL=true \
      OAUTH_USERNAME=... OAUTH_PASSWORD=...

    Your MariaDB instance needs to be reachable from Fly.io's network (a public host with firewall rules allowing Fly's egress IPs, or a private connection such as a Fly.io WireGuard peer / Tailscale, depending on where it's hosted).

  3. Deploy on push to main. This repo is wired to Fly.io's GitHub integration (set up via fly launch's GitHub connection), which builds and deploys automatically on push — there's no .github/workflows/*.yml in this repo driving it. If you'd rather drive deploys from a GitHub Actions workflow instead, create .github/workflows/deploy.yml running flyctl deploy --remote-only on push, authenticated with a repo secret FLY_API_TOKEN from fly tokens create deploy -x 999999h — just don't run both mechanisms at once, or you'll get duplicate/competing deploys.

Connecting an AI client

Point your MCP client at https://<your-app-name>.fly.dev/mcp. The client will discover the OAuth metadata automatically, register itself, and prompt you to log in with OAUTH_USERNAME / OAUTH_PASSWORD the first time.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables AI memory persistence and secure credential management via vault tools for MCP-compatible clients like Claude Desktop, Cursor, and VS Code.
    12
    4 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Provides persistent memory for AI agents via 10 MCP tools that map to the AgentRAM REST API, enabling store, retrieve, search, and share memories across personal and shared namespaces.
    10
    40 npm
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    MCP-native persistent memory for AI agents. Stores and retrieves encrypted memories with Trust Quotient scoring, cross-agent handover protocol, and immutable audit trail. 13 tools. Remote endpoint available.
    13
    13
    Apache 2.0