Skip to main content
Glama
ecestnrkl

figjam-context-mcp

figjam-context-mcp

A local MCP server that turns FigJam boards into source-cited context for LLMs. It reads a board through the Figma REST API, groups stickies, tables, images and arrows into clusters, and answers questions with links back to the original nodes.

Pipeline: a FigJam board is read through the Figma API, clustered by geometry, refined with vision and turned into LLM-ready context

Why

Workshop boards hold research notes, decisions and open questions, but an LLM cannot read a canvas. Screenshots and PDF exports lose tables, arrow direction and the link to the source. This server keeps the board's structure and cites every answer to the nodes it came from.

Related MCP server: Miro MCP Server

Tools

Tool

What it does

LLM call

ingest_board

Reads a board, clusters it and saves a local snapshot. Re-ingests reuse unchanged clusters.

In balanced (default) and max_quality mode

get_board_context

Returns paginated, source-linked context, optionally for a topic or exact node IDs. Use it for overviews, summaries and documentation.

No

answer_from_board

Answers one specific question (a number, status or decision) from the most relevant excerpts, with node-level citations or an insufficient-evidence result. Not meant for whole-board summaries.

Yes

diff_board

Compares two snapshots: new, removed and changed clusters, nodes, table cells and arrows.

No

diagnose_llm_config

Tests the configured models with small text and image JSON checks.

Yes

Quick start

Requires Node.js 22.12 or later.

  1. Create a Figma personal access token under Settings → Security → Personal access tokens with the scope file_content:read. Add file_metadata:read so re-ingests of an unchanged board skip the download. The token's account needs access to the board.

  2. Optional: create an OpenRouter key at openrouter.ai/keys. It enables image interpretation, answer_from_board and diagnose_llm_config. Without it, use ingestMode: "max_speed" with get_board_context and diff_board.

  3. Add the server to your MCP client. @latest makes npx check for a new release on every start instead of reusing a cached older version:

{
  "mcpServers": {
    "figjam-context": {
      "command": "npx",
      "args": ["-y", "figjam-context-mcp@latest"],
      "env": {
        "FIGMA_ACCESS_TOKEN": "your-figma-token",
        "LLM_BASE_URL": "https://openrouter.ai/api/v1",
        "LLM_API_KEY": "your-openrouter-key"
      }
    }
  }
}

For Claude Code:

claude mcp add figjam-context -e FIGMA_ACCESS_TOKEN=your-figma-token -e LLM_BASE_URL=https://openrouter.ai/api/v1 -e LLM_API_KEY=your-openrouter-key -- npx -y figjam-context-mcp@latest

Then ask your assistant to ingest a board URL, for example "Ingest https://www.figma.com/board/FILE_KEY/Name and list the open questions." The boardId of every later call is the file key from that URL. To summarize a board, the assistant calls ingest_board, then get_board_context without parameters, whose first page names the largest sections and lists all sections with IDs, and then reads the largest sections by passing their IDs as nodeIds. Everything that lies in no section, such as loose notes and tables, comes with outsideSections: true.

All settings: configuration. Problems: troubleshooting.

How it works

  1. Read. ingest_board downloads the board through the Figma REST API. If Figma reports the same version as the last ingest, the download is skipped.

  2. Normalize. Nodes become text, table cells, images and connectors, with their pages and sections. Tables are read row by row: row and column come from the cell IDs, and each row becomes one excerpt.

  3. Cluster. Nearby nodes are grouped by rotation-aware distance. Arrows between groups become directed relations.

  4. Interpret. In balanced mode, clusters with an image, or drawings without any text, get a vision-model summary within a 40-second budget; text clusters, however short, keep their extracted text. A cluster starts only when the time left fits it; unfinished clusters continue on the next ingest.

  5. Serve. The snapshot is saved to a private local cache. get_board_context searches it (BM25 over original text, table rows and names), answer_from_board answers with citations and diff_board compares snapshots. Its first page lists the board's sections with IDs; pass a page, section, frame or group ID as nodeIds to read everything inside it; several IDs in one call take turns, so each of them appears on every page. Its text content is the readable page; structuredContent holds the same data without repeating it, with excerpts in evidence and location per cluster in clusters.

Models and cost

The default preset student-free uses free OpenRouter models: text goes to nvidia/nemotron-3-super-120b-a12b:free and then openrouter/free; images go to openrouter/free, which picks a free model that accepts images and structured outputs. The free default is best effort: free models change, hit rate limits and time out.

  • OpenRouter allows free models 20 requests per minute and 50 requests per day, or 1,000 per day once you have bought at least 10 credits (limits).

  • Figma limits requests by seat and plan (rate limits). File downloads and image renders are Tier 1: Dev and Full seats on paid plans get 10–20 requests per minute, View and Collab seats and files in Starter plans at most 20 per month. Images come from the image fills instead, Tier 2 with at least 5 requests per minute, in one request per ingest. Renders are left for drawings without an image and as a fallback for single images; one render request covers up to 18 nodes. max_speed needs neither.

  • For a team, configure your own model: LLM_BASE_URL takes any OpenAI-compatible endpoint, and LLM_TEXT_MODELS / LLM_VISION_MODELS set the model lists.

  • Run diagnose_llm_config after every model change. It checks JSON replies and image understanding with synthetic inputs.

Privacy

  • The server reads from Figma and never changes a board.

  • balanced and max_quality ingests send board text and images (originals or renders) to the configured LLM provider. answer_from_board sends the question and selected excerpts. max_speed with get_board_context and diff_board sends nothing to an LLM provider.

  • Snapshots stay in a private per-user cache on your machine. Delete the cache directory to remove them.

  • Explicit credentials such as Passwort: … or API keys are redacted before they reach the cache, tool output or an LLM provider (FIGJAM_MCP_REDACT_CREDENTIALS). This is a safety net, not a guarantee: images are not redacted, so keep credentials off the board.

  • Keep tokens in the client's environment. A token passed as a tool argument can appear in client logs.

Limitations

  • Image interpretation gets 40 seconds per ingest by default; large boards need several ingests to interpret every image cluster.

  • A client that cancels an ingest, for example after a 60-second timeout, gets no partial result.

  • Free models are best effort. Citations show where an answer comes from, not that its conclusion is right.

  • Search is lexical; synonyms without shared words do not match.

  • Local stdio only; no hosted or multi-user mode.

Measured results: evaluation.

Development

git clone https://github.com/ecestnrkl/figjam-mcp.git
cd figjam-mcp
npm ci
cp .env.example .env    # add your tokens
npm run check           # typecheck, tests, build, package validation
npm run package:smoke   # install the packed package and exercise all tools
npm run eval:retrieval  # offline retrieval and diff evaluation
npx @modelcontextprotocol/inspector --config inspector.config.json

See CONTRIBUTING.md and the changelog.

License

MIT © 2026 ecestnrkl

Available Tools

5 tools
answer_from_boardAnswer From BoardA
Read-only

Answer one specific question, such as a number, a status or a decision, from the most relevant excerpts of an ingested board, with validated source citations or an insufficient-evidence result. It reads only a handful of excerpts: not for summaries, lists, risks or next steps across several sections; read those with get_board_context. Sends the question and the selected excerpts to the configured LLM provider; calls may incur charges.

ParametersJSON Schema
NameRequiredDescriptionDefault
boardIdYesThe Figma file key returned by ingest_board
questionYes
snapshotIdNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
answerYes
citationsYes
snapshotIdYes
citedClustersYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, non-destructive, open-world, non-idempotent), so the bar is lower. The description adds genuinely useful non-structured context: it reads only a handful of excerpts, sends the question plus excerpts to the configured LLM provider, and that calls may incur charges. It stops short of latency, rate limits, or what happens on provider misconfiguration, but the cost disclosure is real added value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, all front-loaded and each earning its place: what it answers, the negative scope with the alternative tool, then the LLM/cost caveat. No filler and the most decision-relevant content comes first.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't explain return values, and it still notes the insufficient-evidence outcome and validated citations. Annotations carry the safety profile and the description carries the cost/LLM behavior; the only meaningful hole is the unexplained optional snapshotId parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% — boardId is documented as a Figma file key, but 'question' and 'snapshotId' carry no schema descriptions, and the description never mentions parameters at all. snapshotId in particular is an optional parameter whose meaning (which point-in-time snapshot to answer from) is left entirely unexplained in both places.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('answer one specific question... from the most relevant excerpts of an ingested board') and scopes the question types it handles. It also explicitly distinguishes itself from the sibling get_board_context by naming what it is not for, so an agent can route between the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-not ('not for summaries, lists, risks or next steps across several sections') and names the alternative tool to use instead (get_board_context). The usage condition is unambiguous and the alternative is named, not merely implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diagnose_llm_configDiagnose LLM ConfigA
Read-only

Test the configured text and vision models with three small synthetic JSON challenges. Sends synthetic text and an image to the configured provider, may incur charges, and reports semantic/schema failures. Does not read board contents. Use after changing model/provider settings.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
checksYes
presetYes
summaryYes
textModelsYes
visionModelsYes
fastTextModelsYes
providerRequireParametersYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, non-destructive, openWorld) and the description adds real value beyond them: potential charges, that synthetic data is sent to the external provider, that board contents are not read, and that semantic/schema failures are reported. It does not contradict the annotations — outbound provider calls are consistent with openWorldHint and the non-idempotent hint aligns with per-call charges.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with what it does, followed by side effects, scope boundary, and timing. Dense but every sentence carries information; minor compression possible in the failure-reporting clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter diagnostic with an output schema (so return values need no explanation), the description covers purpose, cost side effects, external data transmission, scope exclusion, and when to invoke it. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so per the rubric the baseline is 4; there is nothing for the description to disambiguate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (diagnose/test) and resource (configured text and vision models) plus the exact scope: three small synthetic JSON challenges. It is unmistakably distinct from the board-oriented siblings like ingest_board and get_board_context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the trigger condition: 'Use after changing model/provider settings.' No alternative tool is named and no when-not-to-use is given, but the diagnostic framing makes the context clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diff_boardDiff Board SnapshotsA
Read-onlyIdempotent

Compare retained local snapshots of the same board, reporting cluster, node and connector changes. Requires at least two distinct ingests. compareTo=1 selects the previous snapshot, 2 selects two states back. No network or LLM calls; ingest_board must capture the current Figma state first.

ParametersJSON Schema
NameRequiredDescriptionDefault
boardIdYesThe Figma file key, as returned by ingest_board
compareToNoHow many snapshots back to use as the baseline (1 = the ingest before the latest)

Output Schema

ParametersJSON Schema
NameRequiredDescription
statsYes
boardIdYes
newClustersYes
summaryTextYesPaste-ready human/LLM-readable change report
removedClustersYes
addedConnectionsYes
currentCreatedAtYesISO timestamp of the latest ingest
modifiedClustersYes
tableCellChangesNo
baselineCreatedAtYesISO timestamp of the baseline ingest
currentSnapshotIdNo
baselineSnapshotIdNo
removedConnectionsYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, non-open-world, so the safety profile is covered. The description adds genuine context beyond that: the two-ingest precondition and that no network or LLM calls are made, which is useful cost/latency information.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with no filler; the scope statement comes first, then the precondition, then the parameter shortcut and the ingest dependency. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description covers the key prerequisites and behavioral constraints. It omits the snapshot-history bound (max 19 back) and any note on what happens when fewer than two snapshots exist, but is otherwise sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters are already documented. The description restates compareTo=1 as 'previous snapshot' and adds '2 selects two states back', which is slightly more intuitive but largely duplicates the schema's own wording. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (compare retained local board snapshots) and names the output (cluster, node and connector changes). An agent can tell it apart from ingest_board and get_board_context immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a hard prerequisite (at least two distinct ingests) and explicitly routes the agent to ingest_board before calling this. It does not say when to prefer this over get_board_context or answer_from_board, so it stops short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_board_contextGet Board ContextA
Read-onlyIdempotent

Read source-cited context from an ingested board snapshot: original text, table rows, cluster summaries and arrows, each with a Figma link. Start here for overviews, summaries and documentation with one call without topic, nodeIds, limit and maxChars: its first page names the largest sections and lists all sections with IDs. Then read sections, pages, frames or groups by passing their IDs as nodeIds (several IDs in one call share every page), read everything outside sections with outsideSections: true, search words with topic, or continue with cursor, and synthesize the answer yourself. Large pages can exceed client output limits. No network or LLM calls; does not refresh Figma content (use ingest_board).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum evidence excerpts per page (default 20)
topicNoOptional topic to focus the context on
cursorNoContinue a page using the same query, snapshot, limit and maxChars
boardIdYesThe Figma file key returned by ingest_board
nodeIdsNoRead exact source nodes, all rows of a table or the row of a table cell, or every excerpt inside a page, section, frame or group by its ID (nested sections included, in reading order); several IDs in one call share every page in request order; cannot be combined with topic
maxCharsNoCharacter budget for each representation: the readable text content and the JSON of structuredContent (default 12000)
snapshotIdNoRead a specific retained snapshot instead of the latest board
outsideSectionsNoRead every excerpt that lies in no section, cluster by cluster in reading order, tables row by row; on a board without sections, all excerpts. Cannot be combined with topic or nodeIds

Output Schema

ParametersJSON Schema
NameRequiredDescription
clustersYes
evidenceYes
relationsNoCluster-to-cluster relations derived from connector arrows
truncatedYes
nextCursorNo
snapshotIdYes
truncationYesExplicit omissions from structured results and the readable text
connectionsYes
contextTextYesOrientation: board header, page position, board overview or subsections. The excerpts are in evidence; the text content carries the readable version
totalMatchedYes

TDQS

A4.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so safety is covered. The description usefully adds that there are no network or LLM calls, that it does not refresh Figma content, and that large pages can exceed client output limits, but it does not cover pagination failure modes or error behavior in depth.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense but well-ordered paragraph: purpose first, entry-point strategy second, follow-on invocation patterns third, caveats last. Every clause carries routing or constraint information rather than restating the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter read tool with an output schema and full annotation coverage, the description supplies everything an agent needs: how to start, how to drill into specific nodes, mutual-exclusion rules, pagination, freshness limits, and the sibling to call instead when refreshing is required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description goes beyond it by explaining that omitting topic/nodeIds/limit/maxChars yields a first page that names the largest sections, that multiple nodeIds share every page in request order, and that cursor resumes the same query. That is genuine added meaning on top of the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('read source-cited context from an ingested board snapshot') and enumerates the content types returned (original text, table rows, cluster summaries, arrows). It also differentiates from siblings by naming ingest_board for refreshes and implying answer_from_board with 'synthesize the answer yourself.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit entry strategy ('Start here... without topic, nodeIds, limit, maxChars'), then a follow-up path for sections/pages/frames by nodeIds, outsideSections, topic, and cursor. Exclusion rules (cannot combine topic with nodeIds) and the alternative for refreshing (use ingest_board) are stated directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ingest_boardIngest FigJam BoardA

Read a FigJam/Figma URL with the configured Figma token and persist a local snapshot for get_board_context, answer_from_board and diff_board; the summary names the largest sections to read next and how many excerpts lie outside sections. Leaves the Figma file unchanged. Balanced/quality modes may send board text and images to the configured LLM provider and incur charges; max_speed skips vision. Re-ingest to refresh stale content; local history is bounded. Supports framework phases or customPhases.

ParametersJSON Schema
NameRequiredDescriptionDefault
ingestModeNoHow aggressively to use vision LLM calls during ingestbalanced
customPhasesNoFree-form phase names to map clusters onto (e.g. ["Ideen", "Feedback", "Offene Fragen"]); overrides docStructureHint
figmaFileUrlYesURL of the FigJam/Figma file to ingest
forceFullIngestNoDownload and extract the board again, skipping the unchanged-board check and cache, and redo the image interpretation of the chosen ingestMode. Interpretations this mode does not redo (all in max_speed; in balanced those of clusters without image or drawing) are kept while a cluster's content is unchanged. The vision time budget still applies, so balanced and max_quality may need several ingests until every image is interpreted again. An unchanged board gives no new snapshot for diff_board, even with forceFullIngest. Model/configuration changes are detected automatically. Default: false
docStructureHintNoBuilt-in framework used to map clusters to phasesfreeform
figmaAccessTokenNoFigma personal access token; falls back to FIGMA_ACCESS_TOKEN env var if omitted

Output Schema

ParametersJSON Schema
NameRequiredDescription
boardIdYes
summaryYes
ingestModeNo
snapshotIdNo
clusterCountYes
figmaVersionNo
qualityReportNo
relationCountNoDirected cluster-to-cluster relations derived from connector arrows
freshnessCheckedAtNo
persistenceWarningNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing cost implications (board text and images sent to the configured LLM provider, charges may be incurred), the vision behavior of max_speed, that the remote Figma file is left unchanged, that local history is bounded, and that stale content requires re-ingest. These are exactly the non-obvious side effects an agent needs, and they are consistent with readOnlyHint=false and idempotentHint=false (each ingest writes a new local snapshot).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and its persistence target in the first clause, then layers cost, freshness, and phase-configuration caveats. It is dense and semicolon-heavy, but each clause carries distinct operational information, so it is appropriately sized for a six-parameter tool with side effects.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool of this complexity it covers the essentials: auth fallback (FIGMA_ACCESS_TOKEN env var), external-cost exposure, the shape of the summary it produces (largest sections, excerpts outside sections), staleness/refresh behavior, and bounded local history. An output schema exists, so it correctly avoids restating full return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters and the baseline would be 3. The description adds genuine meaning on top by tying ingestMode to external cost and vision behavior and by noting the framework-phases vs customPhases choice, which helps an agent pick a mode rather than just read an enum label.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb pair (read a FigJam/Figma URL) plus the concrete effect (persist a local snapshot), and explicitly names the three sibling tools that consume that snapshot (get_board_context, answer_from_board, diff_board). An agent can distinguish this from its siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear conditional guidance: 'Re-ingest to refresh stale content' establishes when to call it again, and the mode sentence tells the agent when cost/vision tradeoffs apply (max_speed skips vision). It stops short of naming an explicit alternative or a when-not-to-use condition, so it is strong context rather than full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.8.0
    • Changedget_board_context2 fields changed
      • changedInput schema / properties / nodeIds / description
        Previous value: -"Read exact source nodes, all rows of a table or the row of a table cell, or every excerpt inside a page, section, frame or group by its ID (nested sections included, in reading order); cannot be combined with topic"New value: +"Read exact source nodes, all rows of a table or the row of a table cell, or every excerpt inside a page, section, frame or group by its ID (nested sections included, in reading order); several IDs in one call share every page in request order; cannot be combined with topic"
      • addedInput schema / properties / outsideSections
        Added value: +{
        +  "description": "Read every excerpt that lies in no section, cluster by cluster in reading order, tables row by row; on a board without sections, all excerpts. Cannot be combined with topic or nodeIds",
        +  "type": "boolean"
        +}
    • Changedingest_board2 fields changed
      • changedInput schema / properties / forceFullIngest / description
        Previous value: -"Deliberately skip all caching and incremental reuse, including successful interpretations. The vision time budget still applies. Model/configuration changes are detected automatically. Default: false"New value: +"Download and extract the board again, skipping the unchanged-board check and cache, and redo the image interpretation of the chosen ingestMode. Interpretations this mode does not redo (all in max_speed; in balanced those of clusters without image or drawing) are kept while a cluster's content is unchanged. The vision time budget still applies, so balanced and max_quality may need several ingests until every image is interpreted again. An unchanged board gives no new snapshot for diff_board, even with forceFullIngest. Model/configuration changes are detected automatically. Default: false"
      • addedOutput schema / properties / qualityReport / properties / figmaRequests
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Figma requests of this ingest for images: image fills (Tier 2) and renders (Tier 1)",
        +  "properties": {
        +    "imageFills": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "renders": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "imageFills",
        +    "renders"
        +  ],
        +  "type": "object"
        +}
  2. 2 tool updatesv0.7.0
    • Changedanswer_from_board1 field changed
      • changedOutput schema / properties / citations / items / properties / sourceType / enum
        Previous value: -[
        -  "board_text",
        -  "table_cell",
        -  "board_metadata",
        -  "model_interpretation",
        -  "cluster_summary"
        -]New value: +[
        +  "board_text",
        +  "table_cell",
        +  "table_row",
        +  "board_metadata",
        +  "model_interpretation",
        +  "cluster_summary"
        +]
    • Changedget_board_context9 fields changed
      • changedInput schema / properties / maxChars / description
        Previous value: -"Character budget for the whole structured result (JSON of structuredContent, including contextText; default 12000)"New value: +"Character budget for each representation: the readable text content and the JSON of structuredContent (default 12000)"
      • changedInput schema / properties / nodeIds / description
        Previous value: -"Read exact source nodes or table cells; cannot be combined with topic"New value: +"Read exact source nodes, all rows of a table or the row of a table cell, or every excerpt inside a page, section, frame or group by its ID (nested sections included, in reading order); cannot be combined with topic"
      • addedOutput schema / properties / clusters / items / properties / pageName
        Added value: +{
        +  "description": "Page of this cluster's excerpts on this page of results; excerpts repeat it only where they differ",
        +  "maxLength": 160,
        +  "type": "string"
        +}
      • addedOutput schema / properties / clusters / items / properties / sectionNames
        Added value: +{
        +  "description": "Enclosing sections, outermost first, of this cluster's excerpts; excerpts repeat them only where they differ",
        +  "items": {
        +    "maxLength": 80,
        +    "type": "string"
        +  },
        +  "maxItems": 16,
        +  "type": "array"
        +}
      • addedOutput schema / properties / clusters / items / properties / summary / description
        Added value: +"Model summary of the cluster; empty for deterministic clusters, whose excerpts carry the text"
      • addedOutput schema / properties / contextText / description
        Added value: +"Orientation: board header, page position, board overview or subsections. The excerpts are in evidence; the text content carries the readable version"
      • addedOutput schema / properties / evidence / items / properties / pageName / description
        Added value: +"Only for an excerpt outside the listed clusters or whose location differs from its cluster's"
      • addedOutput schema / properties / evidence / items / properties / sectionNames / description
        Added value: +"Same rule as pageName; an empty list means outside sections"
      • changedOutput schema / properties / evidence / items / properties / sourceType / enum
        Previous value: -[
        -  "board_text",
        -  "table_cell",
        -  "board_metadata",
        -  "model_interpretation",
        -  "cluster_summary"
        -]New value: +[
        +  "board_text",
        +  "table_cell",
        +  "table_row",
        +  "board_metadata",
        +  "model_interpretation",
        +  "cluster_summary"
        +]
  3. 1 tool updatev0.6.0
    • Changedget_board_context1 field changed
      • changedInput schema / properties / maxChars / description
        Previous value: -"Character budget for the readable context (default 12000)"New value: +"Character budget for the whole structured result (JSON of structuredContent, including contextText; default 12000)"
  4. 5 tool updatesv0.4.0
    • Changedanswer_from_board13 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / boardId / description
        Added value: +"The Figma file key returned by ingest_board"
      • addedInput schema / properties / boardId / maxLength
        Added value: +128
      • addedInput schema / properties / boardId / minLength
        Added value: +6
      • addedInput schema / properties / boardId / pattern
        Added value: +"^[A-Za-z0-9]+$"
      • addedInput schema / properties / question / maxLength
        Added value: +2000
      • addedInput schema / properties / question / minLength
        Added value: +1
      • addedInput schema / properties / snapshotId
        Added value: +{
        +  "maxLength": 128,
        +  "minLength": 1,
        +  "pattern": "^[A-Za-z0-9_-]+$",
        +  "type": "string"
        +}
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / properties / citations
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "clusterId": {
        +        "type": "string"
        +      },
        +      "clusterLabel": {
        +        "type": "string"
        +      },
        +      "column": {
        +        "type": "number"
        +      },
        +      "evidenceId": {
        +        "type": "string"
        +      },
        +      "modelDerived": {
        +        "type": "boolean"
        +      },
        +      "nodeId": {
        +        "type": "string"
        +      },
        +      "nodeName": {
        +        "maxLength": 160,
        +        "type": "string"
        +      },
        +      "pageId": {
        +        "type": "string"
        +      },
        +      "pageName": {
        +        "maxLength": 160,
        +        "type": "string"
        +      },
        +      "quote": {
        +        "type": "string"
        +      },
        +      "row": {
        +        "type": "number"
        +      },
        +      "sectionIds": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "sectionNames": {
        +        "items": {
        +          "maxLength": 80,
        +          "type": "string"
        +        },
        +        "maxItems": 16,
        +        "type": "array"
        +      },
        +      "snapshotId": {
        +        "type": "string"
        +      },
        +      "sourceType": {
        +        "enum": [
        +          "board_text",
        +          "table_cell",
        +          "board_metadata",
        +          "model_interpretation",
        +          "cluster_summary"
        +        ],
        +        "type": "string"
        +      },
        +      "url": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "evidenceId",
        +      "snapshotId",
        +      "nodeId",
        +      "quote",
        +      "url",
        +      "sourceType",
        +      "modelDerived"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / snapshotId
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "answer",
        -  "citedClusters"
        -]New value: +[
        +  "answer",
        +  "citedClusters",
        +  "snapshotId",
        +  "citations"
        +]
    • Addeddiagnose_llm_config
    • Addeddiff_board
    • Changedget_board_context27 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / boardId / description
        Added value: +"The Figma file key returned by ingest_board"
      • addedInput schema / properties / boardId / maxLength
        Added value: +128
      • addedInput schema / properties / boardId / minLength
        Added value: +6
      • addedInput schema / properties / boardId / pattern
        Added value: +"^[A-Za-z0-9]+$"
      • addedInput schema / properties / cursor
        Added value: +{
        +  "description": "Continue a page using the same query, snapshot, limit and maxChars",
        +  "maxLength": 2048,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 20,
        +  "description": "Maximum evidence excerpts per page (default 20)",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / maxChars
        Added value: +{
        +  "default": 12000,
        +  "description": "Character budget for the readable context (default 12000)",
        +  "maximum": 24000,
        +  "minimum": 512,
        +  "type": "integer"
        +}
      • addedInput schema / properties / nodeIds
        Added value: +{
        +  "description": "Read exact source nodes or table cells; cannot be combined with topic",
        +  "items": {
        +    "maxLength": 200,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 50,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / snapshotId
        Added value: +{
        +  "description": "Read a specific retained snapshot instead of the latest board",
        +  "maxLength": 128,
        +  "minLength": 1,
        +  "pattern": "^[A-Za-z0-9_-]+$",
        +  "type": "string"
        +}
      • addedInput schema / properties / topic / maxLength
        Added value: +200
      • addedInput schema / properties / topic / minLength
        Added value: +1
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / properties / clusters / items / properties / modelDerived
        Added value: +{
        +  "description": "True for model summaries and summaries whose non-model origin cannot be established",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / clusters / items / properties / sourceNodeIds / description
        Added value: +"Source nodes displayed on this page, not citations validating the cluster summary"
      • addedOutput schema / properties / clusters / items / properties / summarySource
        Added value: +{
        +  "description": "Origin of the derived cluster summary; the summary is not verbatim source evidence",
        +  "enum": [
        +    "vision_llm",
        +    "text_llm",
        +    "deterministic",
        +    "cache",
        +    "unknown"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / clusters / items / required
        Previous value: -[
        -  "label",
        -  "summary",
        -  "sourceNodeIds"
        -]New value: +[
        +  "label",
        +  "summary",
        +  "summarySource",
        +  "modelDerived",
        +  "sourceNodeIds"
        +]
      • addedOutput schema / properties / connections
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "connectorId": {
        +        "type": "string"
        +      },
        +      "direction": {
        +        "enum": [
        +          "forward",
        +          "reverse",
        +          "bidirectional",
        +          "undirected"
        +        ],
        +        "type": "string"
        +      },
        +      "fromNodeId": {
        +        "type": "string"
        +      },
        +      "label": {
        +        "type": "string"
        +      },
        +      "toNodeId": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "connectorId",
        +      "fromNodeId",
        +      "toNodeId",
        +      "direction",
        +      "url"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / evidence
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "chunkIndex": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "clusterId": {
        +        "type": "string"
        +      },
        +      "clusterLabel": {
        +        "type": "string"
        +      },
        +      "column": {
        +        "type": "number"
        +      },
        +      "evidenceId": {
        +        "type": "string"
        +      },
        +      "modelDerived": {
        +        "type": "boolean"
        +      },
        +      "nodeId": {
        +        "type": "string"
        +      },
        +      "nodeName": {
        +        "maxLength": 160,
        +        "type": "string"
        +      },
        +      "pageId": {
        +        "type": "string"
        +      },
        +      "pageName": {
        +        "maxLength": 160,
        +        "type": "string"
        +      },
        +      "renderNodeId": {
        +        "type": "string"
        +      },
        +      "row": {
        +        "type": "number"
        +      },
        +      "sectionIds": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "sectionNames": {
        +        "items": {
        +          "maxLength": 80,
        +          "type": "string"
        +        },
        +        "maxItems": 16,
        +        "type": "array"
        +      },
        +      "snapshotId": {
        +        "type": "string"
        +      },
        +      "sourceType": {
        +        "enum": [
        +          "board_text",
        +          "table_cell",
        +          "board_metadata",
        +          "model_interpretation",
        +          "cluster_summary"
        +        ],
        +        "type": "string"
        +      },
        +      "text": {
        +        "type": "string"
        +      },
        +      "truncated": {
        +        "type": "boolean"
        +      },
        +      "url": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "evidenceId",
        +      "snapshotId",
        +      "nodeId",
        +      "text",
        +      "sourceType",
        +      "modelDerived",
        +      "chunkIndex",
        +      "url",
        +      "truncated"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / nextCursor
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / relations
        Added value: +{
        +  "description": "Cluster-to-cluster relations derived from connector arrows",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "edgeCount": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "from": {
        +        "description": "Label of the source cluster",
        +        "type": "string"
        +      },
        +      "label": {
        +        "description": "Connector label(s), when the arrows are annotated",
        +        "type": "string"
        +      },
        +      "to": {
        +        "description": "Label of the target cluster",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "from",
        +      "to",
        +      "edgeCount"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / snapshotId
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalMatched
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / truncation
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Explicit omissions from structured results and the readable text",
        +  "properties": {
        +    "omittedConnections": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "omittedRelations": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "omittedTextConnections": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "omittedTextRelations": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "remainingEvidence": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "remainingEvidence",
        +    "omittedConnections",
        +    "omittedRelations",
        +    "omittedTextConnections",
        +    "omittedTextRelations"
        +  ],
        +  "type": "object"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "contextText",
        -  "clusters"
        -]New value: +[
        +  "contextText",
        +  "clusters",
        +  "snapshotId",
        +  "evidence",
        +  "connections",
        +  "totalMatched",
        +  "truncated",
        +  "truncation"
        +]
    • Changedingest_board22 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / customPhases
        Added value: +{
        +  "description": "Free-form phase names to map clusters onto (e.g. [\"Ideen\", \"Feedback\", \"Offene Fragen\"]); overrides docStructureHint",
        +  "items": {
        +    "maxLength": 80,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 12,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / docStructureHint / description
        Previous value: -"How to interpret the board's structure when mapping clusters to phases"New value: +"Built-in framework used to map clusters to phases"
      • changedInput schema / properties / docStructureHint / enum
        Previous value: -[
        -  "double_diamond",
        -  "freeform"
        -]New value: +[
        +  "freeform",
        +  "double_diamond",
        +  "lean_canvas",
        +  "retro",
        +  "user_journey"
        +]
      • addedInput schema / properties / figmaAccessToken / maxLength
        Added value: +512
      • addedInput schema / properties / figmaAccessToken / minLength
        Added value: +1
      • addedInput schema / properties / figmaFileUrl / maxLength
        Added value: +2048
      • addedInput schema / properties / forceFullIngest
        Added value: +{
        +  "description": "Deliberately skip all caching and incremental reuse, including successful interpretations. The vision time budget still applies. Model/configuration changes are detected automatically. Default: false",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / ingestMode
        Added value: +{
        +  "default": "balanced",
        +  "description": "How aggressively to use vision LLM calls during ingest",
        +  "enum": [
        +    "balanced",
        +    "max_quality",
        +    "max_speed"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / properties / boardId / maxLength
        Added value: +128
      • addedOutput schema / properties / boardId / minLength
        Added value: +6
      • addedOutput schema / properties / boardId / pattern
        Added value: +"^[A-Za-z0-9]+$"
      • addedOutput schema / properties / clusterCount / maximum
        Added value: +9007199254740991
      • addedOutput schema / properties / figmaVersion
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / freshnessCheckedAt
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / ingestMode
        Added value: +{
        +  "enum": [
        +    "balanced",
        +    "max_quality",
        +    "max_speed"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / persistenceWarning
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / qualityReport
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "cachedClusters": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "deterministicClusters": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "fallbackCount": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "fallbackReasons": {
        +      "additionalProperties": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "incompleteClusters": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "modelsUsed": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "nextRetryAt": {
        +      "type": "number"
        +    },
        +    "reusedClusters": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "visionClusters": {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "modelsUsed",
        +    "cachedClusters",
        +    "deterministicClusters",
        +    "visionClusters",
        +    "fallbackCount"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / relationCount
        Added value: +{
        +  "description": "Directed cluster-to-cluster relations derived from connector arrows",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / snapshotId
        Added value: +{
        +  "type": "string"
        +}
  5. 3 tool updatesv0.1.0
    • First observedanswer_from_board
    • First observedget_board_context
    • First observedingest_board

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a distinct role: ingest_board persists a snapshot, get_board_context reads structured context, answer_from_board handles single-question LLM Q&A, diff_board compares snapshots, and diagnose_llm_config tests configuration. Descriptions explicitly delineate boundaries (e.g., answer_from_board is not for summaries; get_board_context is not for single questions), eliminating overlap.

Naming Consistency5/5

All names use snake_case with a verb-first pattern (ingest_board, get_board_context, answer_from_board, diff_board, diagnose_llm_config). The convention is consistent and predictable throughout.

Tool Count5/5

Five tools are well-scoped for the workflow: ingest, read, answer, diff, and config check. No redundant or trivial tools are present, and the count sits comfortably within the typical 3-15 range.

Completeness4/5

The toolset covers ingestion, context retrieval, Q&A, diffing, and LLM diagnostics, forming a coherent lifecycle. Minor gaps exist, such as no explicit tool to list or delete stored snapshots, but agents can work around this by re-ingesting since local history is bounded.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers