loading…
Search for a command to run...
loading…
Detects and breaks repetitive fix loops in AI coding assistants by tracking attempts and providing escalating intervention strategies. It utilizes error fingerp
Detects and breaks repetitive fix loops in AI coding assistants by tracking attempts and providing escalating intervention strategies. It utilizes error fingerprinting and similarity analysis to redirect the AI toward new approaches when it gets stuck on the same error.
Break the Loop. Ship the Code.
MCP server that detects when AI coding assistants get stuck in fix loops and forces them to change approach.
Paste this into Claude Code, Cursor, or any MCP-compatible assistant and it will install and configure Unloop for you:
Install Unloop MCP to detect fix loops in this project. Here's what to do:
1. Run: claude mcp add unloop -s user -- npx -y unloop-mcp
(Or for Cursor: create .cursor/mcp.json with {"mcpServers":{"unloop":{"command":"npx","args":["-y","unloop-mcp"]}}})
2. Download the rules file for this IDE from https://raw.githubusercontent.com/protonese3/unloop-mcp/master/rules/claude.md
and save it to .claude/rules/unloop.md (or the equivalent for Cursor: .cursor/rules/unloop.mdc)
3. Verify the MCP server is connected by running: claude mcp list
After setup, you must follow the Unloop protocol: call log_fix_attempt after every fix attempt,
obey escalation levels (NUDGE/WARNING/CRITICAL), and call resolve_loop when the error is fixed.
When you use an AI coding assistant (Claude, Cursor, Copilot, Cline...), it sometimes hits an error and tries to fix it — but keeps attempting the same failing approach 5, 10, 20+ times without realizing it's going in circles.
Unloop stops this. It's an MCP server that runs alongside your AI assistant, tracking every fix attempt. When it detects repetition, it intervenes with escalating alerts and concrete strategies to redirect the AI toward a different approach.
Without Unloop, a stuck AI burns 30+ minutes and 150k+ tokens on the same error. With Unloop, it course-corrects at attempt 3.
1. AI Attempts a Fix — Your AI assistant encounters an error and tries to fix it. Unloop silently tracks every attempt by calling log_fix_attempt.
2. Unloop Detects the Loop — The engine normalizes each error into a fingerprint (stripping paths, line numbers, timestamps) and compares fix descriptions using Jaccard similarity. When similarity exceeds 55%, it flags a loop.
3. AI Gets Redirected — Escalating alerts force the AI to stop repeating and try a fundamentally different approach. Strategies are targeted by error category (import, type, build, test, runtime).
| Level | Trigger | What happens |
|---|---|---|
| NONE | 1-2 attempts | Silent tracking. No intervention. |
| NUDGE | 3-4 attempts | "You're repeating yourself. Change approach." + strategies |
| WARNING | 5-6 attempts | "STOP. Revert your changes. Research first." + strategies |
| CRITICAL | 7+ attempts | "STOP. Revert everything. Ask the user for help." |
npm install -g unloop-mcp
Or use directly without installing:
npx unloop-mcp
Claude Code (one command, works in all projects):
claude mcp add unloop -s user -- npx -y unloop-mcp
Cursor — add to .cursor/mcp.json:
{
"mcpServers": {
"unloop": {
"command": "npx",
"args": ["-y", "unloop-mcp"]
}
}
}
Windsurf — add to .windsurf/mcp.json:
{
"mcpServers": {
"unloop": {
"command": "npx",
"args": ["-y", "unloop-mcp"]
}
}
}
The rules file tells the AI when and how to call the Unloop tools. Without it, the AI won't know to use them.
| IDE | Command |
|---|---|
| Claude Code | cp rules/claude.md your-project/.claude/rules/unloop.md |
| Cursor | cp rules/cursor.mdc your-project/.cursor/rules/unloop.mdc |
| Windsurf | cp rules/windsurf.md your-project/.windsurfrules (append) |
| Cline | cp rules/cline.md your-project/.clinerules (append) |
claude mcp list
# unloop: ... - ✓ Connected
Restart your IDE. The AI now has access to the 4 Unloop tools and the rules instruct it to use them on every fix attempt.
Each error message is normalized before comparison:
/Users/alice/src/App.tsx:42 becomes generic)This means the same error on different files produces the same fingerprint:
Cannot find module './Button' in /Users/alice/src/App.tsx:42 → fingerprint a1b2c3...
Cannot find module './Button' in /Users/bob/src/Main.tsx:7 → fingerprint a1b2c3... (same)
Fix descriptions are tokenized (lowercased, stop-words removed) and compared using Jaccard similarity. If two descriptions share more than 55% of their meaningful words, they're flagged as "the same approach."
This is why the rules file instructs the AI to write specific fix descriptions — "Changed import from ./Button to @/components/Button because tsconfig has path aliases" instead of "fixed the import."
Errors are auto-categorized for targeted strategy selection:
| Category | Patterns matched |
|---|---|
syntax |
SyntaxError, unexpected token, parsing error |
type |
TypeError, type not assignable, TS errors |
import |
Cannot find module, module not found |
build |
Build failed, compilation error, webpack/vite/tsc |
test |
Test failed, assertion errors, jest/vitest/pytest |
runtime |
ReferenceError, null pointer, ENOENT, unhandled rejection |
Unloop exposes 4 tools via the Model Context Protocol:
log_fix_attemptCall after every fix attempt. Records the attempt and returns loop analysis.
Parameters:
error_message string The error being fixed
files_involved string[] Files modified in this attempt
fix_description string What was changed and why (be specific)
session_id string? For parallel task isolation (optional)
Returns:
status "ok" | "loop_detected"
loop_level "NONE" | "NUDGE" | "WARNING" | "CRITICAL"
attempt_number number
similar_attempts number How many previous fixes used the same approach
max_similarity number Highest similarity score vs any previous fix (0-1)
diagnosis object? Pattern analysis + what to try next (when loop detected)
strategies array? Escape strategies (when loop detected)
previous_attempts array? History of what was tried
When a loop is detected, the diagnosis field tells the AI exactly what's happening:
{
"diagnosis": {
"pattern": "You've been changing import/module paths 3 times for an import error. This approach isn't working.",
"suggested_action": "Stop changing paths. Check if the file actually exists at the expected location. Then check the module resolution config.",
"what_was_tried": ["Changed path to ../Button", "Changed path to ../../Button", "Changed to @/Button"],
"what_to_try_next": "Approaches you haven't tried yet: Check the relevant config files. Verify dependencies are installed correctly. Stop changing paths. Check if the file actually exists."
}
}
The diagnosis engine classifies each fix attempt into approach categories (path changes, type annotations, null checks, config changes, etc.), detects which approach is being repeated, and suggests a specific pivot based on the error category.
check_loop_statusRead-only status check. Returns current state without recording a new attempt. Use before starting complex fixes.
get_escape_strategiesGet strategies without logging. Returns category-specific strategies for planning your next move.
resolve_loopCall when the error is fixed. Resets all tracking counters. If you skip this, the next unrelated error inherits stale state.
Unloop includes 30+ built-in escape strategies, matched by error category and escalation level. Examples:
NUDGE (import error):
WARNING (type error):
CRITICAL (any):
# Unit + integration + E2E tests (75 tests)
npm test
# Quick smoke test — all tools, escalation, isolation (24 checks)
npx tsx smoke-test.ts
# Interactive demo — simulated loop session with colored output
npx tsx demo.ts
src/
├── index.ts # Entry point (stdio transport)
├── server.ts # MCP tool registration and handlers
├── types.ts # Shared TypeScript types
├── detection/
│ ├── fingerprint.ts # Error normalization, hashing, categorization
│ ├── similarity.ts # Jaccard similarity on tokenized descriptions
│ └── escalation.ts # NONE → NUDGE → WARNING → CRITICAL state machine
├── strategies/
│ ├── builtin.ts # 30+ strategies by category and level
│ └── registry.ts # Strategy lookup
└── session/
└── store.ts # In-memory session state with garbage collection
rules/ # IDE-specific instruction files
├── cursor.mdc # Cursor rules
├── claude.md # Claude Code rules
├── windsurf.md # Windsurf rules
└── cline.md # Cline rules
| IDE | MCP Support | Rules file |
|---|---|---|
| Claude Code | Native (stdio) | .claude/rules/unloop.md |
| Cursor | Native (stdio) | .cursor/rules/unloop.mdc |
| Windsurf | Native | .windsurfrules |
| Cline (VS Code) | Native | .clinerules |
An MCP server works across every IDE that supports the protocol — one codebase, one server, works everywhere. It's designed to be called by AI, not by humans. And it's the emerging standard: Cursor, Claude Code, Windsurf, and Cline all support it natively.
The alternative (a VS Code extension, a custom CLI wrapper, manual prompt engineering) would be single-IDE, harder to maintain, and less reliable.
PRs welcome. The codebase is straightforward:
src/strategies/builtin.ts, add to the relevant LEVEL:CATEGORY keysrc/detection/fingerprint.ts, add normalization patternsCATEGORY_PATTERNS array in fingerprint.tsrules/, add to the CLI init commandRun npm test before submitting. All 75 tests must pass.
MIT
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"unloop-mcp": {
"command": "npx",
"args": []
}
}
}Web content fetching and conversion for efficient LLM usage.
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also