Skip to content

Getting started

Arrowhead needs Python 3.12 or newer and uv, or just Docker. The package is not on PyPI (that name belongs to an unrelated project), so install it from a checkout or a git URL; deployments run the container image.

Terminal window
git clone https://github.com/jagguvarma15/arrowhead.git
cd arrowhead
uv sync
uv run python -m arrowhead.server

That serves over stdio, ready for a pipe-connected client. Auth is off in stdio mode, so every tool in the active profile is immediately callable. The MCP Inspector gives you an interactive console:

Terminal window
npx @modelcontextprotocol/inspector uv run python -m arrowhead.server

Only the data family needs packaging extras (the parser and database drivers); the rest runs on the base install:

Terminal window
uv sync --extra sql --extra postgres # SQL and pgvector connectors
uv sync --extra treesitter # exact non-Python symbol extraction

Try calculate with 2 * (3 + 4), or read_file with welcome.txt (a sample lives in sandbox/). The command line shows the surface you are serving:

Terminal window
uv run arrowhead list-tools # each tool and the scope it requires
uv run arrowhead list-tools --json # the full client-visible catalog with schemas

A deployment sets ARROWHEAD_PROFILE so a connection carries only the tool families it needs; a tool outside the active profile is never registered, so it costs no context and a call to it is unknown.

Profile Serves
core The general-purpose utilities only
docs The document corpus, data connectors, tasks, memory, and notify
coding The repo, assist, exec, and context families over the data connectors
full (default) Every family

Two families gate a second time regardless of profile: exec registers only when ARROWHEAD_EXEC_ENABLED is true, and notify only when ARROWHEAD_NOTIFY_ALLOWLIST is non-empty. The tool reference lists every family and tool; the configuration reference lists every variable.

Terminal window
docker compose -f deploy/docker-compose.yml up

That serves a streamable-HTTP endpoint on http://localhost:8000/mcp with a shared rate-limit store.

The deployment runbook walks through a live instance end to end, and each release tag publishes the image to ghcr.io/jagguvarma15/arrowhead.

Integrations has tabbed, copy-paste instructions for Claude Desktop, Claude Code, Cursor, VS Code, the Claude Agent SDK, agent-scaffold projects, and any generic MCP client, plus one-click install links for Cursor and VS Code.

Arrowhead.call and the HTTP transport route through the same dispatch, so an imported call runs the identical authorization, sanitization, and middleware path as a call over the wire:

from arrowhead import Arrowhead
app = Arrowhead()
with app.as_principal("service:etl", {"docs:read"}):
result = await app.call("doc_read", {"path": "notes.md"})
document = await app.read_resource("doc://notes.md")

A call with no principal is anonymous, and every scoped component is denied, so the guarded path is the default whichever door a call comes through.