@channel47/google-ads-mcp 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/LICENSE +21 -0
- package/README.md +195 -0
- package/package.json +48 -0
- package/server/auth.js +74 -0
- package/server/index.js +199 -0
- package/server/prompts/templates.js +231 -0
- package/server/resources/index.js +67 -0
- package/server/tools/gaql-query.js +141 -0
- package/server/tools/list-accounts.js +61 -0
- package/server/tools/mutate.js +64 -0
- package/server/utils/gaql-templates.js +417 -0
- package/server/utils/mutations.js +436 -0
- package/server/utils/query-validator.js +74 -0
- package/server/utils/response-format.js +138 -0
- package/server/utils/validation.js +166 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Channel47
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# @channel47/google-ads-mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@channel47/google-ads-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
MCP server for Google Ads API access via GAQL (Google Ads Query Language).
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
This is a Model Context Protocol (MCP) server that provides tools for querying and mutating Google Ads data using GAQL. It's designed to work seamlessly with Claude Code and other MCP-compatible clients.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### For Claude Code Plugin Users
|
|
15
|
+
|
|
16
|
+
This package is automatically installed when using the [google-ads-specialist Claude Code plugin](https://marketplace.claude.com/plugins/google-ads-specialist). No manual installation required!
|
|
17
|
+
|
|
18
|
+
### Standalone Use
|
|
19
|
+
|
|
20
|
+
For use with other MCP clients or standalone testing:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx @channel47/google-ads-mcp@latest
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or install globally:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install -g @channel47/google-ads-mcp
|
|
30
|
+
google-ads-mcp
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
Set these environment variables before running:
|
|
36
|
+
|
|
37
|
+
### Required
|
|
38
|
+
|
|
39
|
+
| Variable | Description |
|
|
40
|
+
|----------|-------------|
|
|
41
|
+
| `GOOGLE_ADS_DEVELOPER_TOKEN` | Your Google Ads API Developer Token |
|
|
42
|
+
| `GOOGLE_ADS_CLIENT_ID` | OAuth 2.0 Client ID from Google Cloud |
|
|
43
|
+
| `GOOGLE_ADS_CLIENT_SECRET` | OAuth 2.0 Client Secret |
|
|
44
|
+
| `GOOGLE_ADS_REFRESH_TOKEN` | OAuth 2.0 Refresh Token |
|
|
45
|
+
|
|
46
|
+
### Optional
|
|
47
|
+
|
|
48
|
+
| Variable | Description |
|
|
49
|
+
|----------|-------------|
|
|
50
|
+
| `GOOGLE_ADS_LOGIN_CUSTOMER_ID` | MCC Account ID (10 digits, no dashes) |
|
|
51
|
+
| `GOOGLE_ADS_DEFAULT_CUSTOMER_ID` | Default account ID for queries |
|
|
52
|
+
|
|
53
|
+
## Tools
|
|
54
|
+
|
|
55
|
+
### list_accounts
|
|
56
|
+
|
|
57
|
+
List all accessible Google Ads accounts.
|
|
58
|
+
|
|
59
|
+
**Returns:** Array of account objects with ID, name, currency, and status.
|
|
60
|
+
|
|
61
|
+
### query
|
|
62
|
+
|
|
63
|
+
Execute any GAQL SELECT query. Returns clean JSON results.
|
|
64
|
+
|
|
65
|
+
**Parameters:**
|
|
66
|
+
- `customer_id` (string, optional): Account ID (10 digits, no dashes)
|
|
67
|
+
- `query` (string, required): GAQL SELECT query
|
|
68
|
+
- `limit` (integer, optional): Max rows to return (default: 100, max: 10000)
|
|
69
|
+
|
|
70
|
+
**Example:**
|
|
71
|
+
```javascript
|
|
72
|
+
{
|
|
73
|
+
"customer_id": "1234567890",
|
|
74
|
+
"query": "SELECT campaign.name, campaign.status FROM campaign WHERE campaign.status = 'ENABLED'",
|
|
75
|
+
"limit": 50
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### mutate
|
|
80
|
+
|
|
81
|
+
Execute write operations using GoogleAdsService.Mutate.
|
|
82
|
+
|
|
83
|
+
**Parameters:**
|
|
84
|
+
- `customer_id` (string, optional): Account ID
|
|
85
|
+
- `operations` (array, required): Mutation operations
|
|
86
|
+
- `partial_failure` (boolean, optional): Enable partial failure mode (default: true)
|
|
87
|
+
- `dry_run` (boolean, optional): Validate without executing (default: true for safety)
|
|
88
|
+
|
|
89
|
+
**Example:**
|
|
90
|
+
```javascript
|
|
91
|
+
{
|
|
92
|
+
"customer_id": "1234567890",
|
|
93
|
+
"operations": [
|
|
94
|
+
{
|
|
95
|
+
"campaignOperation": {
|
|
96
|
+
"update": {
|
|
97
|
+
"resourceName": "customers/1234567890/campaigns/123",
|
|
98
|
+
"status": "PAUSED"
|
|
99
|
+
},
|
|
100
|
+
"updateMask": "status"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"dry_run": false
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Resources & Prompts
|
|
109
|
+
|
|
110
|
+
The server provides:
|
|
111
|
+
- **Resources**: GAQL reference documentation accessible via MCP resources
|
|
112
|
+
- **Prompts**: Templates for common Google Ads operations
|
|
113
|
+
|
|
114
|
+
## Usage with Claude Code
|
|
115
|
+
|
|
116
|
+
This server is designed to work with the [google-ads-specialist plugin](https://marketplace.claude.com/plugins/google-ads-specialist), which provides:
|
|
117
|
+
|
|
118
|
+
- **9 Skill Files**: Progressive disclosure of GAQL patterns and best practices
|
|
119
|
+
- Atomic skills for focused tasks (campaign performance, search terms, wasted spend, etc.)
|
|
120
|
+
- Playbooks for comprehensive workflows (account health audit)
|
|
121
|
+
- Troubleshooting guides for common errors
|
|
122
|
+
- **PreToolUse Hook**: Validates skill references before query/mutate operations
|
|
123
|
+
- **Comprehensive Documentation**: Setup guides and OAuth configuration help
|
|
124
|
+
|
|
125
|
+
The plugin ensures Claude consults domain knowledge before executing queries, preventing hallucinated GAQL.
|
|
126
|
+
|
|
127
|
+
## Development
|
|
128
|
+
|
|
129
|
+
### Prerequisites
|
|
130
|
+
|
|
131
|
+
- Node.js 18 or higher
|
|
132
|
+
- Google Ads API access (Developer Token)
|
|
133
|
+
- OAuth 2.0 credentials from Google Cloud
|
|
134
|
+
|
|
135
|
+
### Setup
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git clone https://github.com/channel47/google-ads-mcp-server.git
|
|
139
|
+
cd google-ads-mcp-server
|
|
140
|
+
npm install
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Testing
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm test
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Running Locally
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm start
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Architecture
|
|
156
|
+
|
|
157
|
+
**Minimal Design:**
|
|
158
|
+
- ~200 lines of server code
|
|
159
|
+
- 3 core tools (list, query, mutate)
|
|
160
|
+
- OAuth 2.0 authentication
|
|
161
|
+
- Resources for GAQL reference
|
|
162
|
+
- Prompts for common patterns
|
|
163
|
+
|
|
164
|
+
**Security:**
|
|
165
|
+
- Dry-run mode enabled by default for mutations
|
|
166
|
+
- Environment-based credential management
|
|
167
|
+
- Input validation for all operations
|
|
168
|
+
|
|
169
|
+
## Contributing
|
|
170
|
+
|
|
171
|
+
Contributions welcome! Please:
|
|
172
|
+
|
|
173
|
+
1. Fork the repository
|
|
174
|
+
2. Create a feature branch
|
|
175
|
+
3. Make your changes with tests
|
|
176
|
+
4. Submit a pull request
|
|
177
|
+
|
|
178
|
+
## Links
|
|
179
|
+
|
|
180
|
+
- [NPM Package](https://www.npmjs.com/package/@channel47/google-ads-mcp)
|
|
181
|
+
- [GitHub Repository](https://github.com/channel47/google-ads-mcp-server)
|
|
182
|
+
- [Claude Code Plugin](https://marketplace.claude.com/plugins/google-ads-specialist)
|
|
183
|
+
- [Google Ads API Documentation](https://developers.google.com/google-ads/api/docs/start)
|
|
184
|
+
- [GAQL Reference](https://developers.google.com/google-ads/api/docs/query/overview)
|
|
185
|
+
- [Model Context Protocol](https://modelcontextprotocol.io)
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT - See [LICENSE](LICENSE) file for details.
|
|
190
|
+
|
|
191
|
+
## Support
|
|
192
|
+
|
|
193
|
+
For issues or questions:
|
|
194
|
+
- Plugin-related: [Plugin Repository Issues](https://github.com/ctrlswing/channel47-marketplace/issues)
|
|
195
|
+
- Server-related: [Server Repository Issues](https://github.com/channel47/google-ads-mcp-server/issues)
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@channel47/google-ads-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Google Ads MCP Server - Query and mutate Google Ads data using GAQL",
|
|
5
|
+
"main": "server/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"google-ads-mcp": "server/index.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"server/**/*.js",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"start": "node server/index.js",
|
|
17
|
+
"test": "node --test *.test.js test/*.test.js",
|
|
18
|
+
"lint": "eslint server/",
|
|
19
|
+
"prepublishOnly": "npm test"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mcp",
|
|
23
|
+
"model-context-protocol",
|
|
24
|
+
"google-ads",
|
|
25
|
+
"gaql",
|
|
26
|
+
"analytics",
|
|
27
|
+
"advertising",
|
|
28
|
+
"claude"
|
|
29
|
+
],
|
|
30
|
+
"author": "Channel47",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/channel47/google-ads-mcp-server.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/channel47/google-ads-mcp-server/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/channel47/google-ads-mcp-server#readme",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
42
|
+
"google-ads-api": "^21.0.1",
|
|
43
|
+
"google-auth-library": "^9.0.0"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/server/auth.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { GoogleAdsApi } from 'google-ads-api';
|
|
3
|
+
|
|
4
|
+
// Required environment variables for OAuth 2.0 authentication
|
|
5
|
+
const REQUIRED_ENV_VARS = [
|
|
6
|
+
'GOOGLE_ADS_DEVELOPER_TOKEN',
|
|
7
|
+
'GOOGLE_ADS_CLIENT_ID',
|
|
8
|
+
'GOOGLE_ADS_CLIENT_SECRET',
|
|
9
|
+
'GOOGLE_ADS_REFRESH_TOKEN',
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Validate all required environment variables are present
|
|
14
|
+
* @returns {{ valid: boolean, missing: string[] }}
|
|
15
|
+
*/
|
|
16
|
+
export function validateEnvironment() {
|
|
17
|
+
const missing = REQUIRED_ENV_VARS.filter(varName => !process.env[varName]);
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
valid: missing.length === 0,
|
|
21
|
+
missing
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let cachedClient = null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Initialize and return Google Ads API client
|
|
29
|
+
* Caches client instance for reuse
|
|
30
|
+
* @returns {GoogleAdsApi}
|
|
31
|
+
* @throws {Error} If environment variables are missing or invalid
|
|
32
|
+
*/
|
|
33
|
+
export function initializeGoogleAdsClient() {
|
|
34
|
+
if (cachedClient) {
|
|
35
|
+
return cachedClient;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Validate environment first
|
|
39
|
+
const { valid, missing } = validateEnvironment();
|
|
40
|
+
if (!valid) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Missing required environment variables: ${missing.join(', ')}\n` +
|
|
43
|
+
`Please set these variables before starting the server.`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Initialize Google Ads client
|
|
48
|
+
try {
|
|
49
|
+
cachedClient = new GoogleAdsApi({
|
|
50
|
+
client_id: process.env.GOOGLE_ADS_CLIENT_ID,
|
|
51
|
+
client_secret: process.env.GOOGLE_ADS_CLIENT_SECRET,
|
|
52
|
+
developer_token: process.env.GOOGLE_ADS_DEVELOPER_TOKEN,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return cachedClient;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
throw new Error(`Failed to initialize Google Ads client: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get authenticated customer client for a specific account
|
|
63
|
+
* @param {string} customerId - Google Ads account ID (without dashes)
|
|
64
|
+
* @returns {Customer}
|
|
65
|
+
*/
|
|
66
|
+
export function getCustomerClient(customerId) {
|
|
67
|
+
const client = initializeGoogleAdsClient();
|
|
68
|
+
|
|
69
|
+
return client.Customer({
|
|
70
|
+
customer_id: customerId,
|
|
71
|
+
refresh_token: process.env.GOOGLE_ADS_REFRESH_TOKEN,
|
|
72
|
+
login_customer_id: process.env.GOOGLE_ADS_LOGIN_CUSTOMER_ID,
|
|
73
|
+
});
|
|
74
|
+
}
|
package/server/index.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import {
|
|
5
|
+
CallToolRequestSchema,
|
|
6
|
+
ListToolsRequestSchema,
|
|
7
|
+
ListPromptsRequestSchema,
|
|
8
|
+
GetPromptRequestSchema,
|
|
9
|
+
ListResourcesRequestSchema,
|
|
10
|
+
ReadResourceRequestSchema,
|
|
11
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
|
|
13
|
+
// Import auth for validation
|
|
14
|
+
import { validateEnvironment } from './auth.js';
|
|
15
|
+
|
|
16
|
+
// Import tools
|
|
17
|
+
import { listAccounts } from './tools/list-accounts.js';
|
|
18
|
+
import { runGaqlQuery } from './tools/gaql-query.js';
|
|
19
|
+
import { mutate } from './tools/mutate.js';
|
|
20
|
+
|
|
21
|
+
// Import resources
|
|
22
|
+
import { getResourcesList, readResource } from './resources/index.js';
|
|
23
|
+
|
|
24
|
+
// Import prompts
|
|
25
|
+
import { getPromptsList, renderPrompt } from './prompts/templates.js';
|
|
26
|
+
|
|
27
|
+
// Server metadata
|
|
28
|
+
const SERVER_NAME = 'google-ads-mcp';
|
|
29
|
+
const SERVER_VERSION = '1.0.0';
|
|
30
|
+
|
|
31
|
+
// Validate environment on startup
|
|
32
|
+
const { valid, missing } = validateEnvironment();
|
|
33
|
+
if (!valid) {
|
|
34
|
+
console.error(`Missing required environment variables: ${missing.join(', ')}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Create MCP server
|
|
39
|
+
const server = new Server(
|
|
40
|
+
{
|
|
41
|
+
name: SERVER_NAME,
|
|
42
|
+
version: SERVER_VERSION,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
capabilities: {
|
|
46
|
+
tools: {},
|
|
47
|
+
prompts: {},
|
|
48
|
+
resources: {},
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Tool definitions
|
|
54
|
+
const TOOLS = [
|
|
55
|
+
{
|
|
56
|
+
name: 'list_accounts',
|
|
57
|
+
description: 'List all accessible Google Ads accounts under the authenticated user or MCC. Use this first to find account IDs before running other tools.',
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: 'object',
|
|
60
|
+
properties: {
|
|
61
|
+
include_manager_accounts: {
|
|
62
|
+
type: 'boolean',
|
|
63
|
+
description: 'Include manager (MCC) accounts in results',
|
|
64
|
+
default: false
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'query',
|
|
71
|
+
description: 'Execute any GAQL SELECT query. Returns clean JSON results. Mutations are blocked - use mutate tool for write operations.',
|
|
72
|
+
inputSchema: {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
customer_id: {
|
|
76
|
+
type: 'string',
|
|
77
|
+
description: 'Google Ads account ID (optional, uses default if not specified)'
|
|
78
|
+
},
|
|
79
|
+
query: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'Full GAQL query string (SELECT only)'
|
|
82
|
+
},
|
|
83
|
+
limit: {
|
|
84
|
+
type: 'integer',
|
|
85
|
+
description: 'Maximum rows to return (default: 100, max: 10000)',
|
|
86
|
+
default: 100
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
required: ['query']
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'mutate',
|
|
94
|
+
description: 'Execute write operations using GoogleAdsService.Mutate. Supports all operation types. Default dry_run=true for safety.',
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
properties: {
|
|
98
|
+
customer_id: {
|
|
99
|
+
type: 'string',
|
|
100
|
+
description: 'Google Ads customer ID (optional, uses default if not specified)'
|
|
101
|
+
},
|
|
102
|
+
operations: {
|
|
103
|
+
type: 'array',
|
|
104
|
+
description: 'Array of mutation operation objects',
|
|
105
|
+
items: {
|
|
106
|
+
type: 'object'
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
partial_failure: {
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
description: 'Enable partial failure mode (default: true)',
|
|
112
|
+
default: true
|
|
113
|
+
},
|
|
114
|
+
dry_run: {
|
|
115
|
+
type: 'boolean',
|
|
116
|
+
description: 'Validate only, do not execute (default: true)',
|
|
117
|
+
default: true
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
required: ['operations']
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
// Register list_tools handler
|
|
126
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
127
|
+
return { tools: TOOLS };
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Register call_tool handler
|
|
131
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
132
|
+
const { name, arguments: params } = request.params;
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
switch (name) {
|
|
136
|
+
case 'list_accounts':
|
|
137
|
+
return await listAccounts(params);
|
|
138
|
+
|
|
139
|
+
case 'query':
|
|
140
|
+
return await runGaqlQuery(params);
|
|
141
|
+
|
|
142
|
+
case 'mutate':
|
|
143
|
+
return await mutate(params);
|
|
144
|
+
|
|
145
|
+
default:
|
|
146
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error(`Tool error (${name}):`, error);
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Register list_prompts handler
|
|
155
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
156
|
+
return { prompts: getPromptsList() };
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Register get_prompt handler
|
|
160
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
161
|
+
const { name, arguments: args } = request.params;
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
return renderPrompt(name, args || {});
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error(`Prompt error (${name}):`, error);
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Register list_resources handler
|
|
172
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
173
|
+
return { resources: getResourcesList() };
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Register read_resource handler
|
|
177
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
178
|
+
const { uri } = request.params;
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
return readResource(uri);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error(`Resource error (${uri}):`, error);
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Start server
|
|
189
|
+
async function main() {
|
|
190
|
+
const transport = new StdioServerTransport();
|
|
191
|
+
await server.connect(transport);
|
|
192
|
+
|
|
193
|
+
console.error(`${SERVER_NAME} v${SERVER_VERSION} started`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
main().catch((error) => {
|
|
197
|
+
console.error('Fatal error:', error);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
});
|