@typeset-page/mcp
v0.1.0
Published
Model Context Protocol server for Typeset: publish Markdown from an AI prompt (Claude Desktop/Code) to a shareable read.typeset.page URL. Local stdio; OAuth PKCE login via Supabase (Google/Microsoft).
Maintainers
Readme
@typeset-page/mcp
MCP server that lets you publish Markdown from an AI prompt straight to a shareable Typeset reader URL — without leaving your terminal or chat.
It exposes three tools over stdio:
| Tool | What it does |
|---|---|
| share_document | Render Markdown → publish → return read.typeset.page/p/<id> |
| list_pages | List your published pages with their URLs |
| unpublish | Take a page down and wipe its stored text |
Publishing goes through your Typeset account. You sign in once with Google or
Microsoft via an OAuth flow in your browser; the session is stored locally
(~/.config/typeset-mcp/session.json, owner-only). Every write uses your
per-user token, so Supabase Row-Level Security enforces that you only touch your
own pages.
Install & sign in
# One-time login (opens your browser)
npx @typeset-page/mcp loginConfigure your MCP host
Claude Desktop
Add to claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"typeset": {
"command": "npx",
"args": ["-y", "@typeset-page/mcp"]
}
}
}Claude Code
claude mcp add typeset -- npx -y @typeset-page/mcpThen, in a prompt: "Publish this note to Typeset" → the host asks you to
approve the share_document call → you get a URL back.
Usage notes
- Confirm before publishing.
share_documentandunpublishare marked destructive; your MCP host will ask for approval on each call.share_documentpublishes to the public web (the page is unlisted — reachable only via its URL, which contains a random id). - Update instead of duplicate. Pass the
page_idreturned by a previousshare_document/list_pagesto re-publish the same page. - Defaults: template
vignelli, themelight, comment policyanyone. Override per call.
Configuration (env vars)
All optional — the defaults point at production Typeset.
| Var | Default |
|---|---|
| TYPESET_MCP_PROVIDER | google (azure for Microsoft) |
| TYPESET_API_URL | https://api.typeset.page |
| TYPESET_SHARE_BASE | https://read.typeset.page |
| TYPESET_SUPABASE_URL | Typeset's Supabase project URL |
| TYPESET_SUPABASE_ANON_KEY | Typeset's public anon key |
The Supabase URL/anon key are public values (the same pair ships in the web client); RLS, not secrecy, guards access.
CLI subcommands
npx @typeset-page/mcp login # interactive OAuth, stores the session
npx @typeset-page/mcp whoami # print who you're signed in as
npx @typeset-page/mcp logout # clear the stored session
npx @typeset-page/mcp # run the MCP server on stdio (hosts do this)Deploy / operator note (Supabase Redirect URLs)
The OAuth flow redirects back to a loopback URL. GoTrue validates
redirect_to against the project's allowlist, so the following must be present
under Authentication → URL Configuration → Redirect URLs in the Supabase
dashboard:
http://127.0.0.1:42813/callback
http://127.0.0.1:42814/callback
http://127.0.0.1:42815/callbackThe server binds the first free port among these (CANDIDATE_PORTS in
src/loopback.ts). Keep the two lists in sync.
Development
npm install
npm run build # tsc → dist/
npm test # vitest (PKCE, config, session, loopback)Ported from the obsidian-docshare share pipeline (auth.ts + platform.ts),
retargeted from Obsidian's requestUrl to native fetch. See
docs/features/mcp-server/implementation.md for the design.
