@hubspot/cli 7.6.0-experimental.0 → 7.7.0-experimental.1
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.
- package/bin/cli.js +2 -2
- package/bin/hsmcp.d.ts +2 -0
- package/bin/hsmcp.js +13 -0
- package/commands/project/validate.d.ts +4 -0
- package/commands/project/validate.js +53 -0
- package/commands/project.js +2 -0
- package/commands/setupMcp.d.ts +8 -0
- package/commands/setupMcp.js +229 -0
- package/lang/en.d.ts +51 -0
- package/lang/en.js +51 -0
- package/lib/prompts/promptUtils.d.ts +0 -1
- package/lib/prompts/promptUtils.js +0 -2
- package/mcp-server/index.d.ts +1 -0
- package/mcp-server/index.js +17 -0
- package/mcp-server/mcpLoader.d.ts +5 -0
- package/mcp-server/mcpLoader.js +24 -0
- package/mcp-server/tools/ExplainProjectStructureTool.d.ts +33 -0
- package/mcp-server/tools/ExplainProjectStructureTool.js +266 -0
- package/mcp-server/tools/GenerateAppComponentTool.d.ts +99 -0
- package/mcp-server/tools/GenerateAppComponentTool.js +193 -0
- package/mcp-server/tools/GenerateCardComponentTool.d.ts +74 -0
- package/mcp-server/tools/GenerateCardComponentTool.js +146 -0
- package/mcp-server/tools/GenerateProjectConfigTool.d.ts +32 -0
- package/mcp-server/tools/GenerateProjectConfigTool.js +40 -0
- package/mcp-server/tools/HubSpotCLIHelper.d.ts +24 -0
- package/mcp-server/tools/HubSpotCLIHelper.js +110 -0
- package/mcp-server/tools/UploadProjectTool.d.ts +44 -0
- package/mcp-server/tools/UploadProjectTool.js +153 -0
- package/mcp-server/tools/ValidateProjectTool.d.ts +62 -0
- package/mcp-server/tools/ValidateProjectTool.js +324 -0
- package/package.json +6 -3
- package/commands/testAccount/create.d.ts +0 -7
- package/commands/testAccount/create.js +0 -118
- package/commands/testAccount.d.ts +0 -3
- package/commands/testAccount.js +0 -23
|
@@ -0,0 +1,266 @@
|
|
|
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;
|
|
@@ -0,0 +1,99 @@
|
|
|
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;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { MCPTool } from 'mcp-framework';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
class GenerateAppComponentTool extends MCPTool {
|
|
4
|
+
name = 'generateAppComponent';
|
|
5
|
+
description = 'Generates an app component (top-level) with proper folder structure and hsmeta.json configuration file. Apps provide OAuth authentication that sub-components depend on.';
|
|
6
|
+
schema = {
|
|
7
|
+
appName: {
|
|
8
|
+
type: z.string(),
|
|
9
|
+
description: 'Name of the app (used for file naming and default display name)',
|
|
10
|
+
},
|
|
11
|
+
uid: {
|
|
12
|
+
type: z.string(),
|
|
13
|
+
description: 'Unique identifier for the app component (must be unique per-project)',
|
|
14
|
+
},
|
|
15
|
+
description: {
|
|
16
|
+
type: z.string().optional(),
|
|
17
|
+
description: "Description of the app. Defaults to 'A public app'",
|
|
18
|
+
},
|
|
19
|
+
displayName: {
|
|
20
|
+
type: z.string().optional(),
|
|
21
|
+
description: 'Display name of the app. Defaults to the appName',
|
|
22
|
+
},
|
|
23
|
+
distribution: {
|
|
24
|
+
type: z.string().optional(),
|
|
25
|
+
description: "Distribution type (one of 'marketplace' or 'private'). Defaults to 'marketplace'",
|
|
26
|
+
},
|
|
27
|
+
supportEmail: {
|
|
28
|
+
type: z.string().optional(),
|
|
29
|
+
description: "Support email address. Defaults to 'support@example.com'",
|
|
30
|
+
},
|
|
31
|
+
documentationUrl: {
|
|
32
|
+
type: z.string().optional(),
|
|
33
|
+
description: "Documentation URL. Defaults to 'https://example.com/docs'",
|
|
34
|
+
},
|
|
35
|
+
supportUrl: {
|
|
36
|
+
type: z.string().optional(),
|
|
37
|
+
description: "Support URL. Defaults to 'https://example.com/support'",
|
|
38
|
+
},
|
|
39
|
+
supportPhone: {
|
|
40
|
+
type: z.string().optional(),
|
|
41
|
+
description: "Support phone number. Defaults to '+18005555555'",
|
|
42
|
+
},
|
|
43
|
+
redirectUrls: {
|
|
44
|
+
type: z.array(z.string()).optional(),
|
|
45
|
+
description: "OAuth redirect URLs. Defaults to ['http://localhost:3000/oauth-callback']",
|
|
46
|
+
},
|
|
47
|
+
requiredScopes: {
|
|
48
|
+
type: z.array(z.string()).optional(),
|
|
49
|
+
description: 'Required OAuth scopes. Consider what sub-components you plan to add. Defaults to basic CRM contact scopes',
|
|
50
|
+
},
|
|
51
|
+
optionalScopes: {
|
|
52
|
+
type: z.array(z.string()).optional(),
|
|
53
|
+
description: 'Optional OAuth scopes. Defaults to empty array',
|
|
54
|
+
},
|
|
55
|
+
permittedFetchUrls: {
|
|
56
|
+
type: z.array(z.string()).optional(),
|
|
57
|
+
description: "URLs permitted for fetch requests. Defaults to ['https://api.example.com']",
|
|
58
|
+
},
|
|
59
|
+
plannedFeatures: {
|
|
60
|
+
type: z.array(z.string()).optional(),
|
|
61
|
+
description: "List of planned sub-components/features (e.g., 'cards', 'functions', 'webhooks'). Used to suggest appropriate OAuth scopes",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
async execute(input) {
|
|
65
|
+
const { appName, uid, description = 'A public app', displayName = appName, distribution = 'marketplace', supportEmail = 'support@example.com', documentationUrl = 'https://example.com/docs', supportUrl = 'https://example.com/support', supportPhone = '+18005555555', redirectUrls = ['http://localhost:3000/oauth-callback'], requiredScopes = [
|
|
66
|
+
'crm.objects.contacts.read',
|
|
67
|
+
'crm.objects.contacts.write',
|
|
68
|
+
], optionalScopes = [], permittedFetchUrls = ['https://api.example.com'], plannedFeatures = [], } = input;
|
|
69
|
+
// Generate the sanitized app name for file naming
|
|
70
|
+
const sanitizedAppName = appName.toLowerCase().replace(/\s+/g, '-');
|
|
71
|
+
const fileName = `${sanitizedAppName}-hsmeta.json`;
|
|
72
|
+
const folderPath = 'src/app';
|
|
73
|
+
const appConfig = {
|
|
74
|
+
uid: uid,
|
|
75
|
+
type: 'app',
|
|
76
|
+
config: {
|
|
77
|
+
description: description,
|
|
78
|
+
name: displayName,
|
|
79
|
+
distribution: distribution,
|
|
80
|
+
auth: {
|
|
81
|
+
type: 'oauth',
|
|
82
|
+
redirectUrls: redirectUrls,
|
|
83
|
+
requiredScopes: requiredScopes,
|
|
84
|
+
optionalScopes: optionalScopes,
|
|
85
|
+
conditionallyRequiredScopes: [],
|
|
86
|
+
},
|
|
87
|
+
permittedUrls: {
|
|
88
|
+
fetch: permittedFetchUrls,
|
|
89
|
+
iframe: [],
|
|
90
|
+
img: [],
|
|
91
|
+
},
|
|
92
|
+
support: {
|
|
93
|
+
supportEmail: supportEmail,
|
|
94
|
+
documentationUrl: documentationUrl,
|
|
95
|
+
supportUrl: supportUrl,
|
|
96
|
+
supportPhone: supportPhone,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
// Generate scope recommendations based on planned features
|
|
101
|
+
const scopeRecommendations = this.generateScopeRecommendations(plannedFeatures);
|
|
102
|
+
// Generate next steps guidance
|
|
103
|
+
const nextSteps = this.generateNextSteps(plannedFeatures, folderPath);
|
|
104
|
+
return {
|
|
105
|
+
message: `Generated app component configuration for "${displayName}"`,
|
|
106
|
+
config: JSON.stringify(appConfig, null, 2),
|
|
107
|
+
folderPath: folderPath,
|
|
108
|
+
fileName: fileName,
|
|
109
|
+
fullPath: `${folderPath}/${fileName}`,
|
|
110
|
+
architecture: {
|
|
111
|
+
componentType: 'top-level',
|
|
112
|
+
role: 'authentication-provider',
|
|
113
|
+
singularComponent: true,
|
|
114
|
+
dependents: "All sub-components (cards, functions, settings, etc.) will depend on this app's authentication",
|
|
115
|
+
},
|
|
116
|
+
scopeRecommendations: scopeRecommendations,
|
|
117
|
+
nextSteps: nextSteps,
|
|
118
|
+
instructions: [
|
|
119
|
+
`Create the directory structure: ${folderPath}/`,
|
|
120
|
+
`Place the configuration file at: ${folderPath}/${fileName}`,
|
|
121
|
+
`This is a TOP-LEVEL component that provides OAuth authentication`,
|
|
122
|
+
`Sub-components (features) will live within ${folderPath}/ and depend on this app's authentication`,
|
|
123
|
+
`The app component uid: ${uid} must be unique within your project`,
|
|
124
|
+
'Consider what sub-components you plan to add and ensure sufficient OAuth scopes',
|
|
125
|
+
'Typically there is one app component per project (singular component)',
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
generateScopeRecommendations(plannedFeatures) {
|
|
130
|
+
const recommendations = [];
|
|
131
|
+
if (plannedFeatures.length === 0) {
|
|
132
|
+
return [
|
|
133
|
+
'Consider what sub-components you plan to add to determine required OAuth scopes',
|
|
134
|
+
'Cards typically need CRM object read access',
|
|
135
|
+
'Functions may need broader API access depending on functionality',
|
|
136
|
+
'Webhooks may need specific event subscription scopes',
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
const scopeMap = {
|
|
140
|
+
cards: [
|
|
141
|
+
'Cards typically need: crm.objects.contacts.read, crm.objects.companies.read, crm.objects.deals.read',
|
|
142
|
+
],
|
|
143
|
+
functions: [
|
|
144
|
+
'Functions may need: broader API access depending on functionality',
|
|
145
|
+
'Consider: crm.objects.*.read, crm.objects.*.write if manipulating CRM data',
|
|
146
|
+
],
|
|
147
|
+
webhooks: [
|
|
148
|
+
'Webhooks may need: specific event subscription scopes',
|
|
149
|
+
'Consider: webhooks scope and relevant object scopes for events you want to receive',
|
|
150
|
+
],
|
|
151
|
+
settings: [
|
|
152
|
+
'Settings typically need: minimal scopes, may inherit from other components',
|
|
153
|
+
],
|
|
154
|
+
'marketing-events': [
|
|
155
|
+
'Marketing events may need: marketing event creation and management scopes',
|
|
156
|
+
],
|
|
157
|
+
'timeline-events': [
|
|
158
|
+
'Timeline events may need: timeline read/write scopes for the relevant objects',
|
|
159
|
+
],
|
|
160
|
+
'workflow-actions': [
|
|
161
|
+
'Workflow actions may need: workflow and automation related scopes',
|
|
162
|
+
],
|
|
163
|
+
};
|
|
164
|
+
plannedFeatures.forEach(feature => {
|
|
165
|
+
if (scopeMap[feature]) {
|
|
166
|
+
recommendations.push(`For ${feature}: ${scopeMap[feature].join(', ')}`);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return recommendations;
|
|
170
|
+
}
|
|
171
|
+
generateNextSteps(plannedFeatures, appPath) {
|
|
172
|
+
const steps = [
|
|
173
|
+
'1. Create the app component configuration file and directory structure',
|
|
174
|
+
'2. Test OAuth flow and ensure authentication works correctly',
|
|
175
|
+
'3. Add sub-components within the app directory as needed:',
|
|
176
|
+
];
|
|
177
|
+
if (plannedFeatures.length > 0) {
|
|
178
|
+
plannedFeatures.forEach(feature => {
|
|
179
|
+
steps.push(` - ${appPath}/${feature}/`);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
steps.push(` - ${appPath}/cards/ (for UI cards)`);
|
|
184
|
+
steps.push(` - ${appPath}/functions/ (for serverless functions)`);
|
|
185
|
+
steps.push(` - ${appPath}/settings/ (for configuration UI)`);
|
|
186
|
+
steps.push(` - ${appPath}/webhooks/ (for event handling)`);
|
|
187
|
+
}
|
|
188
|
+
steps.push("4. Ensure all sub-components can access required APIs with the app's OAuth scopes");
|
|
189
|
+
steps.push('5. Test the complete application with all components integrated');
|
|
190
|
+
return steps;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export default GenerateAppComponentTool;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { MCPTool } from "mcp-framework";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
interface GenerateCardComponentInput {
|
|
4
|
+
cardName: string;
|
|
5
|
+
uid: string;
|
|
6
|
+
displayName?: string;
|
|
7
|
+
location?: string;
|
|
8
|
+
objectTypes?: string[];
|
|
9
|
+
componentFileName?: string;
|
|
10
|
+
}
|
|
11
|
+
declare class GenerateCardComponentTool extends MCPTool<GenerateCardComponentInput> {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
schema: {
|
|
15
|
+
cardName: {
|
|
16
|
+
type: z.ZodString;
|
|
17
|
+
description: string;
|
|
18
|
+
};
|
|
19
|
+
uid: {
|
|
20
|
+
type: z.ZodString;
|
|
21
|
+
description: string;
|
|
22
|
+
};
|
|
23
|
+
displayName: {
|
|
24
|
+
type: z.ZodOptional<z.ZodString>;
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
location: {
|
|
28
|
+
type: z.ZodOptional<z.ZodString>;
|
|
29
|
+
description: string;
|
|
30
|
+
};
|
|
31
|
+
objectTypes: {
|
|
32
|
+
type: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
33
|
+
description: string;
|
|
34
|
+
};
|
|
35
|
+
componentFileName: {
|
|
36
|
+
type: z.ZodOptional<z.ZodString>;
|
|
37
|
+
description: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
execute(input: GenerateCardComponentInput): Promise<{
|
|
41
|
+
message: string;
|
|
42
|
+
files: {
|
|
43
|
+
configuration: {
|
|
44
|
+
path: string;
|
|
45
|
+
content: string;
|
|
46
|
+
description: string;
|
|
47
|
+
};
|
|
48
|
+
packageJson: {
|
|
49
|
+
path: string;
|
|
50
|
+
content: string;
|
|
51
|
+
description: string;
|
|
52
|
+
};
|
|
53
|
+
reactComponent: {
|
|
54
|
+
path: string;
|
|
55
|
+
content: string;
|
|
56
|
+
description: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
folderPath: string;
|
|
60
|
+
architecture: {
|
|
61
|
+
componentType: string;
|
|
62
|
+
parentComponent: string;
|
|
63
|
+
category: string;
|
|
64
|
+
authenticationDependency: string;
|
|
65
|
+
allowMultiple: boolean;
|
|
66
|
+
technology: string;
|
|
67
|
+
};
|
|
68
|
+
instructions: string[];
|
|
69
|
+
nextSteps: string[];
|
|
70
|
+
developmentNotes: string[];
|
|
71
|
+
}>;
|
|
72
|
+
private toPascalCase;
|
|
73
|
+
}
|
|
74
|
+
export default GenerateCardComponentTool;
|