MCP generation and dependency knowledge
Vext MCP provides project facts, generated candidates, and a validation workflow. The host applies files, runs commands, and verifies business behavior. ready means a candidate can enter host review; scaffold: true identifies a scaffold, not completed business functionality. Installing or exporting a Skill does not prove the host actually called MCP.
Start with an existing Vext project and connect the host to that project's MCP. See the CLI MCP guide for installation, stdio startup, and configuration checks. This page covers use after connection. The dependency knowledge here is packaged MCP retrieval content; it differs from site documentation data and the future capability graph. The existence of one source does not prove that another is integrated.
Development workflow
- Call
vext_project_inspectfor current identity, directories, configuration, and dependencies. Check analysis coverage. - Search relevant framework and dependency knowledge with
vext_knowledge_search. Check exact versions, prerequisites, and limitations. - Express user conventions through
policyPatch, then requestvext_generate_changeswith real inputs, outputs, and use cases. - Review files,
scaffold,prerequisites, andrequiredHostSteps. Validate the same identity withvext_validate_changes. - The host applies create-only files and incrementally integrates existing configuration and consumers. Inspect again after project changes; stale identities cannot authorize new candidates.
- Run existing type checks, focused tests, formatting, builds, and runtime checks. Record commands, exit codes, and behavior evidence, then stop verification services and remove temporary artifacts.
Analysis JSON uses schemaVersion: 2; workspace/dev.mcp configuration remains version 1. Dependency ranges, content identity, loaded implementation identity, and runtime state describe separate facts.
Minimal candidate example
To generate a shared function that adds two nonnegative finite amounts, first inspect the project and obtain its actual projectId and contextRevision. This is the business input for vext_generate_changes; attach expectedIdentity from the current inspection when calling the tool. Never copy an older identity:
After receiving status: "ready", pass the complete changeSet, the same expectedIdentity, and policy to vext_validate_changes. Check actual paths, exports, and SHA values, then let the host apply the candidate. Test the returned export with 2 + 3 = 5 and rejection of a negative value. Neither ready nor candidate validation proves those business tests ran. A create-only candidate must be rejected when its target already exists; the host should edit existing code incrementally.
Default roles and project overrides
Directories are selected by responsibility and created only when needed. server denotes a server-only boundary; services identifies service contracts within it. The default is src/types/server/services/, not a collection of unrelated types directly under server/.
The effective roles returned by inspection are authoritative. Unambiguous existing layouts such as src/mocks and tests may be adopted. Explicit configuration and child-role overrides take precedence; parent overrides propagate to children without their own override.
A project may place service contracts in src/types/service/ by setting the following policyPatch content (or workspace policyDefaults):
This is a policy object, not a complete Tool request or workspace file. server-service-types is an alias of the same role; conflicting paths are rejected.
Moving implementation files does not change runtime loaders. Candidates include re-export entries in actual loader directories when required. Feature architecture may place implementation under src/modules/<feature>/ while preserving those entries. Monorepo inspection reads the current service and declared, verified shared sources; it does not grant arbitrary writes outside the fixed root. Model paths models/<database>/<file> and models/<pool>/<database>/<file> identify database and pool placement, not ordinary business categories. Shared model packages share definitions, while each application owns its connections.
Maintainable generated code
Routes own HTTP validation, authorization, responses, and use-case calls. Services own orchestration; models own persistence schema/hooks/indexes. Reused pure transformations belong in utils and domain validators in validators. Callbacks, short local expressions, and service private methods are valid. Do not use function counts as a quality rule or export cross-route helpers from loader-owned route files.
Do not treat function count as a quality rule. A callback, short one-use expression, private service method, or local function can stay local; do not force an obvious one-line expression into a helper. Simple internal results may be inferred, without a separate type file when no consumer reuses them. TS projects generate TS/TSX; JS projects generate JS/JSX with necessary JSDoc contracts. Mixed target directories require options.language. Naming and architecture policy cannot override actual loader boundaries.
Comments explain non-obvious contracts, authorization, transactions, idempotency, cache failures, and time units. Explicit commentLanguage wins; auto considers existing comments and outputLanguage. Static formatter JSON/.editorconfig settings affect generation. The host executes dynamic formatter configuration and final formatting.
Route and page Recipes accept JSON-safe routeOptions plus top-level auth, middlewares, cache, docs, operationId, security, and access. Explicit false, empty arrays, and null are preserved. Function auth, runtime stores/clients, and dynamic checks cannot be serialized into MCP options; wire them in host code or existing modules. Protected pages and admin APIs should declare authorization or middleware boundaries before reading protected data.
Backend locale files describe error keys with code, message, and HTTP status semantics. Frontend locale files describe user-facing copy, actions, and states. Mock data, scenarios, and adapters stay in mock-data/mock-scenarios/mock-adapters rather than service seed data.
Recipe inputs and integration
All 17 Recipes have independent options schemas in vext://catalog/recipes. Unknown fields and conflicting options are rejected.
api-module always calls its newly generated service; use api-route for an existing service or custom handler. Free-form parameters require serviceArgs. Explicit input requires validate.body unless serviceArgs selects another validated boundary. Standalone serviceArgs/serviceMethod require a target service.
These generators have explicit boundaries: RCP-10 does not invent browser E2E flows, RCP-13 does not invent business interactions, and RCP-16 does not install or guess third-party adapters. Missing inputs produce incomplete; unsupported combinations produce unsupported. Host integration and behavior validation remain required.
vext_project_check and vext_validate_changes accept configTarget: "development" | "production" | "all". Specify it when Redis, rateLimit, session, Job, cache, or production startup may differ; all checks development and production static config. vext_capability_check returns catalog status, framework support, MCP coverage, and current project state separately. Do not promote partial, planned, unknown, or unverified surfaces to supported.
Versioned dependency evidence
Knowledge is compiled into the framework package; project startup does not fetch the latest online documentation.
Coverage includes schema-dsl, monSQLize, response-cache-kit, cache-hub, flex-rate-limit, esbuild, croner, ioredis, React/ReactDOM, MCP SDK, and Oxc. Official main-branch documentation is not evidence for a different installed version. Advanced upstream features are not automatically verified Vext features.
Use native app.db.model<Document>(key) and findPage({ query, ... }). findPage returns items/pageInfo; findAndCount returns data/total. See Database. Response cache, database cache, rate limiting, Jobs, and session each own configuration and lifecycle; one Redis target does not enable or verify all consumers.
domain uses the same domains and aliases as project checks (for example database→models) and combines with kinds/ids. Unknown domains are input errors. locale selects the retrieval notice language; entries preserve packaged Chinese/English and API text. localization.status: partial explicitly reports that full per-entry translation is unavailable.
Every requirement, configuration, directory, dependency, or public API change must evaluate knowledge, Recipes, checks, documentation, and consumer tests. Record why an area is unaffected when no change is needed; changing a version string alone is insufficient.
Verify host adoption
Run vext mcp sync --root . --check --skill --json from the service root. The adoption result separates configuration, launcher, and Skill files from host discovery, actual connection, and current-task usage. Codex retains user-level MCP configuration; its project Skill is .agents/skills/vextjs/SKILL.md, with YAML name/description. Custom content is preserved. To deliberately replace an old export after reviewing it, use vext mcp skill write --output .agents/skills/vextjs/SKILL.md --force.
Matching files do not prove host adoption. TOML evidence is managed-block text matching, not whole-file host parsing. Discovery, connection, and taskUsage remain unverified until actual host evidence exists. Call vext_project_inspect through the host and compare rootDir, projectId, and implementation.loadedDigest. Retain actual Tool results, candidate SHA values, host commands and outcomes. Missing task history cannot establish whether an earlier task used MCP.
The scaffolded src/config/bootstrap.ts defaults to defineBootstrapConfig({ providers: [] }). That zero-provider entry does not hide a static dev.mcp declaration or block vext mcp sync from writing host configuration. MCP keeps configuration facts unknown only when bootstrap providers are non-empty, dynamic, or not statically proven empty.
Managed builds publish dist/.implementation.json last. MCP captures its loaded digest; a changed manifest requires reconnecting, while missing/building/invalid evidence remains unverified and prevents apply-ready candidates. For framework development, npm run build emits ESM+CJS; build:esm and dev/watch emit ESM, and build:cjs requires current ESM inputs. Use build for complete local package behavior. Direct tsc execution does not publish a completed implementation manifest.
CLI sourceBuild checks source/build inputs only when framework sources exist. Changed inputs report build-required; installed production packages need no src directory. Normal MCP requests read only the small manifest. It records managed builds, rather than auditing manually modified dist files. Reconnect and compare the actual Tool's loaded digest; Vext does not terminate host processes.
Multiple runtime instances
Each owner (development process, web, cluster master) records schemaVersion=2 under .vext/runtime/snapshots/<instanceId>.json. A random startup UUID separates instances even when a PID is reused. Real service roots/projectId separate services. Development child restarts append events to their owner's history; each cluster master aggregates its own workers.
Use vext_runtime_inspect with section summary to page through instances, then select the returned instanceId for summary/workers/reloads/events. Aggregate detail items carry instanceId. Cursors bind project, section, instance selection and snapshot contents; restart at the first page after a stale cursor.
Inspection visits at most 200 directory entries, reads at most 1 MiB per file and 8 MiB total. Events/reloads/workers retain 200/100/200 items. Responses also have a byte budget; reducing limit cannot turn incomplete collection into complete evidence. Unsafe links, invalid schema/ownership, concurrent changes and limits produce invalid/partial evidence with reasons.
updatedAt is not a heartbeat; liveness remains unverified. Source freshness requires a supplied revision with the same input contract. Current startup owners lack a revision covering the MCP input set, so sourceRevision remains null/unverified rather than performing a full source scan at startup. Neither presence nor absence proves process health or shutdown.
Updates for one owner are serialized and random temporary files are cleaned on success/failure. Graceful shutdown records stopped. Startup cleanup considers at most 200 records and removes only same-project snapshots stopped for at least 24 hours whose PID is absent; unknown ownership/liveness and abnormal exits are retained. At the inventory limit, the host must establish actual process state before manually removing specific records. Legacy snapshot.json is only a legacy/unverified notice. MCP does not start, restart, stop services or execute Jobs.
Default request validation versus response schemas
The default RouteOptions.validate.body/query/param and app.getValidator().compile() consume DSL field maps, for example { "title!": { type: "string" }, featured: "boolean?" }. Do not pass a whole { type: "object", properties: ..., required: [...] } schema there: those keys become field names. responses[status].schema is a separate boundary that accepts full JSON Schema.
MCP asks for corrected inputs or explicit integration when it detects this root-object mix-up; project checks flag it for review. An explicitly replaced validator requires its own real request tests. Default validation allows coercion. Enforce strict JSON booleans, extra-field rules and business whitespace checks in request middleware and validators without changing application-wide query conversion.
Additional boundaries verified by business consumers
- Scheduled job recipes generate cron / interval definitions. Handlers derive business input; no queue or payload schema is generated. Verify scheduling with createTestJobScheduler and real Redis.
- Scheduled Jobs derives business input in the handler. Redis trigger markers survive lease release; no queues, retries or execution records are generated.
- Field-level
{ type: "boolean" }and{ enum: ["draft", "published"] }must retain the runtime meaning, rather than becoming objects with type/enum subfields. Each request location still receives a DSL field map, not a whole-object JSON Schema. - For generated login, editing, or image pages, the host must verify business behavior: logout or 401 clears token, legacy storage, data, and editing state; distinguish a committed save from a failed refresh. SSR images can fail before hydration, so check the mounted native image's
complete/naturalWidthas well asonError. These are consumer acceptance responsibilities, not automatic Recipe behavior. - Consume the actual generated API client after it exists; do not invent a source import into absent output. Consumer evidence covers TS/JS, HTTP, OpenAPI, client types and browsers independently of static candidate acceptance.