PinchMCP
Analyzes Linear project issues and blocking relations to identify keystone tickets and blockers using dominator analysis.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PinchMCPWhat ticket unblocks the most downstream work in my project?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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/blockingrelations 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 |
|
| Fetches issues + relations and (re)builds the cached graph. Reports issue/edge counts. |
|
| Tickets ranked by leverage (dominated-subtree size), with plain-language explanations, plus warnings (cycles) and ungrounded tickets. |
|
| Transitive blockers (must finish first) and downstream unblocks for one ticket. |
Related MCP server: Linear MCP Server
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 buildnpm 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
Linear → Settings → Security & access → Personal API keys.
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.
.envis 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 } } }"}' | jqEach 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.jsVerify 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 textLinear layer (
src/linear/) — a GraphQL client behind anIssueSourceinterface (the seam where a future MCP-to-MCP client could slot in), plus normalization of raw payloads into domainIssue/Relationtypes.Graph layer (
src/graph/) — pure, I/O-free functions:buildFeatureGraphnormalizesblocks/blocked_byinto one canonical "A unblocks B" edge direction, de-dups, drops out-of-project and self edges, and keepsrelated/duplicateas side metadata.rankKeystonesadds 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.explainBlockerswalks predecessors/successors transitively.
Cache (
src/cache.ts) — one built graph perproject_id;build_feature_graphforces 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.
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
branchNameand 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_blockersdoesn't annotate cycles, thoughrank_keystonesdoes.Inferred direction from code coupling is not here yet — this slice uses only Linear's explicit, human-asserted relations.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/0xdefence/PinchMCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server