Skip to main content
This guide covers migrating schemas from v1.2.0 to v2.0.0 format. The FlowMCP core v2.0.0 supports both formats during a transition period. Legacy v1.2.0 format will be deprecated in v3.0.0.
The full migration specification is maintained at github.com/FlowMCP/flowmcp-spec. This page provides a practical walkthrough.

Schema Categories

Existing schemas fall into three categories based on migration effort:
Category% of SchemasMigration EffortDescription
Pure declarative~60%AutomaticNo handlers, no imports. Only URL construction and parameters.
With handlers~30%Semi-automaticHas preRequest/postRequest handlers but no imports.
With imports~10%Manual reviewImports shared data that must become shared list references.

Migration Steps

1

Wrap existing fields in main block

The biggest structural change — fields move into a main export, and handlers become a separate factory function.Before (v1.2.0):
export const schema = {
    namespace: 'etherscan',
    name: 'SmartContractExplorer',
    flowMCP: '1.2.0',
    root: 'https://api.etherscan.io/v2/api',
    requiredServerParams: [ 'ETHERSCAN_API_KEY' ],
    routes: { /* ... */ },
    handlers: { /* ... */ }
}
After (v2.0.0):
export const main = {
    namespace: 'etherscan',
    name: 'SmartContractExplorer',
    version: '2.0.0',
    root: 'https://api.etherscan.io/v2/api',
    requiredServerParams: [ 'ETHERSCAN_API_KEY' ],
    requiredLibraries: [],
    routes: { /* ... */ }
}

export const handlers = ( { sharedLists, libraries } ) => ({
    /* ... */
})
Key changes:
  • Two separate named exports: main (static) and handlers (factory function)
  • flowMCP: '1.2.0' becomes version: '2.0.0'
  • handlers is now a factory function receiving { sharedLists, libraries }
  • New field requiredLibraries declares needed npm packages
  • Zero import statements
2

Update version field

BeforeAfter
flowMCP: '1.2.0'version: '2.0.0'
The version field moves inside main and follows semver starting with 2..
3

Convert imports to shared list references

Before (v1.2.0):
import { evmChains } from '../_shared/evm-chains.mjs'

export const schema = {
    namespace: 'etherscan',
    handlers: {
        getContractAbi: {
            preRequest: async ( { struct, payload } ) => {
                const chain = evmChains
                    .find( ( c ) => c.alias === payload.chainName )
                // ...
            }
        }
    }
}
After (v2.0.0):
export const main = {
    namespace: 'etherscan',
    sharedLists: [
        { ref: 'evmChains', version: '1.0.0' }
    ],
    routes: { /* ... */ }
}

export const handlers = ( { sharedLists } ) => ({
    getContractAbi: {
        preRequest: async ( { struct, payload } ) => {
            const chain = sharedLists.evmChains
                .find( ( c ) => c.alias === payload.chainName )
            return { struct, payload }
        }
    }
})
Key changes:
  • Remove import statement entirely (zero imports policy)
  • Add sharedLists reference in main
  • Access list data via sharedLists.evmChains (injected by factory function)
4

Add output schemas (optional but recommended)

New in v2.0.0 — declare expected response shapes:
routes: {
    getContractAbi: {
        // ... existing fields ...
        output: {
            mimeType: 'application/json',
            schema: {
                type: 'object',
                properties: {
                    abi: { type: 'string', description: 'Contract ABI as JSON string' }
                }
            }
        }
    }
}
Optional in v2.0.0, will become recommended in v2.1.0.
5

Run security scan

flowmcp validate --security <schema-path>
Verifies no forbidden patterns, JSON-serializable main, handler constraints met, shared list references valid.
6

Run full validation

flowmcp validate <schema-path>
Checks required fields, namespace format, version format, route count (max 8), parameter definitions, output schema validity.

Automatic Migration Tool

A CLI command assists with migration:
flowmcp migrate <schema-path>
The tool:
  1. Reads the v1.2.0 schema
  2. Wraps fields in main block
  3. Updates version field
  4. Detects imports and suggests shared list conversions
  5. Writes the v2.0.0 schema to <name>.v2.mjs
  6. Runs validation on the new file
The migration tool does not auto-convert imports. It flags them and creates TODO comments:
// TODO: Convert import to shared list reference
// Original: import { evmChains } from '../_shared/evm-chains.mjs'
// Suggested: main.sharedLists: [{ ref: 'evmChains', version: '1.0.0' }]

Backward Compatibility

Featurev1.2.0 Schemav2.0.0 Schema
Core v1.x runtimeSupportedNot supported
Core v2.0 runtimeSupported (legacy mode)Supported
Core v3.0 runtime (future)DeprecatedSupported
Legacy mode in Core v2.0:
  • Detects v1.2.0 format (no main wrapper, has flowMCP field)
  • Internally wraps in main block at load-time
  • Emits deprecation warning: WARN: Schema uses v1.2.0 format. Run "flowmcp migrate <path>" to upgrade.
  • All features work except: shared list references, output schema, groups, async

Common Migration Issues

IssueCauseFix
SEC001: Forbidden pattern "import"Import statement still presentConvert to sharedLists reference
VAL003: "flowMCP" is not a valid fieldOld version fieldChange to version inside main
VAL007: Route count exceeds 8v1.2.0 allowed 10 routesSplit schema into two files
VAL012: Handler references undefined routeRoute name mismatch after refactorAlign handler keys with route keys

Migration Checklist

Per schema:
  • Fields wrapped in main block
  • flowMCP: '1.2.0' changed to version: '2.0.0' inside main
  • handlers at top level (sibling of main)
  • All import statements removed
  • Imported data converted to sharedLists references
  • Handler code uses sharedLists via factory injection
  • requiredLibraries declared (can be empty [])
  • Security scan passes (flowmcp validate --security)
  • Full validation passes (flowmcp validate)
  • All routes still functional (manual or automated test)