@volaticloud/mcp-server 0.1.0-dev.pr507.25e1c71

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 ADDED
@@ -0,0 +1,104 @@
1
+ # @volaticloud/mcp-server
2
+
3
+ MCP (Model Context Protocol) server for the VolatiCloud GraphQL API. Lets AI agents manage strategies, bots, exchanges, and backtests through natural language.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx -y @volaticloud/mcp-server
9
+ ```
10
+
11
+ ## Prerequisites
12
+
13
+ 1. A VolatiCloud account with an organization
14
+ 2. An API client (create one at **Organization > API Keys** in the dashboard)
15
+
16
+ ## Configuration
17
+
18
+ ### Claude Code
19
+
20
+ Add to your project's `.mcp.json`:
21
+
22
+ ```json
23
+ {
24
+ "mcpServers": {
25
+ "volaticloud": {
26
+ "command": "npx",
27
+ "args": ["-y", "@volaticloud/mcp-server"],
28
+ "env": {
29
+ "VOLATICLOUD_ENDPOINT": "https://api.volaticloud.com/gateway/v1/query",
30
+ "VOLATICLOUD_CLIENT_ID": "<your-client-id>",
31
+ "VOLATICLOUD_CLIENT_SECRET": "<your-client-secret>"
32
+ }
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ### Claude Desktop
39
+
40
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
41
+
42
+ ```json
43
+ {
44
+ "mcpServers": {
45
+ "volaticloud": {
46
+ "command": "npx",
47
+ "args": ["-y", "@volaticloud/mcp-server"],
48
+ "env": {
49
+ "VOLATICLOUD_ENDPOINT": "https://api.volaticloud.com/gateway/v1/query",
50
+ "VOLATICLOUD_CLIENT_ID": "<your-client-id>",
51
+ "VOLATICLOUD_CLIENT_SECRET": "<your-client-secret>"
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ ## Environment Variables
59
+
60
+ | Variable | Required | Default | Description |
61
+ |----------|----------|---------|-------------|
62
+ | `VOLATICLOUD_CLIENT_ID` | Yes | — | API client ID |
63
+ | `VOLATICLOUD_CLIENT_SECRET` | Yes | — | API client secret |
64
+ | `VOLATICLOUD_ENDPOINT` | No | `https://api.volaticloud.com/gateway/v1/query` | GraphQL endpoint URL |
65
+
66
+ ## Available Tools
67
+
68
+ ### Static Tools
69
+
70
+ | Tool | Description |
71
+ |------|-------------|
72
+ | `introspect_schema` | Explore the API schema, optionally drill into a specific type |
73
+ | `search_schema` | Search types, fields, and enums by keyword |
74
+ | `execute_query` | Run any GraphQL query with variables |
75
+ | `execute_mutation` | Run any GraphQL mutation with variables |
76
+
77
+ ### Dynamic Tools (auto-generated)
78
+
79
+ The server introspects the GraphQL schema at startup and generates individual tools for each query and mutation. Examples:
80
+
81
+ - `strategies`, `bots`, `exchanges`, `runners` — List resources
82
+ - `create_strategy`, `create_bot`, `create_exchange` — Create resources
83
+ - `update_strategy`, `update_bot` — Update resources
84
+ - `delete_strategy`, `delete_bot` — Delete resources
85
+ - `start_bot`, `stop_bot`, `restart_bot` — Bot lifecycle
86
+ - `run_backtest`, `run_simulation` — Run analysis
87
+ - `get_bot_open_positions`, `get_bot_trading_config` — Live data
88
+
89
+ ## How It Works
90
+
91
+ 1. On startup, authenticates using your API client credentials (OAuth2 client_credentials flow)
92
+ 2. Introspects the GraphQL schema to discover all available operations
93
+ 3. Generates MCP tool definitions from each query and mutation
94
+ 4. Communicates with AI agents via stdio (standard MCP transport)
95
+ 5. Automatically refreshes the access token before expiry
96
+
97
+ ## Development
98
+
99
+ ```bash
100
+ cd mcp-server
101
+ npm install
102
+ npm run build
103
+ node dist/index.js
104
+ ```
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath } from "url";
3
+ import { dirname, resolve } from "path";
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const entry = resolve(__dirname, "..", "dist", "index.js");
7
+
8
+ import(entry).catch((err) => {
9
+ console.error("Failed to start VolatiCloud MCP server:", err.message);
10
+ process.exit(1);
11
+ });
@@ -0,0 +1,9 @@
1
+ import type { ServerConfig } from "../types.js";
2
+ export declare class AuthManager {
3
+ private token;
4
+ private config;
5
+ constructor(config: ServerConfig);
6
+ getAccessToken(): Promise<string>;
7
+ private authenticate;
8
+ }
9
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/graphql/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,YAAY,EAAE,MAAM,aAAa,CAAC;AAY5E,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,YAAY;IAI1B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;YAQzB,YAAY;CAyC3B"}
@@ -0,0 +1,51 @@
1
+ const AUTHENTICATE_MUTATION = `
2
+ mutation AuthenticateAPIClient($clientId: String!, $clientSecret: String!) {
3
+ authenticateAPIClient(clientId: $clientId, clientSecret: $clientSecret) {
4
+ accessToken
5
+ tokenType
6
+ expiresIn
7
+ }
8
+ }
9
+ `;
10
+ export class AuthManager {
11
+ token = null;
12
+ config;
13
+ constructor(config) {
14
+ this.config = config;
15
+ }
16
+ async getAccessToken() {
17
+ if (this.token && Date.now() < this.token.expiresAt - 30_000) {
18
+ return this.token.accessToken;
19
+ }
20
+ await this.authenticate();
21
+ return this.token.accessToken;
22
+ }
23
+ async authenticate() {
24
+ const response = await fetch(this.config.endpoint, {
25
+ method: "POST",
26
+ headers: { "Content-Type": "application/json" },
27
+ body: JSON.stringify({
28
+ query: AUTHENTICATE_MUTATION,
29
+ variables: {
30
+ clientId: this.config.clientId,
31
+ clientSecret: this.config.clientSecret,
32
+ },
33
+ }),
34
+ });
35
+ if (!response.ok) {
36
+ throw new Error(`Authentication failed: HTTP ${response.status} ${response.statusText}`);
37
+ }
38
+ const result = await response.json();
39
+ if (result.errors?.length) {
40
+ throw new Error(`Authentication failed: ${result.errors.map((e) => e.message).join(", ")}`);
41
+ }
42
+ const auth = result.data.authenticateAPIClient;
43
+ this.token = {
44
+ accessToken: auth.accessToken,
45
+ tokenType: auth.tokenType,
46
+ expiresIn: auth.expiresIn,
47
+ expiresAt: Date.now() + auth.expiresIn * 1000,
48
+ };
49
+ }
50
+ }
51
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/graphql/auth.ts"],"names":[],"mappings":"AAEA,MAAM,qBAAqB,GAAG;;;;;;;;CAQ7B,CAAC;AAEF,MAAM,OAAO,WAAW;IACd,KAAK,GAAqB,IAAI,CAAC;IAC/B,MAAM,CAAe;IAE7B,YAAY,MAAoB;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,EAAE,CAAC;YAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QAChC,CAAC;QACD,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,KAAM,CAAC,WAAW,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;YACjD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,qBAAqB;gBAC5B,SAAS,EAAE;oBACT,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;oBAC9B,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;iBACvC;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,+BAA+B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACxE,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAMP,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE3B,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,0BAA0B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAK,CAAC,qBAAqB,CAAC;QAChD,IAAI,CAAC,KAAK,GAAG;YACX,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI;SAC9C,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import type { GraphQLResponse } from "../types.js";
2
+ import type { AuthManager } from "./auth.js";
3
+ export declare class GraphQLClient {
4
+ private endpoint;
5
+ private auth;
6
+ constructor(endpoint: string, auth: AuthManager);
7
+ execute<T = Record<string, unknown>>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResponse<T>>;
8
+ executeUnauthenticated<T = Record<string, unknown>>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResponse<T>>;
9
+ }
10
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/graphql/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAc;gBAEd,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW;IAKzC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAqBxB,sBAAsB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtD,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;CAe/B"}
@@ -0,0 +1,35 @@
1
+ export class GraphQLClient {
2
+ endpoint;
3
+ auth;
4
+ constructor(endpoint, auth) {
5
+ this.endpoint = endpoint;
6
+ this.auth = auth;
7
+ }
8
+ async execute(query, variables) {
9
+ const token = await this.auth.getAccessToken();
10
+ const response = await fetch(this.endpoint, {
11
+ method: "POST",
12
+ headers: {
13
+ "Content-Type": "application/json",
14
+ Authorization: `Bearer ${token}`,
15
+ },
16
+ body: JSON.stringify({ query, variables }),
17
+ });
18
+ if (!response.ok) {
19
+ throw new Error(`GraphQL request failed: HTTP ${response.status} ${response.statusText}`);
20
+ }
21
+ return response.json();
22
+ }
23
+ async executeUnauthenticated(query, variables) {
24
+ const response = await fetch(this.endpoint, {
25
+ method: "POST",
26
+ headers: { "Content-Type": "application/json" },
27
+ body: JSON.stringify({ query, variables }),
28
+ });
29
+ if (!response.ok) {
30
+ throw new Error(`GraphQL request failed: HTTP ${response.status} ${response.statusText}`);
31
+ }
32
+ return response.json();
33
+ }
34
+ }
35
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/graphql/client.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,aAAa;IAChB,QAAQ,CAAS;IACjB,IAAI,CAAc;IAE1B,YAAY,QAAgB,EAAE,IAAiB;QAC7C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,OAAO,CACX,KAAa,EACb,SAAmC;QAEnC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAE/C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC1C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;aACjC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,gCAAgC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACzE,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAiC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,sBAAsB,CAC1B,KAAa,EACb,SAAmC;QAEnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC1C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,gCAAgC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACzE,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAiC,CAAC;IACxD,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import type { GraphQLClient } from "./client.js";
2
+ import type { IntrospectedSchema, IntrospectedField, IntrospectedFullType, IntrospectedType } from "../types.js";
3
+ export declare class SchemaIntrospector {
4
+ private client;
5
+ private schema;
6
+ private typeMap;
7
+ constructor(client: GraphQLClient);
8
+ introspect(): Promise<IntrospectedSchema>;
9
+ getSchema(): IntrospectedSchema;
10
+ getType(name: string): IntrospectedFullType | undefined;
11
+ getQueryFields(): IntrospectedField[];
12
+ getMutationFields(): IntrospectedField[];
13
+ resolveTypeName(type: IntrospectedType): string;
14
+ isRequired(type: IntrospectedType): boolean;
15
+ isList(type: IntrospectedType): boolean;
16
+ searchTypes(keyword: string): IntrospectedFullType[];
17
+ describeType(typeName: string): string;
18
+ formatType(type: IntrospectedType): string;
19
+ }
20
+ //# sourceMappingURL=introspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../../src/graphql/introspect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAkFrB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,OAAO,CAAgD;gBAEnD,MAAM,EAAE,aAAa;IAI3B,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAoB/C,SAAS,IAAI,kBAAkB;IAK/B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAIvD,cAAc,IAAI,iBAAiB,EAAE;IAMrC,iBAAiB,IAAI,iBAAiB,EAAE;IAMxC,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM;IAM/C,UAAU,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO;IAI3C,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO;IAMvC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAUpD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAoCtC,UAAU,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM;CAS3C"}
@@ -0,0 +1,184 @@
1
+ const INTROSPECTION_QUERY = `
2
+ query IntrospectionQuery {
3
+ __schema {
4
+ queryType { name }
5
+ mutationType { name }
6
+ types {
7
+ kind
8
+ name
9
+ description
10
+ fields(includeDeprecated: false) {
11
+ name
12
+ description
13
+ args {
14
+ name
15
+ description
16
+ type {
17
+ kind
18
+ name
19
+ ofType {
20
+ kind
21
+ name
22
+ ofType {
23
+ kind
24
+ name
25
+ ofType {
26
+ kind
27
+ name
28
+ }
29
+ }
30
+ }
31
+ }
32
+ defaultValue
33
+ }
34
+ type {
35
+ kind
36
+ name
37
+ ofType {
38
+ kind
39
+ name
40
+ ofType {
41
+ kind
42
+ name
43
+ ofType {
44
+ kind
45
+ name
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ inputFields {
52
+ name
53
+ description
54
+ type {
55
+ kind
56
+ name
57
+ ofType {
58
+ kind
59
+ name
60
+ ofType {
61
+ kind
62
+ name
63
+ ofType {
64
+ kind
65
+ name
66
+ }
67
+ }
68
+ }
69
+ }
70
+ defaultValue
71
+ }
72
+ enumValues(includeDeprecated: false) {
73
+ name
74
+ description
75
+ }
76
+ }
77
+ }
78
+ }
79
+ `;
80
+ export class SchemaIntrospector {
81
+ client;
82
+ schema = null;
83
+ typeMap = new Map();
84
+ constructor(client) {
85
+ this.client = client;
86
+ }
87
+ async introspect() {
88
+ const result = await this.client.executeUnauthenticated(INTROSPECTION_QUERY);
89
+ if (result.errors?.length) {
90
+ throw new Error(`Introspection failed: ${result.errors.map((e) => e.message).join(", ")}`);
91
+ }
92
+ this.schema = result.data.__schema;
93
+ this.typeMap.clear();
94
+ for (const type of this.schema.types) {
95
+ this.typeMap.set(type.name, type);
96
+ }
97
+ return this.schema;
98
+ }
99
+ getSchema() {
100
+ if (!this.schema)
101
+ throw new Error("Schema not introspected yet");
102
+ return this.schema;
103
+ }
104
+ getType(name) {
105
+ return this.typeMap.get(name);
106
+ }
107
+ getQueryFields() {
108
+ if (!this.schema?.queryType)
109
+ return [];
110
+ const queryType = this.typeMap.get(this.schema.queryType.name);
111
+ return queryType?.fields ?? [];
112
+ }
113
+ getMutationFields() {
114
+ if (!this.schema?.mutationType)
115
+ return [];
116
+ const mutationType = this.typeMap.get(this.schema.mutationType.name);
117
+ return mutationType?.fields ?? [];
118
+ }
119
+ resolveTypeName(type) {
120
+ if (type.name)
121
+ return type.name;
122
+ if (type.ofType)
123
+ return this.resolveTypeName(type.ofType);
124
+ return "Unknown";
125
+ }
126
+ isRequired(type) {
127
+ return type.kind === "NON_NULL";
128
+ }
129
+ isList(type) {
130
+ if (type.kind === "LIST")
131
+ return true;
132
+ if (type.ofType)
133
+ return this.isList(type.ofType);
134
+ return false;
135
+ }
136
+ searchTypes(keyword) {
137
+ const lower = keyword.toLowerCase();
138
+ return this.schema.types.filter((t) => !t.name.startsWith("__") &&
139
+ (t.name.toLowerCase().includes(lower) ||
140
+ t.description?.toLowerCase().includes(lower)));
141
+ }
142
+ describeType(typeName) {
143
+ const type = this.typeMap.get(typeName);
144
+ if (!type)
145
+ return `Type "${typeName}" not found`;
146
+ const lines = [`${type.kind} ${type.name}`];
147
+ if (type.description)
148
+ lines.push(type.description);
149
+ if (type.fields) {
150
+ lines.push("\nFields:");
151
+ for (const field of type.fields) {
152
+ const typeName = this.formatType(field.type);
153
+ const desc = field.description ? ` — ${field.description}` : "";
154
+ lines.push(` ${field.name}: ${typeName}${desc}`);
155
+ }
156
+ }
157
+ if (type.inputFields) {
158
+ lines.push("\nInput Fields:");
159
+ for (const field of type.inputFields) {
160
+ const typeName = this.formatType(field.type);
161
+ const desc = field.description ? ` — ${field.description}` : "";
162
+ lines.push(` ${field.name}: ${typeName}${desc}`);
163
+ }
164
+ }
165
+ if (type.enumValues) {
166
+ lines.push("\nValues:");
167
+ for (const val of type.enumValues) {
168
+ const desc = val.description ? ` — ${val.description}` : "";
169
+ lines.push(` ${val.name}${desc}`);
170
+ }
171
+ }
172
+ return lines.join("\n");
173
+ }
174
+ formatType(type) {
175
+ if (type.kind === "NON_NULL") {
176
+ return `${this.formatType(type.ofType)}!`;
177
+ }
178
+ if (type.kind === "LIST") {
179
+ return `[${this.formatType(type.ofType)}]`;
180
+ }
181
+ return type.name ?? "Unknown";
182
+ }
183
+ }
184
+ //# sourceMappingURL=introspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect.js","sourceRoot":"","sources":["../../src/graphql/introspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { createServer } from "./server.js";
3
+ function getConfig() {
4
+ const endpoint = process.env.VOLATICLOUD_ENDPOINT ??
5
+ "https://api.volaticloud.com/gateway/v1/query";
6
+ const clientId = process.env.VOLATICLOUD_CLIENT_ID;
7
+ const clientSecret = process.env.VOLATICLOUD_CLIENT_SECRET;
8
+ if (!clientId || !clientSecret) {
9
+ console.error("Error: VOLATICLOUD_CLIENT_ID and VOLATICLOUD_CLIENT_SECRET environment variables are required.\n\n" +
10
+ "Create an API client at: https://console.volaticloud.com/organization/api-keys\n" +
11
+ "Then configure:\n" +
12
+ " VOLATICLOUD_CLIENT_ID=<your client id>\n" +
13
+ " VOLATICLOUD_CLIENT_SECRET=<your client secret>\n" +
14
+ " VOLATICLOUD_ENDPOINT=https://api.volaticloud.com/gateway/v1/query (optional)");
15
+ process.exit(1);
16
+ }
17
+ return { endpoint, clientId, clientSecret };
18
+ }
19
+ async function main() {
20
+ const config = getConfig();
21
+ const server = await createServer(config);
22
+ const transport = new StdioServerTransport();
23
+ await server.connect(transport);
24
+ }
25
+ main().catch((err) => {
26
+ console.error("Fatal:", err);
27
+ process.exit(1);
28
+ });
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,SAAS,SAAS;IAChB,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAChC,8CAA8C,CAAC;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACnD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAE3D,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CACX,oGAAoG;YAClG,kFAAkF;YAClF,mBAAmB;YACnB,4CAA4C;YAC5C,oDAAoD;YACpD,gFAAgF,CACnF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AAC9C,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ServerConfig } from "./types.js";
3
+ export declare function createServer(config: ServerConfig): Promise<McpServer>;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAW/C,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAgI3E"}
package/dist/server.js ADDED
@@ -0,0 +1,94 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { AuthManager } from "./graphql/auth.js";
4
+ import { GraphQLClient } from "./graphql/client.js";
5
+ import { SchemaIntrospector } from "./graphql/introspect.js";
6
+ import { ToolGenerator } from "./tools/generator.js";
7
+ import { ToolExecutor } from "./tools/executor.js";
8
+ import { formatSchemaOverview, formatSearchResults, } from "./tools/formatter.js";
9
+ export async function createServer(config) {
10
+ const server = new McpServer({
11
+ name: "volaticloud",
12
+ version: "0.1.0",
13
+ });
14
+ // Initialize auth and client
15
+ const auth = new AuthManager(config);
16
+ const client = new GraphQLClient(config.endpoint, auth);
17
+ const introspector = new SchemaIntrospector(client);
18
+ // Introspect schema
19
+ await introspector.introspect();
20
+ // Generate dynamic tools from schema
21
+ const generator = new ToolGenerator(introspector);
22
+ const dynamicTools = generator.generate();
23
+ const executor = new ToolExecutor(client, dynamicTools);
24
+ // --- Static tools ---
25
+ server.tool("introspect_schema", "Get the VolatiCloud GraphQL schema overview, or drill into a specific type by name", { typeName: z.string().optional().describe("Specific type name to inspect (e.g. 'Bot', 'Strategy', 'CreateBotInput')") }, async ({ typeName }) => {
26
+ if (typeName) {
27
+ return {
28
+ content: [{ type: "text", text: introspector.describeType(typeName) }],
29
+ };
30
+ }
31
+ return {
32
+ content: [{ type: "text", text: formatSchemaOverview(introspector) }],
33
+ };
34
+ });
35
+ server.tool("search_schema", "Search the GraphQL schema for types, fields, or enums matching a keyword", { keyword: z.string().describe("Search keyword") }, async ({ keyword }) => ({
36
+ content: [
37
+ { type: "text", text: formatSearchResults(introspector, keyword) },
38
+ ],
39
+ }));
40
+ server.tool("execute_query", "Execute an arbitrary GraphQL query against the VolatiCloud API", {
41
+ query: z.string().describe("GraphQL query string"),
42
+ variables: z.record(z.string(), z.unknown()).optional().describe("Query variables as JSON object"),
43
+ }, async ({ query, variables }) => {
44
+ const result = await client.execute(query, variables);
45
+ if (result.errors?.length) {
46
+ return {
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: JSON.stringify({ errors: result.errors, data: result.data }, null, 2),
51
+ },
52
+ ],
53
+ isError: true,
54
+ };
55
+ }
56
+ return {
57
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }],
58
+ };
59
+ });
60
+ server.tool("execute_mutation", "Execute a GraphQL mutation against the VolatiCloud API (creates, updates, or deletes resources)", {
61
+ query: z.string().describe("GraphQL mutation string"),
62
+ variables: z.record(z.string(), z.unknown()).optional().describe("Mutation variables as JSON object"),
63
+ }, async ({ query, variables }) => {
64
+ const result = await client.execute(query, variables);
65
+ if (result.errors?.length) {
66
+ return {
67
+ content: [
68
+ {
69
+ type: "text",
70
+ text: JSON.stringify({ errors: result.errors, data: result.data }, null, 2),
71
+ },
72
+ ],
73
+ isError: true,
74
+ };
75
+ }
76
+ return {
77
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }],
78
+ };
79
+ });
80
+ // --- Dynamic tools (auto-generated from schema) ---
81
+ for (const tool of dynamicTools) {
82
+ server.tool(tool.name, tool.description, tool.zodParams, async (args) => {
83
+ const result = await executor.execute(tool.name, args);
84
+ const parsed = JSON.parse(result);
85
+ const isError = parsed !== null && typeof parsed === "object" && "error" in parsed;
86
+ return {
87
+ content: [{ type: "text", text: result }],
88
+ isError,
89
+ };
90
+ });
91
+ }
92
+ return server;
93
+ }
94
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { GraphQLClient } from "../graphql/client.js";
2
+ import type { GeneratedTool } from "../types.js";
3
+ export declare class ToolExecutor {
4
+ private client;
5
+ private toolMap;
6
+ constructor(client: GraphQLClient, tools: GeneratedTool[]);
7
+ execute(toolName: string, args: Record<string, unknown>): Promise<string>;
8
+ getTool(name: string): GeneratedTool | undefined;
9
+ }
10
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/tools/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAA6B;gBAEhC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;IAKnD,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC;IAkBlB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;CAGjD"}
@@ -0,0 +1,26 @@
1
+ export class ToolExecutor {
2
+ client;
3
+ toolMap;
4
+ constructor(client, tools) {
5
+ this.client = client;
6
+ this.toolMap = new Map(tools.map((t) => [t.name, t]));
7
+ }
8
+ async execute(toolName, args) {
9
+ const tool = this.toolMap.get(toolName);
10
+ if (!tool) {
11
+ return JSON.stringify({ error: `Unknown tool: ${toolName}` });
12
+ }
13
+ const result = await this.client.execute(tool.graphqlQuery, args);
14
+ if (result.errors?.length) {
15
+ return JSON.stringify({
16
+ error: result.errors.map((e) => e.message).join("; "),
17
+ data: result.data ?? null,
18
+ });
19
+ }
20
+ return JSON.stringify(result.data, null, 2);
21
+ }
22
+ getTool(name) {
23
+ return this.toolMap.get(name);
24
+ }
25
+ }
26
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/tools/executor.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,YAAY;IACf,MAAM,CAAgB;IACtB,OAAO,CAA6B;IAE5C,YAAY,MAAqB,EAAE,KAAsB;QACvD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,OAAO,CACX,QAAgB,EAChB,IAA6B;QAE7B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,iBAAiB,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAElE,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACrD,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;aAC1B,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ import type { SchemaIntrospector } from "../graphql/introspect.js";
2
+ export declare function formatSchemaOverview(introspector: SchemaIntrospector): string;
3
+ export declare function formatSearchResults(introspector: SchemaIntrospector, keyword: string): string;
4
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/tools/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,kBAAkB,GAC/B,MAAM,CA8BR;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,kBAAkB,EAChC,OAAO,EAAE,MAAM,GACd,MAAM,CAQR"}
@@ -0,0 +1,34 @@
1
+ export function formatSchemaOverview(introspector) {
2
+ const queries = introspector.getQueryFields();
3
+ const mutations = introspector.getMutationFields();
4
+ const lines = ["# VolatiCloud GraphQL Schema\n"];
5
+ lines.push("## Queries\n");
6
+ for (const q of queries) {
7
+ if (q.name.startsWith("__"))
8
+ continue;
9
+ const args = q.args.map((a) => `${a.name}: ${introspector.formatType(a.type)}`);
10
+ const argsStr = args.length > 0 ? `(${args.join(", ")})` : "";
11
+ const ret = introspector.formatType(q.type);
12
+ const desc = q.description ? ` — ${q.description}` : "";
13
+ lines.push(`- **${q.name}**${argsStr}: ${ret}${desc}`);
14
+ }
15
+ lines.push("\n## Mutations\n");
16
+ for (const m of mutations) {
17
+ const args = m.args.map((a) => `${a.name}: ${introspector.formatType(a.type)}`);
18
+ const argsStr = args.length > 0 ? `(${args.join(", ")})` : "";
19
+ const ret = introspector.formatType(m.type);
20
+ const desc = m.description ? ` — ${m.description}` : "";
21
+ lines.push(`- **${m.name}**${argsStr}: ${ret}${desc}`);
22
+ }
23
+ return lines.join("\n");
24
+ }
25
+ export function formatSearchResults(introspector, keyword) {
26
+ const types = introspector.searchTypes(keyword);
27
+ if (types.length === 0)
28
+ return `No types found matching "${keyword}"`;
29
+ return types
30
+ .slice(0, 20)
31
+ .map((t) => introspector.describeType(t.name))
32
+ .join("\n\n---\n\n");
33
+ }
34
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/tools/formatter.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAClC,YAAgC;IAEhC,MAAM,OAAO,GAAG,YAAY,CAAC,cAAc,EAAE,CAAC;IAC9C,MAAM,SAAS,GAAG,YAAY,CAAC,iBAAiB,EAAE,CAAC;IAEnD,MAAM,KAAK,GAAa,CAAC,gCAAgC,CAAC,CAAC;IAE3D,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QACtC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CACvD,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,KAAK,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CACvD,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,KAAK,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,YAAgC,EAChC,OAAe;IAEf,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,4BAA4B,OAAO,GAAG,CAAC;IAEtE,OAAO,KAAK;SACT,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAC7C,IAAI,CAAC,aAAa,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { SchemaIntrospector } from "../graphql/introspect.js";
2
+ import type { GeneratedTool } from "../types.js";
3
+ export declare class ToolGenerator {
4
+ private introspector;
5
+ constructor(introspector: SchemaIntrospector);
6
+ generate(): GeneratedTool[];
7
+ private fieldToTool;
8
+ private argToZod;
9
+ private typeToZod;
10
+ private buildGraphQLOperation;
11
+ private buildSelectionSet;
12
+ private toSnakeCase;
13
+ }
14
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/tools/generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EACV,aAAa,EAId,MAAM,aAAa,CAAC;AAKrB,qBAAa,aAAa;IACxB,OAAO,CAAC,YAAY,CAAqB;gBAE7B,YAAY,EAAE,kBAAkB;IAI5C,QAAQ,IAAI,aAAa,EAAE;IAkB3B,OAAO,CAAC,WAAW;IA6BnB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,SAAS;IA6DjB,OAAO,CAAC,qBAAqB;IAsB7B,OAAO,CAAC,iBAAiB;IAqCzB,OAAO,CAAC,WAAW;CAMpB"}
@@ -0,0 +1,159 @@
1
+ import { z } from "zod";
2
+ const SKIP_QUERIES = new Set(["node", "nodes", "__schema", "__type"]);
3
+ const SKIP_MUTATIONS = new Set(["authenticateAPIClient"]);
4
+ export class ToolGenerator {
5
+ introspector;
6
+ constructor(introspector) {
7
+ this.introspector = introspector;
8
+ }
9
+ generate() {
10
+ const tools = [];
11
+ for (const field of this.introspector.getQueryFields()) {
12
+ if (SKIP_QUERIES.has(field.name))
13
+ continue;
14
+ const tool = this.fieldToTool(field, "query");
15
+ if (tool)
16
+ tools.push(tool);
17
+ }
18
+ for (const field of this.introspector.getMutationFields()) {
19
+ if (SKIP_MUTATIONS.has(field.name))
20
+ continue;
21
+ const tool = this.fieldToTool(field, "mutation");
22
+ if (tool)
23
+ tools.push(tool);
24
+ }
25
+ return tools;
26
+ }
27
+ fieldToTool(field, operationType) {
28
+ const toolName = this.toSnakeCase(field.name);
29
+ const description = field.description || `${operationType}: ${field.name}`;
30
+ const zodParams = {};
31
+ for (const arg of field.args) {
32
+ let schema = this.argToZod(arg, new Set());
33
+ if (!this.introspector.isRequired(arg.type)) {
34
+ schema = schema.optional();
35
+ }
36
+ zodParams[arg.name] = schema;
37
+ }
38
+ const graphqlQuery = this.buildGraphQLOperation(field, operationType);
39
+ return {
40
+ name: toolName,
41
+ description,
42
+ zodParams,
43
+ operationType,
44
+ operationName: field.name,
45
+ graphqlQuery,
46
+ };
47
+ }
48
+ argToZod(arg, visited) {
49
+ let schema = this.typeToZod(arg.type, visited);
50
+ if (arg.description) {
51
+ schema = schema.describe(arg.description);
52
+ }
53
+ return schema;
54
+ }
55
+ typeToZod(type, visited) {
56
+ if (type.kind === "NON_NULL") {
57
+ return this.typeToZod(type.ofType, visited);
58
+ }
59
+ if (type.kind === "LIST") {
60
+ return z.array(this.typeToZod(type.ofType, visited));
61
+ }
62
+ const name = type.name ?? "Unknown";
63
+ switch (name) {
64
+ case "String":
65
+ case "ID":
66
+ case "Cursor":
67
+ case "Time":
68
+ case "UUID":
69
+ return z.string();
70
+ case "Int":
71
+ return z.number().int();
72
+ case "Float":
73
+ return z.number();
74
+ case "Boolean":
75
+ return z.boolean();
76
+ case "Map":
77
+ case "JSON":
78
+ return z.record(z.string(), z.unknown());
79
+ default: {
80
+ const fullType = this.introspector.getType(name);
81
+ if (fullType?.kind === "ENUM" && fullType.enumValues) {
82
+ const values = fullType.enumValues.map((v) => v.name);
83
+ if (values.length > 0) {
84
+ return z.enum(values);
85
+ }
86
+ return z.string();
87
+ }
88
+ if (fullType?.kind === "INPUT_OBJECT" && fullType.inputFields) {
89
+ // Cycle detection for self-referential WhereInput types
90
+ if (visited.has(name)) {
91
+ return z.record(z.string(), z.unknown()).describe(`${name} (recursive, accepts any object)`);
92
+ }
93
+ visited.add(name);
94
+ const shape = {};
95
+ for (const field of fullType.inputFields) {
96
+ let fieldSchema = this.argToZod(field, visited);
97
+ if (!this.introspector.isRequired(field.type)) {
98
+ fieldSchema = fieldSchema.optional();
99
+ }
100
+ shape[field.name] = fieldSchema;
101
+ }
102
+ return z.object(shape).passthrough();
103
+ }
104
+ return z.record(z.string(), z.unknown());
105
+ }
106
+ }
107
+ }
108
+ buildGraphQLOperation(field, operationType) {
109
+ const varDefs = field.args
110
+ .map((a) => `$${a.name}: ${this.introspector.formatType(a.type)}`)
111
+ .join(", ");
112
+ const args = field.args
113
+ .map((a) => `${a.name}: $${a.name}`)
114
+ .join(", ");
115
+ const returnTypeName = this.introspector.resolveTypeName(field.type);
116
+ const selectionSet = this.buildSelectionSet(returnTypeName, 2);
117
+ const opName = field.name.charAt(0).toUpperCase() + field.name.slice(1);
118
+ const varDefsStr = varDefs ? `(${varDefs})` : "";
119
+ const argsStr = args ? `(${args})` : "";
120
+ return `${operationType} ${opName}${varDefsStr} {\n ${field.name}${argsStr} ${selectionSet}\n}`;
121
+ }
122
+ buildSelectionSet(typeName, depth) {
123
+ if (depth <= 0)
124
+ return "";
125
+ const type = this.introspector.getType(typeName);
126
+ if (!type?.fields)
127
+ return "";
128
+ if (typeName.endsWith("Connection")) {
129
+ const edgesField = type.fields.find((f) => f.name === "edges");
130
+ if (edgesField) {
131
+ const edgeTypeName = this.introspector.resolveTypeName(edgesField.type);
132
+ const edgeType = this.introspector.getType(edgeTypeName);
133
+ const nodeField = edgeType?.fields?.find((f) => f.name === "node");
134
+ if (nodeField) {
135
+ const nodeTypeName = this.introspector.resolveTypeName(nodeField.type);
136
+ const nodeSelection = this.buildSelectionSet(nodeTypeName, depth - 1);
137
+ return `{\n totalCount\n edges {\n node ${nodeSelection}\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }`;
138
+ }
139
+ }
140
+ }
141
+ const scalars = type.fields.filter((f) => {
142
+ const resolvedName = this.introspector.resolveTypeName(f.type);
143
+ const resolved = this.introspector.getType(resolvedName);
144
+ return ((resolved !== undefined && !resolved.fields) ||
145
+ ["String", "Int", "Float", "Boolean", "ID", "Time", "UUID", "Map", "JSON"].includes(resolvedName));
146
+ });
147
+ if (scalars.length === 0)
148
+ return "";
149
+ const fields = scalars.map((f) => f.name).join("\n ");
150
+ return `{\n ${fields}\n }`;
151
+ }
152
+ toSnakeCase(name) {
153
+ return name
154
+ .replace(/([A-Z])/g, "_$1")
155
+ .toLowerCase()
156
+ .replace(/^_/, "");
157
+ }
158
+ }
159
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/tools/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ export interface ServerConfig {
2
+ endpoint: string;
3
+ clientId: string;
4
+ clientSecret: string;
5
+ }
6
+ export interface AuthToken {
7
+ accessToken: string;
8
+ tokenType: string;
9
+ expiresIn: number;
10
+ expiresAt: number;
11
+ }
12
+ export interface GraphQLResponse<T = Record<string, unknown>> {
13
+ data?: T;
14
+ errors?: GraphQLError[];
15
+ }
16
+ export interface GraphQLError {
17
+ message: string;
18
+ path?: string[];
19
+ extensions?: Record<string, unknown>;
20
+ }
21
+ export interface IntrospectedField {
22
+ name: string;
23
+ description: string | null;
24
+ args: IntrospectedArg[];
25
+ type: IntrospectedType;
26
+ }
27
+ export interface IntrospectedArg {
28
+ name: string;
29
+ description: string | null;
30
+ type: IntrospectedType;
31
+ defaultValue: string | null;
32
+ }
33
+ export interface IntrospectedType {
34
+ kind: string;
35
+ name: string | null;
36
+ ofType: IntrospectedType | null;
37
+ }
38
+ export interface IntrospectedSchema {
39
+ queryType: {
40
+ name: string;
41
+ } | null;
42
+ mutationType: {
43
+ name: string;
44
+ } | null;
45
+ types: IntrospectedFullType[];
46
+ }
47
+ export interface IntrospectedFullType {
48
+ kind: string;
49
+ name: string;
50
+ description: string | null;
51
+ fields: IntrospectedField[] | null;
52
+ inputFields: IntrospectedArg[] | null;
53
+ enumValues: {
54
+ name: string;
55
+ description: string | null;
56
+ }[] | null;
57
+ }
58
+ import type { ZodTypeAny } from "zod";
59
+ export interface GeneratedTool {
60
+ name: string;
61
+ description: string;
62
+ zodParams: Record<string, ZodTypeAny>;
63
+ operationType: "query" | "mutation";
64
+ operationName: string;
65
+ graphqlQuery: string;
66
+ }
67
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1D,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnC,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtC,KAAK,EAAE,oBAAoB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;CACnE;AAED,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC,aAAa,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@volaticloud/mcp-server",
3
+ "version": "0.1.0-dev.pr507.25e1c71",
4
+ "description": "MCP server for the VolatiCloud GraphQL API — manage strategies, bots, exchanges, and backtests via AI agents",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "volaticloud-mcp": "bin/mcp-server.mjs"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "bin"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "start": "node dist/index.js",
18
+ "lint": "tsc --noEmit"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "model-context-protocol",
23
+ "volaticloud",
24
+ "graphql",
25
+ "trading",
26
+ "ai-agent"
27
+ ],
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.12.1",
31
+ "zod": "^3.25 || ^4.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.0.0",
35
+ "typescript": "^5.7.0"
36
+ },
37
+ "engines": {
38
+ "node": ">=18"
39
+ }
40
+ }