|
| 1 | +# flet-mcp |
| 2 | + |
| 3 | +MCP (Model Context Protocol) server that gives LLM agents access to Flet examples, documentation, and API reference. |
| 4 | + |
| 5 | +## Installation |
| 6 | + |
| 7 | +```bash |
| 8 | +pip install flet-mcp |
| 9 | +``` |
| 10 | + |
| 11 | +## Building the data files |
| 12 | + |
| 13 | +The MCP server reads a Griffe-introspected `api.json` and (optionally) a |
| 14 | +SQLite index of examples and docs. Build them from inside the flet SDK |
| 15 | +workspace so every Flet extension package (`flet-audio`, `flet-map`, …) is |
| 16 | +importable — the workspace declares them all as members, but you need the |
| 17 | +`mcp-build` dependency group to pick up the build-time deps (`markdownify`, |
| 18 | +`griffe`): |
| 19 | + |
| 20 | +```bash |
| 21 | +cd sdk/python |
| 22 | +uv sync --group mcp-build |
| 23 | +uv run flet mcp build # api.json only |
| 24 | +uv run flet mcp build --examples ./examples # add examples index |
| 25 | +``` |
| 26 | + |
| 27 | +> **Docs index is currently deferred.** The `--docs` flag still expects a mkdocs |
| 28 | +> `search_index.json`, which the site no longer produces after the migration to |
| 29 | +> Docusaurus + Algolia. The `DOCS` tool group stays off by default; rebuilding |
| 30 | +> docs search against Docusaurus is tracked as follow-up work. |
| 31 | +
|
| 32 | +Running the build from elsewhere (a downstream project's venv that only |
| 33 | +installs core `flet`) works too, but the resulting `api.json` will be missing |
| 34 | +controls from every extension package not installed in that venv — the |
| 35 | +indexer logs a "Failed to load" line per missing package and skips it. |
| 36 | + |
| 37 | +## Usage |
| 38 | + |
| 39 | +### Start the MCP server |
| 40 | + |
| 41 | +```bash |
| 42 | +# stdio transport (default, for use with Claude Desktop, Cursor, etc.) |
| 43 | +flet mcp |
| 44 | + |
| 45 | +# HTTP transport |
| 46 | +flet mcp --transport streamable-http --port 8000 |
| 47 | +``` |
| 48 | + |
| 49 | +### Configure in Claude Desktop |
| 50 | + |
| 51 | +Add to your `claude_desktop_config.json`: |
| 52 | + |
| 53 | +```json |
| 54 | +{ |
| 55 | + "mcpServers": { |
| 56 | + "flet": { |
| 57 | + "command": "flet", |
| 58 | + "args": ["mcp"] |
| 59 | + } |
| 60 | + } |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +### List available tools |
| 65 | + |
| 66 | +```bash |
| 67 | +fastmcp list packages/flet-mcp/src/flet_mcp/server.py |
| 68 | +``` |
| 69 | + |
| 70 | +### Call tools from the command line |
| 71 | + |
| 72 | +```bash |
| 73 | +# Search examples |
| 74 | +fastmcp call packages/flet-mcp/src/flet_mcp/server.py search_examples '{"query": "dropdown"}' |
| 75 | + |
| 76 | +# Get full example code |
| 77 | +fastmcp call packages/flet-mcp/src/flet_mcp/server.py get_example '{"example_id": "controls_dropdown_styled"}' |
| 78 | + |
| 79 | +# Get API reference for any symbol (control, service, type, event, enum) |
| 80 | +fastmcp call packages/flet-mcp/src/flet_mcp/server.py get_api '{"name": "TextField"}' |
| 81 | + |
| 82 | +# Find an icon |
| 83 | +fastmcp call packages/flet-mcp/src/flet_mcp/server.py find_icon '{"query": "settings"}' |
| 84 | + |
| 85 | +# Search large enums |
| 86 | +fastmcp call packages/flet-mcp/src/flet_mcp/server.py search_enum_members '{"name": "Icons", "query": "arrow"}' |
| 87 | + |
| 88 | +# Get CLI help |
| 89 | +fastmcp call packages/flet-mcp/src/flet_mcp/server.py get_cli_help '{"command": "run"}' |
| 90 | +``` |
| 91 | + |
| 92 | +### Use with Pydantic AI |
| 93 | + |
| 94 | +```python |
| 95 | +from pydantic_ai import Agent |
| 96 | +from pydantic_ai.toolsets import MCPToolset |
| 97 | +from flet_mcp import mcp |
| 98 | + |
| 99 | +agent = Agent("anthropic:claude-sonnet-4-6", toolsets=[MCPToolset(mcp)]) |
| 100 | +result = agent.run_sync("Create a Flet app with a login form") |
| 101 | +``` |
| 102 | + |
| 103 | +### Use in-process via a FastMCP client |
| 104 | + |
| 105 | +The exported `mcp` is a `FastMCP` instance, so a custom agent can talk to it |
| 106 | +in-process (no subprocess, no transport) by handing it to a `fastmcp.Client`. |
| 107 | +Set the `FLET_MCP_ENABLE_*` env vars before importing `flet_mcp` so the desired |
| 108 | +tool groups register. The client deserializes structured results onto `.data`: |
| 109 | + |
| 110 | +```python |
| 111 | +import asyncio |
| 112 | +from fastmcp import Client |
| 113 | +from flet_mcp import mcp |
| 114 | + |
| 115 | +async def main(): |
| 116 | + async with Client(mcp) as client: |
| 117 | + api = (await client.call_tool("get_api", {"name": "TextField"})).data |
| 118 | + print(api["kind"], api["package"], len(api["properties"])) |
| 119 | + |
| 120 | +asyncio.run(main()) |
| 121 | +``` |
| 122 | + |
| 123 | +## Tools |
| 124 | + |
| 125 | +Tools are organized into groups that can be toggled at server startup. Defaults |
| 126 | +focus on the hallucination-reduction starter set: **API** and **icons** are on; |
| 127 | +**examples**, **docs**, and **CLI** are off. |
| 128 | + |
| 129 | +| Group | Default | Tools | |
| 130 | +|---|---|---| |
| 131 | +| `API` | on | `list_controls`, `get_api`, `get_enum`, `search_enum_members`, `enum_has_member` | |
| 132 | +| `ICONS` | on | `find_icon` | |
| 133 | +| `EXAMPLES` | off | `search_examples`, `get_example` | |
| 134 | +| `DOCS` | off | `search_docs`, `get_doc` | |
| 135 | +| `CLI` | off | `get_cli_help` | |
| 136 | + |
| 137 | +| Tool | Description | |
| 138 | +|------|-------------| |
| 139 | +| `list_controls` | Browse controls and services, with optional filtering | |
| 140 | +| `get_api` | Get the API reference for a class by name — looks across controls, services, dataclass types (ButtonStyle, Padding, ...), and event classes. Async methods are marked `"async": true`; every entry carries a `"package"` field naming the pip-installable source package (`"flet"` = core, anything else needs adding to deps). | |
| 141 | +| `get_enum` | Get enum members | |
| 142 | +| `search_enum_members` | Search large enums (Icons, CupertinoIcons) | |
| 143 | +| `enum_has_member` | Check if an enum value exists | |
| 144 | +| `find_icon` | Search Material and Cupertino icons by keyword | |
| 145 | +| `search_examples` | Search example projects by keyword | |
| 146 | +| `get_example` | Get full source code for an example | |
| 147 | +| `search_docs` | Search documentation by keyword | |
| 148 | +| `get_doc` | Get full content of a doc section | |
| 149 | +| `get_cli_help` | Get structured CLI command options | |
| 150 | + |
| 151 | +### Toggling groups |
| 152 | + |
| 153 | +Each group is gated by an environment variable read at server startup: |
| 154 | + |
| 155 | +| Variable | Default | Effect | |
| 156 | +|---|---|---| |
| 157 | +| `FLET_MCP_ENABLE_API` | `1` | Register the API tool group | |
| 158 | +| `FLET_MCP_ENABLE_ICONS` | `1` | Register `find_icon` | |
| 159 | +| `FLET_MCP_ENABLE_EXAMPLES` | `0` | Register example search/get tools | |
| 160 | +| `FLET_MCP_ENABLE_DOCS` | `0` | Register docs search/get tools | |
| 161 | +| `FLET_MCP_ENABLE_CLI` | `0` | Register `get_cli_help` | |
| 162 | + |
| 163 | +Accepted truthy values: `1`, `true`, `yes` (case-insensitive). The active |
| 164 | +groups are also surfaced in the server's `initialize` instructions, so MCP |
| 165 | +clients that forward those instructions to the model (e.g. Pydantic AI's |
| 166 | +`MCPToolset(..., include_instructions=True)`) keep the model's guidance |
| 167 | +in sync with what's actually registered. |
| 168 | + |
| 169 | +Examples: |
| 170 | + |
| 171 | +```bash |
| 172 | +# Default starter surface (API + icons only) |
| 173 | +flet mcp |
| 174 | + |
| 175 | +# Add examples and docs once their indexes have been built |
| 176 | +FLET_MCP_ENABLE_EXAMPLES=1 FLET_MCP_ENABLE_DOCS=1 flet mcp |
| 177 | + |
| 178 | +# Narrow further: API tools only, drop icons |
| 179 | +FLET_MCP_ENABLE_ICONS=0 flet mcp |
| 180 | +``` |
| 181 | + |
| 182 | +Note: enabling `EXAMPLES` only registers the tools — you also need to populate |
| 183 | +the SQLite index by running `flet mcp build --examples <path>`. Without an index |
| 184 | +the tools register cleanly but return empty results. `DOCS` is deferred (see |
| 185 | +"Building the data files" above): the tools register and degrade gracefully to |
| 186 | +empty results, but no docs index is built yet. |
0 commit comments