Skip to content

docs(project): plan doc-query scoped MCP integration on the KB control plane#5168

Draft
rschlaefli wants to merge 1 commit into
v3from
docs/doc-query-scoped-mcp-plan
Draft

docs(project): plan doc-query scoped MCP integration on the KB control plane#5168
rschlaefli wants to merge 1 commit into
v3from
docs/doc-query-scoped-mcp-plan

Conversation

@rschlaefli

Copy link
Copy Markdown
Member

What

Planning-only doc (no code, no migration, no seed change): project/plans_future/PLAN-doc-query-scoped-mcp-integration.md.

Documents how Klicker chatbots will query one shared, deployment-configured doc-query MCP endpoint through a single stable doc_query tool, with tenant isolation carried by a short-lived signed Scope Token (ES256 JWT, kb_id claim) minted per chat request. doc-query verifies the token and injects a mandatory kb_id retrieval filter server-side. The scope unit is the Knowledge Base from PR #5078 (KB/KBResource/KBChatbot), not the chatbot, so re-linking a KB to a different chatbot never triggers re-ingestion.

Why draft

Scope

  • 1 file, +553 lines, docs only.
  • Base v3. Full dependency/sequencing, current-state file:line audit, and open questions are in the doc.

Verification

None required — no code. Rendered-markdown review only.

…l plane

Klicker-side child plan of the producer-neutral runtime-config umbrella
(deployment repo). Builds on PR #5078 (KB management control plane):
Scope Token (ES256, kb_id claim) via a new scope_token MCP auth type,
follow-up migration for version/digest fences, ingestion API client
replacing fire-and-forget webhooks, Source Gateway, upload SAS flow,
and KB manager wiring. All open questions ruled 2026-07-12 (documents
mode, opaque sub, v3-ai base, client digest, SNIPPET-as-blob).
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1609f708-23c4-4e1b-8b58-0494d284d2ca

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 13, 2026

Copy link
Copy Markdown

Confidence Score: 4/5

The planning document needs fixes around URL fetching, stale operation activation, and versioned blob reads before it guides implementation.

  • Website URL ingestion can fetch lecturer-controlled hosts without an explicit default-deny policy.
  • Late webhook success for an old operation can advance serving state after a newer desired version exists.
  • Versioned gateway URLs can read a moving storage pointer instead of immutable per-version content.

project/plans_future/PLAN-doc-query-scoped-mcp-integration.md

Security Review

The Scope Token design removes caller-controlled MCP scope headers, but URL-based website ingestion still needs a mandatory default-deny fetch policy to prevent SSRF-style access to internal hosts.

Important Files Changed

Filename Overview
project/plans_future/PLAN-doc-query-scoped-mcp-integration.md Adds the full design plan for KB-scoped doc-query MCP integration; the plan needs tighter URL-fetch, stale-operation, and versioned-blob rules before implementation.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
  participant Chat as Chat request
  participant Klicker as Klicker backend
  participant MCP as doc-query MCP
  participant Ingest as data-ingestion
  participant Gateway as Source Gateway
  Chat->>Klicker: authorized chatbot chat
  Klicker->>Klicker: resolve enabled KB link
  Klicker->>MCP: call doc_query with Scope Token
  MCP->>MCP: verify kb_id and inject filter
  Klicker->>Ingest: submit resource operation
  Ingest->>Gateway: fetch versioned blob URL
  Ingest-->>Klicker: signed status webhook
  Klicker->>Klicker: update operation and serving state
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
  participant Chat as Chat request
  participant Klicker as Klicker backend
  participant MCP as doc-query MCP
  participant Ingest as data-ingestion
  participant Gateway as Source Gateway
  Chat->>Klicker: authorized chatbot chat
  Klicker->>Klicker: resolve enabled KB link
  Klicker->>MCP: call doc_query with Scope Token
  MCP->>MCP: verify kb_id and inject filter
  Klicker->>Ingest: submit resource operation
  Ingest->>Gateway: fetch versioned blob URL
  Ingest-->>Klicker: signed status webhook
  Klicker->>Klicker: update operation and serving state
Loading

Fix All in Codex Fix All in Claude Code

Reviews (1): Last reviewed commit: "docs(project): plan doc-query scoped MCP..." | Re-trigger Greptile

- Calls (producer-neutral contract from the umbrella plan): create/update →
`POST /v1/resources` with `{project_id: "klicker-course-materials", producer: "klicker",
external_resource_id: <KBResource.id>, resource_version, scope: {kb_id: <KB.id>},
source: {kind, url: <gateway version URL or public URL>, mime_type, display_name},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Website Fetches Lack Guardrails

WEBSITE resources submit a lecturer-provided public URL for ingestion to fetch, but the plan only defines the SSRF restriction for blob sources. A URL like an internal service, link-local address, or redirect to a cluster-local host can be fetched by ingestion unless URL sources also have a mandatory default-deny policy.

Context Used: CLAUDE.md (source)

Fix in Codex Fix in Claude Code

Comment on lines +412 to +414
- State-machine hardening: duplicate/out-of-order events must not regress terminal state; only
a `resource_version` ≥ the current `activeResourceVersion` may advance serving state
(`activeResourceVersion`/`activeContentSha256` set on `resource.processing_succeeded`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Stale Operation Can Activate

The out-of-order guard only compares resource_version with activeResourceVersion. If version 2 is still running, version 3 is submitted, and the version 2 success arrives late, 2 >= 1 can still mark stale content active even though it is no longer the desired operation.

Context Used: CLAUDE.md (source)

Fix in Codex Fix in Claude Code

Comment on lines +389 to +392
- Behavior: stream the exact immutable blob for that resource version (`KBResource.storagePath`)
from Azure Blob using the server-side credential (never expose SAS); set `Content-Type`,
`Content-Length`, and `ETag: "<contentSha256>"`; 404/410 for unknown, soft-deleted (`deletedAt`),
or fenced resources; enforce size cap on read.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Version Route Reads Moving Pointer

The gateway URL includes :version, but the described read uses KBResource.storagePath, a single current pointer. After a replace, a retry for an older /versions/1 URL can stream the newer blob path and let ingestion process the wrong bytes for that operation.

Context Used: CLAUDE.md (source)

Fix in Codex Fix in Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant