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
32 changes: 29 additions & 3 deletions docs/configuration/flights.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ A flight carries four details:
while normal local and Hub authorization still applies. It never raises the
identity's actual KEG role. `manage_flights` exposes flight mutation tools
to the session, but Hub still requires the authenticated identity to own or
administer the target namespace. The capabilities are independent.
administer the target namespace. `manage_kegs` exposes `keg_create`, and
Hub still requires the identity to belong to the target namespace. The
capabilities are independent.

Because a flight is not a KEG target selector, `tap mcp --flight` binds only
the process flight identity. `tap mcp --keg` remains an independent default for
Expand Down Expand Up @@ -113,14 +115,24 @@ current values. A Hub-backed active flight may edit or delete itself:
- a successful self-delete immediately enters recovery-only mode;
- editing or deleting another flight does not change current session authority.

Local `flights.d` manifests remain MCP read-only. Flight mutations always use
normal Hub authorization in addition to the active flight capability.
Local `flights.d` manifests remain MCP read-only — *reading* them is fully
supported (discovery, orientation, and cover enforcement all work off
`flights.d`), but create/update/delete is not implemented for local hubs and
refuses with a message naming the manifest path to write instead. Flight
mutations always use normal Hub authorization in addition to the active flight
capability.

## Behavior

- MCP tools reject a keg outside the active flight's cover
with a "keg … is not available in flight …" error.
- MCP writes against a `viewer` cover row are rejected as viewer-only.
- Every cover and role-cap denial closes by telling the agent to call `orient`.
A session pins its flight snapshot until it re-orients, so a flight edited
elsewhere mid-session is the usual reason a call the agent expected to
succeed is refused, and the refusal alone cannot reveal that. Hosted `/mcp`
appends the same instruction when a Hub grant — rather than the cover —
is what denies the keg.
- `keg_settings_edit` replaces the complete validated KEG YAML document and
requires an `admin` cover (or `full_access`) plus editor/admin identity access
to that KEG. An admin flight cap never creates a Hub admin identity.
Expand All @@ -130,6 +142,20 @@ normal Hub authorization in addition to the active flight capability.
- Without a selected flight, MCP starts in recovery-only mode and lists only
`orient`, `list_flights`, `flight_show`, and credential-safe `auth_info`.
After selecting a flight outside MCP, call `orient` on the same connection.
- When the session can reach **no flights at all**, it instead runs on a
synthetic **bootstrap flight**. Selecting from an empty list is not a
recovery, so the session is given the authority to populate it: the cover is
empty (every KEG tool stays locked) and the capabilities are `manage_flights`
plus `manage_kegs`, so `flight_create`, `flight_edit`, `flight_delete`, and
`keg_create` join the recovery four. The flight is never persisted, and its
instructions name the surface that owns selection for that transport — `tap`
configuration for stdio, the account page for hosted `/mcp`.
- Creating a flight from bootstrap does not select it. The next `orient` sees a
reachable flight and moves the session to recovery-only mode, where "select
one" has become the actionable step.
- On a local-only setup `flight_create` still fails: flight mutation is not
implemented for local hubs (see below). The bootstrap instructions say so and
point at the manifest path to write by hand.
- Config-driven `tap mcp` reloads user, project, and environment configuration
on every orientation. A successful orientation atomically replaces session
authority; configuration changes alone do nothing.
Expand Down
76 changes: 66 additions & 10 deletions integrations/content/agent-orient.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# tapper

Interact with Tapper KEGs (Knowledge Exchange Graphs) through the native MCP
server. At the start of KEG work, call `mcp__tapper__orient`, identify the
relevant covered KEGs from their titles and summaries, then call
`mcp__tapper__keg_settings` for those KEGs before operating. Treat the active
flight, cover, flight instructions, and targeted KEG instructions as the
authoritative context for the session.
server.

**Call `mcp__tapper__orient` first, in every session, before doing anything
else — including answering the user.** Do not wait until KEG work looks like it
is starting. The active flight carries the instructions describing what this
session is for, so until you orient you cannot know whether the work is KEG
work, which KEGs you may touch, or what the user actually expects of you. A
message as small as "test" is not a reason to defer: orient, then respond with
that context in hand.

After orienting, identify the relevant covered KEGs from their titles and
summaries and call `mcp__tapper__keg_settings` for those KEGs before operating
on them. Treat the active flight, cover, flight instructions, and targeted KEG
instructions as the authoritative context for the session.

## Rules

Expand All @@ -21,6 +30,24 @@ authoritative context for the session.
- **Treat the active flight as MCP authority.** It determines the instructions
and KEGs available to the agent. `defaultKeg` does not grant authority for an
MCP session.
- **Leave node 0 alone.** It is the keg's placeholder landing node, created with
the keg itself.

## Node 0

Every keg has a node `0`. It is not an ordinary node and is not yours to write:

- It is the **placeholder** a link to unwritten content lands on, so its content
is deliberately generic.
- It carries **no `type`**, on purpose. Do not add one, and do not read its
absence as a defect to repair — a node without a type is normally a schema
error, and node 0 is the documented exception.
- **Removing it breaks the keg.** Tapper treats a missing node 0 as an
uninitialized keg, so deleting it makes every other node unreachable.

When you have content to write, create a new node. If node 0 genuinely needs to
change — a keg's landing page is a reasonable thing to want — say so and let the
user decide; do not fold it into unrelated work.

## Flight-first orientation

Expand All @@ -37,11 +64,40 @@ restarting the MCP server.

## Bootstrapping a session

Call `mcp__tapper__orient` first, then load the selected KEG instructions with
`mcp__tapper__keg_settings`. When no flight is selected, the local MCP server connects in a
recovery-only state: KEG tools are locked, while `mcp__tapper__list_flights`
and `mcp__tapper__flight_show` remain available for discovery. Ask the user to
select a flight in Tapper configuration, then call `mcp__tapper__orient` again.
Orientation is unconditional and comes first, before any other tool call and
before your first reply. It is not a lookup step you reach for once KEG work is
identified — it is how the session learns what it is for. Then load the
selected KEG instructions with `mcp__tapper__keg_settings`.

**Orient again after any context reset**, such as a clear or a compact. The MCP
connection survives those, so the server does not re-initialize and will not
re-send anything on its own — but the flight instructions you were operating
under are gone from your context. Re-orienting is cheap and idempotent, and it
also picks up any configuration change made since you connected. If you cannot
tell whether you have oriented in the current context, you have not; orient.

**The newest orientation wins.** More than one copy can be present at once: the
connection's startup instructions are captured when the server connects and are
never refreshed afterwards, and a compaction summary may carry a paraphrase of
an earlier orientation. Both can be stale, and a stale copy may sit earlier in
your context than the fresh one. Treat the most recent `mcp__tapper__orient`
result as authoritative and discard the others outright rather than reconciling
them — in particular, a startup copy saying KEG tools are locked is wrong once
a later orientation has returned a flight. When no flight is selected, the MCP
server connects in a recovery-only state: KEG tools are locked, while
`mcp__tapper__list_flights` and `mcp__tapper__flight_show` remain available for
discovery. Ask the user to select a flight in Tapper configuration, then call
`mcp__tapper__orient` again.

When there is no flight to select — a fresh machine or account — the session
instead starts on a temporary **bootstrap flight**. Its cover is empty, so the
KEG tools stay locked, but `mcp__tapper__keg_create` and the flight mutation
tools are available so you can create the first KEG and the first flight.
Setting that up is the session's work; do it before anything else. You still
cannot *select* a flight — that stays a human action — so hand the setup back
to the user and call `mcp__tapper__orient` again once they confirm. The
orientation payload names exactly where they should do it.

If `mcp__tapper__orient` is unavailable, report that the Tapper MCP connection
is unavailable, ask the user to reconnect or restart the host session, and
never kill or signal host-owned processes. A flight with an empty cover exposes
Expand Down
18 changes: 18 additions & 0 deletions integrations/content/linking.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,21 @@ Tapper supports two link forms in node bodies:

Both forms appear in backlinks. Prefer intra-keg links when the target is in
the same keg.

## Attachments

A node's uploaded files and images live in two directories inside the node's
own directory, so they are linked relative to it — the same base the `../NODEID`
form above counts from:

- **File:** `[label](./assets/FILE)` — anything uploaded with
`mcp__tapper__upload_file`.
- **Image:** `![alt](./images/IMAGE)` — anything uploaded with
`mcp__tapper__upload_image`.

**Both directory names are plural**: `assets/` and `images/`, never `asset/` or
`image/`. Uploading succeeds regardless of how you later write the link, so a
singular path fails silently as a broken reference rather than as an error.

Use `mcp__tapper__list_files` and `mcp__tapper__list_images` to get the exact
stored names; the upload may normalize the filename you supplied.
94 changes: 84 additions & 10 deletions integrations/rendered/claude/tapper/skills/tapper/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@ description: Orient to Tapper flights and operate on KEGs through MCP-first safe
# tapper

Interact with Tapper KEGs (Knowledge Exchange Graphs) through the native MCP
server. At the start of KEG work, call `mcp__tapper__orient`, identify the
relevant covered KEGs from their titles and summaries, then call
`mcp__tapper__keg_settings` for those KEGs before operating. Treat the active
flight, cover, flight instructions, and targeted KEG instructions as the
authoritative context for the session.
server.

**Call `mcp__tapper__orient` first, in every session, before doing anything
else — including answering the user.** Do not wait until KEG work looks like it
is starting. The active flight carries the instructions describing what this
session is for, so until you orient you cannot know whether the work is KEG
work, which KEGs you may touch, or what the user actually expects of you. A
message as small as "test" is not a reason to defer: orient, then respond with
that context in hand.

After orienting, identify the relevant covered KEGs from their titles and
summaries and call `mcp__tapper__keg_settings` for those KEGs before operating
on them. Treat the active flight, cover, flight instructions, and targeted KEG
instructions as the authoritative context for the session.

## Rules

Expand All @@ -26,6 +35,24 @@ authoritative context for the session.
- **Treat the active flight as MCP authority.** It determines the instructions
and KEGs available to the agent. `defaultKeg` does not grant authority for an
MCP session.
- **Leave node 0 alone.** It is the keg's placeholder landing node, created with
the keg itself.

## Node 0

Every keg has a node `0`. It is not an ordinary node and is not yours to write:

- It is the **placeholder** a link to unwritten content lands on, so its content
is deliberately generic.
- It carries **no `type`**, on purpose. Do not add one, and do not read its
absence as a defect to repair — a node without a type is normally a schema
error, and node 0 is the documented exception.
- **Removing it breaks the keg.** Tapper treats a missing node 0 as an
uninitialized keg, so deleting it makes every other node unreachable.

When you have content to write, create a new node. If node 0 genuinely needs to
change — a keg's landing page is a reasonable thing to want — say so and let the
user decide; do not fold it into unrelated work.

## Flight-first orientation

Expand All @@ -42,11 +69,40 @@ restarting the MCP server.

## Bootstrapping a session

Call `mcp__tapper__orient` first, then load the selected KEG instructions with
`mcp__tapper__keg_settings`. When no flight is selected, the local MCP server connects in a
recovery-only state: KEG tools are locked, while `mcp__tapper__list_flights`
and `mcp__tapper__flight_show` remain available for discovery. Ask the user to
select a flight in Tapper configuration, then call `mcp__tapper__orient` again.
Orientation is unconditional and comes first, before any other tool call and
before your first reply. It is not a lookup step you reach for once KEG work is
identified — it is how the session learns what it is for. Then load the
selected KEG instructions with `mcp__tapper__keg_settings`.

**Orient again after any context reset**, such as a clear or a compact. The MCP
connection survives those, so the server does not re-initialize and will not
re-send anything on its own — but the flight instructions you were operating
under are gone from your context. Re-orienting is cheap and idempotent, and it
also picks up any configuration change made since you connected. If you cannot
tell whether you have oriented in the current context, you have not; orient.

**The newest orientation wins.** More than one copy can be present at once: the
connection's startup instructions are captured when the server connects and are
never refreshed afterwards, and a compaction summary may carry a paraphrase of
an earlier orientation. Both can be stale, and a stale copy may sit earlier in
your context than the fresh one. Treat the most recent `mcp__tapper__orient`
result as authoritative and discard the others outright rather than reconciling
them — in particular, a startup copy saying KEG tools are locked is wrong once
a later orientation has returned a flight. When no flight is selected, the MCP
server connects in a recovery-only state: KEG tools are locked, while
`mcp__tapper__list_flights` and `mcp__tapper__flight_show` remain available for
discovery. Ask the user to select a flight in Tapper configuration, then call
`mcp__tapper__orient` again.

When there is no flight to select — a fresh machine or account — the session
instead starts on a temporary **bootstrap flight**. Its cover is empty, so the
KEG tools stay locked, but `mcp__tapper__keg_create` and the flight mutation
tools are available so you can create the first KEG and the first flight.
Setting that up is the session's work; do it before anything else. You still
cannot *select* a flight — that stays a human action — so hand the setup back
to the user and call `mcp__tapper__orient` again once they confirm. The
orientation payload names exactly where they should do it.

If `mcp__tapper__orient` is unavailable, report that the Tapper MCP connection
is unavailable, ask the user to reconnect or restart the host session, and
never kill or signal host-owned processes. A flight with an empty cover exposes
Expand Down Expand Up @@ -169,6 +225,24 @@ Tapper supports two link forms in node bodies:
Both forms appear in backlinks. Prefer intra-keg links when the target is in
the same keg.

## Attachments

A node's uploaded files and images live in two directories inside the node's
own directory, so they are linked relative to it — the same base the `../NODEID`
form above counts from:

- **File:** `[label](./assets/FILE)` — anything uploaded with
`mcp__tapper__upload_file`.
- **Image:** `![alt](./images/IMAGE)` — anything uploaded with
`mcp__tapper__upload_image`.

**Both directory names are plural**: `assets/` and `images/`, never `asset/` or
`image/`. Uploading succeeds regardless of how you later write the link, so a
singular path fails silently as a broken reference rather than as an error.

Use `mcp__tapper__list_files` and `mcp__tapper__list_images` to get the exact
stored names; the upload may normalize the filename you supplied.

## Secret handling

- Never store credentials, API tokens, private keys, session cookies, customer
Expand Down
2 changes: 2 additions & 0 deletions integrations/rendered/codex/tapper/.mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"command": "tap",
"args": ["mcp"],
"env_vars": [
"HOME",
"TAP_FLIGHT",
"XDG_CONFIG_HOME",
"XDG_DATA_HOME",
"XDG_STATE_HOME",
Expand Down
Loading