skein_show
Read one issue by id. BY DEFAULT you get: the issue card, dependency COUNTS (depsCounts) and no edges, child counters, and the last 3 comments. Edges of a named type, the thread index and the event feed are opt-in — each is named below. Use this when you have an id; for browsing without one use skein_list. id must be the full hierarchical id (e.g. "demo-42" or "demo-42.1") — bare numbers are rejected.
Navigating DOWN a tree without pulling the graph: read the counters here (unclosedChildrenCount, or depsCounts.down["parent-child"]), then list the children with skein_list(parentId=), then ask for the edges you actually need with skein_show(depsTypes:["parent-child"]). Each step is bounded; the graph dump is not.
Comments (when includeComments=true, the default):
Default returns the last 3 comments ASC (to save tokens).
commentsTotal / commentsReturned / commentsTruncated are always present (including 0/false on empty threads).
commentsLimit:0 returns the thread INDEX — one entry per comment (id, author, date, first 80 characters, and a per-entry truncation flag), capped at 200 most recent of the population — plus the last 3 comments in full. Read any one of them whole with skein_comment_get(id); to get N bodies at once ask for commentsLimit:N.
commentsSince (RFC3339) is a coarse exclusive lower bound on createdAt (not a lossless cursor).
commentsTruncated means the thread's ENUMERATION is not known to be complete — NOT that some bodies were withheld. It is set when fewer entries were listed than the population holds, AND whenever the listing hit the index cap (200): a listing exactly as long as the valve that produced it is reported incomplete regardless of
commentsTotal, becausetotaland the page are read in two statements and a thread that grew between them would otherwise pass a CUT listing off as whole. So on a thread of exactly 200 comments, commentsLimit:0 returns returned == total with commentsTruncated=true — the safe direction, not a contradiction. On an unfiltered show with commentsTruncated=true, commentsLimit:0 lists every comment up to that cap. When includeComments=false: comments is null, meta keys are absent, and limit/since params are ignored (even if invalid).
Description: pass includeDescription:false for the cheap re-read of version before a write — the description key then arrives as null (present, not absent); the other prose fields are unaffected.
Dependencies: the default is depsCounts — a direction × type × status aggregate (up = parent side, down = children side, plus an unavailable bucket per cell for edges whose other end you cannot see) — and NO edges. A non-zero unavailable means the counts cannot answer "is this branch finished". Ask for edges by naming types in depsTypes; includeDeps:false drops the block entirely — including the card's childrenCount / unclosedChildrenCount, which ride with it. The deps key is no longer guaranteed to be present.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"id": "<id>"
},
"name": "skein_show"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Full hierarchical issue id, e.g. "demo-42" or "demo-42.1". | |
| depsTypes | No | Edge types to return in full, e.g. ["parent-child"]. Supplying it returns every edge of those types (up to 200 per type) ALONGSIDE `depsCounts`, and needs no includeDeps. An empty array is rejected — it does not mean "all types". The cap is per TYPE across BOTH directions and is spent outgoing-first, so a node with more than the cap of outgoing edges of a requested type comes back with `incoming: []`. Over the cap the response therefore carries `deps.truncated[<type>]` with the aggregate `returned` / `total`, the route to the rest, AND the two direction halves — `outgoing` and `incoming`, each with its own `returned` / `total`. Read the halves, not the aggregate, to tell a direction the budget zeroed (incoming.returned 0 with incoming.total > 0) from one that genuinely has no edges (both 0). Known types: blocks, waits-for, related, discovered-from, supersedes, duplicates, parent-child. | |
| includeDeps | No | Dependency block switch. OMIT IT to get `depsCounts` (counts only, no edges) plus the child counters (`childrenCount` / `unclosedChildrenCount`) on the issue card — that is the effective default and the cheapest answer to "how many children, how many closed". The default cannot be spelled as a value, which is why this parameter declares none: passing true WITHOUT `depsTypes` is REJECTED (it used to mean "every edge", the 20 KB this tool no longer sends by accident) — name the types in `depsTypes` instead. Pass false to drop the whole block: no edges, no `depsCounts`, AND no child counters on the card — the cheapest re-read of `version`, and the one mode where the counters are absent rather than zero. | |
| commentsLimit | No | When includeComments=true: max number of most-recent comments to return IN FULL from the filtered population (ASC order). Default 3. 0 = the thread INDEX — one entry per comment (id, author, date, first 80 characters) for up to 200 most recent of the population, plus the last 3 comments in full — NOT every body. Read a body by id with skein_comment_get, or ask for commentsLimit:N to get N bodies. Must be a whole integer ≥ 0; negative or non-integer → validation_error. Ignored when comments off. | |
| commentsSince | No | When includeComments=true: exclusive lower bound on comment createdAt (RFC3339). Only comments with createdAt > since enter the population; total/truncated are computed after this filter. Omit or empty = no time filter. Invalid timestamp → validation_error. Not a lossless cursor (equal timestamps may skip siblings). Ignored when comments off. | |
| includeEvents | No | Include up to 20 most-recent events. Default: false. Every returned event contains actorSessionId: the originating MCP session id, or explicit null for session-less actors. When true the field is always an array (empty [] if none); when false the JSON field is null (not omitted). | |
| includeComments | No | Include comment list in the response. Default: true. When true the field is always an array (empty [] if none) and commentsTotal/commentsReturned/commentsTruncated are always set; when false the JSON field is null (not omitted) and meta keys are absent. commentsLimit/commentsSince are only validated when true. | |
| includeDescription | No | Include the issue `description` body. Default: true. When false the `description` key is still PRESENT and renders as null (not omitted), so "not requested" stays distinguishable from "empty" (""). The other prose fields (`design`, `acceptanceCriteria`, `notes`) are returned as usual — this flag elides the description only. Typical use: the cheap read of `version` before a write (expectedVersion cycle), where a long description can be tens of KB of dead context on the single most frequent call of a run; pair with includeComments:false and includeDeps:false for the minimal read. |