Skip to content
Open
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
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This file is the entry point for agents. It is intentionally short.
2. Read `docs/design-docs/index.md` for design invariants.
3. Pick a domain:
- `kb-server`: API, Git workflows, current-view composition.
- `mcp-server`: MCP adapter for structured agent access to notes and context bundles.
- `vault-sync`: local mirror and push/pull convergence.
4. Read topical constraints before implementation:
- `docs/SECURITY.md`
Expand All @@ -38,6 +39,7 @@ This file is the entry point for agents. It is intentionally short.
## Domain Maps

- Backend domain: `docs/product-specs/kb-server.md`
- MCP adapter domain: `docs/product-specs/mcp-server.md`
- Sync client domain: `docs/product-specs/vault-sync.md`
- Branching + current view model: `kb-server/BRANCHING_AND_CURRENT_VIEW.md`

Expand Down Expand Up @@ -86,4 +88,3 @@ Update docs in the same PR when changing:
- Security: `docs/SECURITY.md`
- Reliability: `docs/RELIABILITY.md`
- Autonomous E2E workflow: `docs/runbooks/autonomous-agent-e2e.md`

9 changes: 9 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ review_cycle_days: 21
## Monorepo Topology

- `kb-server/`: authoritative API and worker processes.
- `mcp-server/`: MCP adapter for agent-native note and context access.
- `vault-sync/`: local daemon that mirrors and edits through API.
- `docs/`: system-of-record documentation for humans and agents.
- `scripts/`: repository-level automation for docs quality and generation.
Expand All @@ -46,6 +47,13 @@ review_cycle_days: 21
- `source=human`: direct commit/push to base branch.
- Implements `view=current` as composed, read-only view.

### mcp-server

- Connects MCP-capable agents to Flight Deck through stdio tools/resources.
- Delegates note CRUD and retrieval requests to `kb-server` over HTTP.
- Defaults reads to `view=current`.
- Forces note mutations through `source=api` so review workflows stay intact.

### vault-sync

- Pulls notes from `view=current`.
Expand Down Expand Up @@ -97,5 +105,6 @@ review_cycle_days: 21
- `docs/design-docs/index.md`
- `docs/product-specs/kb-server.md`
- `docs/product-specs/vault-sync.md`
- `docs/product-specs/mcp-server.md`
- `docs/SECURITY.md`
- `docs/RELIABILITY.md`
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ A file-first knowledge base with Git-backed approval workflows. Edit notes local
## What it does

- **kb-server**: API and workers that manage a Markdown vault, auto-commit to Git, and expose a `current` view (approved content + pending PRs).
- **mcp-server**: MCP adapter that gives agents structured tools/resources over notes and server-built context bundles.
- **vault-sync**: Daemon that mirrors the current view to a local folder and pushes your edits back as human-origin commits.

## Get started
Expand All @@ -22,6 +23,7 @@ A file-first knowledge base with Git-backed approval workflows. Edit notes local
| Path | Purpose |
| ------------- | -------------------------------------------- |
| `kb-server/` | API, Git workflows, current-view composition |
| `mcp-server/` | MCP adapter over kb-server |
| `vault-sync/` | Local sync daemon (pull + push) |
| `docs/` | Architecture, runbooks, product specs |

Expand Down
7 changes: 7 additions & 0 deletions docs/RELIABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ review_cycle_days: 21

- `kb-server` readiness requires database and Git-backed vault access.
- `kb-server` retrieval endpoints should rebuild or refresh in-process graph state when visible note state changes.
- `mcp-server` should surface upstream `kb-server` failures as explicit tool errors rather than hanging or fabricating output.
- Autosave worker should tolerate transient Git/network failures.
- `vault-sync` should converge after temporary API outages.

Expand Down Expand Up @@ -56,6 +57,12 @@ review_cycle_days: 21
- Signal: local filesystem remains intact; no destructive cleanup on transient failures.
- Recovery check: after API is reachable, next pull repopulates `view=current` and pending local changes push successfully.

### API outage (`mcp-server`)

- Signal: MCP tools return upstream request failures with `kb-server` status/detail.
- Signal: note/resource reads fail closed rather than returning stale fabricated content.
- Recovery check: once `kb-server` is reachable, the next MCP tool invocation succeeds without restarting the adapter.

## Runbook Links

- `runbooks/deployment.md`
Expand Down
8 changes: 8 additions & 0 deletions docs/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ review_cycle_days: 21
- Secrets remain in local `.env` files or deployment secret stores.
- Docs should only reference secret names, not values.
- Generated docs must redact secrets by default.
- `mcp-server` stores `KB_API_KEY` locally and must never echo it back through tool output or logs.

## MCP Boundary

- `mcp-server` is a local adapter over `kb-server`, not a second source of truth.
- v1 transport is stdio only; no remote MCP transport is exposed by default.
- MCP writes must use `source=api` and must not expose a path to `source=human`.

## Write Safety

Expand All @@ -40,5 +47,6 @@ Update this document when changing:

- auth middleware/dependency behavior
- request validation and path sanitization
- MCP transport or upstream auth handling
- external webhook/publish execution semantics
- GitHub token scope or PR automation behavior
17 changes: 15 additions & 2 deletions docs/generated/env-catalog.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
---
owner: platform
status: generated
last_verified: 2026-03-06
last_verified: 2026-03-12
source_of_truth:
- ../../kb-server/.env.example
- ../../kb-server/app/core/config.py
- ../../mcp-server/mcp_server/config.py
- ../../vault-sync/vault_sync/config.py
related_code:
- ../../scripts/generate_context_artifacts.py
related_tests:
- ../../kb-server/tests
- ../../mcp-server/tests
- ../../vault-sync/tests
review_cycle_days: 7
---

# Environment Catalog (Generated)

Generated on `2026-03-06` from settings and env sources.
Generated on `2026-03-12` from settings and env sources.

## kb-server `.env.example`

Expand Down Expand Up @@ -60,6 +62,17 @@ Generated on `2026-03-06` from settings and env sources.
| `api_host` | `"0.0.0.0"` |
| `api_port` | `8000` |

## mcp-server Settings Defaults

| Field | Default Expression |
| --- | --- |
| `kb_server_url` | `"http://127.0.0.1:8000"` |
| `kb_api_key` | `""` |
| `mcp_default_view` | `"current"` |
| `mcp_default_limit` | `Field(default=10, ge=1, le=50)` |
| `mcp_default_token_budget` | `Field(default=4000, ge=1, le=50000)` |
| `mcp_transport` | `"stdio"` |

## vault-sync Settings Defaults

| Field | Default Expression |
Expand Down
2 changes: 1 addition & 1 deletion docs/product-specs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ review_cycle_days: 21
## Domain Specs

- `kb-server.md`: API and branch/workflow product contract.
- `mcp-server.md`: MCP adapter contract for agent tools/resources.
- `vault-sync.md`: local sync and human-edit UX contract.

## Scope
Expand All @@ -31,4 +32,3 @@ Implementation details belong in design docs or code comments.
- `../DESIGN.md`
- `../PRODUCT_SENSE.md`
- `../RELIABILITY.md`

49 changes: 49 additions & 0 deletions docs/product-specs/mcp-server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
owner: platform
status: draft
last_verified: 2026-03-12
source_of_truth:
- ../../mcp-server/mcp_server/server.py
- ../../mcp-server/mcp_server/client.py
- ../../kb-server/app/api/routes/context.py
related_code:
- ../../kb-server/app/api/routes/notes.py
related_tests:
- ../../mcp-server/tests
- ../../kb-server/tests/test_context_api.py
review_cycle_days: 14
---

# Product Spec: mcp-server

## Purpose

Expose Flight Deck note operations and context retrieval to MCP-capable agents without duplicating backend approval or Git logic.

## User-Visible Behavior

- Provides MCP tools for:
- finding relevant notes
- building bounded context bundles
- listing notes
- reading notes
- writing notes as API-origin changes
- deleting notes as API-origin changes
- Provides a note resource for direct page reads through MCP.
- Defaults reads and retrieval to `view=current`.
- Forces writes to `view=main` and `source=api`.

## Guardrails

- Uses `kb-server` as the only backend authority.
- Must be configured with `KB_SERVER_URL` and `KB_API_KEY`.
- Does not expose `source=human`.
- Does not expose publish or prompt workflows in v1.
- v1 transport is stdio.

## Related Operational Docs

- `../../mcp-server/README.md`
- `../SECURITY.md`
- `../RELIABILITY.md`
- `../../ARCHITECTURE.md`
9 changes: 9 additions & 0 deletions mcp-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# mcp-server

MCP adapter for Flight Deck. This package exposes note operations and context retrieval to MCP-capable agents while delegating all vault, approval, and provenance rules to `kb-server`.

See:

- `../docs/product-specs/mcp-server.md`
- `../ARCHITECTURE.md`
- `../docs/SECURITY.md`
10 changes: 10 additions & 0 deletions mcp-server/flight_deck_mcp_server.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Metadata-Version: 2.4
Name: flight-deck-mcp-server
Version: 0.1.0
Summary: MCP adapter for Flight Deck
Requires-Python: >=3.10
Requires-Dist: httpx>=0.28
Requires-Dist: mcp>=1.2.0
Requires-Dist: pydantic-settings>=2.7
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
13 changes: 13 additions & 0 deletions mcp-server/flight_deck_mcp_server.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pyproject.toml
flight_deck_mcp_server.egg-info/PKG-INFO
flight_deck_mcp_server.egg-info/SOURCES.txt
flight_deck_mcp_server.egg-info/dependency_links.txt
flight_deck_mcp_server.egg-info/entry_points.txt
flight_deck_mcp_server.egg-info/requires.txt
flight_deck_mcp_server.egg-info/top_level.txt
mcp_server/__init__.py
mcp_server/client.py
mcp_server/config.py
mcp_server/server.py
tests/test_client.py
tests/test_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

2 changes: 2 additions & 0 deletions mcp-server/flight_deck_mcp_server.egg-info/entry_points.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[console_scripts]
flight-deck-mcp = mcp_server.server:main
6 changes: 6 additions & 0 deletions mcp-server/flight_deck_mcp_server.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
httpx>=0.28
mcp>=1.2.0
pydantic-settings>=2.7

[dev]
pytest>=8.0
1 change: 1 addition & 0 deletions mcp-server/flight_deck_mcp_server.egg-info/top_level.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mcp_server
1 change: 1 addition & 0 deletions mcp-server/mcp_server/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Flight Deck MCP adapter."""
120 changes: 120 additions & 0 deletions mcp-server/mcp_server/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
from __future__ import annotations

from typing import Any

import httpx


class KBServerError(RuntimeError):
def __init__(self, status_code: int, detail: str):
super().__init__(detail)
self.status_code = status_code
self.detail = detail


class KBServerClient:
def __init__(
self,
base_url: str,
api_key: str,
timeout: float = 30.0,
transport: httpx.BaseTransport | None = None,
):
if not api_key:
raise ValueError("KB_API_KEY must be configured")

self._client = httpx.Client(
base_url=base_url.rstrip("/"),
headers={"X-API-Key": api_key},
timeout=timeout,
transport=transport,
)

def close(self) -> None:
self._client.close()

def find_notes(self, query: str, *, view: str, limit: int) -> dict[str, Any]:
return self._request(
"POST",
"/context/search",
json={"query": query, "view": view, "limit": limit},
)

def build_context_bundle(
self,
query: str,
*,
view: str,
limit: int,
token_budget: int,
) -> dict[str, Any]:
return self._request(
"POST",
"/context/bundle",
json={
"query": query,
"view": view,
"limit": limit,
"token_budget": token_budget,
},
)

def list_notes(self, *, prefix: str = "", view: str) -> list[dict[str, Any]]:
return self._request(
"GET",
"/notes/",
params={"prefix": prefix, "view": view},
)

def read_note(self, path: str, *, view: str) -> dict[str, Any]:
return self._request(
"GET",
f"/notes/{path}",
params={"view": view},
)

def write_note(self, path: str, content: str) -> dict[str, Any]:
return self._request(
"PUT",
f"/notes/{path}",
params={"view": "main", "source": "api"},
json={"content": content},
)

def delete_note(self, path: str) -> None:
self._request(
"DELETE",
f"/notes/{path}",
params={"source": "api"},
)

def _request(
self,
method: str,
path: str,
*,
params: dict[str, Any] | None = None,
json: dict[str, Any] | None = None,
) -> Any:
try:
response = self._client.request(method, path, params=params, json=json)
except httpx.HTTPError as exc:
raise KBServerError(502, f"kb-server request failed: {exc}") from exc

if response.status_code >= 400:
detail = _extract_detail(response)
raise KBServerError(response.status_code, detail)

if response.status_code == 204:
return None
return response.json()


def _extract_detail(response: httpx.Response) -> str:
try:
payload = response.json()
except ValueError:
return response.text.strip() or f"kb-server returned {response.status_code}"
if isinstance(payload, dict) and "detail" in payload:
return str(payload["detail"])
return str(payload)
Loading
Loading