LogoSkills

mcp-toolkit

App-internal Flutter automation via dynamically-registered MCP tools (mcp_flutter wrapper).

ํ•ญ๋ชฉ๋‚ด์šฉ
Invoke/mcp-toolkit
Aliases/mcp-flutter, /in-app
Categorycocode-flutter
Complexityhigh
MCP Serversmcp_flutter

/mcp-toolkit โ€” ์•ฑ ์†์„ ์ง์ ‘ ์กฐ์ž‘ํ•˜๋Š” ๋ฆฌ๋ชจ์ปจ#

ํ•œ๋งˆ๋””๋กœ#

์‹คํ–‰ ์ค‘์ธ Flutter ์•ฑ์˜ ๊ฒ‰(ํ™”๋ฉด ํƒญยท์Šคํฌ๋ฆฐ์ƒท)์ด ์•„๋‹ˆ๋ผ ์†(๋ฐ์ดํ„ฐยท์ƒํƒœยท์„ค์ •๊ฐ’)์„ ์ง์ ‘ ๋งŒ์ง€๋Š” ๋ฆฌ๋ชจ์ปจ์ž…๋‹ˆ๋‹ค. ์—ฐ๊ทน ๋ฌด๋Œ€ ๋’ค์—์„œ ์†Œํ’ˆ์„ ๋ฏธ๋ฆฌ ์„ธํŒ…ํ•˜๊ณ  ์กฐ๋ช… ์Šค์œ„์น˜๋ฅผ ์ง์ ‘ ์ผœ๋Š” ์Šคํƒœํ”„์ฒ˜๋Ÿผ, AI๊ฐ€ ์•ฑ ๋‚ด๋ถ€๋ฅผ ์›ํ•˜๋Š” ์ƒํƒœ๋กœ ๋ฐ”๋กœ ๋ฐ”๊ฟ” ๋†“์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ฐ€ยท์–ธ์ œ ์“ฐ๋‚˜์š”#

  • AI ์—์ด์ „ํŠธ๊ฐ€ ์‹คํ–‰ ์ค‘์ธ Flutter ์•ฑ์˜ ๋‚ด๋ถ€ ์ƒํƒœ(BLoC, DB, ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ)๋ฅผ ์ง์ ‘ ๋ฐ”๊ฟ”์•ผ ํ•  ๋•Œ
  • ๋‹จ์ˆœํžˆ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์žฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์šด ์ƒํ™ฉ(์˜ˆ: "๋ฐ์ดํ„ฐ๊ฐ€ 10๊ฐœ ์žˆ๋Š” ํ™”๋ฉด", "๋„คํŠธ์›Œํฌ๊ฐ€ ๋Š๊ธด ์˜ค๋ฅ˜ ํ™”๋ฉด")์„ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ

๋ฌด์—‡์„ ํ•ด์ฃผ๋‚˜์š”#

  • ์•ฑ์— ๊ฒ€์‚ฌยท์กฐ์ž‘์šฉ ๋„๊ตฌ๋ฅผ ์‹ฌ์–ด ์ฃผ๊ณ (setup), ์ง€๊ธˆ ์•ฑ์ด ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋Š”์ง€ ๋ชฉ๋ก์œผ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค(list-tools).
  • ๋ฏธ๋ฆฌ ์ค€๋น„๋œ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์•ฑ์— ์ฑ„์›Œ ๋„ฃ๊ณ  ์›ํ•˜๋Š” ํ™”๋ฉด์œผ๋กœ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค(seed).
  • ํŠน์ • ์ƒํƒœ๊ฐ’(BLoC)์ด ์ง€๊ธˆ ์–ด๋–ค์ง€ ๊ทธ๋Œ€๋กœ ์ฐ์–ด์„œ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค(dump-bloc).
  • ์—ฌ๋Ÿฌ ๋™์ž‘์„ ์ •ํ•ด์ง„ ์ˆœ์„œ๋Œ€๋กœ ์ž๋™ ์‹คํ–‰ํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค(YAML ํŒŒ์ผ)๋ฅผ ํ•œ ๋ฒˆ์— ๋Œ๋ฆฝ๋‹ˆ๋‹ค(scenario).
  • ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” .claude/docs/mcp-toolkit/<run_id>/ ํด๋”์— ๊ธฐ๋ก์œผ๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ์“ฐ๋‚˜์š”#

# ์ฒ˜์Œ ํ•œ ๋ฒˆ: ์•ฑ์— ๋„๊ตฌ๋ฅผ ์„ค์น˜ยท๋“ฑ๋ก
/mcp-toolkit setup

# ์ง€๊ธˆ ์•ฑ์ด ์“ธ ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ ๋ชฉ๋ก ํ™•์ธ
/mcp-toolkit list-tools

# ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฑ„์šฐ๊ณ  ํ•ด๋‹น ํ™”๋ฉด์œผ๋กœ ์ด๋™
/mcp-toolkit seed --fixture=feed_with_10 --route=feed

# ํŠน์ • ์ƒํƒœ๊ฐ’(FeedBloc)์„ ๊ทธ๋Œ€๋กœ ์ฐ์–ด๋ณด๊ธฐ
/mcp-toolkit dump-bloc --type=FeedBloc

# ์ •ํ•ด์ง„ ์ˆœ์„œ๋ฅผ ๋‹ด์€ ์‹œ๋‚˜๋ฆฌ์˜ค ํŒŒ์ผ ์‹คํ–‰
/mcp-toolkit scenario --file=test/scenarios/feed_offline_error.yaml
  • seed๋Š” --fixture(์ฑ„์šธ ๋ฐ์ดํ„ฐ)๊ฐ€ ๊ผญ ํ•„์š”ํ•˜๊ณ , --route(์ด๋™ํ•  ํ™”๋ฉด)๋Š” ์„ ํƒ์ž…๋‹ˆ๋‹ค.
  • dump-bloc๋Š” --type(์ƒํƒœ ์ข…๋ฅ˜)์ด ๊ผญ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • scenario๋Š” --file(์‹œ๋‚˜๋ฆฌ์˜ค ํŒŒ์ผ ๊ฒฝ๋กœ)์ด ๊ผญ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์•ˆ์—์„œ ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์ง€๋‚˜์š”#

์ด ๋ช…๋ น์€ ์„ธ ๊ฐœ์˜ ์ธต(์•ฑ ๋‚ด๋ถ€ ์กฐ์ž‘ยท์œ„์ ฏ ํŠธ๋ฆฌยท์‹ค์ œ ํ™”๋ฉด ์บก์ฒ˜)์„ ํ•œ ์ค„๋กœ ์—ฎ์–ด ์ž๋™์œผ๋กœ ๊ตด๋ฆฌ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

  1. ๋จผ์ € ์•ฑ ๋‚ด๋ถ€์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฑ„์›๋‹ˆ๋‹ค.
  2. ์›ํ•˜๋Š” ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๊ณ , ๋„คํŠธ์›Œํฌ๋ฅผ ๋Š๋Š” ๋“ฑ ์›ํ•˜๋Š” ์กฐ๊ฑด์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  3. ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜(marionette) ํ™”๋ฉด์„ ์บก์ฒ˜(pixel-loop)ํ•˜๋Š” ๋™์ž‘์„ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  4. ๋งˆ์ง€๋ง‰์— ํŠน์ • ์ƒํƒœ๊ฐ’์ด ๊ธฐ๋Œ€ํ•œ ๋Œ€๋กœ ๋˜์—ˆ๋Š”์ง€(์˜ˆ: "์˜คํ”„๋ผ์ธ ์˜ค๋ฅ˜" ์ƒํƒœ์ธ์ง€) ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

โš™๏ธ ์ƒ์„ธ ์˜ต์…˜ยท์‹คํ–‰ ๋ช…์„ธ (๊ฐœ๋ฐœ์ž / AI ์—์ด์ „ํŠธ์šฉ)

Subcommands#

SubcommandPurpose
setupInstall MCP server, add mcp_toolkit to the app, register cocode standard tools (commands/mcp-toolkit/setup.md)
list-toolsPrint every dynamic tool the running app currently exposes
seedShortcut to db.seed_fixture + optional nav.go_named
dump-blocShortcut to bloc.dump_state with formatting
scenarioRun a YAML-defined sequence of dynamic tool calls

Quick Start#

# Onboarding
/mcp-toolkit setup

# Inspect what ' s registered
/mcp-toolkit list-tools

# Seed and navigate
/mcp-toolkit seed --fixture=feed_with_10 --route=feed

# Dump a BLoC ' s current state
/mcp-toolkit dump-bloc --type=FeedBloc

# Run a YAML scenario
/mcp-toolkit scenario --file=test/scenarios/feed_offline_error.yaml

YAML Scenario Format#

# test/scenarios/feed_offline_error.yaml
name: feed_offline_error
steps:
  - tool: db.reset
  - tool: db.seed_fixture
    args: { name:  " feed_with_10 "   }
  - tool: nav.go_named
    args: { name:  " feed "   }
  - tool: network.offline
    args: { value: true }
  - external: cc-flutter-marionette:tap
    args: { key:  " refresh_button "   }
  - external: cc-flutter-pixel-loop:capture
    args: { route:  " /feed " , label:  " offline-error "   }
  - tool: network.offline
    args: { value: false }
asserts:
  - tool: bloc.dump_state
    args: { type:  " FeedBloc "   }
    expect: { status:  " offlineError "   }

The scenario runner orchestrates calls across all three layers (mcp_toolkit, marionette, pixel-loop) โ€” that's the whole point of the layered model.

Required Inputs#

SubcommandRequiredOptional
setupโ€”โ€”
list-toolsโ€”--filter
seed--fixture--route, --reset-first
dump-bloc--type--redact-pii=false
scenario--file--output

Output#

.claude/docs/mcp-toolkit/<run_id>/ โ€” see skill SKILL.md for schema.

  • Skill: cc-flutter-mcp-toolkit:mcp-toolkit
  • Templates: cc-flutter-mcp-toolkit:mcp-toolkit/TEMPLATES.md
  • Companion: cc-flutter-marionette:marionette (widget tree)
  • Companion: cc-flutter-pixel-loop:pixel-loop (external pixels)