Skip to content

Commit a4f104e

Browse files
committed
docs(autodoc[prompts,resources]): wire FastMCP autodoc for prompts and resources
Switch ``docs/tools/prompts.md`` and ``docs/reference/api/resources.md`` from hand-written signatures / ``automodule`` to the new ``{fastmcp-prompt}`` / ``{fastmcp-prompt-input}`` and ``{fastmcp-resource-template}`` directives from gp-sphinx. Each recipe now has a live-introspected card (name, description, tags, type badge) and an auto-generated arguments table, while the editorial prose (``**Use when**``, ``**Why use this**``, ``**Sample render**``) stays hand-written around the directive blocks. ``docs/conf.py`` now sets ``fastmcp_server_module = "libtmux_mcp.server:mcp"`` so the collector can enumerate the live FastMCP instance. Because ``server.py`` defers registration to ``run_server()``, the collector invokes ``_register_all()`` internally to populate the component registry before reading. Also add three short ``docs/topics/`` pages for the MCP protocol utilities that map conceptually rather than as first-class autodoc: - ``completion.md`` — what FastMCP derives automatically from prompt args and resource-template parameters; notes that live tmux state is not yet wired in as a completion source. - ``logging.md`` — the ``libtmux_mcp.*`` logger hierarchy and how FastMCP forwards records to clients via the MCP logging capability. - ``pagination.md`` — contrasts MCP protocol-level cursors (automatic, server-owned) with tool-level ``offset`` / ``limit`` on ``search_panes`` (agent-controlled bounded cost). Topics index grows a new "MCP protocol utilities" grid row linking to them.
1 parent d834713 commit a4f104e

7 files changed

Lines changed: 260 additions & 30 deletions

File tree

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
"wait_for_tools": "waits",
8989
"hook_tools": "hooks",
9090
}
91+
conf["fastmcp_server_module"] = "libtmux_mcp.server:mcp"
9192
conf["fastmcp_model_module"] = "libtmux_mcp.models"
9293
conf["fastmcp_model_classes"] = (
9394
"SessionInfo",

docs/reference/api/resources.md

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,40 @@
1+
(resources-overview)=
2+
13
# Resources
24

3-
```{eval-rst}
4-
.. automodule:: libtmux_mcp.resources.hierarchy
5-
:members:
6-
:undoc-members:
7-
:show-inheritance:
5+
MCP resources are addressable documents the server exposes at
6+
``tmux://`` URIs. Clients read them via ``resources/read``. All
7+
libtmux-mcp resources are **resource templates** — each URI includes
8+
a ``{?socket_name}`` query parameter for socket isolation, plus
9+
structural path parameters (``{session_name}``, ``{pane_id}``, …) so
10+
a single template covers every session, window, or pane.
11+
12+
Every resource delivers a snapshot of the tmux hierarchy at call
13+
time. Agents use them for read-only inspection; any write workflow
14+
goes through the corresponding {doc}`tools </tools/index>`.
15+
16+
---
17+
18+
## Sessions
19+
20+
```{fastmcp-resource-template} get_sessions
21+
```
22+
23+
```{fastmcp-resource-template} get_session
24+
```
25+
26+
```{fastmcp-resource-template} get_session_windows
27+
```
28+
29+
## Windows
30+
31+
```{fastmcp-resource-template} get_window
32+
```
33+
34+
## Panes
35+
36+
```{fastmcp-resource-template} get_pane
37+
```
38+
39+
```{fastmcp-resource-template} get_pane_content
840
```

docs/tools/prompts.md

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ tools instead.
2929

3030
---
3131

32-
(run-and-wait)=
33-
3432
## `run_and_wait`
3533

34+
```{fastmcp-prompt} run_and_wait
35+
```
36+
3637
**Use when** the agent needs to execute a single shell command and
3738
must know whether it succeeded before deciding the next step.
3839

@@ -43,11 +44,8 @@ never cross-signal each other. The server side blocks until the
4344
channel is signalled — strictly cheaper in agent turns than a
4445
``capture_pane`` retry loop.
4546

46-
**Parameters:**
47-
48-
- ``command`` (str) — the shell command to run.
49-
- ``pane_id`` (str) — target pane (e.g. ``%1``).
50-
- ``timeout`` (float, default ``60.0``) — maximum seconds to wait.
47+
```{fastmcp-prompt-input} run_and_wait
48+
```
5149

5250
**Sample render** (``command="pytest"``, ``pane_id="%1"``):
5351

@@ -76,10 +74,11 @@ success or failure.
7674

7775
---
7876

79-
(diagnose-failing-pane)=
80-
8177
## `diagnose_failing_pane`
8278

79+
```{fastmcp-prompt} diagnose_failing_pane
80+
```
81+
8382
**Use when** something visibly went wrong in a pane and the agent
8483
needs to investigate before deciding what to fix. Produces a plan,
8584
not an action.
@@ -91,9 +90,8 @@ follow-up ``get_pane_info`` round-trip. It also explicitly forbids
9190
the agent from acting before it has a hypothesis, which prevents
9291
"fix the symptom" anti-patterns.
9392

94-
**Parameters:**
95-
96-
- ``pane_id`` (str) — the pane to diagnose.
93+
```{fastmcp-prompt-input} diagnose_failing_pane
94+
```
9795

9896
**Sample render** (``pane_id="%1"``):
9997

@@ -111,10 +109,11 @@ Something went wrong in tmux pane %1. Diagnose it:
111109

112110
---
113111

114-
(build-dev-workspace)=
115-
116112
## `build_dev_workspace`
117113

114+
```{fastmcp-prompt} build_dev_workspace
115+
```
116+
118117
**Use when** the operator wants a fresh 3-pane workspace with editor
119118
on top, terminal bottom-left, and a logs pane bottom-right — the
120119
most common shape for active development.
@@ -128,13 +127,12 @@ also explicitly avoids waiting for shell prompts after launching
128127
deadlock an agent following naïve "wait for the prompt between each
129128
step" advice.
130129

131-
**Parameters:**
130+
```{fastmcp-prompt-input} build_dev_workspace
131+
```
132132

133-
- ``session_name`` (str) — name for the new session.
134-
- ``log_command`` (str, default ``"watch -n 1 date"``) — command to
135-
run in the logs pane. Pass e.g. ``"tail -f /var/log/syslog"`` on
136-
Linux or ``"log stream --level info"`` on macOS to override the
137-
OS-neutral default.
133+
Pass e.g. ``"tail -f /var/log/syslog"`` on Linux or
134+
``"log stream --level info"`` on macOS as the ``log_command`` to
135+
override the OS-neutral default.
138136

139137
**Sample render** (``session_name="dev"``):
140138

@@ -173,10 +171,11 @@ across layout changes; window renames are not.
173171

174172
---
175173

176-
(interrupt-gracefully)=
177-
178174
## `interrupt_gracefully`
179175

176+
```{fastmcp-prompt} interrupt_gracefully
177+
```
178+
180179
**Use when** the agent needs to stop a running command and confirm
181180
control returned to the shell — without escalating beyond SIGINT.
182181

@@ -187,9 +186,8 @@ times out. That prevents the most dangerous failure mode — an agent
187186
auto-escalating to ``C-\\`` (SIGQUIT, may core-dump) or ``kill``
188187
without operator consent — by drawing a clear escalation boundary.
189188

190-
**Parameters:**
191-
192-
- ``pane_id`` (str) — target pane.
189+
```{fastmcp-prompt-input} interrupt_gracefully
190+
```
193191

194192
**Sample render** (``pane_id="%1"``):
195193

docs/topics/completion.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
(completion-overview)=
2+
3+
# Completion
4+
5+
libtmux-mcp inherits FastMCP's built-in
6+
[MCP completion](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/completion)
7+
behaviour. We don't hand-author completion providers — the argument
8+
shapes on our prompts and resource templates are what the client
9+
sees.
10+
11+
## What the spec does
12+
13+
A client calls ``completion/complete`` with a partial argument for a
14+
prompt or resource URI template; the server replies with up to 100
15+
suggestions. Agents use this to offer auto-complete UX — e.g. a
16+
session picker popup when filling ``session_name=`` on
17+
``get_session``.
18+
19+
## What libtmux-mcp currently exposes
20+
21+
- **Prompt arguments** — the four recipes ({doc}`/tools/prompts`)
22+
advertise their argument names and types. FastMCP derives a default
23+
completion shape from the Python signatures:
24+
``str`` arguments accept free text, ``float`` arguments accept
25+
numeric strings, no enum / list suggestions.
26+
- **Resource template parameters**
27+
{doc}`/reference/api/resources` URIs carry ``{session_name}``,
28+
``{window_index}``, ``{pane_id}``, and ``{?socket_name}``
29+
placeholders. Completion suggestions are again derived from the
30+
function signatures' types, not from live tmux state.
31+
32+
```{warning}
33+
libtmux-mcp does **not** currently wire completion back to live
34+
tmux enumeration — i.e. the completion for ``session_name`` will not
35+
return the names of sessions that exist on the server right now.
36+
Adding that requires a dedicated FastMCP completion handler;
37+
tracked as a potential enhancement.
38+
```
39+
40+
## Workarounds for clients that need live enumeration
41+
42+
Agents that need to pick a real session / window / pane can call
43+
{tool}`list-sessions`, {tool}`list-windows`, or {tool}`list-panes`
44+
directly before rendering a prompt, then feed the chosen ID back
45+
into the prompt's arguments.
46+
47+
## Further reading
48+
49+
- [MCP completion spec](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/completion)
50+
- {doc}`/tools/prompts` — the prompt argument surface
51+
- {doc}`/reference/api/resources` — the resource-template parameter surface

docs/topics/index.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,37 @@ Write effective instructions for AI agents using tmux tools.
4343

4444
::::
4545

46+
## MCP protocol utilities
47+
48+
How libtmux-mcp maps to three optional utility capabilities from
49+
the Model Context Protocol specification.
50+
51+
::::{grid} 1 1 3 3
52+
:gutter: 2 2 3 3
53+
54+
:::{grid-item-card} Completion
55+
:link: completion
56+
:link-type: doc
57+
Argument auto-complete — what FastMCP derives automatically and
58+
what libtmux-mcp does not yet wire up.
59+
:::
60+
61+
:::{grid-item-card} Logging
62+
:link: logging
63+
:link-type: doc
64+
Server-to-client log forwarding and the ``libtmux_mcp.*`` logger
65+
hierarchy.
66+
:::
67+
68+
:::{grid-item-card} Pagination
69+
:link: pagination
70+
:link-type: doc
71+
Protocol-level cursors vs tool-level ``offset`` / ``limit`` (as in
72+
``search_panes``).
73+
:::
74+
75+
::::
76+
4677
```{toctree}
4778
:hidden:
4879
@@ -51,5 +82,8 @@ concepts
5182
safety
5283
gotchas
5384
prompting
85+
completion
86+
logging
87+
pagination
5488
troubleshooting
5589
```

docs/topics/logging.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
(logging-overview)=
2+
3+
# Logging
4+
5+
libtmux-mcp uses Python's standard ``logging`` module under the
6+
``libtmux_mcp.*`` namespace. FastMCP forwards server-side log
7+
records to connected MCP clients via the
8+
[MCP logging capability](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/logging).
9+
No manual wiring needed.
10+
11+
## Logger hierarchy
12+
13+
All loggers are children of ``libtmux_mcp``. The primary streams
14+
are:
15+
16+
- ``libtmux_mcp.audit`` — one structured line per tool call, emitted
17+
by {class}`~libtmux_mcp.middleware.AuditMiddleware`. Includes
18+
tool name, digest-redacted arguments, latency, outcome. See
19+
{doc}`/topics/safety` for the argument-redaction rules.
20+
- ``libtmux_mcp.retry`` — warnings from
21+
{class}`~libtmux_mcp.middleware.ReadonlyRetryMiddleware` when a
22+
readonly tool retried after a transient
23+
{exc}`libtmux.exc.LibTmuxException`.
24+
- ``libtmux_mcp.server`` / ``libtmux_mcp.tools.*`` / etc. — ad-hoc
25+
warnings and debug messages from the codebase.
26+
27+
## Level control
28+
29+
Set the logger level via standard Python mechanisms — for local
30+
development, the simplest is an environment variable:
31+
32+
```console
33+
$ FASTMCP_LOG_LEVEL=DEBUG libtmux-mcp
34+
```
35+
36+
FastMCP reads ``FASTMCP_LOG_LEVEL`` at startup and applies it to
37+
every ``fastmcp.*`` and ``libtmux_mcp.*`` logger.
38+
39+
## What clients see
40+
41+
MCP clients render incoming ``notifications/message`` records in
42+
their log pane (e.g. Claude Desktop's "MCP server logs" panel, or
43+
``claude-cli``'s ``--verbose`` output). The records include the
44+
server name (``libtmux-mcp``), level, and the log message — but not
45+
the Python logger name, which the protocol doesn't model.
46+
47+
```{tip}
48+
If a tool call fails silently (no user-visible error, no side
49+
effect), the ``libtmux_mcp.audit`` log will show the invocation and
50+
its return value. That's usually the fastest way to tell whether a
51+
tool ran at all.
52+
```
53+
54+
## Further reading
55+
56+
- [MCP logging spec](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/logging)
57+
- {doc}`/topics/safety` — audit log redaction rules
58+
- {class}`~libtmux_mcp.middleware.AuditMiddleware` — the primary
59+
audit emitter

docs/topics/pagination.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
(pagination-overview)=
2+
3+
# Pagination
4+
5+
libtmux-mcp follows the
6+
[MCP pagination spec](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/pagination):
7+
``tools/list``, ``prompts/list``, ``resources/list``, and
8+
``resources/templates/list`` all return an opaque ``nextCursor`` when
9+
a page is truncated, and accept ``cursor`` on the next call to
10+
resume.
11+
12+
## Two places pagination shows up
13+
14+
### Protocol-level list calls
15+
16+
FastMCP handles ``tools/list`` / ``prompts/list`` / ``resources/list``
17+
/ ``resources/templates/list`` pagination automatically. Neither
18+
libtmux-mcp nor the agent needs to do anything: the server chooses
19+
a sensible page size, encodes the cursor in an opaque base64 blob,
20+
and replays state from it. Callers only need to thread through
21+
``nextCursor`` if they consume the raw MCP protocol.
22+
23+
### Tool-level pagination on ``search_panes``
24+
25+
One libtmux-mcp tool owns its own pagination surface because a
26+
single tmux server can carry tens of thousands of pane lines:
27+
28+
- {tool}`search-panes` returns a
29+
{class}`~libtmux_mcp.models.SearchPanesResult` wrapper with
30+
``matches``, ``truncated``, ``truncated_panes``,
31+
``total_panes_matched``, ``offset``, and ``limit``.
32+
- Agents detect ``truncated=True`` and re-call with a higher
33+
``offset`` to page through the match set.
34+
35+
This is application-level pagination (not MCP-cursor pagination) —
36+
the agent decides how many matches it needs and when to stop.
37+
38+
## Why separate paths
39+
40+
Protocol-level cursors are for **collections the server owns
41+
end-to-end**: the tool / prompt / resource registries. The server
42+
knows what it has, so an opaque cursor is cheap.
43+
44+
Tool-level pagination is for **collections derived from live tmux
45+
state**: capturing every pane's contents and running a regex is
46+
expensive, and the result set can change mid-scan (new panes open,
47+
old ones close). Exposing ``offset`` / ``limit`` lets the agent
48+
bound cost explicitly, without pretending the snapshot is stable.
49+
50+
## Further reading
51+
52+
- [MCP pagination spec](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/pagination)
53+
- {class}`~libtmux_mcp.models.SearchPanesResult` — the structured
54+
wrapper for ``search_panes``
55+
- {tool}`search-panes` — the tool itself

0 commit comments

Comments
 (0)