PinchMCP
Analyzes Linear project issues and blocking relations to identify keystone tickets and blockers using dominator analysis.
Click on "Deploy 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., "@PinchMCP What 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
Find the keystone ticket — the one that, once done, unblocks the most downstream work.
An MCP server between Claude Code and Linear. It reads a project's issues and their blocking relations, fuses them into an in-memory dependency graph, and points you at the leverage — via dominator analysis, not a bare score. Then it goes further: the critical path (CPM), inferred code coupling, cold-start predictions for not-yet-built tickets, and graph hygiene.
Deterministic, read-only, no LLM in the server — it analyzes; you decide.
Status —
v0.4.0. Phases I–III shipped (9 tools spanning the explicit dependency graph, inferred code coupling, cold-start prediction, graph hygiene, and feature-decomposition grounding), plus the first Phase IV deliverable — 10 tools in total. Phase IV (Slack + Granola integrations) is on the roadmap — the Granola reconciliation server side has shipped asreconcile_notes; the ingestion/delivery integration remains. Seedocs/ROADMAP.mdfor done vs. planned anddocs/SECURITY.mdfor the trust model.
Running locally (quickstart)
There is nothing to deploy. PinchMCP is a stdio MCP server: Claude Code launches it as a local subprocess on demand and talks to it over stdin/stdout. "Running it" just means the built code lives on the machine where you run Claude Code — no port, no daemon, no hosting. Each developer who wants it does this once on their own machine, with their own Linear key.
End to end:
# 1. Get the code and build it (needs Node 22+)
git clone https://github.com/0xdefence/PinchMCP.git
cd PinchMCP
npm install
npm run build# 2. Get a Linear personal API key
# Linear → Settings → Security & access → Personal API keys → Create key
# (copy the lin_api_… value)
# 3. Find the project_id you want to analyze
curl -s https://api.linear.app/graphql \
-H "Authorization: lin_api_your_key" \
-H "Content-Type: application/json" \
-d '{"query":"{ projects(first: 50) { nodes { id name } } }"}'// 4. Register the server with Claude Code.
// Create .mcp.json in your project root (or ~/), using the ABSOLUTE path
// to dist/src/index.js printed by `pwd`:
{
"mcpServers": {
"pinch-mcp": {
"command": "node",
"args": ["/absolute/path/to/PinchMCP/dist/src/index.js"],
"env": { "LINEAR_API_KEY": "lin_api_your_key" }
}
}
}5. Restart Claude Code, run /mcp to confirm "pinch-mcp" is connected,
then ask: "Rank the keystones for Linear project <project_id>."Each step is expanded in the sections below (Install · API key · project_id · Connect to Claude Code · Use it).
Related MCP server: SYKE
What it does
Questions teams actually ask, with 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.
Critical path — "What sets the total timeline?" Answered by CPM over estimates: the longest-duration dependency chain, plus how much slack every other ticket has. Distinct from keystone — max-leverage unlock vs. what sets duration.
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 |
| (none) | Lists the workspace's projects with their ids and URL slugs, so you can pick a |
|
| 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. |
|
| CPM over estimates: the longest-duration chain that sets the timeline, plus per-ticket slack. Answers "what sets total duration" (vs keystones' "max leverage unlock"). Unestimated tickets default to 1. |
|
| Transitive blockers (must finish first) and downstream unblocks for one ticket. |
|
| Infers coupling from code (shared files, intra-repo imports, git co-change) and suggests ticket links Linear doesn't record — evidence-backed, confirm-before-acting. Never folded into keystone/critical_path. |
|
| Cold-start: predicts which code areas a ticket will likely touch and which tickets likely couple, from ticket text vs a keyword index of the repo — for backlog tickets with no code yet. Planning aid; never used in keystone/critical_path. |
|
| Reports graph hygiene gaps — cycles, isolated tickets, stale blockers (blocker already done), and keystones missing an estimate or owner. Deterministic; asserts/writes nothing. |
|
| Cold-start grounding for a free-text feature: predicted code areas + related existing tickets, for the client to decompose. Never creates tickets. |
|
| Reconciles client-extracted meeting-note items (blockers, ticket refs, feature/bug mentions) against the graph: unrecorded blockers, ref status vs what was said, overlap with existing tickets. Extraction is the client's job; pinch stays deterministic and never writes. |
Across the analysis tools, project_id accepts a Linear project name,
URL slug, or UUID — it's resolved internally, so you can speak in names
("rank keystones for 0xDefence") and PinchMCP maps it to the right project.
Requirements
Node.js 22 or newer (active LTS; Node 18 is end-of-life). 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.
Fetched project graphs are cached in memory for 5 minutes by default. Set
PINCH_CACHE_TTL_MS (a positive integer, in milliseconds) to override the TTL.
build_feature_graph always forces a refresh regardless of the cache.
Find your project_id
The analysis tools take a Linear project UUID or the URL slug — not a
display name (Linear's project(id:) lookup rejects names). Three ways to get a
valid value:
Ask Claude Code once the server is connected: "list my Linear projects" runs the
list_projectstool and prints every project with its id and slug.From the project URL —
linear.app/<workspace>/project/<name>-<slugId>. Paste the whole<name>-<slugId>slug or just the trailing hex; both work.Via curl:
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 slugId } } }"}' | jqAny id or slugId from the output works 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 ten
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.
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.docs/ROADMAP.md— what's shipped vs. planned across Phase I (explicit graph), Phase II (code grounding), and Phase III (generative scoping).docs/DECOMPOSITION-WORKFLOW.md— how to break a free-text feature into grounded Linear tickets usingdecompose_grounding, Claude Code, and the Linear MCP together.docs/RECONCILIATION-WORKFLOW.md— how to reconcile client-extracted meeting-note items against the graph usingreconcile_notes, Claude Code, and the Linear MCP together.docs/SECURITY.md— trust model: read-only, one local secret (never logged), writes delegated to the Linear MCP, and how integrations keep secrets with their own MCP.
Develop
npm test # full vitest suite
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
Phase I (this explicit-graph slice) is shipped. Phase II adds the inferred
code-coupling graph + critical_path; Phase III adds generative scoping (break
features into tickets, surface gaps). Full status — done vs. not — is tracked in
docs/ROADMAP.md.
Known limitations (slice 1)
Issues are paged at 50 per request to stay under Linear's 10k query-complexity cap (up to 10,000 issues across pages). A single issue's relations beyond the first 50 are fetched via follow-up paginated queries, so no overflow is missed.
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.
Available Tools
10 toolsbuild_feature_graphBuild feature graphA
Fetch a Linear project's issues and blocking relations and (re)build the in-memory dependency graph. project_id accepts a project name, URL slug, or UUID.
Inputs: project_id (required).
critical_pathCritical path (CPM)A
Compute the critical path via CPM over ticket estimates: the longest-duration chain that sets the timeline, plus slack per ticket. Answers 'what sets total duration' (vs rank_keystones' 'max leverage unlock'). project_id accepts a project name, URL slug, or UUID.
Inputs: project_id (required).
decompose_groundingGround a feature for decomposition (cold-start)A
Given a free-text feature description, predict which code areas it will touch and which existing tickets overlap — grounding for the client to decompose it into tickets. Suggestions only; pinch never creates tickets (use the Linear MCP). project_id accepts a name/slug/UUID; repo_path is the local checkout; feature is the description to ground.
Inputs: feature (required), repo_path (required), project_id (required).
explain_blockersExplain a ticket's blockersB
Show what transitively blocks a ticket and what it transitively unblocks. project_id accepts a project name, URL slug, or UUID.
Inputs: ticket_id (required), project_id (required).
list_projectsList Linear projectsA
List the workspace's Linear projects with their ids and slugs, so a project_id can be chosen. Linear's project lookup needs a UUID or URL slug, not a display name.
Inputs: no named parameters.
rank_keystonesRank keystone ticketsA
Rank tickets by leverage: how much downstream work each one gatekeeps, via dominator analysis of the blocking graph. project_id accepts a project name, URL slug, or UUID.
Inputs: project_id (required).
reconcile_notesReconcile meeting notes against the graphA
Given structured items extracted from meeting notes (blockers, ticket refs, feature/bug mentions — extraction is the client's job), reconcile them against the Linear dependency graph: unrecorded blockers, ref status, overlap with existing tickets. Suggestions only — pinch never writes; use the Linear MCP to act. project_id accepts a name/slug/UUID; repo_path (optional) enables code-area grounding for mentions.
Inputs: items (required), project_id (required), repo_path.
suggest_linksSuggest missing ticket links from codeA
Infer coupling between tickets from the code they touch (shared files, intra-repo imports, git co-change) and suggest links Linear doesn't record. Suggestions only — never asserted; never folded into keystone/critical_path. project_id accepts a name, slug, or UUID; repo_path is the absolute path to the project's local git checkout.
Inputs: repo_path (required), project_id (required).
suggest_scopePredict a ticket's code scope (cold-start)A
For tickets with no code yet, predict which code areas each will likely touch and which tickets likely couple — by matching ticket text against a keyword index of the repo. Planning aid: suggestions only, never asserted, never used in keystone/critical_path. project_id accepts a name, slug, or UUID; repo_path is the absolute path to the project's local git checkout.
Inputs: repo_path (required), project_id (required).
surface_gapsSurface graph hygiene gapsA
Report deterministic planning gaps in a project's dependency graph: cycles, isolated tickets, and high-leverage (keystone) tickets missing an estimate or owner. Analysis only — asserts nothing, writes nothing. project_id accepts a name, slug, or UUID.
Inputs: project_id (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 10 tools
Each tool has a clearly distinct analytical purpose – from ranking keystones to computing critical paths, explaining blockers, suggesting code links/scope, surfacing gaps, grounding features, reconciling notes, listing projects, and rebuilding graphs – with no overlapping or ambiguous boundaries.
All tool names follow a consistent verb_noun pattern using snake_case (e.g., rank_keystones, list_projects, build_feature_graph), with no mixing of conventions or vague verbs.
With 10 tools, the set is well-scoped for a dependency analysis server – enough to cover essential analyses without redundancy or bloat.
The tool surface covers the full analytical lifecycle: project discovery, graph building, multi-angle dependency analysis, coupling inference, gap detection, feature grounding, and meeting note reconciliation – with no obvious gaps given the server's read-only, suggestion-only design.
Related MCP Connectors
The MCP server for Azure DevOps, bringing the power of Azure DevOps directly to your agents.
MCP server for generating rough-draft project plans from natural-language prompts.
MCP server for VC pitch-deck scoring, thesis-fit matching, and deal-flow management.
An MCP server that provides congressional transcripts
Related MCP Servers
AlicenseNot gradedqualityAmaintenanceMCP server that gives AI assistants impact analysis, cross-project reference tracking, and code health scoring.86 PyPI4Apache 2.0- AlicenseNot gradedqualityDmaintenanceAI code impact analysis MCP server that monitors file changes, maps dependency graphs, detects cascading breakage, and gates builds before damage spreads.80 npm2Elastic 2.0
- AlicenseAqualityDmaintenanceMCP server for auditing infrastructure-as-code attack paths, finding multi-hop chains from public internet to sensitive resources.2MIT
- AlicenseNot gradedqualityBmaintenanceMCP server that extracts and links code, tasks, documentation, and git history into a graph, then diagnoses discrepancies and generates reports.Apache 2.0