@hubspot/cli 7.7.0-experimental.2 → 7.7.1-experimental.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.
Files changed (65) hide show
  1. package/bin/cli.js +96 -94
  2. package/commands/account.js +0 -2
  3. package/commands/app.js +0 -2
  4. package/commands/auth.js +0 -2
  5. package/commands/cms.js +0 -2
  6. package/commands/completion.js +0 -2
  7. package/commands/config.js +0 -2
  8. package/commands/create.js +0 -2
  9. package/commands/customObject.js +0 -2
  10. package/commands/doctor.js +0 -2
  11. package/commands/feedback.js +0 -2
  12. package/commands/filemanager.js +0 -2
  13. package/commands/function.js +0 -2
  14. package/commands/hubdb.js +0 -2
  15. package/commands/init.js +0 -2
  16. package/commands/lint.js +0 -2
  17. package/commands/list.js +0 -2
  18. package/commands/mv.js +0 -2
  19. package/commands/open.js +0 -2
  20. package/commands/project/dev/deprecatedFlow.d.ts +8 -2
  21. package/commands/project/dev/deprecatedFlow.js +9 -1
  22. package/commands/project/dev/index.js +59 -34
  23. package/commands/project/dev/unifiedFlow.d.ts +10 -2
  24. package/commands/project/dev/unifiedFlow.js +27 -41
  25. package/commands/project.js +0 -4
  26. package/commands/remove.js +0 -2
  27. package/commands/sandbox.js +0 -2
  28. package/commands/secret.js +0 -2
  29. package/commands/theme.js +0 -2
  30. package/commands/upload.js +0 -2
  31. package/lang/en.d.ts +14 -54
  32. package/lang/en.js +14 -54
  33. package/lib/accountTypes.js +1 -3
  34. package/lib/commonOpts.d.ts +1 -3
  35. package/lib/commonOpts.js +1 -1
  36. package/lib/middleware/fireAlarmMiddleware.d.ts +2 -2
  37. package/lib/middleware/fireAlarmMiddleware.js +5 -3
  38. package/lib/projects/localDev/AppDevModeInterface.js +0 -6
  39. package/lib/projects/upload.js +6 -0
  40. package/package.json +4 -7
  41. package/types/Yargs.d.ts +2 -0
  42. package/bin/hsmcp.d.ts +0 -2
  43. package/bin/hsmcp.js +0 -13
  44. package/commands/project/validate.d.ts +0 -4
  45. package/commands/project/validate.js +0 -53
  46. package/commands/setupMcp.d.ts +0 -8
  47. package/commands/setupMcp.js +0 -229
  48. package/mcp-server/index.d.ts +0 -1
  49. package/mcp-server/index.js +0 -17
  50. package/mcp-server/mcpLoader.d.ts +0 -5
  51. package/mcp-server/mcpLoader.js +0 -24
  52. package/mcp-server/tools/ExplainProjectStructureTool.d.ts +0 -33
  53. package/mcp-server/tools/ExplainProjectStructureTool.js +0 -266
  54. package/mcp-server/tools/GenerateAppComponentTool.d.ts +0 -99
  55. package/mcp-server/tools/GenerateAppComponentTool.js +0 -193
  56. package/mcp-server/tools/GenerateCardComponentTool.d.ts +0 -74
  57. package/mcp-server/tools/GenerateCardComponentTool.js +0 -146
  58. package/mcp-server/tools/GenerateProjectConfigTool.d.ts +0 -32
  59. package/mcp-server/tools/GenerateProjectConfigTool.js +0 -40
  60. package/mcp-server/tools/HubSpotCLIHelper.d.ts +0 -24
  61. package/mcp-server/tools/HubSpotCLIHelper.js +0 -110
  62. package/mcp-server/tools/UploadProjectTool.d.ts +0 -44
  63. package/mcp-server/tools/UploadProjectTool.js +0 -166
  64. package/mcp-server/tools/ValidateProjectTool.d.ts +0 -62
  65. package/mcp-server/tools/ValidateProjectTool.js +0 -336
@@ -1,229 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const exitCodes_1 = require("../lib/enums/exitCodes");
7
- const en_1 = require("../lang/en");
8
- const yargsUtils_1 = require("../lib/yargsUtils");
9
- const logger_1 = require("@hubspot/local-dev-lib/logger");
10
- const promptUtils_1 = require("../lib/prompts/promptUtils");
11
- const fs_extra_1 = __importDefault(require("fs-extra"));
12
- const path_1 = __importDefault(require("path"));
13
- const os_1 = __importDefault(require("os"));
14
- const command = 'setup-mcp';
15
- const describe = en_1.commands.setupMcp.describe;
16
- function getCursorMcpConfigPath(global = true) {
17
- if (global) {
18
- // Global configuration: ~/.cursor/mcp.json
19
- const homeDir = os_1.default.homedir();
20
- return path_1.default.join(homeDir, '.cursor', 'mcp.json');
21
- }
22
- else {
23
- // Project-specific configuration: .cursor/mcp.json in current directory
24
- return path_1.default.join(process.cwd(), '.cursor', 'mcp.json');
25
- }
26
- }
27
- const MCP_SERVER_COMMAND = 'hsmcp';
28
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- async function readCursorConfig(global = true) {
30
- const configPath = getCursorMcpConfigPath(global);
31
- try {
32
- if (await fs_extra_1.default.pathExists(configPath)) {
33
- const content = await fs_extra_1.default.readFile(configPath, 'utf8');
34
- return JSON.parse(content);
35
- }
36
- }
37
- catch (error) {
38
- logger_1.logger.debug(`Error reading Cursor config: ${error}`);
39
- }
40
- return { mcpServers: {} };
41
- }
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- async function writeCursorConfig(config, global = true) {
44
- const configPath = getCursorMcpConfigPath(global);
45
- const configDir = path_1.default.dirname(configPath);
46
- // Ensure the directory exists
47
- await fs_extra_1.default.ensureDir(configDir);
48
- // Write the config with proper formatting
49
- await fs_extra_1.default.writeFile(configPath, JSON.stringify(config, null, 2));
50
- }
51
- async function setupMcpServer(global = true) {
52
- try {
53
- const config = await readCursorConfig(global);
54
- // Check if hsmcp command is available
55
- try {
56
- require('child_process').execSync(`which ${MCP_SERVER_COMMAND} 2>/dev/null`, {
57
- encoding: 'utf8',
58
- });
59
- }
60
- catch (error) {
61
- logger_1.logger.error(en_1.commands.setupMcp.errors.serverNotFound);
62
- logger_1.logger.error(en_1.commands.setupMcp.errors.installHint);
63
- return false;
64
- }
65
- // Check if already configured
66
- if (config.mcpServers && config.mcpServers['hubspot-cli-mcp']) {
67
- logger_1.logger.info(en_1.commands.setupMcp.warnings.alreadyConfigured);
68
- const { shouldOverwrite } = await (0, promptUtils_1.promptUser)([
69
- {
70
- type: 'confirm',
71
- name: 'shouldOverwrite',
72
- message: en_1.commands.setupMcp.prompts.overwrite,
73
- default: false,
74
- },
75
- ]);
76
- if (!shouldOverwrite) {
77
- return true;
78
- }
79
- }
80
- // Configure the MCP server with the simple global command
81
- if (!config.mcpServers) {
82
- config.mcpServers = {};
83
- }
84
- config.mcpServers['hubspot-cli-mcp'] = {
85
- command: MCP_SERVER_COMMAND,
86
- args: [],
87
- };
88
- await writeCursorConfig(config, global);
89
- const configType = global ? 'global' : 'project-specific';
90
- logger_1.logger.success(en_1.commands.setupMcp.success.configured.replace('Claude', `Cursor (${configType})`));
91
- logger_1.logger.info(en_1.commands.setupMcp.success.restartCursor);
92
- return true;
93
- }
94
- catch (error) {
95
- logger_1.logger.error(`${en_1.commands.setupMcp.errors.configurationFailed}: ${error}`);
96
- return false;
97
- }
98
- }
99
- function displayInstructions(global = true) {
100
- const configPath = getCursorMcpConfigPath(global);
101
- const configType = global ? 'global' : 'project-specific';
102
- logger_1.logger.log(en_1.commands.setupMcp.instructions.title.replace('Claude', `Cursor (${configType})`));
103
- logger_1.logger.log('');
104
- logger_1.logger.log(en_1.commands.setupMcp.instructions.step1);
105
- logger_1.logger.log(` ${configPath}`);
106
- logger_1.logger.log('');
107
- logger_1.logger.log(en_1.commands.setupMcp.instructions.step2);
108
- logger_1.logger.log(' {');
109
- logger_1.logger.log(' "mcpServers": {');
110
- logger_1.logger.log(' "hubspot-cli-mcp": {');
111
- logger_1.logger.log(` "command": "${MCP_SERVER_COMMAND}",`);
112
- logger_1.logger.log(' "args": []');
113
- logger_1.logger.log(' }');
114
- logger_1.logger.log(' }');
115
- logger_1.logger.log(' }');
116
- logger_1.logger.log('');
117
- logger_1.logger.log(en_1.commands.setupMcp.instructions.step3.replace('Claude', 'Cursor'));
118
- logger_1.logger.log('');
119
- logger_1.logger.log(en_1.commands.setupMcp.instructions.documentation);
120
- }
121
- async function handler(args) {
122
- const useGlobal = args.global !== false; // Default to global unless explicitly set to false
123
- if (args.showInstructions) {
124
- displayInstructions(useGlobal);
125
- process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
126
- return;
127
- }
128
- if (args.autoSetup) {
129
- const success = await setupMcpServer(useGlobal);
130
- process.exit(success ? exitCodes_1.EXIT_CODES.SUCCESS : exitCodes_1.EXIT_CODES.ERROR);
131
- return;
132
- }
133
- // Interactive mode - determine scope first if not specified
134
- let isGlobal = useGlobal;
135
- if (args.global === undefined) {
136
- const { scope } = await (0, promptUtils_1.promptUser)([
137
- {
138
- type: 'list',
139
- name: 'scope',
140
- message: en_1.commands.setupMcp.prompts.selectScope,
141
- choices: [
142
- {
143
- name: en_1.commands.setupMcp.choices.global,
144
- value: 'global',
145
- },
146
- {
147
- name: en_1.commands.setupMcp.choices.project,
148
- value: 'project',
149
- },
150
- ],
151
- },
152
- ]);
153
- isGlobal = scope === 'global';
154
- }
155
- // Then ask what action to take
156
- const { action } = await (0, promptUtils_1.promptUser)([
157
- {
158
- type: 'list',
159
- name: 'action',
160
- message: en_1.commands.setupMcp.prompts.selectAction,
161
- choices: [
162
- {
163
- name: en_1.commands.setupMcp.choices.autoSetup,
164
- value: 'auto',
165
- },
166
- {
167
- name: en_1.commands.setupMcp.choices.showInstructions,
168
- value: 'instructions',
169
- },
170
- ],
171
- },
172
- ]);
173
- if (action === 'auto') {
174
- const success = await setupMcpServer(isGlobal);
175
- process.exit(success ? exitCodes_1.EXIT_CODES.SUCCESS : exitCodes_1.EXIT_CODES.ERROR);
176
- }
177
- else {
178
- displayInstructions(isGlobal);
179
- process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
180
- }
181
- }
182
- function setupMcpBuilder(yargs) {
183
- yargs
184
- .options({
185
- 'auto-setup': {
186
- describe: en_1.commands.setupMcp.options.autoSetup.describe,
187
- type: 'boolean',
188
- default: false,
189
- },
190
- 'show-instructions': {
191
- describe: en_1.commands.setupMcp.options.showInstructions.describe,
192
- type: 'boolean',
193
- default: false,
194
- },
195
- global: {
196
- describe: en_1.commands.setupMcp.options.global.describe,
197
- type: 'boolean',
198
- },
199
- })
200
- .example([
201
- ['$0 setup-mcp', en_1.commands.setupMcp.examples.default],
202
- ['$0 setup-mcp --auto-setup', en_1.commands.setupMcp.examples.autoSetup],
203
- [
204
- '$0 setup-mcp --auto-setup --global',
205
- en_1.commands.setupMcp.examples.autoSetupGlobal,
206
- ],
207
- [
208
- '$0 setup-mcp --auto-setup --no-global',
209
- en_1.commands.setupMcp.examples.autoSetupProject,
210
- ],
211
- [
212
- '$0 setup-mcp --show-instructions',
213
- en_1.commands.setupMcp.examples.showInstructions,
214
- ],
215
- ]);
216
- return yargs;
217
- }
218
- const builder = (0, yargsUtils_1.makeYargsBuilder)(setupMcpBuilder, command, describe, {
219
- useGlobalOptions: true,
220
- });
221
- const setupMcpCommand = {
222
- command,
223
- describe,
224
- handler,
225
- builder,
226
- };
227
- exports.default = setupMcpCommand;
228
- // Legacy export for compatibility
229
- module.exports = setupMcpCommand;
@@ -1 +0,0 @@
1
- export {};
@@ -1,17 +0,0 @@
1
- import { MCPServer } from 'mcp-framework';
2
- import { dirname, join } from 'path';
3
- import { fileURLToPath } from 'url';
4
- const __filename = fileURLToPath(import.meta.url);
5
- const __dirname = dirname(__filename);
6
- // Calculate the correct base path for tools
7
- // ToolLoader does: dirname(basePath) + "/tools"
8
- // We want it to look in dist/mcp-server/tools
9
- // So basePath should be dist/mcp-server/anything
10
- // __filename is dist/mcp-server/index.js, so dirname is dist/mcp-server
11
- // We need to provide a path like dist/mcp-server/main.js
12
- const basePath = join(__dirname, 'main.js');
13
- console.log('Debug: basePath:', basePath);
14
- const server = new MCPServer({
15
- basePath: basePath,
16
- });
17
- server.start();
@@ -1,5 +0,0 @@
1
- export declare function getMCPServer(): Promise<any>;
2
- export declare function getMCPTool(): Promise<any>;
3
- export declare class MCPToolBase {
4
- static create(): Promise<any>;
5
- }
@@ -1,24 +0,0 @@
1
- // Dynamic import loader for mcp-framework to handle ESM/CommonJS compatibility
2
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
- let mcpFramework = null;
4
- async function loadMCPFramework() {
5
- if (!mcpFramework) {
6
- mcpFramework = await import('mcp-framework');
7
- }
8
- return mcpFramework;
9
- }
10
- export async function getMCPServer() {
11
- const framework = await loadMCPFramework();
12
- return framework.MCPServer;
13
- }
14
- export async function getMCPTool() {
15
- const framework = await loadMCPFramework();
16
- return framework.MCPTool;
17
- }
18
- // Export a ready-to-use MCPTool base class
19
- export class MCPToolBase {
20
- static async create() {
21
- const MCPTool = await getMCPTool();
22
- return MCPTool;
23
- }
24
- }
@@ -1,33 +0,0 @@
1
- import { MCPTool } from "mcp-framework";
2
- import { z } from "zod";
3
- interface ExplainProjectStructureInput {
4
- section?: string;
5
- }
6
- declare class ExplainProjectStructureTool extends MCPTool<ExplainProjectStructureInput> {
7
- name: string;
8
- description: string;
9
- schema: {
10
- section: {
11
- type: z.ZodOptional<z.ZodString>;
12
- description: string;
13
- };
14
- };
15
- execute(input: ExplainProjectStructureInput): Promise<{
16
- section: string;
17
- title: string;
18
- content: string;
19
- message?: undefined;
20
- sections?: undefined;
21
- } | {
22
- message: string;
23
- sections: {
24
- section: string;
25
- title: string;
26
- content: string;
27
- }[];
28
- section?: undefined;
29
- title?: undefined;
30
- content?: undefined;
31
- }>;
32
- }
33
- export default ExplainProjectStructureTool;
@@ -1,266 +0,0 @@
1
- import { MCPTool } from "mcp-framework";
2
- import { z } from "zod";
3
- class ExplainProjectStructureTool extends MCPTool {
4
- name = "explainProjectStructure";
5
- description = "Explains the developer projects platform structure, conventions, and best practices";
6
- schema = {
7
- section: {
8
- type: z.string().optional(),
9
- description: "Specific section to explain (overview, projectFiles, components, hierarchy, fileNaming, bestPractices, envelope). If not provided, returns complete explanation",
10
- },
11
- };
12
- async execute(input) {
13
- const { section } = input;
14
- const explanation = {
15
- overview: {
16
- title: "Developer Projects Platform Overview",
17
- content: `
18
- The developer projects platform allows users to build applications using a hierarchical component-based architecture with consistency and predictability as core principles.
19
-
20
- Key Concepts:
21
- - Projects are defined by hsproject.json files in the root directory
22
- - Components follow a hierarchical structure with top-level and sub-components
23
- - Apps are the primary top-level components that provide authentication
24
- - Sub-components (features) live within apps and depend on app authentication
25
- - All components live in the src directory with dedicated folders
26
- - Component instances are declared via *-hsmeta.json files
27
- - 1:1 relationship between components and their configuration files
28
- - Envelope layer (uid, type) provides meta information about components
29
- `,
30
- },
31
- projectFiles: {
32
- title: "Project Configuration Files",
33
- content: `
34
- hsproject.json (Project Root):
35
- - Designates a folder as a developer project
36
- - Contains project metadata including name, source directory, and platform version
37
- - Required fields:
38
- * name: Project name (e.g., "North Star Project")
39
- * srcDir: Source code directory (typically "src")
40
- * platformVersion: Platform version (e.g., "2025.1", defaults to "2025.2")
41
-
42
- Example:
43
- {
44
- "name": "North Star Project",
45
- "srcDir": "src",
46
- "platformVersion": "2025.1"
47
- }
48
- `,
49
- },
50
- components: {
51
- title: "Component Architecture",
52
- content: `
53
- Components follow a structured, predictable architecture with two main categories:
54
-
55
- **Top-Level Components:**
56
- - Stand-alone components that provide core functionality
57
- - Currently: Apps (and Themes)
58
- - Located directly in src/[component-type]/
59
- - Provide authentication and foundational services
60
-
61
- **Sub-Components (Features):**
62
- - Live within top-level components (primarily apps)
63
- - Depend on parent component's authentication
64
- - Located in src/app/[feature-type]/
65
- - Include: cards, functions, settings, webhooks, marketing-events, timeline-events, etc.
66
-
67
- Standard Component Structure (Envelope Layer):
68
- {
69
- "uid": "unique-component-id", // Unique identifier
70
- "type": "component-type", // Component type
71
- "config": { // Component-specific configuration
72
- // Configuration details here
73
- }
74
- }
75
-
76
- Component Characteristics:
77
- - Each component has a dedicated folder and *-hsmeta.json file (1:1 relationship)
78
- - Some components are singular (only one per app): settings, webhooks, calling
79
- - Others can have multiple instances: cards, functions, marketing-events
80
- - All follow the envelope layer structure for consistency
81
- `,
82
- },
83
- hierarchy: {
84
- title: "Component Hierarchy & Authentication",
85
- content: `
86
- The platform uses a hierarchical architecture where authentication flows from top-level components to sub-components.
87
-
88
- **Top-Level Components:**
89
- - App: Primary component providing OAuth authentication
90
- - Theme: Styling and branding (top-level but may depend on app context)
91
-
92
- **Sub-Components within Apps:**
93
- Sub-components rely on their parent app's authentication and include:
94
-
95
- - App Objects: Custom CRM objects
96
- - App Object Associations: Relationships between objects
97
- - Cards: UI cards displayed in HubSpot
98
- - Functions: Serverless functions
99
- - Settings: Configuration interfaces
100
- - Marketing Events: Custom marketing event types
101
- - Timeline Events: Custom timeline activities
102
- - Webhooks: Event notification endpoints
103
- - Workflow Actions: Custom workflow steps
104
- - Calling: Phone/communication features
105
- - Video Conferencing: Meeting integrations
106
- - Media Bridge: Media handling capabilities
107
-
108
- **Authentication Flow:**
109
- 1. App component defines OAuth scopes and authentication
110
- 2. Sub-components inherit and utilize app authentication
111
- 3. Sub-components cannot exist without a parent app
112
- 4. All API calls from sub-components use app credentials
113
- `,
114
- },
115
- fileNaming: {
116
- title: "File Naming Conventions & Structure",
117
- content: `
118
- Component Configuration Files (*-hsmeta.json):
119
- - Must end with "-hsmeta.json"
120
- - Prefix can be anything meaningful to the user
121
- - Recommended: use component name as prefix for clarity
122
- - Examples: "my-app-hsmeta.json", "contact-card-hsmeta.json"
123
- - Maintain 1:1 relationship between components and configuration files
124
-
125
- Complete Directory Structure:
126
- my-project/
127
- ├── hsproject.json # Project configuration
128
- └── src/ # Source code directory
129
- ├── app/ # App component directory (top-level)
130
- │ ├── my-app-hsmeta.json # App component configuration
131
- │ ├── cards/ # Cards sub-components
132
- │ │ ├── contact-card-hsmeta.json
133
- │ │ └── deal-card-hsmeta.json
134
- │ ├── functions/ # Function sub-components
135
- │ │ ├── data-sync-hsmeta.json
136
- │ │ └── email-validator-hsmeta.json
137
- │ ├── settings/ # Settings sub-component (singular)
138
- │ │ └── app-settings-hsmeta.json
139
- │ ├── webhooks/ # Webhooks sub-component (singular)
140
- │ │ └── event-handler-hsmeta.json
141
- │ └── [other-features]/ # Other sub-component directories
142
- └── theme/ # Theme component (if applicable)
143
- └── brand-theme-hsmeta.json
144
-
145
- UIDs (Unique Identifiers):
146
- - Must be unique within each project
147
- - Use descriptive, kebab-case naming
148
- - Examples: "my-unified-app", "contact-summary-card", "lead-scoring-function"
149
- - Should clearly identify the component's purpose and type
150
- `,
151
- },
152
- envelope: {
153
- title: "Envelope Layer Architecture",
154
- content: `
155
- The envelope layer provides a consistent structure for all components, enabling the system to derive meta information automatically.
156
-
157
- Envelope Structure:
158
- {
159
- "uid": "component-identifier", // Unique ID for component identification
160
- "type": "component-type", // Type determines component behavior
161
- "config": { // Component-specific configuration
162
- // All component-specific settings go here
163
- }
164
- }
165
-
166
- Benefits of Envelope Layer:
167
- - Consistent metadata extraction across all component types
168
- - Predictable structure for tooling and validation
169
- - Clear separation between component identity (uid, type) and configuration
170
- - Enables automatic component discovery and management
171
- - Supports hierarchical relationships between components
172
-
173
- Example App Component (Top-Level):
174
- {
175
- "uid": "my-unified-app",
176
- "type": "app",
177
- "config": {
178
- "description": "An example to demonstrate how to build a public app with developer projects.",
179
- "name": "My unified app",
180
- "logo": "./app-logo.png",
181
- "distribution": "A public app",
182
- "auth": {
183
- "type": "oauth",
184
- "redirectUrls": ["http://localhost:3000/oauth-callback"],
185
- "requiredScopes": ["crm.objects.contacts.read"]
186
- }
187
- }
188
- }
189
-
190
- Example Sub-Component (Card):
191
- {
192
- "uid": "contact-summary-card",
193
- "type": "cards",
194
- "config": {
195
- "title": "Contact Summary",
196
- "description": "Displays key contact information",
197
- "displayOptions": {
198
- "width": "medium",
199
- "height": "auto"
200
- }
201
- }
202
- }
203
- `,
204
- },
205
- bestPractices: {
206
- title: "Best Practices & Guidelines",
207
- content: `
208
- 1. Hierarchy and Authentication:
209
- - Always create an app component first (provides authentication)
210
- - Sub-components must live within the app directory structure
211
- - Ensure app has sufficient OAuth scopes for all sub-components
212
- - Consider authentication requirements when planning components
213
-
214
- 2. Consistency and Predictability:
215
- - Follow established folder structures exactly
216
- - Maintain 1:1 relationship between components and configuration files
217
- - Use consistent naming conventions across all components
218
- - Ensure each component has a dedicated folder
219
-
220
- 3. Project Organization:
221
- - Keep hsproject.json in project root
222
- - Organize sub-components in their dedicated directories within src/app/
223
- - Group related functionality (e.g., all cards in cards/ directory)
224
- - Follow the hierarchical structure religiously
225
-
226
- 4. Component Configuration:
227
- - Keep configurations clear and concise
228
- - Focus on the rules established by the schema
229
- - Use the envelope layer (uid, type, config) consistently
230
- - Ensure UIDs are unique and descriptive across all component types
231
-
232
- 5. File Management:
233
- - Use meaningful -hsmeta.json file names that reflect component purpose
234
- - Place sub-component files in appropriate feature directories
235
- - Include necessary assets (like logos) in component directories
236
- - Follow kebab-case for consistency
237
-
238
- 6. Component Development:
239
- - Start with app component to establish authentication foundation
240
- - Plan OAuth scopes to cover all intended sub-components
241
- - Consider component relationships and dependencies
242
- - Validate component configurations against the schema
243
- - Remember some components are singular (settings, webhooks) vs. multiple instances (cards, functions)
244
- `,
245
- },
246
- };
247
- if (section && explanation[section]) {
248
- const selectedSection = explanation[section];
249
- return {
250
- section: section,
251
- title: selectedSection.title,
252
- content: selectedSection.content.trim(),
253
- };
254
- }
255
- // Return complete explanation
256
- return {
257
- message: "Complete Developer Projects Platform Structure Guide",
258
- sections: Object.entries(explanation).map(([key, value]) => ({
259
- section: key,
260
- title: value.title,
261
- content: value.content.trim(),
262
- })),
263
- };
264
- }
265
- }
266
- export default ExplainProjectStructureTool;
@@ -1,99 +0,0 @@
1
- import { MCPTool } from 'mcp-framework';
2
- import { z } from 'zod';
3
- interface GenerateAppComponentInput {
4
- appName: string;
5
- uid: string;
6
- description?: string;
7
- displayName?: string;
8
- distribution?: string;
9
- supportEmail?: string;
10
- documentationUrl?: string;
11
- supportUrl?: string;
12
- supportPhone?: string;
13
- redirectUrls?: string[];
14
- requiredScopes?: string[];
15
- optionalScopes?: string[];
16
- permittedFetchUrls?: string[];
17
- plannedFeatures?: string[];
18
- }
19
- declare class GenerateAppComponentTool extends MCPTool<GenerateAppComponentInput> {
20
- name: string;
21
- description: string;
22
- schema: {
23
- appName: {
24
- type: z.ZodString;
25
- description: string;
26
- };
27
- uid: {
28
- type: z.ZodString;
29
- description: string;
30
- };
31
- description: {
32
- type: z.ZodOptional<z.ZodString>;
33
- description: string;
34
- };
35
- displayName: {
36
- type: z.ZodOptional<z.ZodString>;
37
- description: string;
38
- };
39
- distribution: {
40
- type: z.ZodOptional<z.ZodString>;
41
- description: string;
42
- };
43
- supportEmail: {
44
- type: z.ZodOptional<z.ZodString>;
45
- description: string;
46
- };
47
- documentationUrl: {
48
- type: z.ZodOptional<z.ZodString>;
49
- description: string;
50
- };
51
- supportUrl: {
52
- type: z.ZodOptional<z.ZodString>;
53
- description: string;
54
- };
55
- supportPhone: {
56
- type: z.ZodOptional<z.ZodString>;
57
- description: string;
58
- };
59
- redirectUrls: {
60
- type: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
61
- description: string;
62
- };
63
- requiredScopes: {
64
- type: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
65
- description: string;
66
- };
67
- optionalScopes: {
68
- type: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
69
- description: string;
70
- };
71
- permittedFetchUrls: {
72
- type: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
73
- description: string;
74
- };
75
- plannedFeatures: {
76
- type: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
77
- description: string;
78
- };
79
- };
80
- execute(input: GenerateAppComponentInput): Promise<{
81
- message: string;
82
- config: string;
83
- folderPath: string;
84
- fileName: string;
85
- fullPath: string;
86
- architecture: {
87
- componentType: string;
88
- role: string;
89
- singularComponent: boolean;
90
- dependents: string;
91
- };
92
- scopeRecommendations: string[];
93
- nextSteps: string[];
94
- instructions: string[];
95
- }>;
96
- private generateScopeRecommendations;
97
- private generateNextSteps;
98
- }
99
- export default GenerateAppComponentTool;