PinchMCP

PinchMCP

An MCP server that analyzes Linear feature dependencies using dominator analysis to identify the keystone ticket that unblocks the most downstream work.

Category
访问服务器

README

PinchMCP

An MCP server that finds the keystone ticket in a Linear feature — the one that, once done, unblocks the most downstream work — via dominator analysis of the dependency graph. It sits between Claude Code and Linear: it reads a project's issues and their blocking relations, fuses them into an in-memory graph, and tells you where the leverage is.

Status — slice 1 (explicit-graph path). This release proves the idea end-to-end using Linear's explicit blocked/blocking relations only. The inferred code-coupling layer (static import graph + git co-change) is on the roadmap, not in this build. See Roadmap.


What it does

Two questions teams actually ask, with two distinct answers:

  • Keystone — "What single ticket, once done, unblocks the most downstream work?" Answered by dominator analysis: a ticket is high-leverage when every path to many downstream tickets must pass through it. This is not the same as "the ticket that touches the most things" — a bottleneck that gatekeeps 5 tickets beats a ticket that merely precedes 20 reachable ones.
  • Blockers — "For this one ticket, what must finish first, and what does it unblock?" Answered by a transitive walk up and down the dependency chain.

Explainability is the product. Output says why: "every path to ENG-2, ENG-3 passes through ENG-1," not a bare score.

Tools exposed to Claude Code

Tool Input What it returns
build_feature_graph project_id Fetches issues + relations and (re)builds the cached graph. Reports issue/edge counts.
rank_keystones project_id Tickets ranked by leverage (dominated-subtree size), with plain-language explanations, plus warnings (cycles) and ungrounded tickets.
explain_blockers project_id, ticket_id Transitive blockers (must finish first) and downstream unblocks for one ticket. ticket_id accepts a Linear UUID or a human identifier like ENG-12.

Requirements

  • Node.js 18 or newer (the server uses the global fetch).
  • A Linear account and a personal API key.
  • Claude Code (or any MCP client that can launch a stdio server).

Install

git clone https://github.com/0xdefence/PinchMCP.git
cd PinchMCP
npm install
npm run build

npm run build compiles TypeScript to dist/. The server entrypoint is dist/src/index.js.

Verify it built and starts (it should wait for stdio input, then exit cleanly on EOF):

LINEAR_API_KEY=dummy node dist/src/index.js < /dev/null && echo "starts OK"

With no key it should fail fast with a clear message:

node dist/src/index.js < /dev/null   # -> Error: LINEAR_API_KEY environment variable is required.

Get a Linear API key

  1. Linear → Settings → Security & access → Personal API keys.
  2. Create key, give it a name, copy the value (looks like lin_api_…).

The key is passed to the server as the LINEAR_API_KEY environment variable. For local CLI use you can also copy .env.example to .env and set it there.

Never commit your key. .env is gitignored. The key grants access to your Linear workspace.


Find your project_id

The tools take a Linear project UUID. The quickest way to list your projects and their ids, using the key from above:

curl -s https://api.linear.app/graphql \
  -H "Authorization: $LINEAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"{ projects(first: 50) { nodes { id name } } }"}' | jq

Each id in the output is a value you can pass as project_id.


Connect it to Claude Code

PinchMCP is a stdio MCP server. Point Claude Code at the built entrypoint with your API key in the environment.

Option A — project config file (recommended)

Create .mcp.json in the root of the repo where you want to use it (or your home directory for global use):

{
  "mcpServers": {
    "pinch-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/PinchMCP/dist/src/index.js"],
      "env": { "LINEAR_API_KEY": "lin_api_your_key_here" }
    }
  }
}

Use the absolute path to dist/src/index.js. Restart Claude Code (or reconnect MCP servers) so it picks up the config.

Option B — Claude Code CLI

claude mcp add pinch-mcp \
  -e LINEAR_API_KEY=lin_api_your_key_here \
  -- node /absolute/path/to/PinchMCP/dist/src/index.js

Verify the connection

In Claude Code, run /mcp — you should see pinch-mcp connected with three tools. If it shows as failed, check: the path is absolute and points at dist/src/index.js, you ran npm run build, and LINEAR_API_KEY is set.


Use it

Once connected, just ask Claude Code in natural language — it will call the tools. Examples:

  • "Build the feature graph for project <project_id> and rank the keystones."
  • "Which ticket is the biggest bottleneck in <project_id>?"
  • "What's blocking ENG-42, and what does it unblock?"

Claude Code decides when to call build_feature_graph, rank_keystones, and explain_blockers, and explains the results using the tool output.


How it works

Claude Code ──tool call──▶ PinchMCP (stdio)
                              │
              config ─▶ LinearGraphQLSource ──GraphQL──▶ api.linear.app
                              │
                         GraphCache (per project_id)
                              │
                       buildFeatureGraph
                       (normalize blocks/blocked_by → canonical edges)
                              │
              ┌───────────────┴───────────────┐
        rankKeystones                   explainBlockers
   (dominator tree, leverage)       (transitive chain walk)
              │                               │
        explainable text ◀── tool handlers ──▶ explainable text
  • Linear layer (src/linear/) — a GraphQL client behind an IssueSource interface (the seam where a future MCP-to-MCP client could slot in), plus normalization of raw payloads into domain Issue/Relation types.
  • Graph layer (src/graph/) — pure, I/O-free functions:
    • buildFeatureGraph normalizes blocks/blocked_by into one canonical "A unblocks B" edge direction, de-dups, drops out-of-project and self edges, and keeps related/duplicate as side metadata.
    • rankKeystones adds a virtual entry node to all unblocked tickets, computes a dominator tree (Cooper-Harvey-Kennedy), and sets each ticket's leverage to the size of its dominated subtree.
    • explainBlockers walks predecessors/successors transitively.
  • Cache (src/cache.ts) — one built graph per project_id; build_feature_graph forces a refresh.
  • Tools (src/tools/) — thin formatters turning graph results into human-readable, explainable output.

Why dominators, not reachability

A node's reachable descendants counts everything downstream, including work reachable by other paths too. A dominator is stricter: ticket X dominates ticket Y only if every path to Y passes through X. That's the real "if this slips, everything behind it slips" signal. The test suite includes a bottleneck graph proving these two metrics diverge.


Documentation

  • docs/ARCHITECTURE.md — layers, modules, data types, request flow, error handling, design decisions, and extension points.
  • docs/KEYSTONE-ALGORITHM.md — the dominator analysis in depth: why dominators beat reachability, the Cooper–Harvey–Kennedy computation, leverage, edge cases, and complexity.

Develop

npm test        # full vitest suite (39 tests)
npm run dev     # run from source via tsx (no build step)
npm run build   # compile to dist/ (emits src only, via tsconfig.build.json)

The graph algorithms are pure functions tested against synthetic fixtures with hand-computed dominator trees; the Linear adapter is tested against a recorded JSON fixture — no live API calls in the test suite.


Roadmap

Slice 1 is the explicit-graph proof. Planned next:

  • Inferred code-coupling graph — map tickets → code via branchName and commit/PR references, then code → code via a tree-sitter/SCIP static import graph plus git co-change history. This is the valuable half; explicit Linear relations are sparse and lossy.
  • critical_path — weighted CPM over estimates ("what sets total duration"), surfaced alongside keystone ("max leverage unlock").
  • Cold-start semantic matching — for future tickets with no code yet, match ticket text against the symbol index so the graph is useful before branches land.
  • LLM-extracted edge enrichment (GraphRAG-style) — mine ticket descriptions, comments, and PR text for dependencies Linear doesn't record explicitly, shipped as suggestions to confirm, never auto-asserted.
  • Linear cursor pagination — slice 1 fetches up to 250 issues; large projects need pagination + a truncation warning.

Known limitations (slice 1)

  • Fetches up to 250 issues per project with no pagination; larger projects are silently truncated (warning is a tracked follow-up).
  • explain_blockers doesn't annotate cycles, though rank_keystones does.
  • Inferred direction from code coupling is not here yet — this slice uses only Linear's explicit, human-asserted relations.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选