Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,14 +561,19 @@ At SessionStart (Claude Code), `kcap` also injects a compact **index** of the me
kcap mcp workitems
```

Stdio MCP server that lets coding agents correlate the current session to the SDLC work item (issue/PR) it belongs to, or list what it's already correlated to. **Claude Code:** auto-registered via the plugin's `.mcp.json`; it isn't offered for Cursor or Codex.
Stdio MCP server that lets coding agents correlate the current session to the SDLC work item (issue/PR) it belongs to, **declare that work item's structure** — its breakdown into parts and its blocks/blocked-by dependencies — and read that structure back. **Claude Code:** auto-registered via the plugin's `.mcp.json`; it isn't offered for Cursor or Codex.

It provides two tools:
It provides seven tools:

- **`declare_work_item`** — attach the current session (and its continuation chain) to a work item. Pass exactly one of `issue_key` (e.g. `"AI-1234"`), `pr_number`, `work_item_id`, or `new_title` (creates a brand-new work item).
- **`get_session_work_items`** — list the work items the current session is attached to.
- **`declare_work_breakdown`** — declare that a work item is broken into parts (`parent_id` + `part_ids`). Idempotent; a part has at most one parent, and all items must live in the same repository.
- **`retract_work_breakdown`** — detach the named parts from the parent.
- **`declare_work_relation`** — declare a dependency between two items (`from_id`, `to_id`, `relation_kind` `"blocks"` or `"blocked_by"`). Same repository, no self-relation.
- **`retract_work_relation`** — retract a previously declared dependency.
- **`get_work_item_topology`** — read a work item's parent, parts, and dependencies (scoped to what the caller can see).

Both tools default `session_id` to the current kcap-hooked session (`KCAP_SESSION_ID`) when omitted. This is the manual-declare path alongside the server's own mechanical and LLM-assisted correlation — use it when an agent already knows which issue or PR a session belongs to.
`declare_work_item` / `get_session_work_items` default `session_id` to the current kcap-hooked session (`KCAP_SESSION_ID`) when omitted. This is the manual path alongside the server's own mechanical and LLM-assisted correlation — use it when an agent already knows which issue or PR a session belongs to, and to record a breakdown/dependency structure the server can't infer (Home's blockers & dependencies and progress figures render only from declared parts and relations).

### Analytics MCP server (for agents)

Expand Down
80 changes: 80 additions & 0 deletions kcap/skills/work-items/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
name: work-items
description: >-
This skill should be used when you are planning or discovering the SHAPE of a
work item — that it breaks into sub-tasks (a parent and its parts), or that
one piece must land before another (a blocks / blocked-by dependency) — and
you want that structure recorded so it shows up in Kurrent Capacitor's Home
"Blockers & dependencies" view and progress figures. Use the `kcap mcp
workitems` MCP tools to DECLARE the breakdown and relations. Do NOT use this
skill for ordinary "attach this session to issue X" correlation alone (a
single `declare_work_item` call, no structure) or when the work is a single
indivisible task with no parts and no dependencies.
---

# Work items — declaring breakdown and dependencies

A work item's **breakdown** (a parent broken into parts) and its **dependencies**
(one item blocks / is blocked by another) are things you **declare** through the
`kcap mcp workitems` tools. The server never infers them — if you don't declare
the structure, the work item has an empty topology and Home renders no blockers,
no dependency graph, and no `n/m parts` progress figure for it.

Only declare structure that is **real and you are confident of**. Fabricated or
speculative parts/relations are worse than none. A single indivisible task needs
no breakdown.

## When to use these tools

- You've planned a work item as several sub-tasks → create the part items and
declare the parent→parts breakdown.
- You know one item must be finished before another can start → declare the
dependency.
- The structure changed (a part was dropped, a dependency no longer holds) →
retract it.
- You want to see the current structure → read the topology.

## The flow

1. **Attach the session to its work item** (if it isn't already). `declare_work_item`
with exactly one of `issue_key`, `pr_number`, `work_item_id`, or `new_title`.
Check `get_session_work_items` first if unsure what the session is attached to.
2. **Create the part items.** Each part is itself a work item — create one per
sub-task with `declare_work_item` (`new_title`), keeping the id each returns.
3. **Declare the breakdown.** `declare_work_breakdown` with `parent_id` and the
`part_ids`. It is idempotent — re-declaring an existing part is accepted, not
an error.
4. **Declare dependencies** where they exist. `declare_work_relation` with
`from_id`, `to_id`, and `relation_kind` `"blocks"` (from_id blocks to_id) or
`"blocked_by"` (from_id is blocked by to_id).
5. **Verify** with `get_work_item_topology` (pass the parent's `work_item_id`) —
it returns the parent, parts, and dependencies you can see.

## Rules the server enforces

- **Same repository.** A parent and its parts, and both ends of a relation, must
live in the same repository. Cross-repo structure is rejected.
- **One parent per part.** A part can belong to at most one parent breakdown.
- **No self-relation.** An item cannot block or be blocked by itself.
- **Idempotent declares.** Re-declaring an existing part or relation is fine.
- **Server-assigned attribution.** These tools take no `source`/`declared_by` —
the server resolves the caller. Don't look for such arguments.
- **Retract, don't delete.** Use `retract_work_breakdown` / `retract_work_relation`
when the structure changes.

## Tool reference

| Tool | Required args | Purpose |
|---|---|---|
| `declare_work_item` | exactly one of `issue_key` \| `pr_number` \| `work_item_id` \| `new_title` | Attach the session to a work item (or create one). `session_id` defaults to `KCAP_SESSION_ID`. |
| `get_session_work_items` | — | List what the current session is attached to. |
| `declare_work_breakdown` | `parent_id`, `part_ids` | Declare parent → parts. |
| `retract_work_breakdown` | `parent_id`, `part_ids` | Detach parts from the parent. |
| `declare_work_relation` | `from_id`, `to_id`, `relation_kind` (`blocks`\|`blocked_by`) | Declare a dependency. |
| `retract_work_relation` | `from_id`, `to_id`, `relation_kind` | Retract a dependency. |
| `get_work_item_topology` | `work_item_id` | Read parent, parts, and dependencies (visibility-scoped). |

## Requirements

Requires `kcap login`. The `kcap-workitems` MCP server is auto-registered for
Claude Code by `kcap setup`; it is not offered for Cursor or Codex.
18 changes: 15 additions & 3 deletions src/Capacitor.Cli.Core/Resources/help-mcp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,28 @@ mcp memory:
# needs an absolute path (e.g. /opt/homebrew/bin/kcap)

mcp workitems:
Exposes two tools — declare_work_item, get_session_work_items — for agents
to attach the current session (and its continuation chain) to a work item,
or list what it's already attached to. Requires `kcap login`.
Exposes seven tools for agents to attach the current session (and its
continuation chain) to an SDLC work item and to DECLARE that work item's
structure — its breakdown (parent -> parts) and dependencies (blocks /
blocked-by). Breakdown and relations are declared, never inferred, so an item
whose structure nobody declares has an empty topology. Requires `kcap login`.

Tools:
declare_work_item Attach the current session to a work item by
issue key, PR number, work item id, or a new
title (exactly one of the four).
get_session_work_items List the work items the current session is
attached to.
declare_work_breakdown Declare that a work item is broken into parts
(parent_id + part_ids); idempotent, one parent
per part, all items in the same repository.
retract_work_breakdown Detach the named parts from the parent.
declare_work_relation Declare a dependency between two items (from_id,
to_id, relation_kind 'blocks' or 'blocked_by');
same repository, no self-relation.
retract_work_relation Retract a previously declared dependency.
get_work_item_topology Read a work item's parent, parts, and
dependencies (scoped to what the caller sees).

Claude Code auto-registers `kcap-workitems` via the plugin's `.mcp.json`
(installed by `kcap setup`); it is not offered for Cursor or Codex.
Expand Down
14 changes: 13 additions & 1 deletion src/Capacitor.Cli/Commands/McpWorkItemsServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,22 @@ async Task<string> TimedDispatchToolCallAsync(JsonNode callId, JsonObject callRe
return 0;
}

// Server-level usage preamble (MCP `instructions`) — steers agents to DECLARE a work item's
// structure (breakdown + relations, which the server never infers), not just attach to it.
internal const string ServerInstructions =
"Use these tools to attach the current session to its SDLC work item AND to declare that work " +
"item's structure. When you plan or discover that a work item breaks into parts, create the part " +
"items (declare_work_item with new_title) and declare the parent→parts breakdown " +
"(declare_work_breakdown); when one item must land before another, declare the dependency " +
"(declare_work_relation — 'blocks'/'blocked_by'). Breakdown and relations are DECLARED, never " +
"inferred: if you don't declare them the work item's topology stays empty. Declare only real " +
"structure you're confident of, keep every item in the same repository, and use the retract_* " +
"tools when it changes.";

static string BuildInitializeResponse(JsonNode id, JsonObject request) =>
ToResponse<McpInitResult>(
id,
new(McpProtocol.NegotiateVersion(request), new(new()), new("kcap-workitems", "1.0.0")),
new(McpProtocol.NegotiateVersion(request), new(new()), new("kcap-workitems", "1.0.0"), ServerInstructions),
McpJsonContext.Default.McpInitResult
);

Expand Down
11 changes: 11 additions & 0 deletions test/Capacitor.Cli.Tests.Unit/McpWorkItemsServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ await Assert.That(tools.Select(t => t.Name).ToArray()).IsEquivalentTo(new[] {
});
}

[Test]
public async Task Server_instructions_steer_agents_to_declare_breakdown_and_relations() {
// Pin that the preamble names both declare tools + the declared-never-inferred rule, so it
// can't silently regress to a bare correlation description.
var instructions = McpWorkItemsServer.ServerInstructions;

await Assert.That(instructions).Contains("declare_work_breakdown");
await Assert.That(instructions).Contains("declare_work_relation");
await Assert.That(instructions).Contains("never"); // "declared, never inferred"
}

// ── declared breakdown + relations ───────────────────────────────────────

[Test]
Expand Down
Loading