From 093c052dc676fe734200765d540a882b423fe5eb Mon Sep 17 00:00:00 2001 From: Mike Clay Date: Sat, 11 Jul 2026 08:46:57 +0100 Subject: [PATCH 1/3] chore: initialize work package for #193 Co-Authored-By: Claude Fable 5 Signed-off-by: Mike Clay From d21f1d73e19707a034d063134fa848e50461fcb6 Mon Sep 17 00:00:00 2001 From: Mike Clay Date: Sun, 12 Jul 2026 07:31:53 +0100 Subject: [PATCH 2/3] feat(tools): add read-only inspect_session tool for #193 Adds inspect_session, a read-only MCP tool returning a compact structured projection of a session's own state (identity, variables, checkpoints, activities, history tally, children) across seven views, with optional child_index descent and single-variable narrowing. Clones the read-only get_workflow_status shape; no checkpoint gate, no advance/save. Projection logic ported from the reference scripts/inspect_session.py with a parity test. Updates README tool count, api-reference, and generated site data. Refs #193 Signed-off-by: Mike Clay --- README.md | 4 +- docs/api-reference.md | 1 + scripts/generate-site-data.ts | 8 +- site/api/tools.html | 26 +- src/tools/workflow-tools.ts | 184 +++++++++++++ .../inspect-session/inspect_session.py | 142 ++++++++++ tests/mcp-server.test.ts | 257 ++++++++++++++++++ 7 files changed, 617 insertions(+), 5 deletions(-) create mode 100644 tests/fixtures/inspect-session/inspect_session.py diff --git a/README.md b/README.md index 0756bf95..4dc92305 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,12 @@ User Goal → Workflow → Activities → Techniques → Tools ### MCP Tools at a Glance -The server registers 16 MCP tools across five concerns. See [docs/api-reference.md](docs/api-reference.md) for full signatures. +The server registers 17 MCP tools across five concerns. See [docs/api-reference.md](docs/api-reference.md) for full signatures. | Concern | Tools | |---------|-------| | Bootstrap (no session token) | `discover`, `list_workflows`, `health_check` | -| Session | `start_session`, `get_workflow_status`, `dispatch_child` | +| Session | `start_session`, `get_workflow_status`, `inspect_session`, `dispatch_child` | | Workflow / activity navigation | `get_workflow`, `next_activity`, `get_activity` | | Checkpoint flow | `yield_checkpoint`, `resume_checkpoint`, `present_checkpoint`, `respond_checkpoint` | | Techniques, resources | `get_technique`, `get_resource` | diff --git a/docs/api-reference.md b/docs/api-reference.md index 75b5a6a9..9235b8de 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -18,6 +18,7 @@ No `session_index` required. |------|------------|---------|-------------| | `start_session` | `agent_id`, `workflow_id?`, `planning_slug?`, `parent_planning_slug?`, `context_mode?` | `session_index`, `planning_slug`, workflow info | Starts a new session or resumes an existing one, optionally with a parent for nested-workflow dispatch. **Fresh sessions default to the `meta` workflow** when no `workflow_id` is provided. `agent_id` sets the recorded agent identity in `session.json`, distinguishing orchestrator from worker calls in the trace. `planning_slug` is a single-segment slug for the planning folder under `/.engineering/artifacts/planning//`; it determines where `session.json` and the sealed `.session-token` live and deterministically derives the 6-character base32 `session_index`. When `planning_slug` is omitted, the server mints a transitional slug. To **resume** a session, pass the same `planning_slug` again — the server loads the existing `session.json`, verifies the seal, and returns the same `session_index`. For **nested dispatch**, also pass `parent_planning_slug`; the server snapshots the parent's `session.json` (seal-verified) under the child's `parentSession` field for trace correlation and recursive parent traversal. `context_mode` declares the session's delivery context model: `"persistent"` opts into [reference delivery](#reference-delivery); omitted (or `"fresh"`) delivers full content on every call — the correct mode when disposable workers each execute in a fresh context. On resume, a supplied `context_mode` overwrites the recorded value. Fresh sessions start with the variable bag seeded from the workflow's declared `defaultValue`s, recorded as a `variables_seeded` history event (resumes never re-seed — the mutated bag is preserved); `dispatch_child` seeds each child's bag from the child workflow's own declarations the same way. Server restarts are transparent because state lives in `session.json` rather than in an agent-held token. | | `get_workflow_status` | `session_index` | `status` (active/blocked/completed), `current_activity`, `completed_activities`, `last_checkpoint` info, `workflow`, and `parent` context | Checks the status of the current workflow session. `session_index` identifies the session. The returned `status` is one of `active`, `blocked`, or `completed`. `current_activity` names the activity the agent is executing. `completed_activities` lists all finished activities (from `session.json`). `last_checkpoint` contains the most recent checkpoint details. `workflow` reflects the current workflow metadata. If the session was created with a `parent_planning_slug`, the `parent` field contains the parent's session info derived from the `parentSession` snapshot. | +| `inspect_session` | `session_index`, `view?`, `child_index?`, `variable?` | A compact structured projection of the addressed session, selected by `view`, serialised as JSON text | Read-only inspection of a session's on-disk state. `view` selects the projection: `summary` (default, the composite of all below), `identity` (workflow/session/agent header + current position), `variables` (the variable bag), `checkpoints` (each checkpoint response as `optionId`, `respondedAt`, `variablesSet`), `activities` (`completed` / `skipped` / `current`), `history` (event `count`, a per-type `byType` tally, and the `milestones` sub-sequence), and `children` (a one-line digest per `triggeredWorkflows` child). `child_index` descends one positional level into the addressed session's `triggeredWorkflows[child_index].state` and projects that child instead (an out-of-range index returns the actionable `NOT_FOUND` message); deeper children are reached by passing that child's own `session_index`. `variable` — meaningful only with `view: variables` — narrows the result to a single key's value. The tool reads through the same sealed load path as every other tool (so it verifies integrity) but never mutates state, and is **not** gated on an active checkpoint — it is usable while the session is blocked, which is exactly when an orchestrator wants to look. It returns a shaped projection, never the raw `session.json`. | ### Workflow Tools diff --git a/scripts/generate-site-data.ts b/scripts/generate-site-data.ts index 5cfb9c91..0653e84e 100644 --- a/scripts/generate-site-data.ts +++ b/scripts/generate-site-data.ts @@ -307,7 +307,7 @@ export function captureTools(): CapturedTool[] { const TOOL_GROUPS: Array<{ title: string; note: string; tools: string[] }> = [ { title: 'Bootstrap', note: 'Callable without a session_index.', tools: ['discover', 'list_workflows', 'health_check'] }, - { title: 'Session', note: 'Create, inspect, and extend workflow sessions.', tools: ['start_session', 'get_workflow_status', 'dispatch_child'] }, + { title: 'Session', note: 'Create, inspect, and extend workflow sessions.', tools: ['start_session', 'get_workflow_status', 'inspect_session', 'dispatch_child'] }, { title: 'Workflow and activity navigation', note: 'Load workflow structure and advance through activities.', tools: ['get_workflow', 'next_activity', 'get_activity'] }, { title: 'Checkpoint flow', note: 'Yield to the orchestrator, present decisions to the user, and resume.', tools: ['yield_checkpoint', 'resume_checkpoint', 'present_checkpoint', 'respond_checkpoint'] }, { title: 'Techniques and resources', note: 'Fetch technique definitions and lazy-loaded reference material.', tools: ['get_technique', 'get_resource'] }, @@ -347,6 +347,12 @@ const SITE_TOOL_GUIDES: Partial> = { 'Returns whether the session is active, blocked at a checkpoint, or completed, plus the current activity and completed steps.', 'If the session is nested under a parent, parent context is included too.', ], + inspect_session: [ + 'Read-only look at a session\'s stored state. Pick a `view`: `summary` (everything), `identity`, `variables`, `checkpoints`, `activities`, `history`, or `children`.', + 'Returns a compact, purpose-built projection — never the raw session file.', + 'Pass `child_index` to look one level into a child session listed under `triggeredWorkflows`; pass `variable` with `view: variables` to read a single value.', + 'It never changes anything and works even while the session is paused at a checkpoint — which is often exactly when you want to look.', + ], dispatch_child: [ 'Starts a child workflow inside the parent session you are already in.', 'Returns the child\'s `session_index` and `planning_folder_path`. The child\'s variables are seeded from the child workflow\'s defaults; the parent is unchanged.', diff --git a/site/api/tools.html b/site/api/tools.html index d38048d6..d6956b4a 100644 --- a/site/api/tools.html +++ b/site/api/tools.html @@ -71,11 +71,11 @@

MCP tool reference

Conventions: most tools identify their session with a session_index — the 6-character token returned by start_session. Tools in the Bootstrap group work without one. The prose reference with usage guidance lives in docs/api-reference.md.

-

The server registers 16 MCP tools. Each entry shows a short summary; expand for the full description and advanced parameters.

+

The server registers 17 MCP tools. Each entry shows a short summary; expand for the full description and advanced parameters.