superops-it 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 +115 -0
- package/docs/api-index.json +7857 -0
- package/docs/introduction.json +9 -0
- package/package.json +41 -0
- package/src/index.mjs +268 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "SuperOps IT Teams GraphQL API",
|
|
3
|
+
"description": "Welcome to the Superops IT GraphQL API reference! This reference includes the complete set of GraphQL types, queries, mutations, and their parameters. For more tutorial-oriented API documentation, please check out our API Guide",
|
|
4
|
+
"contact": "support@superops.com",
|
|
5
|
+
"endpoints": {
|
|
6
|
+
"us": "https://api.superops.ai/it",
|
|
7
|
+
"eu": "https://euapi.superops.ai/it"
|
|
8
|
+
}
|
|
9
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "superops-it",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for SuperOps IT Teams GraphQL API documentation",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.mjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"superops-it": "src/index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node src/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"superops",
|
|
16
|
+
"it-teams",
|
|
17
|
+
"graphql",
|
|
18
|
+
"api",
|
|
19
|
+
"claude",
|
|
20
|
+
"ai"
|
|
21
|
+
],
|
|
22
|
+
"author": "Limehawk",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/Limehawk/superops-mcp.git",
|
|
27
|
+
"directory": "packages/it"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/Limehawk/superops-mcp/tree/main/packages/it#readme",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/Limehawk/superops-mcp/issues"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@modelcontextprotocol/sdk": "^1.25.2"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"src/",
|
|
38
|
+
"docs/api-index.json",
|
|
39
|
+
"docs/introduction.json"
|
|
40
|
+
]
|
|
41
|
+
}
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
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
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
8
|
+
import { readFile } from 'fs/promises';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const SERVER_NAME = 'superops-it';
|
|
14
|
+
const SERVER_VERSION = '1.0.0';
|
|
15
|
+
const PRODUCT_NAME = 'SuperOps IT Teams';
|
|
16
|
+
|
|
17
|
+
// API data cache
|
|
18
|
+
let apiData = null;
|
|
19
|
+
|
|
20
|
+
async function loadApiData() {
|
|
21
|
+
if (apiData) return apiData;
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const indexPath = join(__dirname, '..', 'docs', 'api-index.json');
|
|
25
|
+
const content = await readFile(indexPath, 'utf-8');
|
|
26
|
+
apiData = JSON.parse(content);
|
|
27
|
+
return apiData;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
throw new Error(`Failed to load API data: ${error.message}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Create server
|
|
34
|
+
const server = new Server(
|
|
35
|
+
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
36
|
+
{ capabilities: { tools: {} } }
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// List available tools
|
|
40
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
41
|
+
return {
|
|
42
|
+
tools: [
|
|
43
|
+
{
|
|
44
|
+
name: 'search_superops_api',
|
|
45
|
+
description: `Search the ${PRODUCT_NAME} API documentation for queries, mutations, and types`,
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
query: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'Search term to find in operation names, descriptions, and types'
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
required: ['query']
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'get_superops_operation',
|
|
59
|
+
description: `Get full details of a specific ${PRODUCT_NAME} API query or mutation`,
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
name: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
description: 'Name of the query or mutation (e.g., "getTicket", "getAsset")'
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
required: ['name']
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'get_superops_type',
|
|
73
|
+
description: `Get full details of a ${PRODUCT_NAME} API type definition`,
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: 'object',
|
|
76
|
+
properties: {
|
|
77
|
+
name: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
description: 'Name of the type (e.g., "Ticket", "Asset", "Department")'
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
required: ['name']
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'list_superops_operations',
|
|
87
|
+
description: `List all available ${PRODUCT_NAME} API operations`,
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
type: {
|
|
92
|
+
type: 'string',
|
|
93
|
+
enum: ['queries', 'mutations', 'all'],
|
|
94
|
+
description: 'Type of operations to list'
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
required: ['type']
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Handle tool calls
|
|
105
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
106
|
+
const { name, arguments: args } = request.params;
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const data = await loadApiData();
|
|
110
|
+
|
|
111
|
+
switch (name) {
|
|
112
|
+
case 'search_superops_api': {
|
|
113
|
+
const query = args.query.toLowerCase();
|
|
114
|
+
const results = {
|
|
115
|
+
queries: [],
|
|
116
|
+
mutations: [],
|
|
117
|
+
types: []
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
for (const op of data.queries) {
|
|
121
|
+
if (op.name.toLowerCase().includes(query) ||
|
|
122
|
+
op.description?.toLowerCase().includes(query)) {
|
|
123
|
+
results.queries.push({
|
|
124
|
+
name: op.name,
|
|
125
|
+
description: op.description,
|
|
126
|
+
returns: op.returns
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const op of data.mutations) {
|
|
132
|
+
if (op.name.toLowerCase().includes(query) ||
|
|
133
|
+
op.description?.toLowerCase().includes(query)) {
|
|
134
|
+
results.mutations.push({
|
|
135
|
+
name: op.name,
|
|
136
|
+
description: op.description,
|
|
137
|
+
returns: op.returns
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
for (const type of data.types) {
|
|
143
|
+
if (type.name.toLowerCase().includes(query) ||
|
|
144
|
+
type.description?.toLowerCase().includes(query)) {
|
|
145
|
+
results.types.push({
|
|
146
|
+
name: type.name,
|
|
147
|
+
kind: type.kind,
|
|
148
|
+
description: type.description
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const total = results.queries.length + results.mutations.length + results.types.length;
|
|
154
|
+
return {
|
|
155
|
+
content: [{
|
|
156
|
+
type: 'text',
|
|
157
|
+
text: JSON.stringify({
|
|
158
|
+
searchTerm: args.query,
|
|
159
|
+
totalResults: total,
|
|
160
|
+
results
|
|
161
|
+
}, null, 2)
|
|
162
|
+
}]
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
case 'get_superops_operation': {
|
|
167
|
+
const opName = args.name.toLowerCase();
|
|
168
|
+
|
|
169
|
+
let operation = data.queries.find(q => q.name.toLowerCase() === opName);
|
|
170
|
+
if (!operation) {
|
|
171
|
+
operation = data.mutations.find(m => m.name.toLowerCase() === opName);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!operation) {
|
|
175
|
+
return {
|
|
176
|
+
content: [{
|
|
177
|
+
type: 'text',
|
|
178
|
+
text: `Operation "${args.name}" not found. Use search_superops_api to find available operations.`
|
|
179
|
+
}],
|
|
180
|
+
isError: true
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
content: [{
|
|
186
|
+
type: 'text',
|
|
187
|
+
text: JSON.stringify(operation, null, 2)
|
|
188
|
+
}]
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
case 'get_superops_type': {
|
|
193
|
+
const typeName = args.name.toLowerCase();
|
|
194
|
+
const type = data.types.find(t => t.name.toLowerCase() === typeName);
|
|
195
|
+
|
|
196
|
+
if (!type) {
|
|
197
|
+
return {
|
|
198
|
+
content: [{
|
|
199
|
+
type: 'text',
|
|
200
|
+
text: `Type "${args.name}" not found. Use search_superops_api to find available types.`
|
|
201
|
+
}],
|
|
202
|
+
isError: true
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
content: [{
|
|
208
|
+
type: 'text',
|
|
209
|
+
text: JSON.stringify(type, null, 2)
|
|
210
|
+
}]
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
case 'list_superops_operations': {
|
|
215
|
+
const listType = args.type;
|
|
216
|
+
let result = {};
|
|
217
|
+
|
|
218
|
+
if (listType === 'queries' || listType === 'all') {
|
|
219
|
+
result.queries = data.queries.map(q => ({
|
|
220
|
+
name: q.name,
|
|
221
|
+
description: q.description
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (listType === 'mutations' || listType === 'all') {
|
|
226
|
+
result.mutations = data.mutations.map(m => ({
|
|
227
|
+
name: m.name,
|
|
228
|
+
description: m.description
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
result.meta = data.meta;
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
content: [{
|
|
236
|
+
type: 'text',
|
|
237
|
+
text: JSON.stringify(result, null, 2)
|
|
238
|
+
}]
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
default:
|
|
243
|
+
return {
|
|
244
|
+
content: [{
|
|
245
|
+
type: 'text',
|
|
246
|
+
text: `Unknown tool: ${name}`
|
|
247
|
+
}],
|
|
248
|
+
isError: true
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
} catch (error) {
|
|
252
|
+
return {
|
|
253
|
+
content: [{
|
|
254
|
+
type: 'text',
|
|
255
|
+
text: `Error: ${error.message}`
|
|
256
|
+
}],
|
|
257
|
+
isError: true
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Start server
|
|
263
|
+
async function main() {
|
|
264
|
+
const transport = new StdioServerTransport();
|
|
265
|
+
await server.connect(transport);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
main().catch(console.error);
|