Built-in MCP endpoint (Streamable HTTP) on top of the public API #105
Labels
No Label
area:auth
area:docs
area:export
area:ops
area:storage
area:supply-chain
auth
backend
blocked
collab
deployment
docs
effort:L
effort:M
effort:S
frontend
plugins
qa
vs-nfd
vs-nfd:blocker
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: stwaidele/dorfteich#105
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
AI frameworks (Claude Code and other MCP clients) should talk to a Dorfteich instance directly. With personal access tokens and the public API in place (#104), the instance exposes MCP itself — no extra process for users; stdio-only clients bridge via
mcp-remote.Scope
/mcp, served by the api (official@modelcontextprotocol/sdkserver, stateless mode). Auth via PAT bearer (same tokens as #104). Honors its own instance switch (mcp.enabled, default off) plus a per-pond opt-in (mcpEnabledpond setting) — switchable independently of the REST API.list_ponds()/list_pages(pond)read_page(pond, page)→ Markdown + metadatasearch(query, pond?, label?)→ snippets + stable refscreate_page(pond, title, markdown)update_page(pond, page, markdown?, title?)— replace semantics, like the REST PATCH (collab-safe content path)add_comment(pond, page, text)list_labels(pond)/set_page_labels(pond, page, labelIds)export_pond(pond)→ link to the ZIP exportdorfteich://{pond}/{page}) for clients that prefer resource reads.mcp-remoteone-liner for stdio clients.Acceptance criteria
writescope; read-only tokens can list/read/search onlyTechnical notes
RateLimitService; tool invocations audit-logged like public-API writes.Dependencies
Depends on #104 (personal access tokens + public API services).
Size: ~2 days
Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add
deanden), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.Implemented in
04e21a0(CI fully green, deployed to Test + Int).What shipped
/api/mcp— deliberately under the/api/path instead of the issue's literal/mcp: every existing reverse proxy (stages, self-hosters, the bundled Caddyfile) already routes/api/*to the api, so the feature needs zero deployment changes anywhere.@modelcontextprotocol/sdk, Streamable HTTP, fully stateless — each POST builds a fresh server+transport pair (no session store; replicas stay trivial), GET/DELETE answer 405. Auth via PAT bearer (#104 tokens), per-token rate limit (429 + Retry-After).mcp.enabled(admin settings, default off — off means 404, feature invisible) + pond settingmcpEnabled(pond-settings toggle, default off).list_ponds,list_pages,read_page,search,create_page,update_page(replace semantics through the collab-owned restore path — open editors converge),add_comment,list_labels,set_page_labels(exact replace),export_pond(link to the REST ZIP). Errors carry the api error codes; results carry stable slugs/ids for chaining. MCP resources stay the documented stage-2 stretch goal.docs/self-hosting/public-api.md—claude mcp add --transport http … --header "Authorization: Bearer dt_pat_…"plus themcp-remotebridge for stdio-only clients.Implementation note: the SDK's typed
registerToolhelpers drove TypeScript's inference out of memory in a program this size — the server sits on the SDK's low-levelServerAPI with a hand-written tool table (mcp-tools.ts, JSON Schema for tools/list + Zod validation of calls).Verification
scope_required.The "Claude Code connects" acceptance criterion is covered by the official SDK client over the same Streamable-HTTP transport Claude Code uses (
claude mcp add --transport http); the config one-liner is documented and ready for a hands-on run against Test/Prod once tokens exist there.