ftc-mcp 1.0.0 → 1.1.0

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.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Centralized knowledge index for progressive discovery.
3
+ *
4
+ * Inspired by Cloudflare's Code Mode pattern: instead of enumerating every
5
+ * possible value in tool descriptions (which wastes context tokens), this
6
+ * module provides runtime lookup functions. Tool descriptions stay compact
7
+ * and options are returned dynamically when needed.
8
+ */
9
+ interface ResourceEntry {
10
+ name: string;
11
+ key: string;
12
+ }
13
+ interface CategoryDef {
14
+ source: Record<string, string>;
15
+ label: string;
16
+ entries: Record<string, ResourceEntry>;
17
+ }
18
+ export declare const CATEGORIES: Record<string, CategoryDef>;
19
+ export declare function getResource(category: string, slug: string): string | null;
20
+ export declare function listResources(category: string): Array<{
21
+ uri: string;
22
+ name: string;
23
+ }>;
24
+ export declare function buildSearchIndex(): Array<{
25
+ category: string;
26
+ key: string;
27
+ content: string;
28
+ }>;
29
+ export declare function getExample(topic: string): string | null;
30
+ export declare function listExamples(): string[];
31
+ export declare function lookupDeviceReference(device: string): string | null;
32
+ export {};
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ /**
3
+ * Centralized knowledge index for progressive discovery.
4
+ *
5
+ * Inspired by Cloudflare's Code Mode pattern: instead of enumerating every
6
+ * possible value in tool descriptions (which wastes context tokens), this
7
+ * module provides runtime lookup functions. Tool descriptions stay compact
8
+ * and options are returned dynamically when needed.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.CATEGORIES = void 0;
12
+ exports.getResource = getResource;
13
+ exports.listResources = listResources;
14
+ exports.buildSearchIndex = buildSearchIndex;
15
+ exports.getExample = getExample;
16
+ exports.listExamples = listExamples;
17
+ exports.lookupDeviceReference = lookupDeviceReference;
18
+ const pedro_js_1 = require("./pedro.js");
19
+ const dashboard_js_1 = require("./dashboard.js");
20
+ const hardware_js_1 = require("./hardware.js");
21
+ const ftc_sdk_js_1 = require("./ftc-sdk.js");
22
+ const gradle_js_1 = require("./gradle.js");
23
+ const roadrunner_js_1 = require("./roadrunner.js");
24
+ const ftclib_js_1 = require("./ftclib.js");
25
+ const vision_js_1 = require("./vision.js");
26
+ const panels_js_1 = require("./panels.js");
27
+ const examples_js_1 = require("./examples.js");
28
+ // ── Category Index ──────────────────────────────────────────────────────
29
+ // Maps: category → slug → { name, knowledgeKey }
30
+ // All hardware URIs are flattened to ftc://{category}/{slug} (no nested paths)
31
+ exports.CATEGORIES = {
32
+ sdk: {
33
+ source: ftc_sdk_js_1.FTC_SDK_KNOWLEDGE,
34
+ label: "FTC SDK",
35
+ entries: {
36
+ "overview": { name: "FTC Overview", key: "overview" },
37
+ "opmode-patterns": { name: "OpMode Patterns", key: "opmodePatterns" },
38
+ "hardware-map": { name: "Hardware Map", key: "hardwareMap" },
39
+ "gamepad-api": { name: "Gamepad API", key: "gamepadApi" },
40
+ "best-practices": { name: "Best Practices", key: "bestPractices" },
41
+ "dev-environment": { name: "Dev Environment Setup", key: "devEnvironment" },
42
+ },
43
+ },
44
+ pedro: {
45
+ source: pedro_js_1.PEDRO_KNOWLEDGE,
46
+ label: "Pedro Pathing",
47
+ entries: {
48
+ "api-reference": { name: "Pedro API Reference", key: "apiReference" },
49
+ "constants-pattern": { name: "Pedro Constants Pattern", key: "constantsPattern" },
50
+ "coordinate-system": { name: "Pedro Coordinate System", key: "coordinateSystem" },
51
+ "auto-structure": { name: "Pedro Auto Structure", key: "autoStructure" },
52
+ "teleop-structure": { name: "Pedro TeleOp Structure", key: "teleopStructure" },
53
+ "callbacks": { name: "Pedro Callbacks", key: "callbacks" },
54
+ },
55
+ },
56
+ dashboard: {
57
+ source: dashboard_js_1.DASHBOARD_KNOWLEDGE,
58
+ label: "FTC Dashboard",
59
+ entries: {
60
+ "config-pattern": { name: "Dashboard Config Pattern", key: "configPattern" },
61
+ "telemetry": { name: "Dashboard Telemetry", key: "telemetry" },
62
+ "canvas": { name: "Dashboard Canvas", key: "canvas" },
63
+ "camera": { name: "Dashboard Camera", key: "camera" },
64
+ "setup": { name: "Dashboard Setup", key: "setup" },
65
+ "api": { name: "Dashboard API", key: "api" },
66
+ },
67
+ },
68
+ gradle: {
69
+ source: gradle_js_1.GRADLE_KNOWLEDGE,
70
+ label: "Gradle",
71
+ entries: {
72
+ "project-structure": { name: "Gradle Project Structure", key: "projectStructure" },
73
+ "adding-libraries": { name: "Adding Libraries", key: "addingLibraries" },
74
+ "all-library-coords": { name: "All Library Coordinates", key: "allLibraryCoords" },
75
+ "common-issues": { name: "Common Gradle Issues", key: "commonIssues" },
76
+ "build-process": { name: "Build Process", key: "buildProcess" },
77
+ "build-and-deploy": { name: "Build and Deploy", key: "buildAndDeploy" },
78
+ },
79
+ },
80
+ hardware: {
81
+ source: hardware_js_1.HARDWARE_KNOWLEDGE,
82
+ label: "Hardware",
83
+ entries: {
84
+ "motors-api": { name: "Motors API", key: "motorsApi" },
85
+ "motor-run-modes": { name: "Motor Run Modes", key: "motorRunModes" },
86
+ "motor-specs": { name: "Motor Specs", key: "motorSpecs" },
87
+ "servos-api": { name: "Servos API", key: "servosApi" },
88
+ "sensors-imu": { name: "IMU Sensor", key: "sensorsImu" },
89
+ "sensors-distance": { name: "Distance Sensor", key: "sensorsDistance" },
90
+ "sensors-color": { name: "Color Sensor", key: "sensorsColor" },
91
+ "sensors-digital": { name: "Digital Sensors", key: "sensorsDigital" },
92
+ "sensors-encoder": { name: "Encoders", key: "sensorsEncoder" },
93
+ "pinpoint": { name: "GoBilda Pinpoint", key: "pinpoint" },
94
+ "otos": { name: "SparkFun OTOS", key: "otos" },
95
+ "rev-hub": { name: "REV Hub", key: "revHub" },
96
+ "bulk-reads": { name: "Bulk Reads", key: "bulkReads" },
97
+ "caching-hardware": { name: "Caching Hardware", key: "cachingHardware" },
98
+ "optimization-summary": { name: "Optimization Summary", key: "optimizationSummary" },
99
+ "custom-wrappers": { name: "Custom Wrappers", key: "customWrappers" },
100
+ "command-pipeline": { name: "Command Pipeline", key: "commandPipeline" },
101
+ "write-optimization": { name: "Write Optimization", key: "writeOptimization" },
102
+ "loop-time-budget": { name: "Loop Time Budget", key: "loopTimeBudget" },
103
+ "vision": { name: "Vision", key: "vision" },
104
+ },
105
+ },
106
+ roadrunner: {
107
+ source: roadrunner_js_1.ROADRUNNER_KNOWLEDGE,
108
+ label: "Road Runner",
109
+ entries: {
110
+ "api-reference": { name: "Road Runner API", key: "apiReference" },
111
+ },
112
+ },
113
+ "command-base": {
114
+ source: ftclib_js_1.FTCLIB_KNOWLEDGE,
115
+ label: "Command-Base (SolversLib)",
116
+ entries: {
117
+ "setup": { name: "Command-Base Setup", key: "setup" },
118
+ "api": { name: "Command-Base API", key: "apiReference" },
119
+ "subsystems": { name: "Command-Base Subsystem Patterns", key: "subsystemPatterns" },
120
+ "commands": { name: "Command-Base Command Patterns", key: "commandPatterns" },
121
+ "triggers": { name: "Command-Base Triggers & GamepadEx", key: "triggers" },
122
+ "organization": { name: "Command-Base Project Organization", key: "organization" },
123
+ "pedro-integration": { name: "Command-Base Pedro Integration", key: "pedroIntegration" },
124
+ "extras": { name: "Command-Base SolversLib Extras", key: "extras" },
125
+ },
126
+ },
127
+ vision: {
128
+ source: vision_js_1.VISION_KNOWLEDGE,
129
+ label: "Vision",
130
+ entries: {
131
+ "overview": { name: "Vision Overview", key: "overview" },
132
+ "visionportal-setup": { name: "VisionPortal Setup", key: "visionPortalSetup" },
133
+ "apriltag-detection": { name: "AprilTag Detection", key: "aprilTagDetection" },
134
+ "camera-controls": { name: "Camera Controls", key: "cameraControls" },
135
+ "limelight": { name: "Limelight 3A Guide", key: "limelight" },
136
+ "megatag": { name: "MegaTag Localization", key: "megaTag" },
137
+ "color-detection": { name: "Color Detection", key: "colorDetection" },
138
+ "optimization": { name: "Vision Optimization", key: "visionOptimization" },
139
+ "multi-camera": { name: "Multi-Camera Setup", key: "multiCamera" },
140
+ "patterns": { name: "Vision Patterns", key: "visionPatterns" },
141
+ },
142
+ },
143
+ panels: {
144
+ source: panels_js_1.PANELS_KNOWLEDGE,
145
+ label: "Panels",
146
+ entries: {
147
+ "overview": { name: "Panels Overview", key: "overview" },
148
+ "setup": { name: "Panels Setup", key: "setup" },
149
+ "configurables": { name: "Panels Configurables", key: "configurables" },
150
+ "telemetry": { name: "Panels Telemetry", key: "telemetry" },
151
+ "field": { name: "Panels Field Drawing", key: "field" },
152
+ "limelight": { name: "Panels Limelight", key: "limelight" },
153
+ "plugins": { name: "Panels Plugins", key: "plugins" },
154
+ "gamepads": { name: "Panels Gamepads", key: "gamepads" },
155
+ },
156
+ },
157
+ };
158
+ // ── Resource Lookup ─────────────────────────────────────────────────────
159
+ function getResource(category, slug) {
160
+ const cat = exports.CATEGORIES[category];
161
+ if (!cat)
162
+ return null;
163
+ const entry = cat.entries[slug];
164
+ if (!entry)
165
+ return null;
166
+ return cat.source[entry.key] ?? null;
167
+ }
168
+ function listResources(category) {
169
+ const cat = exports.CATEGORIES[category];
170
+ if (!cat)
171
+ return [];
172
+ return Object.entries(cat.entries).map(([slug, entry]) => ({
173
+ uri: `ftc://${category}/${slug}`,
174
+ name: entry.name,
175
+ }));
176
+ }
177
+ // ── Full-Text Search ────────────────────────────────────────────────────
178
+ function buildSearchIndex() {
179
+ const index = [];
180
+ for (const [category, catDef] of Object.entries(exports.CATEGORIES)) {
181
+ for (const [slug, entry] of Object.entries(catDef.entries)) {
182
+ const content = catDef.source[entry.key];
183
+ if (content) {
184
+ index.push({ category, key: slug, content });
185
+ }
186
+ }
187
+ }
188
+ return index;
189
+ }
190
+ // ── Example Lookup ──────────────────────────────────────────────────────
191
+ function getExample(topic) {
192
+ return examples_js_1.EXAMPLES[topic] ?? null;
193
+ }
194
+ function listExamples() {
195
+ return Object.keys(examples_js_1.EXAMPLES);
196
+ }
197
+ // ── Hardware/Vision Device Alias Lookup ─────────────────────────────────
198
+ // Allows flexible device name queries (e.g., "DcMotorEx", "motor", "imu")
199
+ const HW_ALIASES = {
200
+ "dcmotor": ["motorsApi", "motorRunModes", "motorSpecs"],
201
+ "dcmotorex": ["motorsApi", "motorRunModes", "motorSpecs"],
202
+ "motor": ["motorsApi", "motorRunModes", "motorSpecs"],
203
+ "motors": ["motorsApi", "motorRunModes", "motorSpecs"],
204
+ "servo": ["servosApi"],
205
+ "crservo": ["servosApi"],
206
+ "imu": ["sensorsImu"],
207
+ "pinpoint": ["pinpoint"],
208
+ "otos": ["otos"],
209
+ "colorsensor": ["sensorsColor"],
210
+ "distancesensor": ["sensorsDistance"],
211
+ "distance": ["sensorsDistance"],
212
+ "touchsensor": ["sensorsDigital"],
213
+ "touch": ["sensorsDigital"],
214
+ "digital": ["sensorsDigital"],
215
+ "bulk-reads": ["bulkReads"],
216
+ "bulkread": ["bulkReads"],
217
+ "bulkreads": ["bulkReads"],
218
+ "bulk-read": ["bulkReads"],
219
+ "caching": ["cachingHardware"],
220
+ "caching-hardware": ["cachingHardware"],
221
+ "cachinghardware": ["cachingHardware"],
222
+ "custom-wrappers": ["customWrappers"],
223
+ "wrappers": ["customWrappers"],
224
+ "customwrappers": ["customWrappers"],
225
+ "encoder": ["sensorsEncoder"],
226
+ "encoders": ["sensorsEncoder"],
227
+ "rev-hub": ["revHub"],
228
+ "revhub": ["revHub"],
229
+ "lynx": ["revHub"],
230
+ "optimization": ["optimizationSummary"],
231
+ "pipeline": ["commandPipeline"],
232
+ "command-pipeline": ["commandPipeline"],
233
+ "commandpipeline": ["commandPipeline"],
234
+ "lynxcommand": ["commandPipeline"],
235
+ "lynx-command": ["commandPipeline"],
236
+ "usb": ["commandPipeline"],
237
+ "write-optimization": ["writeOptimization"],
238
+ "writeoptimization": ["writeOptimization"],
239
+ "write-caching": ["writeOptimization", "cachingHardware"],
240
+ "queueing": ["commandPipeline", "writeOptimization"],
241
+ "queuing": ["commandPipeline", "writeOptimization"],
242
+ "loop-time": ["loopTimeBudget"],
243
+ "looptime": ["loopTimeBudget"],
244
+ "loop-budget": ["loopTimeBudget"],
245
+ "performance": ["optimizationSummary", "commandPipeline", "writeOptimization", "loopTimeBudget"],
246
+ };
247
+ const VISION_ALIASES = {
248
+ "vision": ["overview", "visionPortalSetup", "aprilTagDetection"],
249
+ "visionportal": ["visionPortalSetup"],
250
+ "vision-portal": ["visionPortalSetup"],
251
+ "apriltag": ["aprilTagDetection"],
252
+ "april-tag": ["aprilTagDetection"],
253
+ "camera": ["cameraControls"],
254
+ "camera-controls": ["cameraControls"],
255
+ "cameracontrols": ["cameraControls"],
256
+ "exposure": ["cameraControls"],
257
+ "gain": ["cameraControls"],
258
+ "focus": ["cameraControls"],
259
+ "white-balance": ["cameraControls"],
260
+ "whitebalance": ["cameraControls"],
261
+ "limelight": ["limelight", "megaTag"],
262
+ "limelight3a": ["limelight", "megaTag"],
263
+ "limelight-3a": ["limelight", "megaTag"],
264
+ "megatag": ["megaTag"],
265
+ "megatag2": ["megaTag"],
266
+ "mega-tag": ["megaTag"],
267
+ "localization": ["megaTag"],
268
+ "color-detection": ["colorDetection"],
269
+ "colordetection": ["colorDetection"],
270
+ "color-detect": ["colorDetection"],
271
+ "hsv": ["colorDetection"],
272
+ "opencv": ["colorDetection"],
273
+ "contour": ["colorDetection"],
274
+ "visionprocessor": ["colorDetection"],
275
+ "vision-processor": ["colorDetection"],
276
+ "vision-optimization": ["visionOptimization"],
277
+ "visionoptimization": ["visionOptimization"],
278
+ "decimation": ["visionOptimization", "aprilTagDetection"],
279
+ "fps": ["visionOptimization"],
280
+ "resolution": ["visionOptimization"],
281
+ "motion-blur": ["visionOptimization", "cameraControls"],
282
+ "multi-camera": ["multiCamera"],
283
+ "multicamera": ["multiCamera"],
284
+ "dual-camera": ["multiCamera"],
285
+ "dualcamera": ["multiCamera"],
286
+ "multiportal": ["multiCamera"],
287
+ "vision-patterns": ["visionPatterns"],
288
+ "visionpatterns": ["visionPatterns"],
289
+ "drive-to-tag": ["visionPatterns"],
290
+ "init-detection": ["visionPatterns"],
291
+ "snapscript": ["megaTag"],
292
+ "python-pipeline": ["megaTag"],
293
+ };
294
+ function lookupDeviceReference(device) {
295
+ const deviceLower = device.toLowerCase();
296
+ // Check hardware aliases
297
+ const hwKeys = HW_ALIASES[deviceLower];
298
+ if (hwKeys) {
299
+ const hw = hardware_js_1.HARDWARE_KNOWLEDGE;
300
+ const sections = hwKeys.map(k => hw[k]).filter(Boolean);
301
+ if (sections.length > 0)
302
+ return sections.join("\n\n---\n\n");
303
+ }
304
+ // Check vision aliases
305
+ const visionKeys = VISION_ALIASES[deviceLower];
306
+ if (visionKeys) {
307
+ const vis = vision_js_1.VISION_KNOWLEDGE;
308
+ const sections = visionKeys.map(k => vis[k]).filter(Boolean);
309
+ if (sections.length > 0)
310
+ return sections.join("\n\n---\n\n");
311
+ }
312
+ return null;
313
+ }
@@ -22,7 +22,7 @@ function registerPrompts(server) {
22
22
 
23
23
  Follow these steps IN ORDER:
24
24
 
25
- 1. Call the scan_ftc_project tool to understand the current project state (existing files, Gradle config, dependencies already present).
25
+ 1. Call the scan_project tool to understand the current project state (existing files, Gradle config, dependencies already present).
26
26
 
27
27
  2. Read these resources for Gradle setup guidance:
28
28
  - ftc://gradle/project-structure — understand the FTC Gradle layout
@@ -82,7 +82,7 @@ Important: Always use the exact library coordinates from the resources. Do not g
82
82
 
83
83
  Follow these steps:
84
84
 
85
- 1. Call scan_ftc_project to understand the current project — existing OpModes, subsystems, Constants file, hardware names.
85
+ 1. Call scan_project to understand the current project — existing OpModes, subsystems, Constants file, hardware names.
86
86
 
87
87
  2. Read the appropriate pathing resources:
88
88
  ${pathing === "roadrunner" ? ` - ftc://roadrunner/api-reference — Road Runner trajectory API` : ` - ftc://pedro/api-reference — Pedro Pathing follower and path building API
@@ -128,15 +128,15 @@ Important: The auto should be competition-ready with proper error handling, stat
128
128
 
129
129
  Follow these steps:
130
130
 
131
- 1. Call scan_ftc_project to find existing subsystems, hardware config names, and Constants files.
131
+ 1. Call scan_project to find existing subsystems, hardware config names, and Constants files.
132
132
 
133
133
  2. Read the relevant resources:
134
134
  - ftc://sdk/gamepad-api — gamepad button/stick API and edge detection
135
135
  - ftc://sdk/opmode-patterns — LinearOpMode vs OpMode patterns
136
136
  - ftc://hardware/bulk-reads — set up bulk read caching (MANUAL mode, clear each loop)
137
137
  - ftc://dashboard/telemetry — MultipleTelemetry for dual DS + Dashboard output
138
- ${drive === "pedro" ? ` - ftc://pedro/teleop-structure — Pedro TeleOp drive integration` : ` - ftc://hardware/motors/api — motor control for mecanum math`}
139
- ${drive === "field-centric" ? ` - ftc://hardware/sensors/imu — IMU heading for field-centric calculation` : ""}
138
+ ${drive === "pedro" ? ` - ftc://pedro/teleop-structure — Pedro TeleOp drive integration` : ` - ftc://hardware/motors-api — motor control for mecanum math`}
139
+ ${drive === "field-centric" ? ` - ftc://hardware/sensors-imu — IMU heading for field-centric calculation` : ""}
140
140
 
141
141
  3. Generate the TeleOp OpMode:
142
142
  - Drive control:
@@ -179,11 +179,11 @@ ${drive === "field-centric" ? ` - ftc://hardware/sensors/imu — IMU heading f
179
179
 
180
180
  Follow these steps:
181
181
 
182
- 1. Call scan_ftc_project to see existing subsystems and hardware configuration names.
182
+ 1. Call scan_project to see existing subsystems and hardware configuration names.
183
183
 
184
184
  2. Read the relevant resources:
185
- - ftc://hardware/motors/api and ftc://hardware/servos/api — motor and servo control API
186
- - ftc://hardware/motors/run-modes — RUN_TO_POSITION, RUN_USING_ENCODER, etc.
185
+ - ftc://hardware/motors-api and ftc://hardware/servos-api — motor and servo control API
186
+ - ftc://hardware/motor-run-modes — RUN_TO_POSITION, RUN_USING_ENCODER, etc.
187
187
  - ftc://dashboard/config-pattern — @Config annotation for live tuning
188
188
 
189
189
  3. Generate the subsystem class:
@@ -227,7 +227,7 @@ Important: The class should be self-contained, testable, and follow FTC best pra
227
227
 
228
228
  Follow these steps:
229
229
 
230
- 1. Call scan_ftc_project to find existing PID controllers and subsystem code.
230
+ 1. Call scan_project to find existing PID controllers and subsystem code.
231
231
 
232
232
  2. Read the relevant resources:
233
233
  - ftc://dashboard/config-pattern — expose PID coefficients as @Config public static
@@ -273,7 +273,7 @@ Follow these steps:
273
273
 
274
274
  Follow these steps:
275
275
 
276
- 1. Call scan_ftc_project to analyze the full project — all OpModes, subsystems, and hardware usage.
276
+ 1. Call scan_project to analyze the full project — all OpModes, subsystems, and hardware usage.
277
277
 
278
278
  2. Read the performance resources:
279
279
  - ftc://hardware/bulk-reads — understand REV Hub bulk read caching modes
@@ -329,7 +329,7 @@ Follow these steps:
329
329
 
330
330
  Follow these steps:
331
331
 
332
- 1. Call scan_ftc_project to find the target class and understand the current code.
332
+ 1. Call scan_project to find the target class and understand the current code.
333
333
 
334
334
  2. Read the dashboard resources:
335
335
  - ftc://dashboard/config-pattern — the @Config annotation pattern and requirements
@@ -381,7 +381,7 @@ Important: Remind the user that Dashboard serves a web UI at http://192.168.43.1
381
381
 
382
382
  Follow these steps:
383
383
 
384
- 1. Call scan_ftc_project to analyze the current project state.
384
+ 1. Call scan_project to analyze the current project state.
385
385
 
386
386
  2. Read the command-base resources:
387
387
  - ftc://command-base/setup — SolversLib vs FTCLib, Gradle installation, import mapping
@@ -463,7 +463,7 @@ Important: Use SolversLib imports (com.seattlesolvers.solverslib.*), NOT FTCLib
463
463
 
464
464
  Follow these steps:
465
465
 
466
- 1. Call scan_ftc_project to check the current project state and Gradle configuration.
466
+ 1. Call scan_project to check the current project state and Gradle configuration.
467
467
 
468
468
  2. Read the development environment resource:
469
469
  - ftc://sdk/dev-environment — prerequisites (JDK 17, Android SDK, ANDROID_HOME), IDE-specific setup instructions for VS Code, Android Studio, and IntelliJ
@@ -528,7 +528,7 @@ Important: The Gradle wrapper handles everything. Android Studio is optional —
528
528
 
529
529
  Follow these steps:
530
530
 
531
- 1. Call scan_ftc_project to check the current project state, existing vision code, and hardware names.
531
+ 1. Call scan_project to check the current project state, existing vision code, and hardware names.
532
532
 
533
533
  2. Read the vision overview to understand the options:
534
534
  - ftc://vision/overview — USB webcam vs Limelight comparison, when to use each
@@ -601,7 +601,7 @@ Important: Set manual camera controls for competition consistency. Always have a
601
601
 
602
602
  Follow these steps:
603
603
 
604
- 1. Call scan_ftc_project to see the current Gradle configuration and what's already installed.
604
+ 1. Call scan_project to see the current Gradle configuration and what's already installed.
605
605
 
606
606
  2. Read the Gradle resources:
607
607
  - ftc://gradle/project-structure — understand which files to edit
@@ -1,2 +1,13 @@
1
+ /**
2
+ * MCP Resource Registration — Template-Based
3
+ *
4
+ * Inspired by Cloudflare's progressive discovery pattern: instead of registering
5
+ * 70+ individual resources (each adding to context window overhead), we register
6
+ * 9 category-level resource templates. Each template provides a list callback for
7
+ * resource discovery and a read callback for content retrieval.
8
+ *
9
+ * This reduces the resource listing from ~70 entries to 9 templates, saving
10
+ * significant tokens in the MCP protocol's resource listing.
11
+ */
1
12
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
13
  export declare function registerResources(server: McpServer): void;