Skip to main content
SDL-MCP provides a structured, token-efficient protocol for AI coding agents. Without explicit instruction, agents default to native file-read and shell tools — wasting tokens on code they don’t need. This guide explains how to enforce SDL-MCP tool use and how agents should work through the Iris Gate Ladder.

Why Tool Enforcement Matters

A client can have SDL-MCP connected and still spend tokens on native reads and shell commands. Without enforcement:
  • Agents read entire files instead of requesting targeted symbol slices
  • Agents shell out to grep or find instead of calling sdl.symbol.search
  • Context windows fill up with irrelevant code before the agent finds what it needs
SDL-MCP’s tool enforcement generates client-specific instruction files and config that redirects agents to SDL tools first.

Enforcing SDL Tools Per Client

Run the init command with --enforce-agent-tools for each client you use:
# Claude Code
sdl-mcp init --client claude-code --enforce-agent-tools

# Codex
sdl-mcp init --client codex --enforce-agent-tools

# Gemini
sdl-mcp init --client gemini --enforce-agent-tools

# OpenCode
sdl-mcp init --client opencode --enforce-agent-tools
This enables SDL runtime and exclusive Code Mode, then generates the repo-local instruction files and client-specific enforcement assets for the chosen client.

Paste-Ready Agent Instruction Block

Copy the block below into AGENTS.md (or CLAUDE.md for Claude) at the root of your project. Replace [repoid] with your repo’s actual ID.
This is the canonical instruction block from SDL-MCP’s own docs. It covers all 12 workflow categories an agent needs to use SDL-MCP correctly.
## SDL-MCP Token-Efficient Protocol (v0.10)

- Repository ID: `[repoid]`
- MCP Server: `sdl-mcp`

### 0) Establish state before deep context

1. Call `sdl.repo.status` first.
2. If local code changed and indexing is stale, run `sdl.index.refresh` with `mode: "incremental"`.
3. Call `sdl.policy.get` and honor returned caps. Current effective policy is:
   - `maxWindowLines: 180`
   - `maxWindowTokens: 1400`
   - `requireIdentifiers: true`

### 1) The Iris Gate Ladder (Token-Efficient Context Escalation)

Use this order unless task constraints force escalation:

1. `sdl.repo.overview` (start with `level: "stats"`; use `directories`/`full` only when needed).
2. `sdl.symbol.search` with a tight `limit` (`5-20` to start; default is `50`, max is `1000`).
   - Add `semantic: true` to enable embedding-based reranking for fuzzy or conceptual queries.
3. `sdl.symbol.getCard` for single lookups; send `ifNoneMatch` to get `notModified` responses.
   - Provide exactly one of `symbolId` or `symbolRef`.
   - Use `sdl.symbol.getCards` (batch, up to 100 IDs) when fetching multiple symbols.
   - Pass `knownEtags` to `getCards` for delta fetching.
   - Use `minCallConfidence` to filter low-confidence call edges from card responses.
4. `sdl.slice.build` with explicit budget and compact output:
   - Keep `wireFormat: "compact"` (default) and `wireFormatVersion: 2` (default).
   - Set budget early: `{ "maxCards": 30, "maxEstimatedTokens": 4000 }`.
   - Use `minConfidence` to drop low-trust edges (default `0.5`).
   - Always provide `entrySymbols` when available.
   - **Auto-discovery mode**: pass `taskText` (and optionally `stackTrace`, `failingTestPath`, or `editedFiles`) instead of `entrySymbols`.
5. `sdl.slice.refresh` if you already have a `sliceHandle`; prefer refresh over rebuilding.
6. `sdl.slice.spillover.get` only when necessary; keep `pageSize` small (default `20`, max `100`).
7. `sdl.code.getSkeleton` before `hotPath` or raw windows.
8. `sdl.code.getHotPath` with focused identifiers (`1-3` identifiers, low `contextLines`, default `3`).
9. `sdl.code.needWindow` last. Keep requests tight:
   - `expectedLines <= 180`
   - `maxTokens <= 1400`
   - Non-empty `identifiersToFind` (required by policy)
   - Pass `sliceContext` to give the gating engine task context.

### 2) Task-specific workflows

- **Debug**: `search -> card -> slice.build -> hotPath -> needWindow (only if still ambiguous)`.
- **Debug (auto-discovery)**: `slice.build` with `taskText` describing the bug + `stackTrace` and/or `failingTestPath`.
- **Feature implementation**: `repo.overview -> search -> card -> slice.build`.
- **PR review**: `delta.get -> pr.risk.analyze -> card/hotPath for high-risk symbols`.
- **Live editing**: `buffer.push` as files change → `buffer.checkpoint` to persist → search/card/slice reflect draft state.
- **Context export**: `context.summary` with `format: "clipboard"` for non-MCP tools.
- **Test execution**: `runtime.execute` with narrowest useful runtime.
- **Multi-step chain** *(Code Mode)*: `sdl.action.search` -> focused `sdl.manual` -> `sdl.chain`.

### 3) Do not

- Do not jump directly to raw file reads if SDL tools can answer the question.
- Do not call `sdl.code.needWindow` before trying `sdl.code.getSkeleton`/`sdl.code.getHotPath`.
- Do not use broad `sdl.symbol.search` limits by default.
- Do not rebuild slices repeatedly when `sdl.slice.refresh` can provide incremental deltas.
- Do not call `sdl.symbol.getCard` N times when `sdl.symbol.getCards` can fetch all N in one call.
- Do not skip `sdl.agent.feedback` after completing a task.
- Do not call `sdl.runtime.execute` without setting `timeoutMs`.
- Do not ignore `nextBestAction`, `fallbackTools`, or `fallbackRationale` in denied responses.

The Iris Gate Ladder

The Iris Gate Ladder is SDL-MCP’s core token-efficiency mechanism. It defines the order in which agents escalate context access — from cheapest to most expensive:
1

Rung 1 — Symbol search and cards

Start here. Use sdl.symbol.search with a tight limit (5–20 results). Fetch individual cards with sdl.symbol.getCard or batch with sdl.symbol.getCards.Cost: Minimal. Cards contain signatures, dependencies, and LLM summaries without raw code bodies.
{
  "repoId": "my-repo",
  "query": "validateToken",
  "limit": 10,
  "semantic": true
}
2

Rung 2 — Graph slice

Build a dependency graph slice from entry symbols. This gives structured context about how symbols relate — far cheaper than reading files.
{
  "repoId": "my-repo",
  "entrySymbols": ["sha256:abc..."],
  "budget": { "maxCards": 30, "maxEstimatedTokens": 4000 },
  "wireFormat": "compact"
}
Use taskText instead of entrySymbols for auto-discovery mode:
{
  "repoId": "my-repo",
  "taskText": "token validation is failing for expired JWTs",
  "stackTrace": "Error: invalid signature\n  at validateToken..."
}
3

Rung 3 — Skeleton and hot path

When a slice isn’t enough, use sdl.code.getSkeleton for deterministic skeleton IR (signatures + control flow, elided bodies), then sdl.code.getHotPath for lines matching specific identifiers.
{
  "repoId": "my-repo",
  "symbolId": "sha256:abc...",
  "identifiersToFind": ["errorCode", "retryCount"],
  "contextLines": 3
}
4

Rung 4 — Raw code window (escalate)

Last resort. Requires proof-of-need: a reason, the identifiers you expect to find, and an expected line count. Gated by the policy engine.
{
  "repoId": "my-repo",
  "symbolId": "sha256:abc...",
  "reason": "Need to inspect the exact error handling branch for expired tokens",
  "identifiersToFind": ["TokenExpiredError", "expiresAt"],
  "expectedLines": 60,
  "maxTokens": 800,
  "sliceContext": {
    "taskText": "debug JWT expiration handling"
  }
}

Optimal Tool Usage Order

Agent Task


 sdl.repo.status          ← Check index freshness


 sdl.symbol.search        ← Locate relevant symbols


 sdl.symbol.getCard(s)    ← Read signatures, deps, summaries


 sdl.slice.build          ← Graph context around entry symbols


 sdl.code.getSkeleton     ← Signatures + control flow (no bodies)


 sdl.code.getHotPath      ← Lines matching specific identifiers


 sdl.code.needWindow      ← Full raw code (gated, last resort)


 sdl.agent.feedback       ← Record useful/missing symbols

Feedback Loop

After completing any task, call sdl.agent.feedback to improve future slice quality:
{
  "repoId": "my-repo",
  "versionId": "<from sdl.repo.status>",
  "sliceHandle": "<from sdl.slice.build>",
  "usefulSymbols": ["sha256:abc...", "sha256:def..."],
  "missingSymbols": ["sha256:xyz..."],
  "taskType": "debug",
  "taskText": "fix JWT expiration handling",
  "taskTags": ["auth", "jwt"]
}
This trains the slice ranker. Use sdl.agent.feedback.query with limit and since (ISO timestamp) to review aggregated stats on which symbols are most frequently useful or missing.

Context Summary for Non-MCP Contexts

Use sdl.context.summary to generate a token-bounded summary for clipboard, PR descriptions, or tickets:
{
  "repoId": "my-repo",
  "query": "authentication middleware",
  "budget": 2000,
  "format": "clipboard",
  "scope": "task"
}
  • scope: "task" — multi-symbol summary
  • scope: "symbol" — single-symbol summary
  • format: "clipboard" — paste-ready plain text
  • format: "markdown" — structured Markdown
  • format: "json" — structured JSON

Complete Tool Reference

SDL-MCP exposes 32 MCP tools across 14 categories:
CategoryToolPurpose
Repositorysdl.repo.statusIndex health, watcher state, prefetch stats
sdl.index.refreshFull or incremental re-indexing
sdl.repo.overviewToken-efficient codebase overview
Symbolssdl.symbol.searchSearch by name or summary; supports semantic: true
sdl.symbol.getCardSingle symbol card with ETag caching
sdl.symbol.getCardsBatch fetch up to 100 cards
Slicessdl.slice.buildBuild graph slice from entry symbols or task text
sdl.slice.refreshIncremental delta from an existing slice handle
sdl.slice.spillover.getPaginated fetch for overflow symbols
Code Accesssdl.code.getSkeletonSignatures + control flow, no bodies
sdl.code.getHotPathLines matching specified identifiers
sdl.code.needWindowFull raw code window (gated)
Policysdl.policy.getRead current policy settings
sdl.policy.setUpdate policy (merge patch)
Agentsdl.agent.orchestrateAutonomous task execution
sdl.agent.feedbackRecord useful/missing symbols after a task
sdl.agent.feedback.queryQuery feedback statistics
Contextsdl.context.summaryToken-bounded summary for non-MCP contexts
Runtimesdl.runtime.executeSandboxed subprocess execution
sdl.runtime.queryOutputSearch stored runtime output artifacts
Memorysdl.memory.storeStore cross-session development memory
sdl.memory.querySearch memories by text, type, or tags
sdl.memory.surfaceAuto-surface relevant memories for a task
sdl.memory.removeSoft-delete a memory
Deltassdl.delta.getDelta pack between two versions
Risksdl.pr.risk.analyzeAnalyze PR risk and blast radius
Live Bufferssdl.buffer.pushPush editor buffer for draft-aware indexing
sdl.buffer.checkpointPersist draft changes into the symbol overlay
sdl.buffer.statusCheck live buffer state
Usagesdl.usage.statsCumulative token usage and savings metrics
Diagnosticssdl.infoRuntime, config, and native-addon status
Code Modesdl.action.searchDiscover relevant SDL actions
sdl.manualFiltered API reference
sdl.chainMulti-step action chain (up to 50 steps)

Build docs developers (and LLMs) love