flutter-mcp-toolkit-custom-tools
Use this skill when the agent exposes app-specific surfaces by registering custom MCP tools and resources inside the Flutter app (mcp_toolkit dynamic registry — AgentCallEntry, bootstrapFlutter additionalEntries / addEntries). Covers tool vs resource vs evaluate-expression, Map-based handlers, schema strictness, discovery via fmt_list_client_tools_and_resources, fmt_client_tool, fmt_client_resource, and lifecycle pitfalls.
Works with
---
name: flutter-mcp-toolkit-custom-tools
description: Use this skill when the agent exposes app-specific surfaces by registering custom MCP tools and resources inside the Flutter app (mcp_toolkit dynamic registry — AgentCallEntry, bootstrapFlutter additionalEntries / addEntries). Covers tool vs resource vs evaluate-expression, Map-based handlers, schema strictness, discovery via fmt_list_client_tools_and_resources, fmt_client_tool, fmt_client_resource, and lifecycle pitfalls.
license: MIT
---
<!-- @FMT_MODE_PRELUDE -->
# Custom MCP Toolkit Tools & Resources (Dynamic Registry)
Use this when bundled MCP tools (screenshot, semantic snapshot, tap, …) are not enough and you need **app-specific** read surfaces or actions — e.g. cart totals, feature flags, curated debug snapshots of internal state. Entries are registered **in the Flutter process** and exposed to the agent through the **dynamic registry**.
> **Migration:** The legacy call-entry type was removed in intentcall Phase 6b. Use **`AgentCallEntry`** or **`mcpToolkitTool` / `mcpToolkitResource`**. See **`flutter-mcp-toolkit-intentcall-migration`**.
> **Boundary:** Change app discovery, Flutter VM-service extensions, or
> app-owned debug surfaces here. Change canonical registry/session semantics,
> schema policy, platform projection, or publish behavior in the upstream
> IntentCall repository.
## Pick the right primitive
| Need | Use |
|------|-----|
| One-off read of a simple value | **`fmt_evaluate_dart_expression`** (no app code change). |
| Stable **read-only** payload (diagnostics, JSON snapshot, “current route”) | **`AgentCallEntry.resource`** + **`fmt_client_resource`**. Prefer resources when the contract is “GET-like” and idempotent. |
| Parameterized or mutating action, or reusable named operation | **`AgentCallEntry.tool`** + **`fmt_client_tool`**. |
## Handler signatures
### Native `AgentCallEntry` (preferred for new code)
Handlers receive **`AgentArguments`** (`Map<String, Object?>`) and return **`AgentResult`**:
```dart
import 'package:mcp_toolkit/mcp_toolkit.dart';
final tool = AgentCallEntry.tool(
namespace: 'app',
name: 'cart_get_snapshot',
description: 'Return current cart total and items for a user.',
inputSchema: const {
'type': 'object',
'additionalProperties': false,
'properties': {
'userId': {'type': 'string'},
},
'required': ['userId'],
},
handler: (final args) async {
final userId = args['userId']?.toString() ?? '';
final cart = CartRepository.instance.forUser(userId);
return AgentResult.success(
message: 'ok',
data: {
'total': cart.total,
'items': cart.items.map((final i) => i.toJson()).toList(),
},
);
},
);
await MCPToolkitBinding.instance.addEntries(entries: {tool});
```
### Legacy `MCPToolDefinition` + `MCPCallResult` (bridge)
Built-in toolkits still use **`mcpToolkitTool`** / **`mcpToolkitResource`** to adapt
`Map<String, String>` service-extension handlers:
```dart
final tool = mcpToolkitTool(
namespace: 'app',
handler: (final request) async {
final userId = request['userId'] ?? '';
return MCPCallResult(
message: 'ok',
parameters: {'userId': userId},
);
},
definition: MCPToolDefinition(
name: 'cart_get_snapshot',
description: 'Return current cart total and items for a user.',
inputSchema: ObjectSchema(
properties: {
'userId': StringSchema(),
},
required: ['userId'],
),
),
);
```
- Tool arguments on the wire are **strings** keyed by schema property names — parse with `int.tryParse`, `jsonDecode`, etc.
- Do **not** use `request.arguments` on the app side.
Prefer **`MCPToolkitBinding.instance.bootstrapFlutter(additionalEntries: { ... }, runApp: ...)`** so tools/resources register in one place with zone/error setup.
Register **once** at bootstrap — not inside `build`, not per-widget `initState`.
## Custom resources
```dart
final resource = AgentCallEntry.resource(
namespace: 'app',
name: 'app_cart_digest',
description: 'Compact cart summary for agents (read-only).',
mimeType: 'application/json',
handler: (final args) async => AgentResult.success(
message: 'Cart digest',
data: {
'itemCount': CartRepository.instance.visibleCount,
'currency': CartRepository.instance.currencyCode,
},
),
);
```
Or via bridge:
```dart
mcpToolkitResource(
namespace: 'app',
definition: MCPResourceDefinition(
name: 'app_cart_digest',
description: 'Compact cart summary for agents (read-only).',
mimeType: 'application/json',
),
handler: (final request) async => MCPCallResult(
message: 'Cart digest',
parameters: {'itemCount': 3},
),
),
```
- **`name`** must be `snake_case`. Published resource URIs follow **`visual://localhost/...`** conventions; agents use **`fmt_client_resource`** and listings from **`fmt_list_client_tools_and_resources`**.
## Schema rules (tools)
The MCP server enforces strict JSON Schema:
- Prefer **`additionalProperties: false`** unless you intentionally accept arbitrary keys.
- Mark **`required`** for anything the handler reads unconditionally.
- **`AgentResult.data`** / **`MCPCallResult.parameters`** must be JSON-serializable.
## Discovery from the agent side
1. **`fmt_list_client_tools_and_resources`** — enumerate app-registered tools and resources.
2. **`fmt_client_tool`** — invoke a dynamic tool by name with JSON args.
3. **`fmt_client_resource`** — fetch a registered resource URI from the listing.
If something should appear but does not: confirm **`addEntries`** completed (**`await`**), then hot **restart**.
## Lifecycle gotchas
- **Hot reload** + **`addEntries`** from widget code → duplicate registrations. Register once in **`main()` / bootstrap**.
- **Debug mode only** — release builds do not expose VM service extensions.
- **Naming**: flat global namespace per app — prefix tools/resources (`cart_`, `flags_`, `nav_`).
## When the agent authors surfaces for the user’s app
1. Ensure **`mcp_toolkit`** is in **`pubspec.yaml`**.
2. Add **`lib/mcp_tools/<domain>_surfaces.dart`** returning **`Set<AgentCallEntry>`** or calling **`addEntries`** once.
3. Wire from **`bootstrapFlutter(..., additionalEntries: ...)`** — never from **`StatefulWidget` lifecycle**.
4. Tight schemas; hot **restart**; then **`fmt_list_client_tools_and_resources`** before first client invoke.
## Safety and scope
- Treat handlers as **powerful debug hooks**: avoid secrets, unchecked IO.
- Keep handlers thin: delegate to existing app services.
## Common traps
- Mixing **`AgentArguments`** with **`Map<String, String>`** — pick one API (native vs `mcpToolkitTool`).
- Missing **`await`** on **`addEntries`** → race before discovery.
- **`inputSchema`** out of sync with the handler → agents trust the schema; update both.
## Related
- **`flutter-mcp-toolkit-intentcall-migration`** — CLI migrator, breaking upgrade
- **`flutter-mcp-toolkit-guide`** → inspect / control / debug skills
- Repository **`ARCHITECTURE.md`** → “Dynamic Registry Architecture”More Mobile skills
animation-vocabulary
emilkowalski/skills
Reverse-lookup glossary that turns a vague description of a web animation or motion effect into its exact term ("the bouncy thing when a popover opens" → Pop in; "the iOS rubber-band scroll" → Rubber-banding). Use when the user asks "what's it called when…", or describes a motion effect without knowing its name and wants the right word to prompt an AI or designer with. For naming an effect, not designing or building one.
cross-border-ecommerce
nexscope-ai/ecommerce-skills
Cross-border e-commerce expansion advisor. Scores target markets on 8 weighted dimensions (market size, ecommerce penetration, competition, regulatory complexity, logistics infrastructure, payment ecosystem, cultural distance, IP protection), compares 5 fulfillment models with cost and transit data, provides country-by-country tax/duty compliance guides (EU VAT/IOSS, UK VAT, US sales tax, CA GST, AU GST, JP consumption tax), maps local payment preferences by market, and builds a phased expansion roadmap. No API key required.
developing-genkit-dart
firebase/agent-skills
Generates code and provides documentation for the Genkit Dart SDK. Use when the user asks to build AI agents in Dart, use Genkit flows, or integrate LLMs into Dart/Flutter applications.

