Vist/ Blog/ Memory & MCP
Memory & MCP 5 min read

MCP, the 60-second version

What MCP is, how Vist exposes it, and the 30-second connection flow that replaced the old stdio-bridge dance. Plus: why we run an OAuth provider for it.

If you've heard of MCP and you're not sure whether you should care: this post is for you. If you've already wired Vist into Claude desktop and you want the implementation behind it: that's later in the post.

MCP in one paragraph

MCP — Model Context Protocol — is an open standard for letting AI assistants talk to external services. Instead of every chat tool writing a bespoke integration with every productivity app, both sides speak MCP and discover each other's capabilities at runtime. The chat tool ("client") asks the productivity app ("server") what can I do?, and the server replies with a list of typed tools. The model decides which to call.

Vist runs an MCP server. The tools it exposes are the operations you'd run yourself: create a note, list tasks, search the knowledge base, record a memory, load context.

Connecting in 30 seconds

The old way to connect AI tools to a remote service was a local stdio bridge — a small process running on your laptop, translating between the chat tool and the remote API. Vist still ships one of those (bin/vist-mcp-bridge) for legacy use, but you almost certainly don't need it.

The new way is direct HTTP. Vist's MCP endpoint is https://app.usevist.dev/mcp. In Claude desktop, the configuration looks like:

{ "mcpServers": {
  "vist": { "url": "https://app.usevist.dev/mcp" }
} }

That's it. On first request, Claude redirects you to a Vist sign-in page (OAuth 2.1 via Doorkeeper). You approve. Claude gets a token scoped to your account. Every subsequent request carries that token; Vist enforces tenant isolation as it would for any other authenticated request.

No API keys to copy around. No local process. No claude_desktop_config.json paths to debug.

What the model can do

The tools fall into three buckets.

Notes & tasks (the CRUD). create_note, update_note, list_notes, get_note, create_task, list_tasks, complete_task. These do what they say. Folders are resolved by name or ID; due dates accept natural-language strings ("next friday at 5pm") and we parse them server-side.

Search. search_knowledge_base(query, mode). Mode is fts (Postgres full-text, exact terms) or semantic (pgvector cosine similarity against Mistral embeddings). The default routes based on the query shape — short, keyword-heavy queries go to FTS; longer, conceptual ones go to semantic. Result entries come back with the note title, a snippet, and a relevance score the model can use to triage.

Memory. record_memory, query_memory, update_project_state, sync_agent_memory, load_context. The agent memory layer is its own thing — there's a separate post on why it lives in your notes app.

Interactive task list

show_task_list is the one tool that doesn't return text. It returns an MCP UI Resource — a small piece of HTML/JavaScript that the host (Claude desktop, the ChatGPT app, anything that supports MCP Apps) renders inline in the chat. The user can check off tasks, change priorities, see due dates, all without leaving the conversation.

Under the hood, it's a small interactive app bundled as a static asset and served back through the MCP protocol's resource channel. It talks to the same Vist API as the web app, signed with the same OAuth token. Complete a task in there, and the next time the model calls list_tasks, the state reflects what you just changed.

Tenancy guarantees

Every MCP request is scoped, by token, to a single account. Tenant isolation is enforced architecturally at the data layer — every query is automatically constrained to the authenticated account without individual tool implementations needing to declare that constraint. There is no MCP tool that can see another account's data.

The full set of tool calls a token has made is auditable: every call is logged with the model identifier, the tool name, the parameter hash, and the response status. You can read your own log in Settings → API & MCP.

The system prompt

In Settings → MCP, there's a system prompt you can copy into the agent config of your choice. It tells the model:

  1. Call load_context() before answering anything substantive.
  2. Use record_memory when the user gives you durable preferences ("I prefer terse summaries"), not for every chat turn.
  3. Prefer update_project_state over a free-form note when capturing project status — it's typed; it deduplicates.
  4. Use search_knowledge_base before asking the user a question they might already have answered in a previous note.

The system prompt is short on purpose. The MCP tool list does most of the work; the prompt just teaches the model when to reach for which.

Security, in short

  • OAuth 2.1 via Doorkeeper. Dynamic Client Registration (RFC 7591) is supported.
  • Tokens scoped per-account, refreshable, revocable from Settings.
  • Tenant isolation at the data layer; not opt-in.
  • Audit log of every tool call.
  • The MCP endpoint and the web app share a database and a single source of truth; there's no parallel "API mirror" that could drift.

Beyond individual notes

The picture above covers the mechanical connection — auth, tools, scoping. It skips a deeper capability: what the model can do once it has access to a full, curated knowledge base, not just individual notes.

Vist has a separate wiki ingestion layer where the model can pull in PDFs, articles, video transcripts, and anything you paste, then link them into your notes, cite them, and query across them semantically. That layer connects to MCP in ways that change what "read my notes" actually means. It deserves its own post — we'll cover it separately.

Memory & MCP