Building a Quick App on the Migrator MCP Connector
This document is the build specification you hand to Amazon Quick so it can
generate a web app on top of the migrator MCP connector. You do not write
the front-end yourself — you register the connectors described below, then give
Quick these instructions and it produces the app.
The connector and action IDs below are shown as placeholders
(<MIGRATOR_MCP_CONNECTOR_ID>, <PREVIEW_ACTION_ID>, <MIGRATE_ACTION_ID>,
<SLACK_CONNECTOR_ID>). Replace them with the IDs from your own registered
connectors. See the main README
for how to register the MCP connector against the AgentCore runtime.
Resource-driven model. The migrator promotes individual resources — a
resource type (agent, connector, or knowledge_base) selected by
id, by name, or all. Spaces are not created or linked, and no
resource-to-Space linkages are produced. The tool names are
preview_migration and migrate_resources.
Overview
A web app that migrates AWS Quick Suite resources (Chat Agents, Action
Connectors, and S3 Knowledge Bases) across AWS accounts using an MCP connector,
with Slack notifications and migration history persistence. Selection is
resource-driven: pick a resource type and select by id, by name, or all. Spaces
are not part of the model.
Prerequisites / Integrations to Register
Before writing any code, register these two ACTION integrations:
1. Migration MCP Connector
Integration Key:
Integration Type: ACTION
Action IDs: ["", ""]
Description: "Invoke Quick Suite resource migration actions — preview_migration (scan) and migrate_resources across accounts"
Permission Level: WRITE (because migrate creates resources)
2. Slack Connector
Integration Key:
Integration Type: ACTION
Action IDs: ["ChatPostMessage"]
Description: "Send Slack notification to channel after migration completes"
Permission Level: WRITE
Architecture
webapp/src/
├── App.tsx (Main orchestrator — state management, API calls, tab routing)
├── main.tsx (Entry point — DO NOT MODIFY)
└── components/
├── MigrationForm.tsx (Input form with source/target accounts, resource type, selection, region, advanced options)
├── MigrationResults.tsx (Results display: stat cards, resource tables, raw JSON viewer)
├── LoadingScreen.tsx (Animated loading indicator with step progress)
├── ConfirmationModal.tsx (Modal to confirm migration before executing)
└── MigrationHistory.tsx (History tab — loads past migrations from shared App Storage)
Prompt / Instructions to Reproduce
Build a Quick Migrator web app with the following functionality:
Core Features:
Migration Form (MigrationForm.tsx)
Fields: Source Account ID (12-digit), Target Account ID (12-digit), Resource Type (agent | connector | knowledge_base; for preview also "all"), Search By (id | name | all, default "all"), Value (the id or name to match; required when Search By is id or name, ignored when "all"), Region (default "us-east-1")
Collapsible "Advanced Options" section with: Source Environment (default "dev"), Target Environment (default "prod"), QuickSight Service Role (default "aws-quicksight-service-role-v0")
Two buttons: "Preview" (requires only source) and "Start Migration" (requires source + target + a concrete resource type)
Info cards at the bottom showing what gets migrated: Chat Agents, Action Connectors, Knowledge Bases
Clean purple gradient design theme
Preview Action — Calls the MCP connector to scan the source account and display an inventory of resources found without making any changes
Connector ID:
Action ID:
Arguments: { source_account_id, resource_type, search_by, value, region }
Migrate Action — After user confirms via modal, calls the migrate action to create resources in the target account
Action ID:
Arguments: { source_account_id, target_account_id, resource_type, search_by, value, region, source_env, target_env, qs_service_role }
Confirmation Modal (ConfirmationModal.tsx)
Shows source → target accounts, resource type, selection (search_by + value), and region
Note: "Agents are recreated with their Action Connectors attached (remapped to the target account) but with no Space attachment. Connectors carry placeholder secrets and must be re-authenticated in the target."
No Space or "manual linkage" language anywhere
Loading Screen (LoadingScreen.tsx)
Spinning animation with step indicators (Connecting to MCP server → Resolving/Scanning resources → Creating/Building inventory)
Different messaging for preview vs. migrate
Results Display (MigrationResults.tsx)
Stat cards showing counts: Chat Agents, Action Connectors, Knowledge Bases, S3 Buckets
Resource tables with columns: Name, ID, Status (for agents/connectors/KBs)
Bucket table with columns: Bucket Name, Environment, Status
Skipped Permissions section — renders the skipped_permissions block from the response (principals that could not be resolved to a registered user in the target account), as cards or a table: Resource, Principal, Reason
No Space linkages: the migrator does not create or report resource-to-Space relationships, so there is no linkages section
Copy All button for the skipped-permissions list
Collapsible Raw JSON viewer (always available via Show/Hide toggle)
"← New Migration" button to reset
Preview banner when showing preview results
Slack Notification — Automatically sent after successful migration
Connector ID:
Action: ChatPostMessage
Channel:
Message: Markdown formatted with source/target accounts, region, resource type, and migrated resources (agents, connectors, KBs), plus any skipped permissions
Status indicator in results header (sending/sent/failed)
Migration History (MigrationHistory.tsx)
Tab-based navigation: "🚀 Migrate" and "📜 History"
Stores each migration in shared App Storage (table: migration-history)
Each record includes: timestamp, source, target, region, resource type, search_by, value, all resource arrays, skipped permissions, slack notification status
Expandable cards showing full details per migration
Empty state, loading state, error state with retry
Technical Requirements:
Timeout wrapper: All invokeAction calls wrapped in a 2-minute (120000ms) timeout using a withTimeout helper that throws a descriptive error if exceeded
MCP response unwrapping: A unwrapMcpResponse function that:
Checks for mcpInvokeActionError envelope and extracts text content error messages
Extracts text from mcpInvokeActionOutput.content[].textContent.text
Throws on empty response
Parses JSON and throws descriptive error on parse failure (shows first 300 chars of raw)
Data parsing: A parseMigrationData function that handles nested result strings (sometimes the API returns { result: "JSON string" }), checks multiple locations for resource data (migrated, inventory, or root)
Error handling: Catch QuickIntegrationError and display message as-is; other errors show generic message
Storage errors: Catch PageStorageError for history operations
All resource name fields are extracted with fallback chains (e.g., a.name || a.agent_id, c.name || c.connector_id, k.name || k.knowledge_base_id)
Bucket fields: Use bucket for name, env for environment
No Space or manual-linkage language anywhere in the app
App Storage: Use putSharedItem / listSharedItems with table name migration-history
Design / Styling:
Purple gradient theme (#667eea → #764ba2)
Font: system font stack (-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, ...)
Light background: linear-gradient(180deg, #f8fafc 0%, #eef2ff 100%)
Rounded cards (12–20px radius), soft shadows
All inline styles (no external CSS files)
Responsive with max-widths: form 680px, results 860px, loading 500px
Tab bar with pill-style active indicator
Status badges with colored backgrounds (green for success, amber for sending, red for errors)
Key Constants
const MIGRATOR_CONNECTOR = '';
const PREVIEW_ACTION = '';
const MIGRATE_ACTION = '';
const SLACK_CONNECTOR = '';
const HISTORY_TABLE = 'migration-history';
const ACTION_TIMEOUT_MS = 120000;
Imports Required
// App.tsx
import { quickSuiteClient, QuickIntegrationError, putSharedItem, PageStorageError } from '@amzn/quick-pages-runtime-lib';
// MigrationHistory.tsx
import { listSharedItems, PageStorageError } from '@amzn/quick-pages-runtime-lib';
API Call Patterns
MCP Invoke (Preview & Migrate)
quickSuiteClient.invokeAction(MIGRATOR_CONNECTOR, {
ActionId: ACTION_ID,
InvokeActionInput: {
mcpInvokeActionInput: {
arguments: JSON.stringify({ / params / }),
},
},
});
// Preview arguments: { source_account_id, resource_type, search_by, value, region }
// Migrate arguments: { source_account_id, target_account_id, resource_type, search_by, value, region, source_env, target_env, qs_service_role }
Slack Notification
quickSuiteClient.invokeAction(SLACK_CONNECTOR, {
ActionId: 'ChatPostMessage',
InvokeActionInput: {
mcpInvokeActionInput: {
arguments: JSON.stringify({
channel: '',
markdown_text: message,
}),
},
},
});
State Flow
User fills form → clicks Preview → Loading screen → Results (isPreview=true)
User fills form → clicks Start Migration → Confirmation Modal → Confirm → Loading screen → Results (isPreview=false) → Auto Slack notification → Save to history
User clicks ← New Migration → Back to form
User clicks 📜 History tab → Loads from App Storage → Expandable cards