Skip to content

MCP Architecture

Who is this for? Contributors working on the rosetta-mcp server, RAGFlow, the Rosetta CLI, or diagnosing MCP-mode behavior.

When should I read this? After Architecture. MCP is the secondary, optional delivery mode — plugins are primary and most teams don’t need MCP. MCP serves teams that want centrally managed, always-fresh instructions with nothing copied into the repository.

Covers: the full MCP pipeline (Instructions Repo → CLI → RAGFlow → rosetta-mcp server → IDE), environments, RAGFlow (datasets, processing pipeline), Rosetta CLI (publish/parse/verify commands, auto-tagging), transports (Streamable HTTP + OAuth, STDIO), authentication, VFS resource paths and auto-tagging (tag-based retrieval), MCP tools and the rosetta://{path} resource, document bundling, listings, and context overflow prevention. The command aliases themselves are mode-agnostic and documented in Architecture; in MCP mode they are bound to server calls by mcp-files-mode.md, and generated shells use ACQUIRE <path> FROM KB verbatim.


System Overview

┌─────────────────────────────────────────────────────────┐
│              Target Repository + IDE                    │
│  Cursor · Claude Code · VS Code · JetBrains · Codex     │
│  Windsurf · Antigravity · OpenCode                      │
│  (MCP integration; native hooks vary by IDE)            │
│                         │                               │
│                    MCP Protocol                         │
│             (Streamable HTTP + OAuth)                   │
└────────────────────────┬────────────────────────────────┘
                         │ PULL
              ┌──────────▼──────────┐
              │    Rosetta MCP      │
              │   (rosetta-mcp on PyPI) │
              │                     │
              │  VFS resource paths │
              │  Bundler · Tags     │
              │  Context headers    │
              └──────────┬──────────┘
                         │ PULL
              ┌──────────▼──────────┐
              │   RAGFlow (Server)  │
              │  (document engine)  │
              │                     │
              │  parse · chunk      │
              │  embed · retrieve   │
              └──────────▲──────────┘
                         │ PUSH
              ┌──────────┴──────────┐
              │    Rosetta CLI      │
              │ (rosetta-cli PyPI)  │
              │                     │
              │  publish · parse    │
              │  verify · cleanup   │
              └──────────▲──────────┘
                         │ PUSH
              ┌──────────┴──────────┐
              │  Instructions Repo  │
              │  /instructions/r3/  │
              │                     │
              │  core/ · <org>/     │
              │  skills · agents    │
              │  workflows · rules  │
              └─────────────────────┘

Instructions flow up: files are published by the CLI into RAGFlow, served by Rosetta MCP to IDEs. Rosetta does not see or process your source code — by design, it only delivers knowledge and instructions.

Plugins have their own, separate delivery pipeline (generator, not CLI/RAGFlow) — see Architecture — System Overview and Plugin Delivery Flow.


Rosetta MCP Server

The MCP server is the guiding layer between IDEs and the knowledge base. It exposes guardrails and common best practices, and provides a structured menu of available instructions; the coding agent selects what it needs, and Rosetta delivers only those — preventing context overload. Published on PyPI as rosetta-mcp. Built on FastMCP v3 (latest stable) with OAuthProxy for authentication and RAGFlow as the document engine backend. Speaks in VFS resource paths, adds context headers describing what information means and how to use it, and controls context size automatically.

Transport options:

Authentication: HTTP uses OAuth 2.1 via OAuthProxy (supports any provider: Keycloak, GitHub, Google, Azure). Cached token introspection. STDIO uses ROSETTA_API_KEY. Policy-based authorization: aia-* read-only, project-* configurable.

Key environment variables: ROSETTA_SERVER_URL, ROSETTA_API_KEY, INSTRUCTION_ROOT_FILTER, REDIS_URL

For MCP setup across all IDEs, see Get Started.

Environments

Note: The repo’s .mcp.json (Claude Code contributor config) intentionally points to the dev MCP endpoint. Contributors developing Rosetta connect to dev so their in-progress instruction changes are reflected immediately. End users should connect to the production endpoint — see MCPs Installation.

RAGFlow (Rosetta Server)

RAGFlow is the document storage and retrieval engine. Rosetta uses it for ingestion, parsing, embedding, and search. Not exposed to end users directly.

Deployment: Local via Docker Compose at http://localhost:80 (development) or hosted instance (production).

Processing pipeline: Upload (upsert by deterministic UUID) → Parse (server-side) → Chunk → Embed → Index. Repeated publishes are idempotent.

Datasets:

Dataset Purpose
aia Base fallback (files without a release)
aia-r1 R1 release (out of support)
aia-r2 R2 release (previous; backports only)
aia-r3 R3 release (current)
project-* Per-repository collections in target repos (per OAuth policy)

Instruction dataset names auto-generated from template aia-{release}.

All prefixes are internal only, it must not be exposed or received. This prevents cross-dataset security issues. Any user of MCP must not be aware of those existence.

Metadata per document: tags, domain, release, content_hash (MD5), resource_path, sort_order, frontmatter, original_path, line_count.

Rosetta CLI

The CLI (rosetta-cli, published on PyPI) publishes instructions from the instructions repository into RAGFlow. It handles change detection, metadata extraction, frontmatter parsing, and auto-tagging.

Core commands:

Command What it does
uvx rosetta-cli@latest publish instructions Publish changed files (incremental, MD5-based)
uvx rosetta-cli@latest publish instructions --force Republish all files regardless of changes
uvx rosetta-cli@latest publish instructions --dry-run Preview what would be published
parse Trigger server-side document parsing
verify Test connection and health
list-dataset --dataset aia-r3 List documents in a dataset
cleanup-dataset --dataset aia-r3 Delete documents from a dataset

Critical rule: Always publish the entire /instructions folder. Never subfolders or single files (breaks tag extraction).

Change detection: MD5 hash of content. Only modified files publish (~77% time savings). Use --force to bypass.

Auto-tagging and metadata extraction. The CLI reads each file during publishing and extracts everything MCP needs to serve it efficiently:

Environment: .env.dev (dev RAGFlow) or .env.prod (production). Switch with cp .env.dev .env.

For deployment details, see Deployment.

Authentication

HTTP uses OAuth 2.1 via FastMCP’s proxy layer (supports any provider: Keycloak, GitHub, Google, Azure). STDIO uses ROSETTA_API_KEY. Policy-based authorization: aia-* read-only, project-* configurable. For the two-leg proxy architecture, scope separation, and token lifecycle details, see AUTHENTICATION.md.

Three OAuth modes controlled by ROSETTA_OAUTH_MODE:

oauth mode (default) — generic OAuth 2.0 with token introspection:

Env var Purpose
ROSETTA_OAUTH_AUTHORIZATION_ENDPOINT Upstream IdP authorization URL
ROSETTA_OAUTH_TOKEN_ENDPOINT Upstream IdP token URL
ROSETTA_OAUTH_INTROSPECTION_ENDPOINT Upstream IdP introspection URL
ROSETTA_OAUTH_CLIENT_ID Pre-registered IdP client ID
ROSETTA_OAUTH_CLIENT_SECRET IdP client secret
ROSETTA_OAUTH_BASE_URL Public URL of Rosetta MCP
ROSETTA_JWT_SIGNING_KEY Secret for signing FastMCP JWTs
ROSETTA_OAUTH_REVOCATION_ENDPOINT (optional) Token revocation URL
ROSETTA_OAUTH_CALLBACK_PATH (optional) Callback path (default: /auth/callback)
ROSETTA_OAUTH_REQUIRED_SCOPES (optional) Scopes required on tokens
ROSETTA_OAUTH_VALID_SCOPES (optional) Scopes advertised in .well-known
ROSETTA_OAUTH_EXTRA_SCOPES (optional) Scopes forwarded to IdP authorize endpoint

Upstream IdP issues opaque tokens; Rosetta introspects them on each request via IntrospectionTokenVerifier. Cached 15 min.

oidc mode — OIDC auto-discovery with local JWT verification:

Env var Purpose
ROSETTA_OAUTH_OIDC_CONFIG_URL IdP OIDC discovery URL (.well-known/openid-configuration)
ROSETTA_OAUTH_CLIENT_ID Pre-registered IdP client ID
ROSETTA_OAUTH_CLIENT_SECRET IdP client secret
ROSETTA_OAUTH_BASE_URL Public URL of Rosetta MCP
ROSETTA_JWT_SIGNING_KEY Secret for signing FastMCP JWTs
ROSETTA_OAUTH_CALLBACK_PATH (optional) Callback path (default: /auth/callback)
ROSETTA_OAUTH_REQUIRED_SCOPES (optional) Scopes required on tokens
ROSETTA_OAUTH_EXTRA_SCOPES (optional) Scopes forwarded to IdP authorize endpoint

Rosetta fetches IdP endpoints automatically from the discovery doc; tokens are JWTs verified locally via JWKS. No per-request introspection calls.

github mode — GitHub OAuth via GitHubProvider:

Env var Purpose
ROSETTA_OAUTH_CLIENT_ID GitHub OAuth App Client ID
ROSETTA_OAUTH_CLIENT_SECRET GitHub OAuth App Client Secret
ROSETTA_OAUTH_BASE_URL Public URL of Rosetta MCP (HTTPS required in production)
ROSETTA_JWT_SIGNING_KEY Secret for signing FastMCP JWTs
ROSETTA_OAUTH_CALLBACK_PATH (optional) Callback path (default: /auth/callback)
ROSETTA_OAUTH_REQUIRED_SCOPES (optional) Required GitHub scopes (default: user)

GitHub endpoints are hardcoded. Tokens are validated via the GitHub API (https://api.github.com/user). User identity is extracted from GitHub profile (login, name, email).

All three modes issue FastMCP JWTs to MCP clients and store upstream tokens in Redis (encrypted with FERNET_KEY). MCP clients never see IdP tokens; the IdP never sees FastMCP JWTs.

Redis Schema Migrations

rosetta_mcp/migrations.py runs sequential schema migrations against Redis on every server startup via the FastMCP lifespan hook. Migrations are numbered methods (_migrate_to_N); only those ahead of the stored version run.

Key details:

Current migrations:

Version What it does
1 Baseline no-op — marks pre-migration deployments as version 1
2 Flushes mcp-oauth-proxy-clients:* keys so DCR/CIMD clients re-register with correct required_scopes

Adding a migration: add _migrate_to_N, bump LATEST_REDIS_SCHEMA_VERSION = N, deploy.

VFS and Tags

Everything MCP works with is VFS (virtual file system) resource paths. The CLI strips instruction root prefixes during publishing, so core/skills/planning/SKILL.md becomes skills/planning/SKILL.md. Files at the same resource path get bundled together.

Tags are the primary access mechanism. Typed load aliases (USE SKILL, READ RULE, APPLY PHASE, …) query by tags, which provides the most direct and fastest access. The CLI’s auto-tagging was designed specifically for this: every folder name, filename, and composite pair/triple becomes a tag, so agents can request exactly what they need. Keyword search (query_instructions(query=...)) remains an MCP-level fallback for discovery.

MCP Tools

Three tools and one resource are exposed to agents.

Tool Purpose
get_context_instructions MCP bootstrap gate: loads bootstrap-alwayson.md
query_instructions Fetch instruction docs by tags (primary) or keyword search (fallback)
list_instructions Browse the VFS hierarchy (flat listing of immediate children)

Resource: rosetta://{path} reads bundled instruction documents by VFS resource path.

Bundler

The Bundler merges multiple documents at the same VFS resource path into a single XML response. When an agent loads a skill (USE SKILL), core and organization files at that path are concatenated into one payload:

<rosetta:file id="..." dataset="..." path="skills/planning/SKILL.md" name="..." tags="..." frontmatter="...">
  [document content from core]
</rosetta:file>
<rosetta:file id="..." dataset="..." path="skills/planning/SKILL.md" name="..." tags="..." frontmatter="...">
  [document content from organization overlay]
</rosetta:file>

Documents sorted by sort_order (default: 1000000), then by name. INSTRUCTION_ROOT_FILTER controls which layers are included (e.g., CORE,GRID).

Plugin mode has no runtime Bundler — the generator merges core and organization layers at build time instead. See Architecture — Instruction Structure.

Listing

Listing shows what exists in the VFS without loading content. Implemented by list_instructions to browse the instruction hierarchy. Two formats:

XML format (default) includes metadata attributes:

<rosetta:folder dataset="..." path="skills/" />
<rosetta:folder dataset="..." path="rules/" />
<rosetta:file id="..." path="skills/planning/SKILL.md" name="..." tag="skills/planning/SKILL.md" frontmatter="..." />

Flat format returns resource paths only:

skills/planning/SKILL.md
skills/coding/SKILL.md
rules/guardrails.md

A full instruction suite listing is ~400 tokens. Frontmatter attributes (extracted by CLI during publishing) let agents understand document purpose from the listing alone, without follow-up reads.

Context Overflow Prevention

MCP manages context size through two mechanisms:


MCP Delivery Flow

Instructions Repo ──► CLI (publish) ──► RAGFlow ──► Rosetta MCP ──► Target Repo + IDE
  1. Publish. CLI reads .md files from instructions repo, extracts tags + frontmatter + metadata, generates deterministic UUID, upserts into dataset.
  2. Index. RAGFlow parses, chunks, embeds, indexes for full-text and semantic search.
  3. Serve. The agent calls get_context_instructions once per session (MCP bootstrap gate), then loads instructions on demand via query_instructions/list_instructions by tag; mcp-files-mode.md binds the typed command aliases to these calls.

Runtime behavior after instructions are loaded — prepare, route, execute — is identical across delivery modes; see Architecture — Bootstrap Flow. Plugins have their own, separate delivery flow (generate once, ship, load locally) — see Architecture — Plugin Delivery Flow.


Development

Prerequisites

MUST use the same venv as the rest of the repo: venv/. There are .env.dev and .env.prod. MUST not read any .env files.

Publishing Instructions

Publish instructions to remote IMS server:

cp .env.dev .env
uvx rosetta-cli@latest publish instructions

Additional publish examples:

Validation

MUST validate MCP changes using .env.dev and src/rosetta-mcp-server/validation/verify_mcp.py (testing harness of MCP itself). Integrate new features to this testing harness if needed and easy. MUST execute venv/bin/python scripts/pre_commit.py from repository root. Never filter/grep/tail its output. Entire verify_mcp.py and ALL tests must work. Always run verify_mcp.py: with R3 only. When backporting a change to R2, also run it with VERSION=r2. If REDIS-dependent feature is affected RUN verify_mcp.py with and without REDIS_URL (example: execution_controller tool). Must run src/validate-types.sh if code was changed. Do not tail or limit output of verify_mcp.py, it is short already. Read first 100 lines of verify_mcp.py to get instructions ON HOW exactly it should all be done.

Validation command examples:

Validation notes discovered during real runs:

Must read docs/mcp/RAGFLOW.md fully to understand RAGFlow actual implementation and known issues if CLI or MCP changes involve RAGFlow.

Reference Sources (readonly, packages currently used)

refsrc/fastmcp-3.3.1 contains source code of FastMCP v3. Use https://gofastmcp.com/llms.txt - fastmcp index of all dev docs. There is also https://gofastmcp.com/llms-full.txt but it is extremely large, it will not fit entirely your context window at all. refsrc/python-sdk-1.26.0 contains source code of MCP Python SDK. refsrc/ragflow-0.25.1 contains source code of RAGFlow Python SDK (v0.25.1+).

This is for reference purposes only: do not change, do not copy.


Tradeoffs

Mode-agnostic tradeoffs (release-based versioning, layered customization, command aliases, native plugin format) are documented in Architecture — Tradeoffs.