@higrowth/mcp-server 1.0.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.
- package/README.md +172 -0
- package/package.json +39 -0
- package/src/cli.js +110 -0
- package/src/index.js +16 -0
- package/src/server.js +188 -0
package/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# @higrowth/mcp-server
|
|
2
|
+
|
|
3
|
+
Connect AI assistants to [HiGrowth](https://higrowthdev.com) SEO tools via the Model Context Protocol (MCP).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔍 **Discover Opportunities** - Find SEO optimization opportunities
|
|
8
|
+
- 💡 **Keyword Ideas** - Generate keyword variations and ideas
|
|
9
|
+
- 📝 **Content Planning** - Create comprehensive content strategies
|
|
10
|
+
- ✍️ **Content Generation** - Generate SEO-optimized content
|
|
11
|
+
- 🔬 **Content Reviews** - Review content for SEO quality
|
|
12
|
+
- 📊 **Page Analysis** - Analyze page performance
|
|
13
|
+
- 🛠️ **Optimization Fixes** - Get specific optimization recommendations
|
|
14
|
+
- 📈 **Keyword Data** - Get keyword performance metrics
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### 1. Get Your API Key
|
|
19
|
+
|
|
20
|
+
Sign up at [higrowthdev.com](https://higrowthdev.com) to get your MCP API key.
|
|
21
|
+
|
|
22
|
+
### 2. Connect to Cursor
|
|
23
|
+
|
|
24
|
+
Add this to your `.mcp.json` file (usually in your project root or `~/.cursor/`):
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"higrowth": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "@higrowth/mcp-server", "--api-key=YOUR_API_KEY"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 3. Restart Cursor
|
|
38
|
+
|
|
39
|
+
Restart Cursor to load the MCP server. You should see "higrowth" in your available tools.
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
Once connected, you can ask your AI assistant questions like:
|
|
44
|
+
|
|
45
|
+
- "Find SEO opportunities for my site"
|
|
46
|
+
- "Generate keyword ideas for 'cloud computing'"
|
|
47
|
+
- "Create a content plan for 'kubernetes best practices'"
|
|
48
|
+
- "Analyze the page at https://example.com/blog/post"
|
|
49
|
+
- "What optimization fixes should I make?"
|
|
50
|
+
|
|
51
|
+
## Available Tools
|
|
52
|
+
|
|
53
|
+
| Tool | Description |
|
|
54
|
+
|------|-------------|
|
|
55
|
+
| `discover_opportunities` | Discover SEO optimization opportunities |
|
|
56
|
+
| `list_opportunities` | List existing opportunities with filters |
|
|
57
|
+
| `suggest_keyword_ideas` | Generate keyword variations from a seed |
|
|
58
|
+
| `create_content_plan` | Create content strategy and outlines |
|
|
59
|
+
| `generate_content` | Generate full SEO-optimized content |
|
|
60
|
+
| `run_content_reviews` | Run SEO and quality reviews |
|
|
61
|
+
| `analyze_page` | Analyze a page for SEO performance |
|
|
62
|
+
| `get_optimization_fixes` | Get specific optimization recommendations |
|
|
63
|
+
| `get_task_status` | Check status of async operations |
|
|
64
|
+
| `get_page_keyword_data` | Get keyword performance metrics |
|
|
65
|
+
| `search_page_keywords` | Semantic search for keywords |
|
|
66
|
+
|
|
67
|
+
## Configuration Options
|
|
68
|
+
|
|
69
|
+
### Command Line
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx @higrowth/mcp-server --api-key=YOUR_KEY
|
|
73
|
+
npx @higrowth/mcp-server --api-key=YOUR_KEY --url=https://custom.api.com/api/v1/mcp
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Environment Variables
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
export HIGROWTH_API_KEY=your_api_key
|
|
80
|
+
export HIGROWTH_MCP_URL=https://api.higrowthdev.com/api/v1/mcp # optional
|
|
81
|
+
|
|
82
|
+
npx @higrowth/mcp-server
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Cursor Configuration with Environment Variables
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"mcpServers": {
|
|
90
|
+
"higrowth": {
|
|
91
|
+
"command": "npx",
|
|
92
|
+
"args": ["-y", "@higrowth/mcp-server"],
|
|
93
|
+
"env": {
|
|
94
|
+
"HIGROWTH_API_KEY": "YOUR_API_KEY"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Self-Hosted / Enterprise
|
|
102
|
+
|
|
103
|
+
For self-hosted HiGrowth installations, specify your custom API URL:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"higrowth": {
|
|
109
|
+
"command": "npx",
|
|
110
|
+
"args": [
|
|
111
|
+
"-y",
|
|
112
|
+
"@higrowth/mcp-server",
|
|
113
|
+
"--api-key=YOUR_KEY",
|
|
114
|
+
"--url=https://your-api.company.com/api/v1/mcp"
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Programmatic Usage
|
|
122
|
+
|
|
123
|
+
You can also use the server programmatically:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
import { MCPServer } from '@higrowth/mcp-server';
|
|
127
|
+
|
|
128
|
+
const server = new MCPServer(
|
|
129
|
+
'https://api.higrowthdev.com/api/v1/mcp',
|
|
130
|
+
'your-api-key'
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
await server.start();
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Troubleshooting
|
|
137
|
+
|
|
138
|
+
### Server not appearing in Cursor
|
|
139
|
+
|
|
140
|
+
1. Ensure your `.mcp.json` is valid JSON
|
|
141
|
+
2. Restart Cursor completely (Cmd/Ctrl+Q, then reopen)
|
|
142
|
+
3. Check Cursor's developer console for errors (Help → Toggle Developer Tools)
|
|
143
|
+
|
|
144
|
+
### Authentication errors
|
|
145
|
+
|
|
146
|
+
1. Verify your API key is correct
|
|
147
|
+
2. Test the connection directly:
|
|
148
|
+
```bash
|
|
149
|
+
curl https://api.higrowthdev.com/api/v1/mcp/tools \
|
|
150
|
+
-H "X-API-Key: YOUR_KEY"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Connection timeouts
|
|
154
|
+
|
|
155
|
+
1. Check your network connection
|
|
156
|
+
2. Verify the API URL is accessible
|
|
157
|
+
3. For enterprise installations, check firewall rules
|
|
158
|
+
|
|
159
|
+
## Requirements
|
|
160
|
+
|
|
161
|
+
- Node.js 18.0.0 or higher
|
|
162
|
+
- Valid HiGrowth API key
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT
|
|
167
|
+
|
|
168
|
+
## Support
|
|
169
|
+
|
|
170
|
+
- 📧 Email: support@higrowthdev.com
|
|
171
|
+
- 📖 Docs: https://docs.higrowthdev.com
|
|
172
|
+
- 🐛 Issues: https://github.com/higrowth/mcp-server/issues
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@higrowth/mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for HiGrowth SEO platform - connect AI assistants to SEO tools",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"seo",
|
|
9
|
+
"ai",
|
|
10
|
+
"cursor",
|
|
11
|
+
"claude",
|
|
12
|
+
"higrowth"
|
|
13
|
+
],
|
|
14
|
+
"author": "HiGrowth",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/higrowth/mcp-server.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://higrowthdev.com",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"main": "src/index.js",
|
|
23
|
+
"bin": {
|
|
24
|
+
"higrowth-mcp": "./src/cli.js"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"src",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18.0.0"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"start": "node src/cli.js",
|
|
35
|
+
"test": "node --test src/*.test.js"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {},
|
|
38
|
+
"devDependencies": {}
|
|
39
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HiGrowth MCP Server CLI
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx @higrowth/mcp-server --api-key=YOUR_KEY
|
|
8
|
+
* npx @higrowth/mcp-server --api-key=YOUR_KEY --url=https://custom.api.com/api/v1/mcp
|
|
9
|
+
*
|
|
10
|
+
* Environment variables:
|
|
11
|
+
* HIGROWTH_API_KEY - Your MCP API key
|
|
12
|
+
* HIGROWTH_MCP_URL - Custom MCP endpoint URL (optional)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { MCPServer } from './server.js';
|
|
16
|
+
|
|
17
|
+
const DEFAULT_URL = 'https://api.higrowthdev.com/api/v1/mcp';
|
|
18
|
+
|
|
19
|
+
function parseArgs(args) {
|
|
20
|
+
const config = {
|
|
21
|
+
apiKey: process.env.HIGROWTH_API_KEY || process.env.CGEN_API_KEY,
|
|
22
|
+
url: process.env.HIGROWTH_MCP_URL || process.env.CGEN_MCP_URL || DEFAULT_URL,
|
|
23
|
+
help: false,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
for (const arg of args) {
|
|
27
|
+
if (arg === '--help' || arg === '-h') {
|
|
28
|
+
config.help = true;
|
|
29
|
+
} else if (arg.startsWith('--api-key=')) {
|
|
30
|
+
config.apiKey = arg.split('=')[1];
|
|
31
|
+
} else if (arg.startsWith('--url=')) {
|
|
32
|
+
config.url = arg.split('=')[1];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return config;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function showHelp() {
|
|
40
|
+
console.error(`
|
|
41
|
+
HiGrowth MCP Server - Connect AI assistants to HiGrowth SEO tools
|
|
42
|
+
|
|
43
|
+
USAGE:
|
|
44
|
+
npx @higrowth/mcp-server --api-key=YOUR_KEY [options]
|
|
45
|
+
|
|
46
|
+
OPTIONS:
|
|
47
|
+
--api-key=KEY Your HiGrowth MCP API key (required)
|
|
48
|
+
--url=URL Custom MCP endpoint URL (default: ${DEFAULT_URL})
|
|
49
|
+
--help, -h Show this help message
|
|
50
|
+
|
|
51
|
+
ENVIRONMENT VARIABLES:
|
|
52
|
+
HIGROWTH_API_KEY Your MCP API key (alternative to --api-key)
|
|
53
|
+
HIGROWTH_MCP_URL Custom endpoint URL (alternative to --url)
|
|
54
|
+
|
|
55
|
+
CURSOR CONFIGURATION:
|
|
56
|
+
Add to your .mcp.json:
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"higrowth": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["-y", "@higrowth/mcp-server", "--api-key=YOUR_KEY"]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
AVAILABLE TOOLS:
|
|
68
|
+
• discover_opportunities - Find SEO optimization opportunities
|
|
69
|
+
• suggest_keyword_ideas - Generate keyword variations
|
|
70
|
+
• create_content_plan - Create content strategies
|
|
71
|
+
• generate_content - Generate SEO-optimized content
|
|
72
|
+
• run_content_reviews - Review content for SEO quality
|
|
73
|
+
• analyze_page - Analyze page performance
|
|
74
|
+
• get_optimization_fixes - Get specific optimization recommendations
|
|
75
|
+
• get_task_status - Check async task status
|
|
76
|
+
• get_page_keyword_data - Get keyword performance data
|
|
77
|
+
• search_page_keywords - Search keywords semantically
|
|
78
|
+
• list_opportunities - List existing opportunities
|
|
79
|
+
|
|
80
|
+
Get your API key at: https://higrowthdev.com
|
|
81
|
+
`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function main() {
|
|
85
|
+
const config = parseArgs(process.argv.slice(2));
|
|
86
|
+
|
|
87
|
+
if (config.help) {
|
|
88
|
+
showHelp();
|
|
89
|
+
process.exit(0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!config.apiKey) {
|
|
93
|
+
console.error('Error: API key is required.');
|
|
94
|
+
console.error('');
|
|
95
|
+
console.error('Provide it via:');
|
|
96
|
+
console.error(' --api-key=YOUR_KEY argument');
|
|
97
|
+
console.error(' HIGROWTH_API_KEY environment variable');
|
|
98
|
+
console.error('');
|
|
99
|
+
console.error('Run with --help for more information.');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const server = new MCPServer(config.url, config.apiKey);
|
|
104
|
+
await server.start();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
main().catch((error) => {
|
|
108
|
+
console.error('Fatal error:', error.message);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
});
|
package/src/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HiGrowth MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Programmatic API for embedding the MCP server in other applications.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* import { MCPServer } from '@higrowth/mcp-server';
|
|
8
|
+
*
|
|
9
|
+
* const server = new MCPServer(
|
|
10
|
+
* 'https://api.higrowthdev.com/api/v1/mcp',
|
|
11
|
+
* 'your-api-key'
|
|
12
|
+
* );
|
|
13
|
+
* await server.start();
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export { MCPServer } from './server.js';
|
package/src/server.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HiGrowth MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Bridges the Model Context Protocol (MCP) to the HiGrowth SEO API.
|
|
5
|
+
* Communicates via stdio with MCP clients like Cursor.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as readline from 'readline';
|
|
9
|
+
|
|
10
|
+
const SERVER_INFO = {
|
|
11
|
+
name: 'higrowth-mcp-server',
|
|
12
|
+
version: '1.0.0',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const CAPABILITIES = {
|
|
16
|
+
tools: {},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export class MCPServer {
|
|
20
|
+
constructor(apiUrl, apiKey) {
|
|
21
|
+
this.apiUrl = apiUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
22
|
+
this.apiKey = apiKey;
|
|
23
|
+
this.tools = null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async start() {
|
|
27
|
+
const rl = readline.createInterface({
|
|
28
|
+
input: process.stdin,
|
|
29
|
+
output: process.stdout,
|
|
30
|
+
terminal: false,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
rl.on('line', async (line) => {
|
|
34
|
+
if (!line.trim()) return;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const request = JSON.parse(line);
|
|
38
|
+
const response = await this.handleRequest(request);
|
|
39
|
+
if (response) {
|
|
40
|
+
console.log(JSON.stringify(response));
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
const errorResponse = {
|
|
44
|
+
jsonrpc: '2.0',
|
|
45
|
+
id: null,
|
|
46
|
+
error: {
|
|
47
|
+
code: -32700,
|
|
48
|
+
message: 'Parse error',
|
|
49
|
+
data: error.message,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
console.log(JSON.stringify(errorResponse));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
rl.on('close', () => {
|
|
57
|
+
process.exit(0);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Keep process alive
|
|
61
|
+
process.stdin.resume();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async handleRequest(request) {
|
|
65
|
+
const { id, method, params } = request;
|
|
66
|
+
|
|
67
|
+
// Notifications (no id) don't need responses
|
|
68
|
+
if (id === undefined && method === 'notifications/initialized') {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
let result;
|
|
74
|
+
|
|
75
|
+
switch (method) {
|
|
76
|
+
case 'initialize':
|
|
77
|
+
result = await this.handleInitialize(params);
|
|
78
|
+
break;
|
|
79
|
+
case 'tools/list':
|
|
80
|
+
result = await this.handleListTools();
|
|
81
|
+
break;
|
|
82
|
+
case 'tools/call':
|
|
83
|
+
result = await this.handleCallTool(params);
|
|
84
|
+
break;
|
|
85
|
+
case 'ping':
|
|
86
|
+
result = {};
|
|
87
|
+
break;
|
|
88
|
+
default:
|
|
89
|
+
return {
|
|
90
|
+
jsonrpc: '2.0',
|
|
91
|
+
id,
|
|
92
|
+
error: {
|
|
93
|
+
code: -32601,
|
|
94
|
+
message: `Method not found: ${method}`,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
jsonrpc: '2.0',
|
|
101
|
+
id,
|
|
102
|
+
result,
|
|
103
|
+
};
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return {
|
|
106
|
+
jsonrpc: '2.0',
|
|
107
|
+
id,
|
|
108
|
+
error: {
|
|
109
|
+
code: -32000,
|
|
110
|
+
message: error.message,
|
|
111
|
+
data: error.stack,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async handleInitialize(params) {
|
|
118
|
+
// Fetch tools on initialization to validate connection
|
|
119
|
+
await this.fetchTools();
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
protocolVersion: '2024-11-05',
|
|
123
|
+
serverInfo: SERVER_INFO,
|
|
124
|
+
capabilities: CAPABILITIES,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async handleListTools() {
|
|
129
|
+
if (!this.tools) {
|
|
130
|
+
await this.fetchTools();
|
|
131
|
+
}
|
|
132
|
+
return { tools: this.tools };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async handleCallTool(params) {
|
|
136
|
+
const { name, arguments: args } = params;
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const response = await fetch(`${this.apiUrl}/tools/call`, {
|
|
140
|
+
method: 'POST',
|
|
141
|
+
headers: {
|
|
142
|
+
'Content-Type': 'application/json',
|
|
143
|
+
'X-API-Key': this.apiKey,
|
|
144
|
+
},
|
|
145
|
+
body: JSON.stringify({ name, arguments: args || {} }),
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (!response.ok) {
|
|
149
|
+
const errorText = await response.text();
|
|
150
|
+
throw new Error(`API error (${response.status}): ${errorText}`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const result = await response.json();
|
|
154
|
+
return result;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
return {
|
|
157
|
+
content: [
|
|
158
|
+
{
|
|
159
|
+
type: 'text',
|
|
160
|
+
text: `Error calling tool ${name}: ${error.message}`,
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
isError: true,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async fetchTools() {
|
|
169
|
+
try {
|
|
170
|
+
const response = await fetch(`${this.apiUrl}/tools`, {
|
|
171
|
+
method: 'GET',
|
|
172
|
+
headers: {
|
|
173
|
+
'X-API-Key': this.apiKey,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (!response.ok) {
|
|
178
|
+
const errorText = await response.text();
|
|
179
|
+
throw new Error(`Failed to fetch tools (${response.status}): ${errorText}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const data = await response.json();
|
|
183
|
+
this.tools = data.tools || [];
|
|
184
|
+
} catch (error) {
|
|
185
|
+
throw new Error(`Cannot connect to HiGrowth API: ${error.message}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|