flextools-mcp 2.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. flextools_mcp-2.3.1.dist-info/METADATA +270 -0
  2. flextools_mcp-2.3.1.dist-info/RECORD +62 -0
  3. flextools_mcp-2.3.1.dist-info/WHEEL +5 -0
  4. flextools_mcp-2.3.1.dist-info/entry_points.txt +3 -0
  5. flextools_mcp-2.3.1.dist-info/licenses/LICENSE +21 -0
  6. flextools_mcp-2.3.1.dist-info/top_level.txt +1 -0
  7. flextoolsmcp/__init__.py +9 -0
  8. flextoolsmcp/__main__.py +9 -0
  9. flextoolsmcp/archive_old_versions.py +159 -0
  10. flextoolsmcp/build_casting_index.py +284 -0
  11. flextoolsmcp/build_embeddings.py +350 -0
  12. flextoolsmcp/build_navigation_graph.py +427 -0
  13. flextoolsmcp/build_reverse_mapping.py +442 -0
  14. flextoolsmcp/casting_helpers.py +236 -0
  15. flextoolsmcp/config.py +234 -0
  16. flextoolsmcp/constants.py +129 -0
  17. flextoolsmcp/extract_patterns.py +305 -0
  18. flextoolsmcp/file_utils.py +144 -0
  19. flextoolsmcp/flexicon_analyzer.py +1913 -0
  20. flextoolsmcp/index/casting_index_liblcm-v11.0.0.json +19116 -0
  21. flextoolsmcp/index/common_patterns_flexicon-v4.1.0.json +2866 -0
  22. flextoolsmcp/index/embeddings/embeddings.npy +0 -0
  23. flextoolsmcp/index/embeddings/faiss.index +0 -0
  24. flextoolsmcp/index/embeddings/metadata.json +37262 -0
  25. flextoolsmcp/index/flexlibs/flexicon_api_v4.1.0.json +76882 -0
  26. flextoolsmcp/index/flexlibs/flexicon_lcm_bridge_v4.1.0.json +83462 -0
  27. flextoolsmcp/index/flexlibs/flexlibs_api_v1.2.8.json +2687 -0
  28. flextoolsmcp/index/flexlibs/flexlibs_lcm_bridge_v1.2.8.json +5591 -0
  29. flextoolsmcp/index/liblcm/liblcm_api_v11.0.0.json +264372 -0
  30. flextoolsmcp/index/navigation_graph_liblcm-v11.0.0.json +28416 -0
  31. flextoolsmcp/index/reverse_mapping_liblcm-v11.0.0.json +7156 -0
  32. flextoolsmcp/json_utils.py +78 -0
  33. flextoolsmcp/liblcm_extractor.py +1098 -0
  34. flextoolsmcp/refresh.py +572 -0
  35. flextoolsmcp/response_utils.py +216 -0
  36. flextoolsmcp/server/__init__.py +162 -0
  37. flextoolsmcp/server/constants.py +93 -0
  38. flextoolsmcp/server/dispatch.py +283 -0
  39. flextoolsmcp/server/handlers/__init__.py +36 -0
  40. flextoolsmcp/server/handlers/_import_helper.py +103 -0
  41. flextoolsmcp/server/handlers/admin.py +728 -0
  42. flextoolsmcp/server/handlers/api.py +1314 -0
  43. flextoolsmcp/server/handlers/catalog.py +242 -0
  44. flextoolsmcp/server/handlers/discovery.py +234 -0
  45. flextoolsmcp/server/handlers/equivalence.py +388 -0
  46. flextoolsmcp/server/handlers/execution.py +2778 -0
  47. flextoolsmcp/server/handlers/utils.py +24 -0
  48. flextoolsmcp/server/headless_report.py +109 -0
  49. flextoolsmcp/server/kernel.py +671 -0
  50. flextoolsmcp/server/models.py +429 -0
  51. flextoolsmcp/server/project_discovery.py +299 -0
  52. flextoolsmcp/server/response_keys.py +278 -0
  53. flextoolsmcp/server/session.py +516 -0
  54. flextoolsmcp/server/skeleton_storage.py +276 -0
  55. flextoolsmcp/server/subprocess_helpers.py +80 -0
  56. flextoolsmcp/server/tool_definitions.py +417 -0
  57. flextoolsmcp/server/undo_subprocess.py +199 -0
  58. flextoolsmcp/server/utils.py +79 -0
  59. flextoolsmcp/server/validators.py +2448 -0
  60. flextoolsmcp/server/versioning.py +320 -0
  61. flextoolsmcp/server/worked_examples.py +368 -0
  62. flextoolsmcp/server.py +906 -0
@@ -0,0 +1,270 @@
1
+ Metadata-Version: 2.4
2
+ Name: flextools-mcp
3
+ Version: 2.3.1
4
+ Summary: MCP server that gives AI assistants searchable LibLCM / FlexLibs / Flexicon API docs for writing FLExTools scripts.
5
+ Author-email: Matthew Lee <matthew_lee@sil.org>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/MattGyverLee/FlexToolsMCP
29
+ Project-URL: Repository, https://github.com/MattGyverLee/FlexToolsMCP
30
+ Project-URL: Issues, https://github.com/MattGyverLee/FlexToolsMCP/issues
31
+ Keywords: mcp,fieldworks,flextools,flexlibs,flexicon,liblcm,linguistics,lexicon
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: Science/Research
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: Microsoft :: Windows
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Topic :: Text Processing :: Linguistic
43
+ Requires-Python: >=3.10
44
+ Description-Content-Type: text/markdown
45
+ License-File: LICENSE
46
+ Requires-Dist: mcp>=1.27.0
47
+ Requires-Dist: anyio>=4.5
48
+ Requires-Dist: httpx>=0.27.1
49
+ Requires-Dist: typing-inspection>=0.4.1
50
+ Requires-Dist: sentence-transformers>=2.2.0
51
+ Requires-Dist: faiss-cpu>=1.7.4
52
+ Requires-Dist: pythonnet>=3.0.0
53
+ Requires-Dist: pydantic>=2.0.0
54
+ Requires-Dist: python-dotenv>=1.0.0
55
+ Requires-Dist: pyflexicon>=4.1.0
56
+ Provides-Extra: dev
57
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
58
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
59
+ Requires-Dist: pre-commit>=4.0.0; extra == "dev"
60
+ Dynamic: license-file
61
+
62
+ # FLExTools MCP
63
+
64
+ An MCP server that enables AI assistants to write FLExTools scripts and directly manipulate FieldWorks lexicon data using natural language.
65
+
66
+ Developed for SIL Global by Matthew Lee in connection with the SIL's AI Integration Advisory Board and the FLExTrans team.
67
+
68
+ ## Quick Overview
69
+
70
+ **What it does:** FLExTools MCP gives AI assistants (Claude, Copilot, Gemini) the knowledge to write FLExTools modules by providing indexed, searchable documentation of LibLCM and FlexLibs APIs.
71
+
72
+ ** Videos **
73
+
74
+ ## Videos
75
+
76
+ **[The MCP Connection: Talking to your Dictinary](https://vimeo.com/showcase/12149678?video=1171396540)**
77
+
78
+ This podcast, for a linguistic audience, gives an overview of using the FLExTools MCP.
79
+
80
+ [![MCP Video Thumbnail](./docs/MCPodcast.png)](https://vimeo.com/showcase/12149678?video=1171396540)
81
+
82
+ **[MCPs for FLEx and FLExTools: LangTech AI Software Engineering CoP](https://www.youtube.com/watch?v=JyNwUbAWYIM)**
83
+
84
+ This presentation, given to an audience of programmers, discusses the background, architecture, and advantages of an MCP, and introduces the FLExTools MCP.
85
+
86
+ [![COP Video Thumbnail](./docs/COP-Thumbnail.png)](https://www.youtube.com/watch?v=JyNwUbAWYIM)
87
+
88
+ **Three ways to use it:**
89
+ 1. Generate legacy modules (FlexLibs stable)
90
+ 2. Generate modern modules (Flexicon with ~1,400 functions)
91
+ 3. Run operations directly on FieldWorks databases using natural language queries
92
+
93
+ **Example:** "Delete any sense with 'q' in the gloss" → AI generates, tests, and runs the operation automatically.
94
+
95
+ ⚠️ **Warning:** Backup your project first - there are no guard-rails.
96
+
97
+ ## Why MCP? Why AI?
98
+
99
+ - **What is an MCP Server?** See [WHY-MCP.md](docs/WHY-MCP.md) - explains the LibLCM complexity problem and why generic AI assistants fail
100
+ - **When is AI useful?** See [WHY-AI.md](docs/WHY-AI.md) - learning curve problems and when manual approaches are better
101
+
102
+ ## Getting Started
103
+
104
+ ### 1. Installation
105
+
106
+ FLExToolsMCP is published on PyPI. The indexed API documentation ships inside
107
+ the package, so there is nothing to clone or build. The one prerequisite is
108
+ FieldWorks/FLExTools, which means **Windows + .NET**.
109
+
110
+ **One-line install (recommended)** — no repo, no manual dependency install:
111
+
112
+ ```bash
113
+ # Claude Code
114
+ claude mcp add flextoolsmcp -- uvx flextoolsmcp
115
+ ```
116
+
117
+ `uvx` (from [uv](https://docs.astral.sh/uv/)) fetches the package and all of its
118
+ dependencies — including [Flexicon](https://pypi.org/project/pyflexicon/), the
119
+ deep FieldWorks wrapper — into an isolated cache and runs the server. Nothing
120
+ else to install. Upgrading FLExToolsMCP re-resolves to the latest compatible
121
+ Flexicon. Prefer a persistent install? `uv tool install flextoolsmcp` or
122
+ `pip install flextoolsmcp`.
123
+
124
+ **Manual MCP config** (Claude Desktop, Cursor, and other tools):
125
+
126
+ ```json
127
+ {
128
+ "mcpServers": {
129
+ "flextoolsmcp": {
130
+ "command": "uvx",
131
+ "args": ["flextoolsmcp"]
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### 2. Connect to Your AI Assistant
138
+ See [SETUP.md](SETUP.md#connecting-to-ai-assistants) for Claude Code, Antigravity, and other tools.
139
+
140
+ **Note:** Each AI tool has different MCP configuration syntax. See SETUP.md for your specific tool.
141
+
142
+ **User data** lives under `~/.flextoolsmcp/` (logs, saved skeletons, cached
143
+ models, and any runtime-refreshed indexes) — it persists across upgrades.
144
+
145
+ ### Developing from source
146
+ ```bash
147
+ git clone https://github.com/MattGyverLee/FlexToolsMCP.git
148
+ cd FlexToolsMCP
149
+ pip install -e ".[dev]" # editable install with dev tools (pulls in Flexicon)
150
+
151
+ # Test it works
152
+ python -c "from flextoolsmcp.server import APIIndex, get_index_dir; i=APIIndex.load(get_index_dir()); print('Loaded', len(i.flexicon.get('entities', {})), 'Flexicon entities')"
153
+ ```
154
+
155
+ ### 3. Updating to New Versions
156
+ See [SETUP.md](SETUP.md#updating-flextoolsmcp) for how to pull new releases.
157
+
158
+ ### 4. Start Using
159
+ See [USAGE.md](USAGE.md) for workflows, tool reference, and examples.
160
+
161
+ ## What's Included
162
+
163
+ ### MCP Tools (16)
164
+
165
+ **Admin & Config:**
166
+ - `flextools_start` - Initialize session, set project and API mode
167
+ - `flextools_manage_config` - Get/set/delete persistent configuration
168
+ - `flextools_get_session_history` - View operation history and undo stack
169
+ - `flextools_undo_last_operation` - Undo the most recent write
170
+ - `flextools_get_module_template` - Get FLExTools module boilerplate
171
+
172
+ **Discovery:**
173
+ - `flextools_search_by_capability` - Find APIs by natural language intent
174
+ - `flextools_get_object_api` - Get full API for an object/operations class
175
+ - `flextools_get_navigation_path` - Find traversal between object types
176
+ - `flextools_find_examples` - Get code examples by operation type
177
+ - `flextools_resolve_property` - Check casting requirements for properties
178
+
179
+ **Catalog:**
180
+ - `flextools_list_categories` - List semantic domains (lexicon, grammar, etc.)
181
+ - `flextools_list_entities_in_category` - List entities in a domain
182
+
183
+ **Module & Execution:**
184
+ - `flextools_start_module` - Interactive wizard for new module
185
+ - `flextools_get_operation_logs` - View logs and pattern recommendations
186
+ - `flextools_run_module` - Execute code with dry-run and write modes
187
+
188
+ ### API Coverage
189
+ - **LibLCM**: 2,295 C# entities
190
+ - **FlexLibs Stable**: ~71 methods
191
+ - **Flexicon**: ~1,400 methods (99% documented, 82% with examples)
192
+
193
+ ### Test-Proven Examples
194
+ ```
195
+ "Remove 'el ' from the beginning of any Spanish gloss"
196
+ "Add an environment named 'pre-y' with the context '/_y'"
197
+ "Delete the entry with lexeme ɛʃːɛr"
198
+ "List entries with "ː" in the headword"
199
+ "Are there any duplicates by gloss (fuzzy match) and POS?"
200
+ ```
201
+
202
+ ## Key Features
203
+
204
+ - **Discovery-first workflow** - the AI assembles modules from indexed building blocks (signatures, navigation skeletons, examples, casting fixes) rather than inventing API calls from training memory. See [USAGE.md](USAGE.md#recommended-workflow).
205
+ - **Automatic index refresh** when you update FieldWorks or libraries
206
+ - **Dry-run mode** to test before writing data
207
+ - **Semantic search** with synonym expansion
208
+ - **Pythonnet casting detection** - warns when you need type conversions
209
+ - **Code examples** extracted from real-world usage
210
+ - **Multiple library versions** supported simultaneously
211
+
212
+ ## Documentation
213
+
214
+ | Document | Purpose |
215
+ |----------|---------|
216
+ | [HISTORY.md](HISTORY.md) | Release notes and version history |
217
+ | [SETUP.md](SETUP.md) | Installation and AI tool configuration |
218
+ | [USAGE.md](USAGE.md) | How to use the MCP, workflows, examples |
219
+ | [DEVELOPMENT.md](DEVELOPMENT.md) | Project structure, architecture, contributing |
220
+ | [docs/WHY-MCP.md](docs/WHY-MCP.md) | Why FieldWorks needs MCP servers |
221
+ | [docs/WHY-AI.md](docs/WHY-AI.md) | When AI is useful for FieldWorks work |
222
+ | [docs/INNOVATIONS.md](docs/INNOVATIONS.md) | Technical innovations in this MCP |
223
+ | [docs/BACKGROUND.md](docs/BACKGROUND.md) | Project history |
224
+
225
+ ## Safety & Limitations
226
+
227
+ ### Safety
228
+ - **Always backup before write operations** - the MCP defaults to dry-run mode
229
+ - Dry run shows what would happen before writing
230
+ - Requires explicit user permission for write operations
231
+
232
+ ### Limitations
233
+ - Cannot control the FLEx GUI (filters, display, etc.)
234
+ - Only manipulates data, not UI state
235
+ - Flexicon still undergoing extensive testing
236
+ - Some Scripture module edge cases recently fixed
237
+
238
+ ## Architecture
239
+
240
+ ```
241
+ User Request -> AI Assistant -> MCP Server -> Indexed APIs
242
+ |
243
+ Generated FLExTools Script or Direct Execution
244
+ |
245
+ FLExTools (IronPython) or Flexicon
246
+ |
247
+ LibLCM (C# data model)
248
+ |
249
+ FieldWorks Database
250
+ ```
251
+
252
+ For technical details, see [DEVELOPMENT.md](DEVELOPMENT.md#architecture).
253
+
254
+ ## License
255
+
256
+ MIT License - See LICENSE file for details
257
+
258
+ ## Contributing
259
+
260
+ Contributions are welcome! Please submit issues and pull requests on GitHub.
261
+
262
+ For development info, see [DEVELOPMENT.md](DEVELOPMENT.md).
263
+
264
+ ## Acknowledgments
265
+
266
+ - The FieldWorks developers (Jason, Ken, Hasso, and team)
267
+ - Craig, the developer of FLExTools and FlexLibs
268
+ - The SIL AI Implementation Advisory Board
269
+ - Ron, Beth and the FLExTrans team
270
+ - My mentors Doug, Jeff, and Jenni at SIL LangTech
@@ -0,0 +1,62 @@
1
+ flextools_mcp-2.3.1.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
2
+ flextoolsmcp/__init__.py,sha256=XSbk7d57HjaxH8oPYBDNE3bNenH9G3jy7Z2xgLBXtCY,258
3
+ flextoolsmcp/__main__.py,sha256=nKbGb0aOaPp7KdlOh7P6hgMQL8svGzx8iU83n34U7tI,179
4
+ flextoolsmcp/archive_old_versions.py,sha256=QabentO9IOx1_BETERPybQtWmPH5UdfeOLVCUKXgwIk,4709
5
+ flextoolsmcp/build_casting_index.py,sha256=65Q68P4RJQr7v4Ko-ttJB1wVHk1MC7-NUlX6Uf2qGYc,10713
6
+ flextoolsmcp/build_embeddings.py,sha256=wman0UsOAgMuUJZs6pcNPYZM6lvX3HUZ-uZouKbB0yA,11409
7
+ flextoolsmcp/build_navigation_graph.py,sha256=8H9q9glaYpsxL5u-aNEJcQtjvQJL8Cs0bMqMvwjGfUY,14062
8
+ flextoolsmcp/build_reverse_mapping.py,sha256=StOgQVIUqWvKWY0ZbrRbKES7lhJMr24JynWyytRngUU,15437
9
+ flextoolsmcp/casting_helpers.py,sha256=DMhzymrrkoE1NK6du6AqYKJ2SXt3VXZ2qV5eFYJMAy0,7104
10
+ flextoolsmcp/config.py,sha256=MfFapEiCT75E1VrAzD6P4BjbQkIBG9wSoupg8GKIViQ,6014
11
+ flextoolsmcp/constants.py,sha256=g1n208dYzeCBLjhY-q0XSw7YlcqPHOSznOjGIROjJ5k,5050
12
+ flextoolsmcp/extract_patterns.py,sha256=lh7Wwxn68qrXRG5GdTAQVI715xKuu341xSIxSf5M4_o,9940
13
+ flextoolsmcp/file_utils.py,sha256=addd38dzKfYHwxzQKXt27yJ36nR8s0HNc5U4nXL47w0,4539
14
+ flextoolsmcp/flexicon_analyzer.py,sha256=HXhdWsrI_A2eAUojZvQFlS4J_ppprcLpohcF2zNBa1I,76281
15
+ flextoolsmcp/json_utils.py,sha256=P0qiu5PVvuVLzROLzHJLxm0vpL4uULQfQ1_mXDdrlqo,2559
16
+ flextoolsmcp/liblcm_extractor.py,sha256=PxpnwnkrHvtoo9JU2KMV1Z7UtC5T_oeMNz3HRyHpJR4,39831
17
+ flextoolsmcp/refresh.py,sha256=wLga4aLycaYKRzPYsB_S04b9tH-PGWGe4bUrlcyp3Ss,19221
18
+ flextoolsmcp/response_utils.py,sha256=06i2cpM8Y4Vev7DsIZ6CGrUKg5Wl3MZkAszwtlRVZpM,7205
19
+ flextoolsmcp/server.py,sha256=rbiC83c2jymCxlF9kMx-RUZpxAYdQvRMErXPCO-bJ6E,34183
20
+ flextoolsmcp/index/casting_index_liblcm-v11.0.0.json,sha256=XOyPBRx7Mr2SC9ZFPPhowiA_gdzpVDFzjg2yGoVtUHE,471212
21
+ flextoolsmcp/index/common_patterns_flexicon-v4.1.0.json,sha256=unckiirNQGFWCklQ4MGrUrlr7u3MlKB9r-0SluJ_kQg,198280
22
+ flextoolsmcp/index/navigation_graph_liblcm-v11.0.0.json,sha256=iJdsHu4GAHFKxGdA7W-AoL8kqDoObcfAvpoU4KAAZn0,648489
23
+ flextoolsmcp/index/reverse_mapping_liblcm-v11.0.0.json,sha256=La0pZ4O5vZM0Tx-wcwYe5albNTIX0iYPA9QlJRTfbC4,192269
24
+ flextoolsmcp/index/embeddings/embeddings.npy,sha256=bVxnTYpAV5uXTF_E6JBYeQyvoZw_O-QnvGr-gw_4lJ0,5479040
25
+ flextoolsmcp/index/embeddings/faiss.index,sha256=s6spp5tydVqJbUmOtZhErVM28jykpMcR8LFZoR159Hk,5478957
26
+ flextoolsmcp/index/embeddings/metadata.json,sha256=K5We7JnhPAfP72RUXX6v578HnUDYLBd920Ih4LZEiSY,2411141
27
+ flextoolsmcp/index/flexlibs/flexicon_api_v4.1.0.json,sha256=SZaaRglzXsHblQ-IfBg-cpy70ON_uUvuG1gyyVwUd5E,3423399
28
+ flextoolsmcp/index/flexlibs/flexicon_lcm_bridge_v4.1.0.json,sha256=kktYw9YjXQzrch60pIC1ZH1IVR7gWWPTQInpmSpXGh0,2273825
29
+ flextoolsmcp/index/flexlibs/flexlibs_api_v1.2.8.json,sha256=QtUHCfFtmvFvHVzeMOWF-AF-UxZRTC5xj6Z7pOuSleg,92170
30
+ flextoolsmcp/index/flexlibs/flexlibs_lcm_bridge_v1.2.8.json,sha256=S4ZbGqY1o93aBKJQs7lYcO9xZQfbSonVRsT3WTlxXw4,158397
31
+ flextoolsmcp/index/liblcm/liblcm_api_v11.0.0.json,sha256=vE5RkscknYPByVAyi65UxcUHBTeAQn0XmFs5OFdv8uo,7899528
32
+ flextoolsmcp/server/__init__.py,sha256=zKfat2VYygcNJ12-6wXFt0LfVWcJAc-bj1_-YaQrIY4,5024
33
+ flextoolsmcp/server/constants.py,sha256=yZkMPnnLimgdlupcrZQvdzczMIoXJLy458nkIwP3CH8,3876
34
+ flextoolsmcp/server/dispatch.py,sha256=K_H0zURsl4HW2vG-zIr_sE4OScaWSF5_RCVBGBTPPmA,10621
35
+ flextoolsmcp/server/headless_report.py,sha256=3SWYAaNNJlAPL-ZI0XLEv_oB-Bs5BDk_YxoEewsOOlc,3250
36
+ flextoolsmcp/server/kernel.py,sha256=QpynrsonQxgh5MNZw5s3cXflfes-en-mReMkJo2zGoE,25182
37
+ flextoolsmcp/server/models.py,sha256=IR1-1iYNd1792io9hiO0qQZlH6VwVOd4j62FolOrp1c,16320
38
+ flextoolsmcp/server/project_discovery.py,sha256=4yW6FrN7_YMhNewPTP8ZVik1312FvZDAGYTvFjIa3pk,10219
39
+ flextoolsmcp/server/response_keys.py,sha256=l-JnNuY_gkspF7ReWCFj8AbH1diDVZaoIv-1lpfGZs8,10023
40
+ flextoolsmcp/server/session.py,sha256=HEGTcKw0Me6_Le-8T-slkzEgRqumWHMTOT0G4Cq3eXM,20804
41
+ flextoolsmcp/server/skeleton_storage.py,sha256=EdEeYMynyq1vgfWXcEnyewLEBLN2b6fOUo8-FRbY9_s,9651
42
+ flextoolsmcp/server/subprocess_helpers.py,sha256=q4dJpzbeAsoP2l6mXmq-zLnVYgRExd7z86X9p30k9BU,2352
43
+ flextoolsmcp/server/tool_definitions.py,sha256=h2m2HBEk5U5Nn6Ak7rclpyfpO8sDYsK3BwTP30r6XBk,17198
44
+ flextoolsmcp/server/undo_subprocess.py,sha256=Xzbt0Dl1zoRK2joXCfjsK3U9ZzsndOBUaoDrtbnE5lg,6230
45
+ flextoolsmcp/server/utils.py,sha256=RGOTuQ9k5E47EWk9sdeyUTTc1mr2TuOSG9nzVw2rMws,2200
46
+ flextoolsmcp/server/validators.py,sha256=ie8xJZ_6vRvs5-bDmSfvgNSF1gxEYpTYVxsRwcYhgHY,106782
47
+ flextoolsmcp/server/versioning.py,sha256=ICN7wf_zfVkP_RgKtsn4adXNlmpz2Wc-BD3ZYgIFwr0,11576
48
+ flextoolsmcp/server/worked_examples.py,sha256=9bEuGwNPDC9TW3C00YDps1jNY98HDqVq9CxYkhbDzsg,15382
49
+ flextoolsmcp/server/handlers/__init__.py,sha256=NYWIroAXv9kYSiqn-UC029UVIdRC-VYUbDE7bvyNLUs,1549
50
+ flextoolsmcp/server/handlers/_import_helper.py,sha256=zyhvZ3anAE5gdX2FtPgPOfZ-UM5sI7llE8PX-iYPDKw,3118
51
+ flextoolsmcp/server/handlers/admin.py,sha256=IFOq44Bipooo32wjczSM0c56Kz7tUzOkqaH_3v1sb2w,28778
52
+ flextoolsmcp/server/handlers/api.py,sha256=CND39CcZeru_tF-q0zF4SKZMSy2HG30eUUIElf-QR8w,59123
53
+ flextoolsmcp/server/handlers/catalog.py,sha256=2OWwIsjLm63cUdhep8jP2dcayHw-MTif_RSUzh89CMY,8950
54
+ flextoolsmcp/server/handlers/discovery.py,sha256=tCUIBp_hW86xrZ8zrrfvASWfBVGEJanCWJ8z339Coe0,9450
55
+ flextoolsmcp/server/handlers/equivalence.py,sha256=YBpWv132Y_8pqimtUZ-B6dvFmXkkha27D7FdNknO8L4,13740
56
+ flextoolsmcp/server/handlers/execution.py,sha256=dIGFw0f63aPYs6DHHmdVyke-NDTMHViT2Q5C8-YUXG0,118384
57
+ flextoolsmcp/server/handlers/utils.py,sha256=Wi8x6H7m6tTu0y6Uv7__mWKUZWXPPKz5TB5uc-uX5fs,662
58
+ flextools_mcp-2.3.1.dist-info/METADATA,sha256=NuAJs8ET-LiTgJ5zC4ljJ_hCOZpelPfUxwAIm5PCBfY,10950
59
+ flextools_mcp-2.3.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
60
+ flextools_mcp-2.3.1.dist-info/entry_points.txt,sha256=o2BDyBqeFAHv8AIs1S59VIgR2XK_SeDf-SNMye86bBw,97
61
+ flextools_mcp-2.3.1.dist-info/top_level.txt,sha256=h0PkvfZ7L1s80bDim-ebiOLJHgKbMXNH2sAOharhmCM,13
62
+ flextools_mcp-2.3.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ flextools-mcp = flextoolsmcp.server:run
3
+ flextoolsmcp = flextoolsmcp.server:run
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ flextoolsmcp
@@ -0,0 +1,9 @@
1
+ # FlexTools MCP Server
2
+ try:
3
+ from importlib.metadata import version as _version
4
+
5
+ __version__ = _version("flextools-mcp")
6
+ except Exception: # pragma: no cover - source checkout without install
7
+ __version__ = "0.0.0.dev0"
8
+
9
+ __all__ = ["__version__"]
@@ -0,0 +1,9 @@
1
+ """Allow running the server via ``python -m flextoolsmcp``."""
2
+
3
+ if __package__:
4
+ from .server import run
5
+ else:
6
+ from server import run
7
+
8
+ if __name__ == "__main__":
9
+ run()
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Archive Old API Versions
5
+
6
+ Moves older versioned API files to archive subdirectories, keeping only
7
+ the latest version of each API in the main index directory. Archived
8
+ versions remain accessible to the build scripts.
9
+
10
+ Usage:
11
+ python src/archive_old_versions.py
12
+ python src/archive_old_versions.py --keep 2 # Keep last 2 versions
13
+ """
14
+
15
+ import argparse
16
+ import re
17
+ import shutil
18
+ from pathlib import Path
19
+ from typing import Dict, List, Tuple
20
+
21
+ if __package__:
22
+ from .file_utils import get_index_dir
23
+ else:
24
+ from file_utils import get_index_dir
25
+
26
+
27
+ def parse_version(filename: str) -> Tuple[int, int, int]:
28
+ """Extract version tuple from filename like 'liblcm_api_v11.0.0.json'."""
29
+ match = re.search(r'v(\d+)\.(\d+)\.(\d+)', filename)
30
+ if match:
31
+ major, minor, patch = match.groups()
32
+ return (int(major), int(minor), int(patch))
33
+ return (0, 0, 0)
34
+
35
+
36
+ def archive_versions_in_directory(
37
+ directory: Path,
38
+ pattern: str,
39
+ keep_count: int = 1
40
+ ) -> Dict[str, List[str]]:
41
+ """Archive old versions in a directory.
42
+
43
+ Args:
44
+ directory: Directory containing versioned files
45
+ pattern: Glob pattern like "liblcm_api_v*.json"
46
+ keep_count: Number of latest versions to keep in main directory
47
+
48
+ Returns:
49
+ Dict with 'archived' and 'kept' file lists
50
+ """
51
+ if not directory.exists():
52
+ return {"archived": [], "kept": []}
53
+
54
+ # Find all versioned files
55
+ files = sorted(directory.glob(pattern))
56
+ if len(files) <= keep_count:
57
+ return {"archived": [], "kept": [f.name for f in files]}
58
+
59
+ # Sort by version (descending, so latest first)
60
+ files_with_versions = [(f, parse_version(f.name)) for f in files]
61
+ files_with_versions.sort(key=lambda x: x[1], reverse=True)
62
+
63
+ # Keep latest N, archive the rest
64
+ keep_files = [f for f, _ in files_with_versions[:keep_count]]
65
+ archive_files = [f for f, _ in files_with_versions[keep_count:]]
66
+
67
+ # Create archive directory
68
+ archive_dir = directory / "archive"
69
+ archive_dir.mkdir(exist_ok=True)
70
+
71
+ # Move old files to archive
72
+ archived = []
73
+ for old_file in archive_files:
74
+ try:
75
+ archive_path = archive_dir / old_file.name
76
+ shutil.move(str(old_file), str(archive_path))
77
+ archived.append(old_file.name)
78
+ print(f" [ARCHIVE] {old_file.name} -> archive/")
79
+ except FileNotFoundError:
80
+ # File already gone - skip it
81
+ pass
82
+
83
+ return {
84
+ "archived": archived,
85
+ "kept": [f.name for f in keep_files]
86
+ }
87
+
88
+
89
+ def main():
90
+ parser = argparse.ArgumentParser(
91
+ description="Archive old API versions to subdirectories"
92
+ )
93
+ parser.add_argument(
94
+ "--keep",
95
+ type=int,
96
+ default=1,
97
+ help="Number of latest versions to keep in main directory (default: 1)"
98
+ )
99
+ parser.add_argument(
100
+ "--quiet",
101
+ action="store_true",
102
+ help="Suppress output"
103
+ )
104
+
105
+ args = parser.parse_args()
106
+
107
+ index_dir = get_index_dir()
108
+
109
+ print("[INFO] Archiving old API versions...")
110
+ print(f" Keeping {args.keep} latest version(s)")
111
+
112
+ # Archive patterns by directory
113
+ # Note: patterns are defined only in their canonical locations to avoid duplication
114
+ patterns = {
115
+ index_dir / "liblcm": [
116
+ ("liblcm_api_v*.json", "LibLCM"),
117
+ ("casting_index_liblcm-v*.json", "Casting Index"),
118
+ ("navigation_graph_liblcm-v*.json", "Navigation Graph"),
119
+ ("reverse_mapping_liblcm-v*.json", "Reverse Mapping"),
120
+ ],
121
+ index_dir / "flexlibs": [
122
+ ("flexlibs_api_v*.json", "FlexLibs"),
123
+ ("flexicon_api_v*.json", "Flexicon"),
124
+ ("common_patterns_flexicon-v*.json", "Common Patterns"),
125
+ ],
126
+ }
127
+
128
+ total_archived = 0
129
+ total_kept = 0
130
+
131
+ for directory, file_patterns in patterns.items():
132
+ if not directory.exists():
133
+ continue
134
+
135
+ for pattern, label in file_patterns:
136
+ result = archive_versions_in_directory(
137
+ directory,
138
+ pattern,
139
+ keep_count=args.keep
140
+ )
141
+
142
+ archived_count = len(result["archived"])
143
+ kept_count = len(result["kept"])
144
+
145
+ if archived_count > 0:
146
+ print(f"[OK] {label}: Archived {archived_count}, Keeping {kept_count}")
147
+ total_archived += archived_count
148
+ total_kept += kept_count
149
+
150
+ if not args.quiet:
151
+ print(f"\n[DONE] Archived {total_archived} old versions")
152
+ if total_archived == 0:
153
+ print(" (No old versions to archive)")
154
+
155
+ return 0
156
+
157
+
158
+ if __name__ == "__main__":
159
+ exit(main())