Skip to main content

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

Project description

Oh My Linear MCP

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.6.tar.gz (125.7 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.6-py3-none-any.whl (127.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for oh_my_linear-0.5.6.tar.gz
Algorithm Hash digest
SHA256 e18fbb7ed639602afc0c80c47fa1d899eb8bf96aac9544b76369f621bac71fb3
MD5 ca793af3f96825809e2ecee9e65158ba
BLAKE2b-256 e95bac7559fda95d2b7f6943297dcd8493e36658f165c250726fa5ac273c753d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for oh_my_linear-0.5.6-py3-none-any.whl
Algorithm Hash digest
SHA256 91ad84e7c5d23d2392d0da55aad68ca3203cd26d30e4c61a9e809591aa5f87c9
MD5 429a2183b5fe19d3003d0d714aa77c51
BLAKE2b-256 40b6a55f9922475c086d2ad8dc70f291a7edfb0d8868e84d41a8a1ceac74d100

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