AI Assistants (MCP)
This is the primary way Align gets used. Your agent knows the code in front of it. It does not know what your team decided, when, or what has since replaced that decision. MCP is how it finds out.
Align speaks the Model Context Protocol. Any MCP client works - Claude Desktop, Claude Code, Cursor, VS Code Copilot Chat, Windsurf, or your own.
Two servers, and you need to know which one you are talking to
They expose different tool names, and nothing in the client tells you which answered.
| Hosted server | CLI server | |
|---|---|---|
| What it reads | Your shared org graph | A local graph until you run align login, then your org's shared graph |
| Started by | Align (or your self-hosted deployment) | align mcp |
| Transport | Streamable HTTP | stdio |
| Tool naming | dotted - search | underscored - search |
| Tools | 24 | 8 |
| Requires | A Growth or Self-Hosted workspace | Nothing for the local graph. align login and a workspace for the shared one |
If you configure both, give them distinct server names in your client config. Asking one graph a question the other holds returns a confident, correct-looking answer about the wrong data.
Option 1: the CLI (free, no account)
Fastest path. Builds a personal graph from your own tools and serves it to any agent.
npm install -g @aligndottech/cli
align import git # or jira, github, linear, confluence, slack, notion...
align mcp --setup # detects your editors and writes their MCP config
--setup writes this for you, but if you prefer to do it by hand:
{
"mcpServers": {
"align": {
"command": "align",
"args": ["mcp"]
}
}
}
Add "--env", "preview" to the args to point the CLI at a non-production workspace.
CLI tools (8)
| Tool | What it does |
|---|---|
search | Search the graph |
align_ask | Natural-language question over the graph |
capture | Capture a decision from a URL |
check_alignment | Check a diff against the graph |
check_drift | Score code or config against one decision |
get_impact | Blast radius of a decision |
get_conflicts | Active contradictions |
get_related_decisions | Decisions related to a file path |
Option 2: the hosted server (shared org graph)
Point your client at the Align MCP endpoint over streamable HTTP:
| Environment | URL |
|---|---|
| Production | https://mcp.align.tech/tools |
| Preview | https://mcp.preview.align.tech/tools |
| Local / self-hosted | http://localhost:8089/tools |
Cursor, VS Code Copilot Chat and Windsurf all take a URL directly. Claude Code supports HTTP MCP servers too, but the hosted endpoint needs a bearer credential and I have not verified a Claude Code setup against it, so the CLI server above is the supported path for Claude Code. Claude Desktop speaks stdio: use the CLI server, or an HTTP-to-stdio bridge.
The hosted server needs an Authorization: Bearer credential bound to your workspace.
Hosted tools (24)
Ask the graph
| Tool | What it does |
|---|---|
search | Natural-language search across every decision |
search_decisions | The same search, tuned for IDE-shaped queries |
get_related_decisions | Decisions related to a file path |
get_decision_rationale | Why a decision was made |
get_decision_timeline | The chronological thread around a decision |
get_decision_history | The supersession chain - what replaced it, what it replaced |
get_impact | Upstream and downstream blast radius |
get_blocking_decisions | What is blocking a given decision |
get_conflicts | Active contradictions between decisions |
get_topic_timeline | The story of a topic in time order, across tools - see below |
get_task_context | Bounded, task-scoped context for implementing something related to a topic |
get_agent_decisions | Premises an agent decided, unratified by any human |
get_decision_artifacts | The artifacts (PRs, tickets, messages) a decision points at |
get_parameter_windows | The active value for a typed parameter |
Check before you act
| Tool | What it does |
|---|---|
check_alignment | Check a git diff against the graph - see below |
check_proposed_action | Check a proposed PR, ticket, message or commit |
check_drift | Score code or config against one decision |
coach | Surface conflicts, missing context and blockers for a direction |
rate_conflict | Record whether a surfaced conflict was right |
Write and administer
| Tool | What it does |
|---|---|
capture | Record a new decision from text |
analyze | Extract decisions and open debates from pasted messages |
list_connectors | Which integrations are connected |
connect | Start an integration's OAuth flow |
connect_status | Whether a connector is connected |
Some tools are deliberate aliases with different affordances for an agent. search,
search_decisions and get_related_decisions all resolve to the same semantic
search; check_alignment and check_proposed_action both resolve to the same
alignment check, with the former prepending the changed file paths from a diff.
get_topic_timeline and get_task_context share one retrieval, relabelled for two
different jobs - a narrative for a human vs. bounded governing context for an agent
about to write code.
We would rather say this than let a tool count read as a capability count.
check_alignment, search and get_topic_timeline, in detail
These three are the ones the instructions above put in front of every agent by default (see
"Getting the most out of it"), so they are worth a worked example each. check_alignment and
search also carry an enforced p95 latency budget and a scheduled regression gate; see
performance-budgets.md
for the current numbers - they move, and a docs page is the wrong place to pin a number that
gets re-measured on a schedule.
check_alignment
Purpose. Checks a proposed change against the decision graph before you make it, and stops you on a real conflict.
Input.
{ "diff": "<the output of git diff or git diff --staged>", "context": "branch name or ticket" }
diff is the raw diff text - the tool extracts the changed file paths from it itself, so you
never pass those separately. context is optional free text (branch name, ticket number, a
one-line description). Phrase what the diff DOES as a decision and its value ("set the worker
pool to 12"), not the chore ("wire up a worker") - the check matches against past decisions,
and a chore description gives it nothing to match against.
Output (shape, not a literal example - the real response includes citations and links):
{ "status": "conflicting", "matched_decisions": [ { "title": "...", "decision_url": "...", "cite": "..." } ] }
Failure modes.
status | Means | What to do |
|---|---|---|
aligned | No conflicting decision found | Proceed |
no-context | Nothing in the graph speaks to this change | Proceed - there is no decision to conflict with |
conflicting | A past decision opposes the change | Stop and confirm with the user before proceeding |
unknown | The check could not run, or ran but reached no reliable verdict | Not a pass. Surface it; do not proceed as if aligned |
A decision matched by the check can itself carry a conflicted status - treat that the same
as a conflict result, not as a match worth citing uncritically.
search
Purpose. Natural-language search across every decision, spanning every connected tool and repository - the thing to call before reading code for "why did we decide X" or "how does Y behave".
Input.
{ "query": "does the webhook handler fail open or closed on a bad signature" }
Output (shape, not exhaustive - see connectors/mcp-align/src/tools/search.ts for the full
field list, including successor/conflicts_with when a decision has been superseded or
disputed):
{ "results": [ { "id": "...", "title": "...", "status": "active", "source_url": "...", "cite": "..." } ] }
Failure modes. An empty results array means no matching decision exists - it does not
mean the behaviour is undecided, only that nothing in the graph documents it. There is no
unknown status for search the way there is for check_alignment: a service outage surfaces
as a tool-call error, not a soft status field.
get_topic_timeline
Purpose. Everything the team ever decided about a topic, in time order, across every
connected tool - "what is the story on X", "how did we end up here", or onboarding onto an
unfamiliar area. Deliberately includes superseded and archived decisions: the retired past is
what explains why the current answer is current. Distinct from get_decision_timeline, which
is the change history of ONE decision.
Input.
{ "topic": "worker pool sizing", "limit": 50 }
limit is optional (default 50, capped at 200 server-side - a request for more is silently
capped, not rejected).
Output. A compact answer by default: the current standard in one sentence, the contested
line if decisions disagree, up to three pivotal dated steps, a one-line chain summary, and the
sharpest open question the chain leaves open. The underlying gateway response (count,
superseded_count, platforms, activity, disagreements, why, still_open, and the
decisions array itself - each entry carrying id, title, status, decided_at,
source_url/decision_url and matched_by) is real JSON, but the tool renders it into
prose - see connectors/mcp-align/src/tools/topicTimeline.ts for the exact contract. Only when
the user asks for the full history does it walk the whole supersession chain oldest first, with
each step's decision_url/source_url inline and the status beside the title.
Failure modes.
| Condition | What happens |
|---|---|
| The brain (semantic half) is unavailable | The lexical half still runs; retrieval.semantic is false in the underlying response rather than the tool silently returning a shorter list that reads as complete |
| No decisions match the topic | An empty timeline, not an error |
limit exceeds the server maximum (200) | Silently capped at 200 |
| The gateway call fails | An error result, not a fabricated timeline |
Its latency budget (2,000 ms at p95, ALI-1276)
has no LLM call on the critical retrieval path the way check_alignment does, so it is the
fastest of the three by a wide margin - see performance-budgets.md for the measured figure
once the scheduled gate has run against live traffic.
Getting the most out of it
The tools work unprompted, but agents use them far better when told when to reach for them. Add
something like this to your CLAUDE.md, .cursorrules or equivalent:
- BEFORE writing or changing non-trivial code, call check_alignment with the diff.
A "conflicting" result means a past decision opposes the change - stop and confirm.
- "unknown" means the check could not run. It is NOT a pass. Surface it.
- To answer "why did we decide X", or any question about BEHAVIOUR ("what happens when
Y fails", "does it fail open"), call search BEFORE reading the code. The graph
spans repositories; grepping this checkout silently misses decisions made elsewhere.
- After acting on a conflict, call rate_conflict with the check_event_id.
That last one matters more than it looks. A flag nobody judges teaches the graph nothing.
Self-hosted configuration
| Variable | Default | Purpose |
|---|---|---|
GATEWAY_URL | http://gateway:8080 | Where the MCP server reaches the Align API |
ALIGN_API_KEY | - | Workspace API key |
ALIGN_TENANT_ID | - | Workspace tenant ID |
MCP_TRANSPORT | http | http or stdio |
PORT | 8089 | Listen port |
Find your tenant ID under Settings → Account, and create an API key under Settings → API Tokens.
Troubleshooting
The agent answers from the code instead of the graph. Usually the instruction, not the wiring. Confirm the tools are listed in your client, then tell the agent explicitly to search the graph first.
The agent gets decisions that are not yours. You have more than one Align server configured and it picked the wrong one. Distinct server names, and name the server in the instruction.
Nothing connects. Check the port is free (lsof -i :8089), the URL ends in /tools, and for
the CLI that align whoami resolves against the environment you expect.
Next steps
- Agent Alignment Layer - the check-before-you-act half
- CLI - every command and flag
- Features - what the graph holds