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.
@@ -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);