Harpyja
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., "@Harpyjawhere is the retry/backoff logic for the payment gateway?"
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.
Harpyja
⚠️ Experimental — not production-ready
This project is entirely experimental. It is a research/work-in-progress prototype: APIs, schemas, defaults, and behavior change without notice; the documented hardware footprint is not validated (see the caveat below); and real-data evaluation is ongoing and
indicative_only. Do not depend on it for anything you can't afford to have break. Use at your own risk.
A precision code-retrieval MCP server for coding agents working in large, legacy, and air-gapped codebases.
Harpyja is a Model Context Protocol server with one job: given a natural-language query, find the exact files and line ranges a coding agent needs across millions of lines of code — without the agent burning its own context window on blind searches.
It is named after Harpia harpyja, the harpy eagle: an apex hunter that locks onto a target in dense canopy and does not miss.
agent ──"where is the retry/backoff logic for the payment gateway?"──▶ Harpyja
│
┌──────────────────────────────────┘
▼
Tier 0 deterministic (AST + ripgrep)
Tier 1 Scout (native tool-calling explorer loop)
Tier 2 Deep (recursive LM, on escalation)
│
agent ◀── src/billing/gateway.py:212-241 ◀──────────────────────────────┘
tests/test_gateway.py:88-103Related MCP server: reflens
Why
Coding agents are good at editing code and bad at finding it in repositories that are too big to fit in context. The usual failure mode is the agent spending half its context window grepping around, then reasoning over a polluted history. This is worse in the codebases that need it most: decades of patched proprietary code, no surviving institutional knowledge, no clean README, and nothing that ever entered an LLM's training set.
Harpyja externalizes retrieval into a dedicated subsystem that does it cheaply and precisely, then hands back compact citations. Not every problem needs a million-token context window. Sometimes you need a small, brutally specialized subsystem that does one thing extremely well.
What it is (and isn't)
It is a read-only locator. It returns
file:linecitations and short rationales.It is not an editor, a RAG chatbot, or a code generator. It never modifies your repository.
It runs offline. Everything — model, search, parsing — stays on the local machine. No telemetry, no external calls. Suitable for fully air-gapped environments and proprietary code that must stay proprietary.
It fits a modest box. Everything runs against a local OpenAI-compatible endpoint (llama.cpp or Ollama). The default model is
hf.co/Qwen/Qwen3-8B-GGUF:latest, which serves both the Scout explorer loop and the Deep tier; any OpenAI-compatible tool-calling model works and is swappable from the eval CLI (--scout-model/--deep-model),harpyja.toml, orHARPYJA_*.⚠️ Footprint not yet validated. An 8B-class model co-loaded with the Deep model and the Deno/Pyodide sandbox under
mode=autoexceeds a small GPU, so treat "8 GB" as an aspirational target rather than a validated minimum. The verification-gate judge scores citations withlm_modelby default (verify_method=instruct_model), keeping the finder and the scorer as separate concerns.
How it works
Harpyja is a three-tier locator with cost-based escalation:
Tier | Engine | Role | Speed |
0 | Tree-sitter symbol index + ripgrep | Deterministic prefilter and exact-symbol lookups | instant |
1 | Scout — a native tool-calling explorer loop (read-only | The default. Handles most "where is X" queries | fast |
2 | Deep — a Recursive Language Model ( | Escalation path for broad/trace/audit queries | slower, thorough |
The Orchestrator runs the cheapest tier that can answer, verifies the result by reading the cited lines
back, and only escalates when verification fails or the query shape demands it. See
ARCHITECTURE.md for the full design and SPEC.md for the contracts.
Tier 1 Scout is a native explorer loop Harpyja owns end-to-end: a general tool-calling model driven over
three read-only tools (grep/glob/read_span) to a submit_citations result, behind a stable, swappable
backend seam. Tier 2 reimplements the dspy.RLM approach demonstrated by
megacode, which serves only as reference and inspiration (not a
dependency). Around both, Harpyja adds the language-agnostic indexing, symbol layer, routing, verification,
and MCP surface that turn them into a reusable locator.
Note: Earlier versions ran Scout on Microsoft FastContext (a fine-tuned 4B finder wrapped as a pinned dependency); it was retired when its upstream model became unobtainable, and replaced by the self-contained explorer loop above — no external finder dependency, model-agnostic over whatever the local endpoint serves.
MCP tools
Harpyja exposes a deliberately tiny surface:
harpyja_locate(query, repo_path, mode="auto", max_results=8)→ rankedfile:linecitations with rationales.harpyja_read(path, start, end)→ a bounded code snippet (for remote/air-gapped repos the agent can't read directly).harpyja_index(repo_path, refresh=false)→ build/refresh the manifest and symbol index ahead of time.
mode is one of auto | fast | deep. In auto, the Orchestrator decides which tiers to run.
Supported languages (symbol layer)
Tree-sitter symbol extraction ships for Go, Rust, Python, JavaScript/TypeScript, C#, Java, and C/C++. Any other language — or a file that fails to parse — degrades gracefully to ripgrep, so Harpyja never goes blind on an unknown file type.
Requirements
Python 3.12+
ripgrep(rg) onPATHDeno (the
dspy.RLMsandbox runs on Deno/Pyodide WASM — installed once, runs locally)A local OpenAI-compatible model endpoint: llama.cpp (
llama-server) or OllamaOptional: a CUDA/Metal GPU (the default profile targets a modest local GPU; an 8B-class model serving Scout + Deep with the WASM sandbox co-loaded under
mode=automeans 8 GB is not a validated minimum yet)
Install
git clone <your-fork>/harpyja
cd harpyja
uv sync # or: pip install -e .Serve a model (pick one)
Ollama
ollama serve
ollama pull <4b-instruct-model>
export HARPYJA_LM_API_BASE="http://localhost:11434/v1"
export HARPYJA_LM_MODEL="<4b-instruct-model>"llama.cpp
llama-server -m ./models/<model>.gguf --port 8000 --ctx-size 8192
export HARPYJA_LM_API_BASE="http://localhost:8000/v1"
export HARPYJA_LM_MODEL="local"Wire it into your agent
Claude Code (.mcp.json in your project, or claude mcp add):
{
"mcpServers": {
"harpyja": {
"command": "uv",
"args": ["run", "harpyja", "serve", "--stdio"],
"env": { "HARPYJA_LM_API_BASE": "http://localhost:11434/v1" }
}
}
}Codex (~/.codex/config.toml):
[mcp_servers.harpyja]
command = "uv"
args = ["run", "harpyja", "serve", "--stdio"]
env = { HARPYJA_LM_API_BASE = "http://localhost:11434/v1" }Both speak MCP over stdio. Harpyja also supports streamable HTTP (harpyja serve --http --port 9000) for
shared or containerized deployments.
Quick start
# One-time (optional) index for faster first query
uv run harpyja index --repo ~/dev/legacy-monolith
# Ask from the CLI (same path the MCP tool uses)
uv run harpyja locate --repo ~/dev/legacy-monolith \
--query "where do we validate inbound webhook signatures?" \
--mode autoThen, inside Claude Code or Codex, just ask naturally — the agent will call harpyja_locate on its own.
Configuration
Settings load from harpyja.toml (project root) with environment-variable overrides
(HARPYJA_*). See SPEC.md for the full table. Common knobs: model endpoints,
escalation thresholds, per-tier token budgets, language toggles, search bounds, and the outbound model-call
timeout (lm_http_timeout_s, default 120 s — bounds each Gateway HTTP call so a stalled local endpoint
degrades instead of hanging).
Project status
Early. The tiers are designed to land incrementally — see IMPLEMENTATION_PLAN.md.
Harpyja stays useful at every wave: even Wave 1 (deterministic AST + ripgrep, no model) is a working locator.
Note: The Scout tier sits behind a stable backend seam, so its finder model or runtime can be swapped without touching the orchestrator, verification gate, or the rest of the stack.
License
MIT. Builds on MIT/permissively-licensed upstreams (DSPy, tree-sitter, ripgrep).
Available Tools
3 toolsharpyja_indexC
Build/refresh the manifest for a repo. No ripgrep required.
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No | ||
| repo_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description bears full responsibility for behavioral disclosure. It only mentions that ripgrep is not required, which is a minor benefit. It does not disclose whether the operation is safe, destructive, idempotent, or what side effects (e.g., overwriting files) occur. The refresh parameter is mentioned but not explained in terms of behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very short—one sentence. It front-loads the core purpose. There is no fluff, but the extreme brevity borders on under-specification. Still, it is appropriately concise for the limited content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema and two parameters, the description needs to provide context on the index/manifest concept, prerequisites (e.g., repo_path validity), and when refreshing is needed. It lacks this context. The sibling tool names (locate, read) hint at a search context, but the description does not connect them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate by explaining parameters. It fails to mention either 'repo_path' or 'refresh'. The parameter names are somewhat self-explanatory, but the description adds no semantics beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Build/refresh the manifest for a repo', which clearly identifies the action (build/refresh) and the target (manifest for a repo). The sibling tools are locate and read, which are different operations, so the purpose is distinct. However, the phrase 'Build/refresh' is somewhat ambiguous—it could imply two modes or a combined action, but overall it is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool vs alternatives. The line 'No ripgrep required' hints at a lightweight alternative but does not specify scenarios or prerequisites. There are no explicit when-to-use or when-not-to-use instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
harpyja_locateC
Find files/lines relevant to a query (Tier 0: deterministic ripgrep).
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | auto | |
| query | Yes | ||
| repo_path | Yes | ||
| max_results | No | ||
| language_hint | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It only implies deterministic behavior via 'deterministic ripgrep', but omits critical traits like side effects, authentication needs, or performance characteristics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise (one sentence), but this underinformativeness harms usability. It is not front-loaded with critical details; it sacrifices completeness for brevity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of annotations, low schema coverage, and no parameter descriptions, the description fails to provide a complete picture. It does not explain return values (though output schema exists) or compare with siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, yet the description does not explain any of the 5 parameters (mode, query, repo_path, max_results, language_hint). The description adds no semantic value beyond the schema itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool finds files/lines relevant to a query, using the specific verb 'Find' and resource 'files/lines'. The mention 'Tier 0: deterministic ripgrep' adds technical context but does not differentiate from sibling tools like harpyja_index or harpyja_read.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. The description lacks context for appropriate invocation scenarios, such as when to prefer locate over index or read.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
harpyja_readC
Return a bounded, path-confined code snippet.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| path | Yes | ||
| start | Yes | ||
| repo_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears full responsibility. It only states what the tool returns, with no mention of side effects, permissions, idempotency, or other behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no wasted words. However, it could be more informative while remaining concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 4 required parameters and an output schema, the description is too sparse. It lacks details on return format, error conditions, or usage examples.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not explicitly explain the parameters. It hints at 'bounded' and 'path-confined', but does not clarify that start and end likely refer to line numbers or offsets.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool returns a bounded code snippet confined to a path, using specific verbs and resource. It distinguishes the read operation from sibling tools like harpyja_index and harpyja_locate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. The description implies reading code snippets, but does not explicate when to choose harpyja_read over harpyja_index or harpyja_locate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a clearly distinct purpose: building an index, locating relevant files/lines, and reading code snippets. There is no overlap or ambiguity.
All tool names follow a consistent pattern: 'harpyja_' prefix followed by a single verb (index, locate, read), ensuring predictability.
With only 3 tools, the surface is minimal but well-scoped for the server's focused purpose of code indexing and retrieval. Slightly low, but not inappropriate.
The tool set covers the core workflow of building an index, searching, and reading code. Minor gaps exist (e.g., no directory listing), but it's sufficient for the intended use case.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
An MCP server that gives your AI access to the source code and docs of all public github repos
Capability registry for the agentic economy. Semantic search over verified MCP server listings.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAgent-safe code retrieval MCP server that indexes repositories and provides semantic search, file navigation, call graph analysis, and bounded file reading tools for coding agents.3,448,4193AGPL 3.0
- AlicenseAqualityBmaintenanceAn MCP server that indexes reference repositories and provides tools for AI coding agents to retrieve lossless code context, enabling reasoning over codebases larger than the agent's context window.82Apache 2.0
- AlicenseNot gradedqualityBmaintenanceSemantic + lexical code search as an MCP server. Agents query in natural language and get back ranked file:line ranges to read precisely.151MIT
- AlicenseNot gradedqualityBmaintenanceA local hybrid-search MCP server that enables coding agents to query files and folders using natural language, returning relevant code chunks with exact source paths. Everything runs on-device with no API keys or network calls.5MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/DCSTOLF/harpyja'
If you have feedback or need assistance with the MCP directory API, please join our Discord server