Skip to main content

OhMyLinearMCP - unified Linear MCP (local-fast reads + official fallback/writes) on macOS

Project description

oh-my-linear

Ask your AI agent to list Linear issues. Watch 37,000 tokens vanish into a single response full of avatar URLs, custom field schemas, and nested workspace metadata nobody asked for. Congratulations -- your context window is now half gone before the real work begins.

This is what happens when every list_issues call goes through the official Linear MCP. The responses are accurate. They're also enormous.

oh-my-linear reads directly from Linear.app's local IndexedDB cache instead. No API call. No network round-trip. Just the fields you actually care about.

"Give me the issues for team Frontend"

Official MCP:  ~37,500 tokens (nested GraphQL, full user objects, attachment metadata, ...)
oh-my-linear: ~2,500 tokens (identifier, title, priority, state, assignee, dueDate)

Same question. 15x less context.

How It Works

Linear.app is an Electron app. Every time you open it, it syncs your workspace into a local IndexedDB (LevelDB on disk). oh-my-linear cracks open that database, parses the binary Chromium storage format, and serves the data as MCP tool responses.

Linear.app (Electron)
  -> syncs workspace to local IndexedDB
  -> oh-my-linear reads it directly
     -> reads:  local cache (no API call, <10ms)
     -> writes: proxied to official Linear MCP
     -> after a write: 30s remote-first window to avoid stale reads

Writes still go through the official MCP -- this isn't trying to replace it. It's a read accelerator that sits in front of it.

The Store Detection Trick

Linear uses hash-based IndexedDB store names that change between app versions. Something like fbaa32a232c2_issues today might be a1b2c3d4e5f6_issues tomorrow. Instead of hardcoding these, oh-my-linear samples the first record from each store and matches the shape -- "has teamId, stateId, title? That's the issues store." Survives Linear updates without code changes.

Setup

One server handles both reads and writes. Replace your existing Linear MCP with this.

Claude Code

# Project scope (default — only this project)
claude mcp add oh-my-linear -- uvx oh-my-linear

# User scope (all projects for this user)
claude mcp add --scope user oh-my-linear -- uvx oh-my-linear

From local checkout:

claude mcp add oh-my-linear -- uvx --from /path/to/oh-my-linear oh-my-linear

Claude Desktop / Cursor / VS Code / Windsurf

{
  "mcpServers": {
    "oh-my-linear": {
      "command": "uvx",
      "args": ["oh-my-linear"]
    }
  }
}

Codex

Use CLI (recommended):

codex mcp add oh-my-linear -- uvx oh-my-linear
codex mcp list
codex mcp get oh-my-linear

Manual config (~/.codex/config.toml):

[mcp_servers.oh-my-linear]
command = "uvx"
args = ["oh-my-linear"]

Scope Guide

Client Default scope How to change
Claude Code Project (.mcp.json) Add --scope user for user-wide
Claude Desktop Per-app config N/A
Cursor / VS Code Per-app config N/A
Codex Global (~/.codex/config.toml) N/A

Requirements

  • macOS (Linear.app cache path is macOS-specific)
  • Linear.app installed and opened at least once
  • Node.js/npm (npx) for official MCP bridge (mcp-remote)
  • Network access for writes and fallback reads

Read/Write Policy

Operation What happens
Read Local cache first. If local data is missing or degraded, falls back to official MCP.
Write Always goes to official MCP.
Read after write 30-second remote-first window to avoid reading your own stale data.

Available Tools

Local Read Tools (cache-first, fast)

list_issues / get_issue / list_teams / get_team / list_projects / get_project / list_users / get_user / list_issue_statuses / get_issue_status / list_comments / list_issue_labels / list_initiatives / get_initiative / list_cycles / list_documents / get_document / list_milestones / get_milestone / list_project_updates / get_status_updates

Bridge Tools

  • official_call_tool -- call any official Linear MCP tool (writes, unsupported reads, etc.)
  • list_official_tools -- discover what the official MCP exposes
  • refresh_cache -- force reload from local IndexedDB
  • get_cache_health -- check local + official backend status

Write Example

list_official_tools()
official_call_tool(name="create_issue", args={...})
official_call_tool(name="update_issue", args={...})

Environment Variables

Variable Default Purpose
LINEAR_OFFICIAL_MCP_TRANSPORT stdio stdio or http
LINEAR_OFFICIAL_MCP_COMMAND npx Command for stdio transport
LINEAR_OFFICIAL_MCP_ARGS -y mcp-remote https://mcp.linear.app/mcp Args for stdio transport
LINEAR_OFFICIAL_MCP_ENV JSON object, env for stdio child process
LINEAR_OFFICIAL_MCP_CWD Working directory for stdio child process
LINEAR_OFFICIAL_MCP_URL https://mcp.linear.app/mcp URL for http transport
LINEAR_OFFICIAL_MCP_HEADERS JSON headers for http transport
LINEAR_FAST_COHERENCE_WINDOW_SECONDS 30 Remote-first window after writes
LINEAR_FAST_IDLE_REFRESH_SECONDS 60 Idle gap (seconds) before auto-refreshing cache on next tool call
LINEAR_FAST_PRECONNECT_OFFICIAL 0 1 enables startup preconnect to official MCP (can trigger OAuth prompt at startup)
LINEAR_FAST_ACCOUNT_EMAILS Comma-separated; filter cache to these orgs
LINEAR_FAST_USER_ACCOUNT_IDS Comma-separated; direct account-id scope

Auto-Refresh

When no tool call has been made for 60 seconds (configurable via LINEAR_FAST_IDLE_REFRESH_SECONDS), the next call triggers a cache reload so you always get fresh data without manually calling refresh_cache.

Troubleshooting

npx: command not found -- Install Node.js, or set LINEAR_OFFICIAL_MCP_TRANSPORT=http.

Official calls unauthorized -- Official MCP uses mcp-remote for OAuth. Re-run npx -y mcp-remote https://mcp.linear.app/mcp to re-authenticate.

Local data seems stale -- Open Linear.app to trigger a sync, or call refresh_cache.

Linear local DB not found -- Check that it exists:

ls ~/Library/Application\ Support/Linear/IndexedDB/

Server is installed but not visible in Codex app -- Verify with codex mcp list. If listed there, fully restart Codex (quit and relaunch the app).

OAuth prompts appear repeatedly -- Keep LINEAR_FAST_PRECONNECT_OFFICIAL unset (or 0) so official MCP connects only when needed. Use reauth() only when you intentionally want a fresh OAuth login.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oh_my_linear-0.5.3.tar.gz (126.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oh_my_linear-0.5.3-py3-none-any.whl (128.2 kB view details)

Uploaded Python 3

File details

Details for the file oh_my_linear-0.5.3.tar.gz.

File metadata

  • Download URL: oh_my_linear-0.5.3.tar.gz
  • Upload date:
  • Size: 126.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.7

File hashes

Hashes for oh_my_linear-0.5.3.tar.gz
Algorithm Hash digest
SHA256 8d6a057fd15a212f2071a5a4e3a52f29cad2b0f1bc8bbc21cd17615cde01b727
MD5 830001e3f7ba54264d75f43dc738cbb3
BLAKE2b-256 0818e8cc313684c412ee6b6e164a2119fb33006f9a9a5f19fdfe2f2270e9c59d

See more details on using hashes here.

File details

Details for the file oh_my_linear-0.5.3-py3-none-any.whl.

File metadata

File hashes

Hashes for oh_my_linear-0.5.3-py3-none-any.whl
Algorithm Hash digest
SHA256 7151ff5f75521a3a3772721942d4545e3a34363d8384d15880c00cab9cc37c07
MD5 275ac097e0bdbf77e67b421dc4706f16
BLAKE2b-256 f72fca393e9c8454cf929e1b9e196a47a4f359f14b20047f63c8d0015f1d8f06

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page