This is page 1 of 3. Use http://codebase.md/noveum/api-market-mcp-server?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .dockerignore
├── .eslintrc.json
├── .gitignore
├── bin
│ └── mcp-server.js
├── build.js
├── CONTRIBUTING.md
├── Dockerfile
├── images
│ ├── example1.png
│ ├── example2.1.png
│ ├── example2.2.png
│ └── example3.png
├── INSTALL.md
├── LICENSE
├── mcp-specs.d.ts
├── modified_files.txt
├── package-lock.json
├── package.json
├── README.md
├── scripts
│ ├── inspect-watch.js
│ └── inspect.js
├── smithery.yaml
├── src
│ ├── APIMarketMCPServer.ts
│ ├── index.ts
│ ├── lib
│ │ ├── modified_brave-brave.json
│ │ ├── modified_bridgeml-codellama.json
│ │ ├── modified_bridgeml-mistralai.json
│ │ ├── modified_bridgeml-mistralai8x22.json
│ │ ├── modified_bridgeml-nsfw-detection.json
│ │ ├── modified_bridgeml-text-to-image.json
│ │ ├── modified_capix-faceswap.json
│ │ ├── modified_capix-free.json
│ │ ├── modified_capix-homegpt.json
│ │ ├── modified_capix-inpainting.json
│ │ ├── modified_capix-shortener.json
│ │ ├── modified_capix-story.json
│ │ ├── modified_magicapi-coder.json
│ │ ├── modified_magicapi-colorizer.json
│ │ ├── modified_magicapi-deblurer.json
│ │ ├── modified_magicapi-dnschecker.json
│ │ ├── modified_magicapi-domainchecker.json
│ │ ├── modified_magicapi-hair.json
│ │ ├── modified_magicapi-pdf-extract.json
│ │ ├── modified_magicapi-period.json
│ │ ├── modified_magicapi-screenshot-api.json
│ │ ├── modified_magicapi-whisper.json
│ │ ├── modified_magicapi-whois.json
│ │ ├── modified_pipfeed-parse.json
│ │ ├── modified_trueway-geocoding.json
│ │ ├── modified_trueway-matrix.json
│ │ ├── modified_trueway-places.json
│ │ └── modified_trueway-routing.json
│ └── utils.ts
├── tsconfig.json
└── utils
├── LLM_summary_shortener.py
├── manual_summary_shortener.py
└── modify_api.py
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | .aider*
2 | .env
3 | dist/
4 | node_modules/
5 | json_files/
6 |
```
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
```
1 | node_modules/
2 | json_files/
3 | dist/
4 | utils/
5 | images/
6 |
```
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "plugins": ["@typescript-eslint"],
4 | "extends": [
5 | "eslint:recommended",
6 | "plugin:@typescript-eslint/recommended"
7 | ],
8 | "parserOptions": {
9 | "ecmaVersion": 2020,
10 | "sourceType": "module"
11 | },
12 | "rules": {
13 | "@typescript-eslint/explicit-function-return-type": "warn",
14 | "@typescript-eslint/no-explicit-any": "warn",
15 | "@typescript-eslint/no-unused-vars": "error"
16 | }
17 | }
18 |
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # API-MARKET MCP Server
2 |
3 | ## About
4 | A Model Context Protocol (MCP) server that exposes API-Market's endpoints as MCP resources. This server allows Large Language Models to discover and interact with APIs defined by OpenAPI specifications through the MCP protocol.
5 | This repository provides access to the APIs available at [API.market](https://api.market/). The tool is free to use and allows agents to communicate freely with all available APIs, making it super powerful. With over **200+ APIs** available at [API.market](https://api.market/), you can leverage a wide range of functionalities.
6 |
7 | ## Quick Start
8 |
9 | You do not need to clone this repository to use this MCP server. You can simply configure it in your client of choice.
10 |
11 | ### For Claude Desktop
12 | 1. Locate or create your Claude Desktop configuration file:
13 | - On macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
14 | 2. Add the following configuration to enable the API-Market MCP server:
15 | ```json
16 | {
17 | "mcpServers": {
18 | "api-market": {
19 | "command": "npx",
20 | "args": ["-y", "@noveum-ai/mcp-server"],
21 | "env": {
22 | "API_HEADERS": "x-magicapi-key:your-api-key"
23 | }
24 | }
25 | }
26 | }
27 | ```
28 | ### For Cursor
29 | 1. Go to File -> Preferences -> Cursor Settings.
30 | 2. Select MCP.
31 | 3. Click on Add new global MCP Server.
32 | 4. Paste the following into the mcp.json file.
33 |
34 | ```json
35 | {
36 | "mcpServers": {
37 | "api-market": {
38 | "command": "npx",
39 | "args": [
40 | "-y",
41 | "@noveum-ai/mcp-server",
42 | "--headers",
43 | "x-magicapi-key:<your-api-key>"
44 | ]
45 | }
46 | }
47 | }
48 | ```
49 | Alternatively, add this as the first entry in mcpServers.
50 | ```json
51 | "api-market": {
52 | "command": "npx",
53 | "args": [
54 | "-y",
55 | "@noveum-ai/mcp-server",
56 | "--headers",
57 | "x-magicapi-key:<your-api-key>"
58 | ]
59 | },
60 | ```
61 | 5. For older versions of Cursor, add the following command after clicking on Add new MCP server
62 | ```bash
63 | npx -y @noveum-ai/mcp-server --headers x-magicapi-key:your-api-key
64 | ```
65 | ## Getting an API Key from API.market
66 |
67 | To obtain an API key
68 | 1. Log in to [API.market](https://api.market/)
69 | 2. Go to your profile and select 'My API Keys'
70 | 3. Your API keys will be displayed here
71 |
72 | ## List of APIs in this MCP
73 |
74 | - [GET-trueway-matrix-MatrixService-CalculateDrivingMatrix](https://api.market/store/trueway/matrix)
75 | - [GET-magicapi-whisper-predictions--request_id](https://api.market/store/magicapi/whisper)
76 | - [POST-magicapi-whisper-whisper](https://api.market/store/magicapi/whisper)
77 | - [POST-capix-faceswap-upload](https://api.market/store/capix/faceswap)
78 | - [POST-capix-faceswap-faceswap-v1-image](https://api.market/store/capix/faceswap)
79 | - [POST-capix-faceswap-faceswap-v1-video](https://api.market/store/capix/faceswap)
80 | - [POST-capix-faceswap-result](https://api.market/store/capix/faceswap)
81 | - [GET-trueway-geocoding-GeocodingService-Geocode](https://api.market/store/trueway/geocoding)
82 | - [GET-trueway-geocoding-GeocodingService-ReverseGeocode](https://api.market/store/trueway/geocoding)
83 | - [POST-magicapi-dnschecker-dnschecker](https://api.market/store/magicapi/dnschecker)
84 | - [GET-magicapi-coder-predictions--request_id](https://api.market/store/magicapi/coder)
85 | - [POST-magicapi-coder-coder](https://api.market/store/magicapi/coder)
86 | - [POST-bridgeml-nsfw-detection-nsfw_detection](https://api.market/store/bridgeml/nsfw)
87 | - [GET-magicapi-whois-whois--domain-](https://api.market/store/magicapi/whois)
88 | - [GET-magicapi-deblurer-predictions--request_id](https://api.market/store/magicapi/deblurer)
89 | - [POST-magicapi-deblurer-deblurer](https://api.market/store/magicapi/deblurer)
90 | - [POST-bridgeml-text-to-image-text_to_image](https://api.market/store/bridgeml/text)
91 | - [GET-magicapi-period-predictions--request_id](https://api.market/store/magicapi/period)
92 | - [POST-magicapi-period-period](https://api.market/store/magicapi/period)
93 | - [GET-trueway-places-PlacesService-FindPlaceByText](https://api.market/store/trueway/places)
94 | - [GET-trueway-places-PlacesService-FindPlacesNearby](https://api.market/store/trueway/places)
95 | - [GET-magicapi-hair-predictions--request_id](https://api.market/store/magicapi/hair)
96 | - [POST-magicapi-hair-hair](https://api.market/store/magicapi/hair)
97 | - [POST-bridgeml-codellama-bridgeml-codellama](https://api.market/store/bridgeml/codellama)
98 | - [GET-brave-brave-videos-search](https://api.market/store/brave/brave)
99 | - [GET-brave-brave-web-search](https://api.market/store/brave/brave)
100 | - [GET-brave-brave-images-search](https://api.market/store/brave/brave)
101 | - [GET-brave-brave-news-search](https://api.market/store/brave/brave)
102 | - [GET-brave-brave-suggest-search](https://api.market/store/brave/brave)
103 | - [GET-brave-brave-spellcheck-search](https://api.market/store/brave/brave)
104 | - [POST-magicapi-domainchecker-check_domains](https://api.market/store/magicapi/domainchecker)
105 | - [GET-trueway-routing-DirectionsService-FindDrivingRoute](https://api.market/store/trueway/routing)
106 | - [GET-trueway-routing-DirectionsService-FindDrivingPath](https://api.market/store/trueway/routing)
107 | - [POST-pipfeed-parse-extract](https://api.market/store/pipfeed/parse)
108 |
109 | ## Example and Usage
110 | ### Example 1
111 | We can use the agent to find a route between any two points
112 |
113 | 
114 |
115 | ### Example 2
116 | We can use the agent to find news about any topic, and then dig deeper into the articles
117 |
118 | 
119 | 
120 |
121 | ### Example 3
122 | We can use the agent to look for available domains
123 |
124 | 
125 |
126 | ## Development
127 |
128 | ### Adding a New API to the MCP Server
129 |
130 | The `utils` folder contains helper scripts for managing API configurations, parsing OpenAPI specifications, and registering new APIs into the MCP server.
131 |
132 | #### 1. Locate the OpenAPI Specification
133 | Find the OpenAPI JSON for the API you want to integrate. After that, create a folder `json_files` in the root directory of the project and add your OpenAPI JSON spec to the folder
134 |
135 | #### 2. Modify the OpenAPI Specification
136 | After obtaining the OpenAPI spec, use `modify_api.py` to update the path inside the spec to include the file name.
137 |
138 | ```bash
139 | python utils/modify_api.py
140 | ```
141 |
142 | #### 3. Update API Summaries
143 | After modifying the paths, update the API summaries by choosing one of the following options:
144 |
145 | - **Automatically shorten summaries using an LLM:**
146 |
147 | ```bash
148 | python utils/LLM_summary_shortener.py
149 | ```
150 |
151 | - **Manually update the summaries:**
152 |
153 | ```bash
154 | python utils/manual_summary_shortener.py
155 | ```
156 |
157 | #### 4. Build and Test
158 |
159 | Rebuild the project to apply the changes:
160 |
161 | ```bash
162 | npm run build
163 | ```
164 |
165 | Then, test the new API integration using:
166 |
167 | ```bash
168 | npm run inspect
169 | ```
170 |
171 | #### 5. Submit Your Changes
172 | If you want to contribute this new API to the repository:
173 | - Fork the repo.
174 | - Create a branch.
175 | - Submit a pull request (PR).
176 |
177 | #### 6. Publish the MCP server (Optional)
178 | If you want to publish your changes:
179 | - Update the `package.json` accordingly (e.g., update the version, name, etc.).
180 | - Publish the package:
181 | ```bash
182 | npm publish --access public
183 | ```
184 |
185 | ## Development Tools
186 |
187 | ### Building
188 | - `npm run build` - Builds the TypeScript source.
189 | - `npm run clean` - Removes build artifacts.
190 | - `npm run typecheck` - Runs TypeScript type checking.
191 |
192 | ### Development Mode
193 | - `npm run dev` - Watches source files and rebuilds on changes.
194 | - `npm run inspect-watch` - Runs the inspector with auto-reload on changes.
195 |
196 | ### Code Quality
197 | - `npm run lint` - Runs ESLint.
198 | - `npm run typecheck` - Verifies TypeScript types.
199 |
200 | <!-- ##### Set Environment Variables:
201 | Configure your environment by running the following commands:
202 | ```bash
203 | export OPENAPI_SPEC_PATH=modified_files.txt # optional
204 | export API_BASE_URL=https://api.magicapi.dev/api/v1/ # optional
205 | export API_HEADERS="x-magicapi-key:your-api-key"
206 | ``` -->
207 |
208 | #### Command Line Arguments
209 | ```bash
210 | npm run inspect -- \
211 | --api-base-url https://api.magicapi.dev/api/v1/ \
212 | --openapi-spec modified_files.txt \
213 | --headers "x-magicapi-key:your-api-key" \
214 | --name "my-mcp-server" \
215 | --version "1.0.0"
216 | ```
217 |
218 | ### Development Workflow
219 | 1. Start the development environment:
220 | ```bash
221 | npm run inspect-watch
222 | ```
223 | 2. Modify the TypeScript files in `src/`.
224 | 3. The server will automatically rebuild and restart.
225 | 4. Use the MCP Inspector UI to test your changes.
226 |
227 | ### Debugging or Running Locally
228 | To debug or run the MCP server locally:
229 | 1. Clone the repository and install dependencies:
230 | ```bash
231 | git clone https://github.com/Noveum/api-market-mcp-server.git
232 | cd api-market-mcp-server
233 | npm install
234 | ```
235 | 2. Build the server:
236 | ```bash
237 | npm run build
238 | ```
239 | 3. For debugging, you can run:
240 | ```bash
241 | npm run inspect
242 | ```
243 |
244 | ### Contributing
245 | 1. Fork the repository.
246 | 2. Create a feature branch.
247 | 3. Make your changes.
248 | 4. Run tests and linting:
249 | ```bash
250 | npm run typecheck
251 | npm run lint
252 | ```
253 | 5. Submit a pull request.
254 |
255 | ### License
256 | MIT
257 |
```
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
```markdown
1 | # Contributing to OpenAPI MCP Server
2 |
3 | Contributions to the OpenAPI MCP Server are welcome! By participating in this project, you agree to abide by our community guidelines and code standards.
4 |
5 | ## How to Contribute
6 |
7 | 1. **Fork & Clone**
8 | Fork the repository on GitHub and clone it to your local machine.
9 |
10 | 2. **Create a Feature Branch**
11 | Create a new branch for your feature or bug fix:
12 |
13 | ```bash
14 | git checkout -b feature/my-new-feature
15 | ```
16 |
17 | 3. **Make Changes**
18 | - Follow the existing code style and best practices (e.g., TypeScript best practices).
19 | - Add or update tests where necessary.
20 | - Ensure your changes do not break existing functionality.
21 |
22 | 4. **Run Tests & Linting**
23 | Before submitting your pull request, run:
24 |
25 | ```bash
26 | npm run typecheck
27 | npm run lint
28 | ```
29 |
30 | 5. **Submit a Pull Request**
31 | Once your changes are ready, open a pull request against the main branch. In your PR, please include:
32 | - A clear description of your changes.
33 | - References to any related issues.
34 | - Any additional context necessary to understand the changes.
35 |
36 | ## Reporting Issues
37 |
38 | If you encounter bugs or have feature requests, please:
39 | - Open an issue on GitHub.
40 | - Provide detailed steps to reproduce the issue if applicable.
41 | - Include relevant logs or screenshots to help diagnose the problem.
42 |
43 | ## Communication
44 |
45 | For questions or further discussion, feel free to join our community on GitHub Discussions or reach out via our project's preferred communication channels.
46 |
47 | Thank you for helping improve the OpenAPI MCP Server!
48 |
```
--------------------------------------------------------------------------------
/bin/mcp-server.js:
--------------------------------------------------------------------------------
```javascript
1 | #!/usr/bin/env node
2 | import "../dist/bundle.js";
3 |
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | FROM node:22.14.0-alpine
2 |
3 | WORKDIR /app
4 |
5 | COPY package*.json ./
6 |
7 | COPY . .
8 |
9 | RUN npm install
10 |
11 | RUN npm run build
12 |
13 | EXPOSE 3000
14 |
```
--------------------------------------------------------------------------------
/build.js:
--------------------------------------------------------------------------------
```javascript
1 | import * as esbuild from "esbuild";
2 | await esbuild.build({
3 | entryPoints: ["./src/index.ts"],
4 | bundle: true,
5 | platform: "node",
6 | format: "esm",
7 | outfile: "./dist/bundle.js",
8 | target: "node18",
9 | banner: {
10 | js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`,
11 | },
12 | });
13 |
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | #!/usr/bin/env node
2 |
3 | import { loadConfig } from "./utils.js";
4 | import { APIMarketMCPServer } from "./APIMarketMCPServer.js";
5 |
6 | async function main(): Promise<void> {
7 | try {
8 | const config = loadConfig();
9 | const server = new APIMarketMCPServer(config);
10 | await server.start();
11 | } catch (error) {
12 | console.error("Failed to start server:", error);
13 | process.exit(1);
14 | }
15 | }
16 |
17 | main();
18 |
19 | export { APIMarketMCPServer, loadConfig };
20 |
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist",
4 | "rootDir": ".",
5 | "target": "ES2022",
6 | "module": "ES2020",
7 | "moduleResolution": "node",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "sourceMap": false,
11 | "skipLibCheck": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "resolveJsonModule": true
14 | },
15 | "include": [
16 | "src/**/*",
17 | "examples/**/*"
18 | ],
19 | "exclude": [
20 | "node_modules",
21 | "dist",
22 | "**/*.test.ts"
23 | ]
24 | }
25 |
```
--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------
```yaml
1 | startCommand:
2 | type: stdio
3 | configSchema:
4 | # JSON Schema defining the configuration options for the MCP.
5 | type: object
6 | required:
7 | - x-magicapi-key
8 | properties:
9 | x-magicapi-key:
10 | type: string
11 | description: The API key for the api.market website
12 | commandFunction:
13 | # A function that produces the CLI command to start the MCP on stdio.
14 | |-
15 | (config) => ({command:'node',args:['./bin/mcp-server.js'],env:{API_HEADERS: `x-magicapi-key:${config["x-magicapi-key"]}`}})
16 |
```
--------------------------------------------------------------------------------
/modified_files.txt:
--------------------------------------------------------------------------------
```
1 | ../src/lib/modified_trueway-matrix.json
2 | ../src/lib/modified_magicapi-whisper.json
3 | ../src/lib/modified_capix-faceswap.json
4 | ../src/lib/modified_trueway-geocoding.json
5 | ../src/lib/modified_magicapi-dnschecker.json
6 | ../src/lib/modified_magicapi-coder.json
7 | ../src/lib/modified_bridgeml-nsfw-detection.json
8 | ../src/lib/modified_magicapi-whois.json
9 | ../src/lib/modified_magicapi-deblurer.json
10 | ../src/lib/modified_bridgeml-text-to-image.json
11 | ../src/lib/modified_magicapi-period.json
12 | ../src/lib/modified_trueway-places.json
13 | ../src/lib/modified_magicapi-hair.json
14 | ../src/lib/modified_bridgeml-codellama.json
15 | ../src/lib/modified_brave-brave.json
16 | ../src/lib/modified_magicapi-domainchecker.json
17 | ../src/lib/modified_trueway-routing.json
18 | ../src/lib/modified_pipfeed-parse.json
```
--------------------------------------------------------------------------------
/scripts/inspect.js:
--------------------------------------------------------------------------------
```javascript
1 | #!/usr/bin/env node
2 |
3 | import { fileURLToPath } from 'url';
4 | import { dirname, resolve } from 'path';
5 |
6 | const __filename = fileURLToPath(import.meta.url);
7 | const __dirname = dirname(__filename);
8 |
9 | const serverPath = resolve(__dirname, '../bin/mcp-server.js');
10 |
11 | const args = [
12 | 'npx',
13 | '@modelcontextprotocol/inspector',
14 | 'node',
15 | serverPath
16 | ];
17 |
18 | // Add environment variables as CLI arguments if they exist
19 | if (process.env.OPENAPI_SPEC_PATH) {
20 | args.push(`--openapi-spec=${process.env.OPENAPI_SPEC_PATH}`);
21 | }
22 | if (process.env.API_BASE_URL) {
23 | args.push(`--api-base-url=${process.env.API_BASE_URL}`);
24 | }
25 | if (process.env.SERVER_NAME) {
26 | args.push(`--name=${process.env.SERVER_NAME}`);
27 | }
28 | if (process.env.API_HEADERS) {
29 | args.push(`--headers=${process.env.API_HEADERS}`);
30 | }
31 |
32 | // Forward command line arguments
33 | // Skip the first two elements which are 'node' and the script path
34 | const cliArgs = process.argv.slice(2);
35 | args.push(...cliArgs);
36 |
37 |
38 | // Execute the command
39 | import { spawn } from 'child_process';
40 | const inspect = spawn(args[0], args.slice(1), { stdio: 'inherit' });
41 |
42 | inspect.on('error', (err) => {
43 | console.error('Failed to start inspector:', err);
44 | process.exit(1);
45 | });
46 |
47 | inspect.on('exit', (code) => {
48 | process.exit(code || 0);
49 | });
50 |
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "@noveum-ai/mcp-server",
3 | "version": "1.0.4",
4 | "description": "An MCP server that exposes OpenAPI endpoints as resources",
5 | "license": "MIT",
6 | "type": "module",
7 | "main": "./dist/bundle.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git+https://github.com/Noveum/api-market-mcp-server.git"
11 | },
12 | "bin": {
13 | "mcp-server-contentful": "./bin/mcp-server.js"
14 | },
15 | "files": [
16 | "dist",
17 | "modified_files.txt",
18 | "src/lib"
19 | ],
20 | "scripts": {
21 | "build": "node build.js && chmod +x bin/mcp-server.js",
22 | "clean": "rm -rf dist",
23 | "lint": "eslint src/**/*.ts",
24 | "watch": "tsc --watch",
25 | "typecheck": "tsc --noEmit",
26 | "prepare": "npm run build",
27 | "dev": "nodemon --watch src -e ts --exec 'npm run build'",
28 | "inspect": "node -r dotenv/config ./scripts/inspect.js",
29 | "inspect-watch": "node ./scripts/inspect-watch.js"
30 | },
31 | "dependencies": {
32 | "@modelcontextprotocol/sdk": "^0.4.0",
33 | "axios": "^1.7.4",
34 | "openapi-types": "^12.1.3",
35 | "yargs": "^17.7.2"
36 | },
37 | "devDependencies": {
38 | "@types/jest": "^29.5.10",
39 | "@types/node": "^20.10.0",
40 | "@typescript-eslint/eslint-plugin": "^6.12.0",
41 | "@typescript-eslint/parser": "^6.12.0",
42 | "dotenv": "^16.4.7",
43 | "esbuild": "^0.19.9",
44 | "eslint": "^8.54.0",
45 | "jest": "^29.7.0",
46 | "nodemon": "^3.1.7",
47 | "ts-jest": "^29.1.1",
48 | "typescript": "^5.3.2"
49 | }
50 | }
51 |
```
--------------------------------------------------------------------------------
/INSTALL.md:
--------------------------------------------------------------------------------
```markdown
1 | # Installing and Using the OpenAPI MCP Server
2 |
3 | This project is designed to be used as an MCP server and is primarily accessed via the **npx** command. There is no traditional installation required—simply configure your client to use the MCP server.
4 |
5 | ## Quick Start with npx
6 |
7 | ### For Claude Desktop
8 |
9 | 1. Locate or create your configuration file (e.g., `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS).
10 |
11 | 2. Add the following configuration:
12 |
13 | ```json
14 | {
15 | "mcpServers": {
16 | "openapi": {
17 | "command": "npx",
18 | "args": ["-y", "@noveum-ai/mcp-server"],
19 | "env": {
20 | "API_HEADERS": "x-magicapi-key:<your-api-key>,Accept:application/json"
21 | }
22 | }
23 | }
24 | }
25 | ```
26 |
27 | 3. Replace the environment variables with your actual API configuration.
28 |
29 | ### For Cursor
30 |
31 | 1. Go to **File -> Preferences -> Cursor Settings**.
32 | 2. Select **MCP**.
33 | 3. Click on **Add New MCP Server**.
34 | 4. Paste the following command:
35 |
36 | ```bash
37 | npx -y @noveum-ai/mcp-server --headers x-magicapi-key:<your-api-key>,Accept:application/json
38 | ```
39 |
40 | <!-- ## Environment Variables
41 |
42 | You can configure the following environment variables for further customization:
43 |
44 | - **API_BASE_URL**: The base URL of your API (optional).
45 | - **OPENAPI_SPEC_PATH**: URL or path to your OpenAPI specification (optional).
46 | - **API_HEADERS**: Comma-separated key:value pairs for API authentication headers. -->
47 |
48 | ## For Development Purposes
49 |
50 | To run the MCP server locally (for debugging or development):
51 |
52 | 1. **Clone the Repository and Install Dependencies**
53 |
54 | ```bash
55 | git clone https://github.com/Noveum/api-market-mcp-server.git
56 | cd api-market-mcp-server
57 | npm install
58 | ```
59 |
60 | 2. **Build the Server**
61 |
62 | ```bash
63 | npm run build
64 | ```
65 |
66 | 3. **Run or Debug the Server**
67 |
68 | For running:
69 |
70 | ```bash
71 | npm run inspect
72 | ```
73 |
74 |
75 | If you have any issues or questions, please open an issue on GitHub or join our community discussions.
76 |
```
--------------------------------------------------------------------------------
/scripts/inspect-watch.js:
--------------------------------------------------------------------------------
```javascript
1 | #!/usr/bin/env node
2 |
3 | import { spawn } from 'child_process';
4 | import nodemon from 'nodemon';
5 | import { exec } from 'child_process';
6 |
7 | let currentInspector = null;
8 | let isShuttingDown = false;
9 |
10 | // Function to kill all node processes running the inspector
11 | function killAllInspectors() {
12 | return new Promise((resolve) => {
13 | if (process.platform === 'win32') {
14 | exec('taskkill /F /IM node.exe /FI "WINDOWTITLE eq @modelcontextprotocol/inspector*"');
15 | } else {
16 | exec('pkill -f "@modelcontextprotocol/inspector"');
17 | }
18 | resolve();
19 | });
20 | }
21 |
22 | // Function to run the inspector
23 | function startInspector() {
24 | if (isShuttingDown) return null;
25 |
26 | const inspector = spawn('npm', ['run', 'inspect'], {
27 | stdio: 'inherit',
28 | shell: true
29 | });
30 |
31 | inspector.on('error', (err) => {
32 | console.error('Inspector failed to start:', err);
33 | });
34 |
35 | return inspector;
36 | }
37 |
38 | // Cleanup function
39 | async function cleanup() {
40 | isShuttingDown = true;
41 |
42 | if (currentInspector) {
43 | currentInspector.kill('SIGTERM');
44 | currentInspector = null;
45 | }
46 |
47 | await killAllInspectors();
48 | nodemon.emit('quit');
49 | }
50 |
51 | // Set up nodemon to watch the src directory
52 | nodemon({
53 | watch: ['src'],
54 | ext: 'ts',
55 | exec: 'npm run build'
56 | });
57 |
58 | // Handle nodemon events
59 | nodemon
60 | .on('start', () => {
61 | console.log('Starting build...');
62 | })
63 | .on('restart', async () => {
64 | console.log('Files changed, rebuilding...');
65 | if (currentInspector) {
66 | currentInspector.kill('SIGTERM');
67 | await killAllInspectors();
68 | }
69 | })
70 | .on('quit', () => {
71 | console.log('Nodemon stopped');
72 | cleanup().then(() => process.exit(0));
73 | })
74 | .on('error', (err) => {
75 | console.error('Nodemon error:', err);
76 | })
77 | .on('crash', () => {
78 | console.error('Application crashed');
79 | cleanup();
80 | })
81 | .on('exit', () => {
82 | if (!isShuttingDown) {
83 | if (currentInspector) {
84 | currentInspector.kill('SIGTERM');
85 | }
86 | currentInspector = startInspector();
87 | }
88 | });
89 |
90 | // Handle process termination
91 | process.on('SIGTERM', cleanup);
92 | process.on('SIGINT', cleanup);
93 | process.on('SIGHUP', cleanup);
94 |
95 | // Handle uncaught exceptions
96 | process.on('uncaughtException', (err) => {
97 | console.error('Uncaught exception:', err);
98 | cleanup().then(() => process.exit(1));
99 | });
100 |
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-dnschecker.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.2.1",
6 | "description": "API for image processing, including toonification and background removal using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/dnschecker"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/dnschecker/dnschecker": {
15 | "post": {
16 | "summary": "DNS Checker API",
17 | "requestBody": {
18 | "required": true,
19 | "content": {
20 | "application/json": {
21 | "schema": {
22 | "type": "object",
23 | "properties": {
24 | "domain": {
25 | "type": "string",
26 | "default": "google.com"
27 | }
28 | },
29 | "required": [
30 | "domain"
31 | ]
32 | }
33 | }
34 | }
35 | },
36 | "responses": {
37 | "200": {
38 | "description": "Successful response",
39 | "content": {
40 | "application/json": {
41 | "schema": {
42 | "type": "object",
43 | "properties": {
44 | "request_id": {
45 | "type": "string",
46 | "description": "Unique identifier for the request."
47 | }
48 | }
49 | }
50 | }
51 | }
52 | },
53 | "400": {
54 | "description": "Bad Request",
55 | "content": {
56 | "application/json": {
57 | "schema": {
58 | "type": "object",
59 | "properties": {
60 | "error": {
61 | "type": "string",
62 | "description": "Description of the error."
63 | }
64 | }
65 | }
66 | }
67 | }
68 | }
69 | },
70 | "security": [
71 | {
72 | "apiKey": []
73 | }
74 | ]
75 | },
76 | "parameters": [
77 | {
78 | "description": "API.market API Key",
79 | "in": "header",
80 | "name": "x-magicapi-key",
81 | "value": "clp7flnx6000j3pifm3pinw92",
82 | "required": true,
83 | "schema": {
84 | "type": "string"
85 | }
86 | }
87 | ]
88 | }
89 | },
90 | "security": {},
91 | "tags": []
92 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_bridgeml-nsfw-detection.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.2.21",
6 | "description": "API for image processing, including toonification and background removal using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/bridgeml/nsfw-detection"
11 | }
12 | ],
13 | "paths": {
14 | "bridgeml/nsfw!detection/nsfw_detection": {
15 | "post": {
16 | "summary": "A fast nsfw detection API",
17 | "requestBody": {
18 | "required": true,
19 | "content": {
20 | "application/json": {
21 | "schema": {
22 | "type": "object",
23 | "properties": {
24 | "image": {
25 | "type": "string",
26 | "default": "https://blog.api.market/wp-content/uploads/2024/07/wonder_woman.png",
27 | "description": "The url for image that wants to be checked for nsfw"
28 | }
29 | },
30 | "required": [
31 | "image"
32 | ]
33 | }
34 | }
35 | }
36 | },
37 | "responses": {
38 | "200": {
39 | "description": "Image checked successfully",
40 | "content": {
41 | "application/json": {
42 | "schema": {
43 | "type": "object",
44 | "properties": {
45 | "image_url": {
46 | "type": "string",
47 | "description": "The image is nsfw or not"
48 | }
49 | }
50 | }
51 | }
52 | }
53 | },
54 | "400": {
55 | "description": "Bad request",
56 | "content": {
57 | "application/json": {
58 | "schema": {
59 | "type": "object",
60 | "properties": {
61 | "error": {
62 | "type": "string",
63 | "description": "Error message"
64 | }
65 | }
66 | }
67 | }
68 | }
69 | }
70 | },
71 | "security": [
72 | {
73 | "apiKey": []
74 | }
75 | ]
76 | },
77 | "parameters": [
78 | {
79 | "description": "API.market API Key",
80 | "in": "header",
81 | "name": "x-magicapi-key",
82 | "value": "clp7flnx6000j3pifm3pinw92",
83 | "required": true,
84 | "schema": {
85 | "type": "string"
86 | }
87 | }
88 | ]
89 | }
90 | },
91 | "security": {},
92 | "tags": []
93 | }
```
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
```typescript
1 | import yargs from "yargs";
2 | import { hideBin } from "yargs/helpers";
3 | import path from "path";
4 | import { fileURLToPath } from "url";
5 | import { dirname } from "path";
6 | import { OpenAPIV3 } from "openapi-types";
7 |
8 | // Define __dirname for ESM compatibility
9 | const __dirname = dirname(fileURLToPath(import.meta.url));
10 |
11 | export interface APIMarketMCPServerConfig {
12 | name: string;
13 | version: string;
14 | apiBaseUrl: string;
15 | openApiSpec: OpenAPIV3.Document | string;
16 | headers?: Record<string, string>;
17 | }
18 |
19 | export function parseHeaders(headerStr?: string): Record<string, string> {
20 | const headers: Record<string, string> = {};
21 | headers['Accept'] = 'application/json';
22 | if (headerStr) {
23 | headerStr.split(",").forEach((header) => {
24 | const [key, value] = header.split(":");
25 | if (key && value) headers[key.trim()] = value.trim();
26 | });
27 | }
28 | return headers;
29 | }
30 |
31 | export function loadConfig(): APIMarketMCPServerConfig {
32 | const argv = yargs(hideBin(process.argv))
33 | .option("api-base-url", {
34 | alias: "u",
35 | type: "string",
36 | description: "Base URL for the API",
37 | })
38 | .option("openapi-spec", {
39 | alias: "s",
40 | type: "string",
41 | description: "Path or URL to OpenAPI specification",
42 | })
43 | .option("headers", {
44 | alias: "H",
45 | type: "string",
46 | description: "API headers in format 'key1:value1,key2:value2'",
47 | })
48 | .option("name", {
49 | alias: "n",
50 | type: "string",
51 | description: "Server name",
52 | })
53 | .option("version", {
54 | alias: "v",
55 | type: "string",
56 | description: "Server version",
57 | })
58 | .help().argv;
59 |
60 | // Combine CLI args and env vars, with CLI taking precedence
61 | const apiBaseUrl = argv["api-base-url"] || process.env.API_BASE_URL || "https://api.magicapi.dev/api/v1/";
62 | const openApiSpec = argv["openapi-spec"] || process.env.OPENAPI_SPEC_PATH || path.resolve(__dirname, '../modified_files.txt');
63 |
64 | if (!apiBaseUrl) {
65 | throw new Error(
66 | "API base URL is required (--api-base-url or API_BASE_URL)",
67 | );
68 | }
69 | if (!openApiSpec) {
70 | throw new Error(
71 | "OpenAPI spec is required (--openapi-spec or OPENAPI_SPEC_PATH)",
72 | );
73 | }
74 |
75 | const headers = parseHeaders(argv.headers || process.env.API_HEADERS);
76 |
77 | return {
78 | name: argv.name || process.env.SERVER_NAME || "mcp-openapi-server",
79 | version: argv.version || process.env.SERVER_VERSION || "1.0.0",
80 | apiBaseUrl,
81 | openApiSpec,
82 | headers,
83 | };
84 | }
85 |
```
--------------------------------------------------------------------------------
/utils/manual_summary_shortener.py:
--------------------------------------------------------------------------------
```python
1 | import os
2 | import glob
3 | import yaml
4 | import json
5 | import re
6 | from pathlib import Path
7 |
8 |
9 | def is_valid_string(s):
10 | pattern = r'^[a-zA-Z0-9 _-]+$'
11 | return bool(re.match(pattern, s))
12 |
13 |
14 | def update_summary(current_summary: str) -> str:
15 | """
16 | Prompts the user to manually enter a new summary based on the current summary.
17 |
18 | Parameters:
19 | current_summary (str): The summary text to be replaced.
20 |
21 | Returns:
22 | new_summary (str): The user-provided summary.
23 | """
24 |
25 | while True:
26 | print(f"\nOriginal summary: {current_summary}")
27 | summaries = ["A fast text-to-image model that makes high-quality images in 4 steps", "Finding the best route and get multiple stops driving directions", "Finding the best route between an origin and a destination", "Calculate distances and durations between a set of origins and destinations."]
28 | shortened_summaries = ["text-to-image", "best route for multiple stops", "best route bw start and stop", "distance and duration bw starts and stops"]
29 | if current_summary in summaries:
30 | index = summaries.index(current_summary)
31 | current_summary = shortened_summaries[index]
32 | print(current_summary)
33 | return current_summary
34 | else:
35 | new_summary = input("Enter a new summary under 54 characters: ").strip()
36 |
37 | if len(new_summary) < 55 and is_valid_string(new_summary):
38 | return new_summary
39 | else:
40 | print("Invalid summary. Please ensure it is under 54 characters and contains only alphanumeric characters, hyphens, and underscores.")
41 |
42 |
43 | HTTP_METHODS = {"get", "post", "put", "delete", "patch", "head", "options", "trace"}
44 |
45 | def update_method_summaries(paths_dict):
46 | """
47 | Iterate over all path entries and update the summary field in method definitions.
48 | """
49 | for path, methods in paths_dict.items():
50 | if isinstance(methods, dict):
51 | for method, operation in methods.items():
52 | if method.lower() in HTTP_METHODS and isinstance(operation, dict):
53 | if "summary" in operation and isinstance(operation["summary"], str) and (len(operation["summary"]) >= 55 or not is_valid_string(operation["summary"])):
54 | original_summary = operation["summary"]
55 | new_summary = update_summary(current_summary=original_summary)
56 | operation["summary"] = new_summary
57 |
58 |
59 | file_patterns = ["*.yaml", "*.yml", "*.json"]
60 | files = []
61 | current_dir = (Path(__file__).parent)
62 | directory = os.path.join( current_dir, r"../src/lib")
63 | for pattern in file_patterns:
64 | search_pattern = os.path.join(directory, pattern)
65 | files.extend(glob.glob(search_pattern))
66 |
67 | for file in files:
68 | try:
69 | with open(file, 'r') as f:
70 | if file.endswith(".json"):
71 | data = json.load(f)
72 | else:
73 | data = yaml.safe_load(f)
74 | except Exception as e:
75 | print(f"Error reading {file}: {e}")
76 | continue
77 |
78 | if "paths" in data and isinstance(data["paths"], dict):
79 | update_method_summaries(data["paths"])
80 |
81 | try:
82 | with open(file, 'w') as f:
83 | if file.endswith(".json"):
84 | json.dump(data, f, indent=2)
85 | else:
86 | yaml.dump(data, f, sort_keys=False)
87 | except Exception as e:
88 | print(f"Error writing {file}: {e}")
89 |
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-whois.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.3",
3 | "info": {
4 | "title": "WHOIS API",
5 | "description": "API for querying domain WHOIS information.",
6 | "version": "1.0.2"
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/whois"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/whois/whois/{domain}": {
15 | "get": {
16 | "summary": "Get WHOIS information for a domain",
17 | "operationId": "getWhoisInfo",
18 | "parameters": [
19 | {
20 | "name": "domain",
21 | "in": "path",
22 | "required": true,
23 | "description": "Domain to query WHOIS information for",
24 | "schema": {
25 | "type": "string"
26 | },
27 | "example": "google.com"
28 | }
29 | ],
30 | "responses": {
31 | "200": {
32 | "description": "Successful response",
33 | "content": {
34 | "application/json": {
35 | "schema": {
36 | "type": "object",
37 | "properties": {
38 | "OrganizationName": {
39 | "type": "string",
40 | "nullable": true
41 | },
42 | "Raw": {
43 | "type": "string"
44 | },
45 | "RespondedServers": {
46 | "type": "array",
47 | "items": {
48 | "type": "string"
49 | }
50 | },
51 | "AddressRange": {
52 | "type": "string",
53 | "nullable": true
54 | }
55 | }
56 | }
57 | }
58 | },
59 | "examples": {
60 | "google_example": {
61 | "summary": "Example response for google.com",
62 | "value": {
63 | "OrganizationName": "Google LLC",
64 | "Raw": "Domain Name: GOOGLE.COM\nRegistrar: MarkMonitor Inc.\n...",
65 | "RespondedServers": [
66 | "whois.verisign-grs.com",
67 | "whois.markmonitor.com"
68 | ],
69 | "AddressRange": "172.217.0.0 - 172.217.255.255"
70 | }
71 | }
72 | }
73 | },
74 | "400": {
75 | "description": "Invalid request"
76 | },
77 | "401": {
78 | "description": "Unauthorized request"
79 | },
80 | "404": {
81 | "description": "Domain not found"
82 | },
83 | "500": {
84 | "description": "Server error"
85 | }
86 | },
87 | "security": [
88 | {
89 | "basicAuth": []
90 | }
91 | ]
92 | },
93 | "parameters": [
94 | {
95 | "description": "API.market API Key",
96 | "in": "header",
97 | "name": "x-magicapi-key",
98 | "value": "clp7flnx6000j3pifm3pinw92",
99 | "required": true,
100 | "schema": {
101 | "type": "string"
102 | }
103 | }
104 | ]
105 | }
106 | },
107 | "components": {
108 | "schemas": {
109 | "WhoisResponse": {
110 | "type": "object",
111 | "properties": {
112 | "OrganizationName": {
113 | "type": "string",
114 | "nullable": true
115 | },
116 | "Raw": {
117 | "type": "string"
118 | },
119 | "RespondedServers": {
120 | "type": "array",
121 | "items": {
122 | "type": "string"
123 | }
124 | },
125 | "AddressRange": {
126 | "type": "string",
127 | "nullable": true
128 | }
129 | }
130 | }
131 | },
132 | "securitySchemes": {}
133 | },
134 | "security": {},
135 | "tags": []
136 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-screenshot-api.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Screenshot API Updated",
5 | "version": "1.0.4"
6 | },
7 | "servers": [
8 | {
9 | "url": "http://api.magicapi.dev/api/v1/magicapi/screenshot-api"
10 | }
11 | ],
12 | "paths": {
13 | "magicapi/screenshot!api/api/screenshot": {
14 | "get": {
15 | "summary": "Capture a screenshot of a webpage",
16 | "parameters": [
17 | {
18 | "in": "query",
19 | "name": "resX",
20 | "required": true,
21 | "schema": {
22 | "type": "integer"
23 | },
24 | "example": 1280
25 | },
26 | {
27 | "in": "query",
28 | "name": "resY",
29 | "required": true,
30 | "schema": {
31 | "type": "integer"
32 | },
33 | "example": 900
34 | },
35 | {
36 | "in": "query",
37 | "name": "outFormat",
38 | "required": true,
39 | "schema": {
40 | "type": "string"
41 | },
42 | "example": "jpg"
43 | },
44 | {
45 | "in": "query",
46 | "name": "waitTime",
47 | "schema": {
48 | "type": "integer"
49 | },
50 | "example": 100
51 | },
52 | {
53 | "in": "query",
54 | "name": "isFullPage",
55 | "schema": {
56 | "type": "boolean"
57 | },
58 | "example": false
59 | },
60 | {
61 | "in": "query",
62 | "name": "dismissModals",
63 | "schema": {
64 | "type": "boolean"
65 | },
66 | "example": false
67 | },
68 | {
69 | "in": "query",
70 | "name": "url",
71 | "required": true,
72 | "schema": {
73 | "type": "string"
74 | },
75 | "example": "https://api.market/"
76 | }
77 | ],
78 | "responses": {
79 | "200": {
80 | "description": "Successful screenshot capture",
81 | "content": {
82 | "image/jpeg": {
83 | "schema": {
84 | "type": "string",
85 | "format": "binary"
86 | },
87 | "example": "<base64_encoded_image>"
88 | }
89 | }
90 | },
91 | "400": {
92 | "description": "Bad request",
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "error": {
99 | "type": "string",
100 | "example": "Invalid parameters provided"
101 | }
102 | }
103 | }
104 | }
105 | }
106 | },
107 | "500": {
108 | "description": "Internal server error",
109 | "content": {
110 | "application/json": {
111 | "schema": {
112 | "type": "object",
113 | "properties": {
114 | "error": {
115 | "type": "string",
116 | "example": "Internal server error occurred"
117 | }
118 | }
119 | }
120 | }
121 | }
122 | }
123 | },
124 | "security": [
125 | {
126 | "basicAuth": []
127 | }
128 | ]
129 | },
130 | "parameters": [
131 | {
132 | "description": "API.market API Key",
133 | "in": "header",
134 | "name": "x-magicapi-key",
135 | "value": "clp7flnx6000j3pifm3pinw92",
136 | "required": true,
137 | "schema": {
138 | "type": "string"
139 | }
140 | }
141 | ]
142 | }
143 | },
144 | "components": {
145 | "securitySchemes": {}
146 | },
147 | "security": {},
148 | "tags": []
149 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_bridgeml-text-to-image.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.2.15",
6 | "description": "API for image processing, including toonification and background removal using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/bridgeml/text-to-image"
11 | }
12 | ],
13 | "paths": {
14 | "bridgeml/text!to!image/text_to_image": {
15 | "post": {
16 | "summary": "text-to-image",
17 | "requestBody": {
18 | "required": true,
19 | "content": {
20 | "application/json": {
21 | "schema": {
22 | "type": "object",
23 | "properties": {
24 | "prompt": {
25 | "type": "string",
26 | "default": "Futuristic space battle, hyper realistic, 4k",
27 | "description": "The prompt for generating the image"
28 | },
29 | "height": {
30 | "type": "integer",
31 | "default": 1024,
32 | "description": "The height of the image"
33 | },
34 | "width": {
35 | "type": "integer",
36 | "default": 1024,
37 | "description": "The width of the image"
38 | },
39 | "scheduler": {
40 | "type": "string",
41 | "default": "K_EULER",
42 | "description": "The scheduler to use"
43 | },
44 | "num_outputs": {
45 | "type": "integer",
46 | "default": 1,
47 | "description": "The number of outputs"
48 | },
49 | "guidance_scale": {
50 | "type": "number",
51 | "default": 0,
52 | "description": "The guidance scale"
53 | },
54 | "negative_prompt": {
55 | "type": "string",
56 | "default": "worst quality, low quality",
57 | "description": "The negative prompt"
58 | },
59 | "num_inference_steps": {
60 | "type": "integer",
61 | "default": 4,
62 | "description": "The number of inference steps"
63 | }
64 | },
65 | "required": [
66 | "prompt",
67 | "height",
68 | "width"
69 | ]
70 | }
71 | }
72 | }
73 | },
74 | "responses": {
75 | "200": {
76 | "description": "Image generated successfully",
77 | "content": {
78 | "application/json": {
79 | "schema": {
80 | "type": "object",
81 | "properties": {
82 | "image_url": {
83 | "type": "string",
84 | "description": "The URL of the generated image"
85 | }
86 | }
87 | }
88 | }
89 | }
90 | },
91 | "400": {
92 | "description": "Bad request",
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "error": {
99 | "type": "string",
100 | "description": "Error message"
101 | }
102 | }
103 | }
104 | }
105 | }
106 | }
107 | },
108 | "security": [
109 | {
110 | "apiKey": []
111 | }
112 | ]
113 | },
114 | "parameters": [
115 | {
116 | "description": "API.market API Key",
117 | "in": "header",
118 | "name": "x-magicapi-key",
119 | "value": "clp7flnx6000j3pifm3pinw92",
120 | "required": true,
121 | "schema": {
122 | "type": "string"
123 | }
124 | }
125 | ]
126 | }
127 | },
128 | "security": {},
129 | "tags": []
130 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_bridgeml-codellama.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.2.5",
6 | "description": "API for image processing, including toonification and background removal using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/bridgeml/codellama"
11 | }
12 | ],
13 | "paths": {
14 | "bridgeml/codellama/bridgeml/codellama": {
15 | "post": {
16 | "summary": "BridgeML API",
17 | "requestBody": {
18 | "required": true,
19 | "content": {
20 | "application/json": {
21 | "schema": {
22 | "type": "object",
23 | "properties": {
24 | "messages": {
25 | "type": "array",
26 | "description": "List of messages",
27 | "items": {
28 | "type": "object",
29 | "properties": {
30 | "role": {
31 | "type": "string",
32 | "description": "Role of the message sender",
33 | "enum": [
34 | "user",
35 | "assistant"
36 | ]
37 | },
38 | "content": {
39 | "type": "string",
40 | "description": "Content of the message"
41 | }
42 | }
43 | },
44 | "example": [
45 | {
46 | "role": "user",
47 | "content": "hello"
48 | },
49 | {
50 | "role": "assistant",
51 | "content": ""
52 | }
53 | ]
54 | },
55 | "temperature": {
56 | "type": "number",
57 | "description": "Temperature for text generation",
58 | "example": 1
59 | },
60 | "max_tokens": {
61 | "type": "number",
62 | "description": "Maximum number of tokens to generate",
63 | "example": 256
64 | },
65 | "top_p": {
66 | "type": "number",
67 | "description": "Top P sampling value",
68 | "example": 1
69 | },
70 | "frequency_penalty": {
71 | "type": "number",
72 | "description": "Frequency penalty value",
73 | "example": 0
74 | },
75 | "stream": {
76 | "type": "boolean",
77 | "description": "Flag indicating if response should be streamed",
78 | "example": false
79 | }
80 | }
81 | }
82 | }
83 | }
84 | },
85 | "responses": {
86 | "200": {
87 | "description": "Successful response",
88 | "content": {
89 | "application/json": {
90 | "schema": {
91 | "type": "object",
92 | "properties": {
93 | "request_id": {
94 | "type": "string",
95 | "description": "Unique identifier for the request."
96 | }
97 | }
98 | }
99 | }
100 | }
101 | },
102 | "400": {
103 | "description": "Bad Request",
104 | "content": {
105 | "application/json": {
106 | "schema": {
107 | "type": "object",
108 | "properties": {
109 | "error": {
110 | "type": "string",
111 | "description": "Description of the error."
112 | }
113 | }
114 | }
115 | }
116 | }
117 | }
118 | },
119 | "security": [
120 | {
121 | "apiKey": []
122 | }
123 | ]
124 | },
125 | "parameters": [
126 | {
127 | "description": "API.market API Key",
128 | "in": "header",
129 | "name": "x-magicapi-key",
130 | "value": "clp7flnx6000j3pifm3pinw92",
131 | "required": true,
132 | "schema": {
133 | "type": "string"
134 | }
135 | }
136 | ]
137 | }
138 | },
139 | "security": {},
140 | "tags": []
141 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_bridgeml-mistralai.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.2.9",
6 | "description": "API for image processing, including toonification and background removal using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/bridgeml/mistralai"
11 | }
12 | ],
13 | "paths": {
14 | "bridgeml/mistralai/bridgeml/mistralai7b": {
15 | "post": {
16 | "summary": "BridgeML API",
17 | "requestBody": {
18 | "required": true,
19 | "content": {
20 | "application/json": {
21 | "schema": {
22 | "type": "object",
23 | "properties": {
24 | "messages": {
25 | "type": "array",
26 | "description": "List of messages",
27 | "items": {
28 | "type": "object",
29 | "properties": {
30 | "role": {
31 | "type": "string",
32 | "description": "Role of the message sender",
33 | "enum": [
34 | "user",
35 | "assistant"
36 | ]
37 | },
38 | "content": {
39 | "type": "string",
40 | "description": "Content of the message"
41 | }
42 | }
43 | },
44 | "example": [
45 | {
46 | "role": "user",
47 | "content": "hello"
48 | },
49 | {
50 | "role": "assistant",
51 | "content": "Use voice of customer from an Amazon review to write an ad for a webcam."
52 | }
53 | ]
54 | },
55 | "temperature": {
56 | "type": "number",
57 | "description": "Temperature for text generation",
58 | "example": 1
59 | },
60 | "max_tokens": {
61 | "type": "number",
62 | "description": "Maximum number of tokens to generate",
63 | "example": 256
64 | },
65 | "top_p": {
66 | "type": "number",
67 | "description": "Top P sampling value",
68 | "example": 1
69 | },
70 | "frequency_penalty": {
71 | "type": "number",
72 | "description": "Frequency penalty value",
73 | "example": 0
74 | },
75 | "stream": {
76 | "type": "boolean",
77 | "description": "Flag indicating if response should be streamed",
78 | "example": false
79 | }
80 | }
81 | }
82 | }
83 | }
84 | },
85 | "responses": {
86 | "200": {
87 | "description": "Successful response",
88 | "content": {
89 | "application/json": {
90 | "schema": {
91 | "type": "object",
92 | "properties": {
93 | "request_id": {
94 | "type": "string",
95 | "description": "Unique identifier for the request."
96 | }
97 | }
98 | }
99 | }
100 | }
101 | },
102 | "400": {
103 | "description": "Bad Request",
104 | "content": {
105 | "application/json": {
106 | "schema": {
107 | "type": "object",
108 | "properties": {
109 | "error": {
110 | "type": "string",
111 | "description": "Description of the error."
112 | }
113 | }
114 | }
115 | }
116 | }
117 | }
118 | },
119 | "security": [
120 | {
121 | "apiKey": []
122 | }
123 | ]
124 | },
125 | "parameters": [
126 | {
127 | "description": "API.market API Key",
128 | "in": "header",
129 | "name": "x-magicapi-key",
130 | "value": "clp7flnx6000j3pifm3pinw92",
131 | "required": true,
132 | "schema": {
133 | "type": "string"
134 | }
135 | }
136 | ]
137 | }
138 | },
139 | "security": {},
140 | "tags": []
141 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_bridgeml-mistralai8x22.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.2.9",
6 | "description": "API for image processing, including toonification and background removal using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/bridgeml/mistralai8x22"
11 | }
12 | ],
13 | "paths": {
14 | "bridgeml/mistralai8x22/bridgeml/mistralai8x22": {
15 | "post": {
16 | "summary": "BridgeML API",
17 | "requestBody": {
18 | "required": true,
19 | "content": {
20 | "application/json": {
21 | "schema": {
22 | "type": "object",
23 | "properties": {
24 | "messages": {
25 | "type": "array",
26 | "description": "List of messages",
27 | "items": {
28 | "type": "object",
29 | "properties": {
30 | "role": {
31 | "type": "string",
32 | "description": "Role of the message sender",
33 | "enum": [
34 | "user",
35 | "assistant"
36 | ]
37 | },
38 | "content": {
39 | "type": "string",
40 | "description": "Content of the message"
41 | }
42 | }
43 | },
44 | "example": [
45 | {
46 | "role": "user",
47 | "content": "hello"
48 | },
49 | {
50 | "role": "assistant",
51 | "content": "Use voice of customer from a G2 review to write an ad for GitLab."
52 | }
53 | ]
54 | },
55 | "temperature": {
56 | "type": "number",
57 | "description": "Temperature for text generation",
58 | "example": 1
59 | },
60 | "max_tokens": {
61 | "type": "number",
62 | "description": "Maximum number of tokens to generate",
63 | "example": 256
64 | },
65 | "top_p": {
66 | "type": "number",
67 | "description": "Top P sampling value",
68 | "example": 1
69 | },
70 | "frequency_penalty": {
71 | "type": "number",
72 | "description": "Frequency penalty value",
73 | "example": 0
74 | },
75 | "stream": {
76 | "type": "boolean",
77 | "description": "Flag indicating if response should be streamed",
78 | "example": false
79 | }
80 | }
81 | }
82 | }
83 | }
84 | },
85 | "responses": {
86 | "200": {
87 | "description": "Successful response",
88 | "content": {
89 | "application/json": {
90 | "schema": {
91 | "type": "object",
92 | "properties": {
93 | "request_id": {
94 | "type": "string",
95 | "description": "Unique identifier for the request."
96 | }
97 | }
98 | }
99 | }
100 | }
101 | },
102 | "400": {
103 | "description": "Bad Request",
104 | "content": {
105 | "application/json": {
106 | "schema": {
107 | "type": "object",
108 | "properties": {
109 | "error": {
110 | "type": "string",
111 | "description": "Description of the error."
112 | }
113 | }
114 | }
115 | }
116 | }
117 | }
118 | },
119 | "security": [
120 | {
121 | "apiKey": []
122 | }
123 | ]
124 | },
125 | "parameters": [
126 | {
127 | "description": "API.market API Key",
128 | "in": "header",
129 | "name": "x-magicapi-key",
130 | "value": "clp7flnx6000j3pifm3pinw92",
131 | "required": true,
132 | "schema": {
133 | "type": "string"
134 | }
135 | }
136 | ]
137 | }
138 | },
139 | "security": {},
140 | "tags": []
141 | }
```
--------------------------------------------------------------------------------
/utils/modify_api.py:
--------------------------------------------------------------------------------
```python
1 | import json
2 | import os
3 | import re
4 | from typing import List
5 |
6 | def get_json_files(directory: str) -> List[str]:
7 | # Pattern to match filenames like a-b-c.json, a-b.json, etc.
8 | pattern = re.compile(r'^([\w\-]+)\.json$')
9 | return [f for f in os.listdir(directory) if pattern.match(f)]
10 |
11 | def replace_hyphens_in_paths(data):
12 | if 'paths' not in data:
13 | return data
14 |
15 | new_paths = {}
16 | for path, details in data['paths'].items():
17 | new_path = path.replace('-', '_')
18 | new_paths[new_path] = details
19 |
20 | data['paths'] = new_paths
21 | return data
22 |
23 | def modify_paths(data: dict, prefix: str) -> dict:
24 | modified_paths = {f"{prefix}{path}": details for path, details in data['paths'].items()}
25 | data['paths'] = modified_paths
26 | return data
27 |
28 | def resolve_references(data):
29 | components = data.get("components", {}).get("schemas", {})
30 |
31 | def _resolve(item):
32 | if isinstance(item, dict):
33 | if "$ref" in item:
34 | # Resolve $ref
35 | ref_path = item["$ref"].replace("#/components/schemas/", "")
36 | ref_obj = components.get(ref_path, {})
37 | if not ref_obj:
38 | raise ValueError(f"Reference {item['$ref']} not found in components.")
39 | return _resolve(ref_obj)
40 |
41 | if "allOf" in item:
42 | # Resolve allOf
43 | combined_schema = {"type": "object", "properties": {}, "required": []}
44 |
45 | for subschema in item["allOf"]:
46 | resolved_schema = _resolve(subschema)
47 | combined_schema["properties"].update(resolved_schema.get("properties", {}))
48 | combined_schema["required"].extend(resolved_schema.get("required", []))
49 |
50 | combined_schema["required"] = list(set(combined_schema["required"]))
51 | if "title" in item:
52 | combined_schema["title"] = item["title"]
53 |
54 | return combined_schema
55 |
56 | # Recursively resolve nested schemas
57 | return {key: _resolve(value) for key, value in item.items()}
58 |
59 | if isinstance(item, list):
60 | return [_resolve(sub_item) for sub_item in item]
61 |
62 | return item
63 |
64 | return _resolve(data)
65 |
66 | def process_files(directory: str):
67 | if not os.path.exists(directory):
68 | print(f"Error: Directory '{directory}' does not exist.")
69 | return
70 |
71 | files = get_json_files(directory)
72 | modified_files = []
73 |
74 | # Create a directory for modified files if it doesn't exist
75 | modified_dir = os.path.join('./', 'src/lib')
76 | os.makedirs(modified_dir, exist_ok=True)
77 |
78 | for file_name in files:
79 | file_path = os.path.join(directory, file_name)
80 | try:
81 | with open(file_path, 'r') as file:
82 | data = json.load(file)
83 | except FileNotFoundError:
84 | print(f"Error: File '{file_path}' not found.")
85 | continue
86 | except json.JSONDecodeError:
87 | print(f"Error: File '{file_path}' contains invalid JSON.")
88 | continue
89 |
90 |
91 | # Generate prefix from the filename, e.g., 'a-b-c.json' -> 'a/b_c/'
92 | file_name_no_ext = file_name.replace('.json', '')
93 |
94 | # Replace the first hyphen with a slash
95 | if '-' in file_name_no_ext:
96 | file_name_no_ext = file_name_no_ext.replace('-', '/', 1)
97 |
98 | prefix = file_name_no_ext.replace('-', '!')
99 | try:
100 | modified_data = modify_paths(data, prefix)
101 | modified_data = resolve_references(modified_data)
102 | modified_data = replace_hyphens_in_paths(modified_data)
103 | # Save modified data to modified_json_files directory
104 | output_file = os.path.relpath(os.path.join(modified_dir, f"modified_{file_name}"))
105 | with open(output_file, 'w') as file:
106 | json.dump(modified_data, file, indent=4)
107 |
108 | modified_files.append(output_file)
109 | except Exception as e:
110 | print(f"Error processing file '{file_name}': {str(e)}")
111 | continue
112 |
113 | # Write all modified file names to a text file in the current directory
114 | try:
115 | with open('./modified_files.txt', 'a') as file:
116 | modified_files = ['../' + x for x in modified_files]
117 | file.write('\n'.join(modified_files) + '\n')
118 | except Exception as e:
119 | print(f"Error writing to modified_files.txt: {str(e)}")
120 |
121 | if __name__ == "__main__":
122 | directory = "../json_files" # Specify your directory containing the JSON files
123 | process_files(directory)
124 |
125 |
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-period.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.1.3",
6 | "description": "API for generating ageing gif using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/period"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/period/predictions/{request_id}": {
15 | "get": {
16 | "summary": "Get ageing gif URL",
17 | "description": "This endpoint retrieves the URL of the ageing gif for a given request ID.\n",
18 | "parameters": [
19 | {
20 | "name": "request_id",
21 | "in": "path",
22 | "required": true,
23 | "description": "Unique identifier for the request.",
24 | "schema": {
25 | "type": "string"
26 | }
27 | }
28 | ],
29 | "responses": {
30 | "200": {
31 | "description": "Successful response",
32 | "content": {
33 | "application/json": {
34 | "schema": {
35 | "type": "object",
36 | "properties": {
37 | "status": {
38 | "type": "string",
39 | "description": "Status of the prediction (e.g., \"succeeded\")."
40 | },
41 | "image_url": {
42 | "type": "string",
43 | "format": "uri",
44 | "description": "URL of the ageing gif."
45 | }
46 | }
47 | }
48 | }
49 | }
50 | },
51 | "400": {
52 | "description": "Bad Request",
53 | "content": {
54 | "application/json": {
55 | "schema": {
56 | "type": "object",
57 | "properties": {
58 | "error": {
59 | "type": "string",
60 | "description": "Description of the error."
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | },
68 | "security": [
69 | {
70 | "apiKey": []
71 | }
72 | ]
73 | },
74 | "parameters": [
75 | {
76 | "description": "API.market API Key",
77 | "in": "header",
78 | "name": "x-magicapi-key",
79 | "value": "clp7flnx6000j3pifm3pinw92",
80 | "required": true,
81 | "schema": {
82 | "type": "string"
83 | }
84 | }
85 | ]
86 | },
87 | "magicapi/period/period": {
88 | "post": {
89 | "summary": "Period changer",
90 | "description": "API for generating ageing gif using AI models. Make sure to call get ageing gif URL, with the result id received from this API",
91 | "requestBody": {
92 | "required": true,
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "image": {
99 | "type": "string",
100 | "default": "https://replicate.delivery/mgxm/806bea64-bb51-4c8a-bf4d-15602eb60fdd/1287.jpg"
101 | },
102 | "target_age": {
103 | "type": "string",
104 | "default": "default"
105 | }
106 | },
107 | "required": [
108 | "image",
109 | "target_age"
110 | ]
111 | }
112 | }
113 | }
114 | },
115 | "responses": {
116 | "200": {
117 | "description": "Successful response",
118 | "content": {
119 | "application/json": {
120 | "schema": {
121 | "type": "object",
122 | "properties": {
123 | "request_id": {
124 | "type": "string",
125 | "description": "Unique identifier for the request."
126 | }
127 | }
128 | }
129 | }
130 | }
131 | },
132 | "400": {
133 | "description": "Bad Request",
134 | "content": {
135 | "application/json": {
136 | "schema": {
137 | "type": "object",
138 | "properties": {
139 | "error": {
140 | "type": "string",
141 | "description": "Description of the error."
142 | }
143 | }
144 | }
145 | }
146 | }
147 | }
148 | },
149 | "security": [
150 | {
151 | "apiKey": []
152 | }
153 | ]
154 | },
155 | "parameters": [
156 | {
157 | "description": "API.market API Key",
158 | "in": "header",
159 | "name": "x-magicapi-key",
160 | "value": "clp7flnx6000j3pifm3pinw92",
161 | "required": true,
162 | "schema": {
163 | "type": "string"
164 | }
165 | }
166 | ]
167 | }
168 | },
169 | "security": {},
170 | "tags": []
171 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-colorizer.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.1.8",
6 | "description": "API for image colorization using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/colorizer"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/colorizer/predictions/{request_id}": {
15 | "get": {
16 | "summary": "Get Colorized Image URL",
17 | "description": "This endpoint retrieves the URL of the colorized image for a given request ID.\n",
18 | "parameters": [
19 | {
20 | "name": "request_id",
21 | "in": "path",
22 | "required": true,
23 | "description": "Unique identifier for the request.",
24 | "schema": {
25 | "type": "string"
26 | }
27 | }
28 | ],
29 | "responses": {
30 | "200": {
31 | "description": "Successful response",
32 | "content": {
33 | "application/json": {
34 | "schema": {
35 | "type": "object",
36 | "properties": {
37 | "status": {
38 | "type": "string",
39 | "description": "Status of the prediction (e.g., \"succeeded\")."
40 | },
41 | "image_url": {
42 | "type": "string",
43 | "format": "uri",
44 | "description": "URL of the colorized image."
45 | }
46 | }
47 | }
48 | }
49 | }
50 | },
51 | "400": {
52 | "description": "Bad Request",
53 | "content": {
54 | "application/json": {
55 | "schema": {
56 | "type": "object",
57 | "properties": {
58 | "error": {
59 | "type": "string",
60 | "description": "Description of the error."
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | },
68 | "security": [
69 | {
70 | "apiKey": []
71 | }
72 | ]
73 | },
74 | "parameters": [
75 | {
76 | "description": "API.market API Key",
77 | "in": "header",
78 | "name": "x-magicapi-key",
79 | "value": "clp7flnx6000j3pifm3pinw92",
80 | "required": true,
81 | "schema": {
82 | "type": "string"
83 | }
84 | }
85 | ]
86 | },
87 | "magicapi/colorizer/colorizer": {
88 | "post": {
89 | "summary": "Colorizes greyscale images",
90 | "description": "This endpoint takes in a URL of an image and colorize old images\n Make sure you call get colorized image URL, MCP tool to get the URL for the request id received from this API",
91 | "requestBody": {
92 | "required": true,
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "image": {
99 | "type": "string",
100 | "format": "uri",
101 | "description": "URL of the main image.",
102 | "default": "https://user-images.githubusercontent.com/5865387/56368408-58561980-61c5-11e9-9800-0678dc02b4e7.png"
103 | }
104 | },
105 | "required": [
106 | "image"
107 | ]
108 | }
109 | }
110 | }
111 | },
112 | "responses": {
113 | "200": {
114 | "description": "Successful response",
115 | "content": {
116 | "application/json": {
117 | "schema": {
118 | "type": "object",
119 | "properties": {
120 | "request_id": {
121 | "type": "string",
122 | "description": "Unique identifier for the request."
123 | }
124 | }
125 | }
126 | }
127 | }
128 | },
129 | "400": {
130 | "description": "Bad Request",
131 | "content": {
132 | "application/json": {
133 | "schema": {
134 | "type": "object",
135 | "properties": {
136 | "error": {
137 | "type": "string",
138 | "description": "Description of the error."
139 | }
140 | }
141 | }
142 | }
143 | }
144 | }
145 | },
146 | "security": [
147 | {
148 | "apiKey": []
149 | }
150 | ]
151 | },
152 | "parameters": [
153 | {
154 | "description": "API.market API Key",
155 | "in": "header",
156 | "name": "x-magicapi-key",
157 | "value": "clp7flnx6000j3pifm3pinw92",
158 | "required": true,
159 | "schema": {
160 | "type": "string"
161 | }
162 | }
163 | ]
164 | }
165 | },
166 | "security": {},
167 | "tags": []
168 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-deblurer.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.2.2",
6 | "description": "API for image deblurring, using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/deblurer"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/deblurer/predictions/{request_id}": {
15 | "get": {
16 | "summary": "Get Unblurred Image URL",
17 | "description": "This endpoint retrieves the URL of the Unblurred image for a given request ID.\n",
18 | "parameters": [
19 | {
20 | "name": "request_id",
21 | "in": "path",
22 | "required": true,
23 | "description": "Unique identifier for the request.",
24 | "schema": {
25 | "type": "string"
26 | }
27 | }
28 | ],
29 | "responses": {
30 | "200": {
31 | "description": "Successful response",
32 | "content": {
33 | "application/json": {
34 | "schema": {
35 | "type": "object",
36 | "properties": {
37 | "status": {
38 | "type": "string",
39 | "description": "Status of the prediction (e.g., \"succeeded\")."
40 | },
41 | "image_url": {
42 | "type": "string",
43 | "format": "uri",
44 | "description": "URL of the deblurred image."
45 | }
46 | }
47 | }
48 | }
49 | }
50 | },
51 | "400": {
52 | "description": "Bad Request",
53 | "content": {
54 | "application/json": {
55 | "schema": {
56 | "type": "object",
57 | "properties": {
58 | "error": {
59 | "type": "string",
60 | "description": "Description of the error."
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | },
68 | "security": [
69 | {
70 | "apiKey": []
71 | }
72 | ]
73 | },
74 | "parameters": [
75 | {
76 | "description": "API.market API Key",
77 | "in": "header",
78 | "name": "x-magicapi-key",
79 | "value": "clp7flnx6000j3pifm3pinw92",
80 | "required": true,
81 | "schema": {
82 | "type": "string"
83 | }
84 | }
85 | ]
86 | },
87 | "magicapi/deblurer/deblurer": {
88 | "post": {
89 | "summary": "Deblurer",
90 | "description": "API for image deblurring. \n Make sure you call get deblurred image URL, MCP tool to get the URL for the request id received from this API",
91 | "requestBody": {
92 | "required": true,
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "image": {
99 | "type": "string",
100 | "default": "https://replicate.delivery/mgxm/e7a66188-34c6-483b-813f-be5c96a3952b/blurry-reds-0.jpg"
101 | },
102 | "task_type": {
103 | "type": "string",
104 | "default": "Image Debluring (REDS)"
105 | }
106 | },
107 | "required": [
108 | "image",
109 | "task_type"
110 | ]
111 | }
112 | }
113 | }
114 | },
115 | "responses": {
116 | "200": {
117 | "description": "Successful response",
118 | "content": {
119 | "application/json": {
120 | "schema": {
121 | "type": "object",
122 | "properties": {
123 | "request_id": {
124 | "type": "string",
125 | "description": "Unique identifier for the request."
126 | }
127 | }
128 | }
129 | }
130 | }
131 | },
132 | "400": {
133 | "description": "Bad Request",
134 | "content": {
135 | "application/json": {
136 | "schema": {
137 | "type": "object",
138 | "properties": {
139 | "error": {
140 | "type": "string",
141 | "description": "Description of the error."
142 | }
143 | }
144 | }
145 | }
146 | }
147 | }
148 | },
149 | "security": [
150 | {
151 | "apiKey": []
152 | }
153 | ]
154 | },
155 | "parameters": [
156 | {
157 | "description": "API.market API Key",
158 | "in": "header",
159 | "name": "x-magicapi-key",
160 | "value": "clp7flnx6000j3pifm3pinw92",
161 | "required": true,
162 | "schema": {
163 | "type": "string"
164 | }
165 | }
166 | ]
167 | }
168 | },
169 | "security": {},
170 | "tags": []
171 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_capix-inpainting.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.1.0",
3 | "info": {
4 | "title": "RemoveBg and Inpainting API",
5 | "version": "0.1.5"
6 | },
7 | "servers": [
8 | {
9 | "url": "http://api.magicapi.dev/api/v1/capix/inpainting"
10 | }
11 | ],
12 | "paths": {
13 | "capix/inpainting/inpainting": {
14 | "post": {
15 | "tags": [
16 | "Inpainting"
17 | ],
18 | "summary": "Inpainting",
19 | "operationId": "Inpainting",
20 | "requestBody": {
21 | "required": true,
22 | "content": {
23 | "application/x-www-form-urlencoded": {
24 | "schema": {
25 | "type": "object",
26 | "properties": {
27 | "image_url": {
28 | "type": "string",
29 | "title": "Image Url",
30 | "default": "https://telegra.ph/file/1dbd57f8abf95e6ae2911.png"
31 | },
32 | "mask_url": {
33 | "type": "string",
34 | "title": "Mask Url",
35 | "default": "https://telegra.ph/file/2402e4a3dd551cc0bca33.png"
36 | }
37 | },
38 | "required": [],
39 | "title": "Body"
40 | }
41 | }
42 | }
43 | },
44 | "responses": {
45 | "200": {
46 | "description": "Successful Response",
47 | "content": {
48 | "application/json": {
49 | "schema": {}
50 | }
51 | }
52 | },
53 | "400": {
54 | "content": {
55 | "application/json": {
56 | "schema": {
57 | "properties": {
58 | "message": {
59 | "type": "string",
60 | "title": "Message"
61 | }
62 | },
63 | "type": "object",
64 | "required": [
65 | "message"
66 | ],
67 | "title": "ValueError"
68 | }
69 | }
70 | },
71 | "description": "Bad Request"
72 | },
73 | "422": {
74 | "content": {
75 | "application/json": {
76 | "schema": {
77 | "properties": {
78 | "message": {
79 | "type": "string",
80 | "title": "Message",
81 | "default": "Invalid request data"
82 | }
83 | },
84 | "type": "object",
85 | "title": "ValidationError"
86 | }
87 | }
88 | },
89 | "description": "Unprocessable Entity"
90 | },
91 | "500": {
92 | "content": {
93 | "application/json": {
94 | "schema": {
95 | "properties": {
96 | "message": {
97 | "type": "string",
98 | "title": "Message",
99 | "default": "Internal Server Error"
100 | }
101 | },
102 | "type": "object",
103 | "title": "ServerError"
104 | }
105 | }
106 | },
107 | "description": "Internal Server Error"
108 | }
109 | }
110 | },
111 | "parameters": [
112 | {
113 | "description": "API.market API Key",
114 | "in": "header",
115 | "name": "x-magicapi-key",
116 | "value": "clp7flnx6000j3pifm3pinw92",
117 | "required": true,
118 | "schema": {
119 | "type": "string"
120 | }
121 | }
122 | ]
123 | }
124 | },
125 | "components": {
126 | "schemas": {
127 | "Body_Inpainting": {
128 | "properties": {
129 | "image_url": {
130 | "type": "string",
131 | "title": "Image Url",
132 | "default": "https://telegra.ph/file/1dbd57f8abf95e6ae2911.png"
133 | },
134 | "mask_url": {
135 | "type": "string",
136 | "title": "Mask Url",
137 | "default": "https://telegra.ph/file/2402e4a3dd551cc0bca33.png"
138 | }
139 | },
140 | "type": "object",
141 | "title": "Body_Inpainting"
142 | },
143 | "Body_RemoveBg": {
144 | "properties": {
145 | "image_url": {
146 | "type": "string",
147 | "title": "Image Url",
148 | "default": "https://telegra.ph/file/46a973ad6ff03f32b40a0.png"
149 | }
150 | },
151 | "type": "object",
152 | "title": "Body_RemoveBg"
153 | },
154 | "ServerError": {
155 | "properties": {
156 | "message": {
157 | "type": "string",
158 | "title": "Message",
159 | "default": "Internal Server Error"
160 | }
161 | },
162 | "type": "object",
163 | "title": "ServerError"
164 | },
165 | "ValidationError": {
166 | "properties": {
167 | "message": {
168 | "type": "string",
169 | "title": "Message",
170 | "default": "Invalid request data"
171 | }
172 | },
173 | "type": "object",
174 | "title": "ValidationError"
175 | },
176 | "ValueError": {
177 | "properties": {
178 | "message": {
179 | "type": "string",
180 | "title": "Message"
181 | }
182 | },
183 | "type": "object",
184 | "required": [
185 | "message"
186 | ],
187 | "title": "ValueError"
188 | }
189 | }
190 | },
191 | "security": {},
192 | "tags": []
193 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-hair.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.1.3",
6 | "description": "API for simulating different hair styles using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/hair"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/hair/predictions/{request_id}": {
15 | "get": {
16 | "summary": "Get hairstyled image URL",
17 | "description": "This endpoint retrieves the URL of the simulated hairstyle image for a given request ID.\n",
18 | "parameters": [
19 | {
20 | "name": "request_id",
21 | "in": "path",
22 | "required": true,
23 | "description": "Unique identifier for the request.",
24 | "schema": {
25 | "type": "string"
26 | }
27 | }
28 | ],
29 | "responses": {
30 | "200": {
31 | "description": "Successful response",
32 | "content": {
33 | "application/json": {
34 | "schema": {
35 | "type": "object",
36 | "properties": {
37 | "status": {
38 | "type": "string",
39 | "description": "Status of the prediction (e.g., \"succeeded\")."
40 | },
41 | "image_url": {
42 | "type": "string",
43 | "format": "uri",
44 | "description": "URL of the hairstyled image."
45 | }
46 | }
47 | }
48 | }
49 | }
50 | },
51 | "400": {
52 | "description": "Bad Request",
53 | "content": {
54 | "application/json": {
55 | "schema": {
56 | "type": "object",
57 | "properties": {
58 | "error": {
59 | "type": "string",
60 | "description": "Description of the error."
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | },
68 | "security": [
69 | {
70 | "apiKey": []
71 | }
72 | ]
73 | },
74 | "parameters": [
75 | {
76 | "description": "API.market API Key",
77 | "in": "header",
78 | "name": "x-magicapi-key",
79 | "value": "clp7flnx6000j3pifm3pinw92",
80 | "required": true,
81 | "schema": {
82 | "type": "string"
83 | }
84 | }
85 | ]
86 | },
87 | "magicapi/hair/hair": {
88 | "post": {
89 | "summary": "Hair style simulator",
90 | "description": "API for simulating different hair styles using AI models. Make sure to call get hairstyled image after with the request id received from this API.",
91 | "requestBody": {
92 | "required": true,
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "image": {
99 | "type": "string",
100 | "default": "https://replicate.delivery/mgxm/b8be17a7-abcb-4421-80f2-e6a1e3fe38c7/MarkZuckerberg.jpg"
101 | },
102 | "editing_type": {
103 | "type": "string",
104 | "default": "both"
105 | },
106 | "color_description": {
107 | "type": "string",
108 | "default": "blond"
109 | },
110 | "hairstyle_description": {
111 | "type": "string",
112 | "default": "hi-top fade hairstyle"
113 | }
114 | },
115 | "required": [
116 | "image",
117 | "editing_type",
118 | "color_description",
119 | "hairstyle_description"
120 | ]
121 | }
122 | }
123 | }
124 | },
125 | "responses": {
126 | "200": {
127 | "description": "Successful response",
128 | "content": {
129 | "application/json": {
130 | "schema": {
131 | "type": "object",
132 | "properties": {
133 | "request_id": {
134 | "type": "string",
135 | "description": "Unique identifier for the request."
136 | }
137 | }
138 | }
139 | }
140 | }
141 | },
142 | "400": {
143 | "description": "Bad Request",
144 | "content": {
145 | "application/json": {
146 | "schema": {
147 | "type": "object",
148 | "properties": {
149 | "error": {
150 | "type": "string",
151 | "description": "Description of the error."
152 | }
153 | }
154 | }
155 | }
156 | }
157 | }
158 | },
159 | "security": [
160 | {
161 | "apiKey": []
162 | }
163 | ]
164 | },
165 | "parameters": [
166 | {
167 | "description": "API.market API Key",
168 | "in": "header",
169 | "name": "x-magicapi-key",
170 | "value": "clp7flnx6000j3pifm3pinw92",
171 | "required": true,
172 | "schema": {
173 | "type": "string"
174 | }
175 | }
176 | ]
177 | }
178 | },
179 | "security": {},
180 | "tags": []
181 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_pipfeed-parse.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Pipfeed Parsing API",
5 | "description": "The Pipfeed Parsing API allows you to extract structured data from online news articles. With advanced AI technology, this API retrieves clean, structured data including content, images, authors, summary, category, keywords, topics, and more from articles, blogs, and discussions.\n\nKey Features:\n- Extracts metadata such as title, author, site name, publication date, and article length.\n- Retrieves full HTML content of the article.\n- Identifies the main image associated with the article.\n- Provides keywords, topics, and a summary generated by AI/ML algorithms.\n- Offers sentiment analysis including score, comparative value, and breakdown of positive and negative sentiment.\n\nThis API eliminates the need for manual rules or site-specific training, providing an efficient solution for extracting valuable information from online articles.",
6 | "termsOfService": "https://pipfeed.com",
7 | "contact": {
8 | "email": "[email protected]"
9 | },
10 | "version": "1.0.3"
11 | },
12 | "externalDocs": {
13 | "description": "Pipfeed Parsing API Documentation",
14 | "url": "https://pipfeed.com/docs"
15 | },
16 | "servers": [
17 | {
18 | "url": "http://api.magicapi.dev/api/v1/pipfeed/parse"
19 | }
20 | ],
21 | "paths": {
22 | "pipfeed/parse/extract": {
23 | "post": {
24 | "summary": "Extract information from a URL",
25 | "requestBody": {
26 | "content": {
27 | "application/json": {
28 | "schema": {
29 | "type": "object",
30 | "properties": {
31 | "url": {
32 | "type": "string",
33 | "example": "https://techcrunch.com/2022/04/18/web-scraping-legal-court/"
34 | }
35 | },
36 | "required": [
37 | "url"
38 | ]
39 | }
40 | }
41 | }
42 | },
43 | "responses": {
44 | "200": {
45 | "description": "Successful response",
46 | "content": {
47 | "application/json": {
48 | "schema": {
49 | "type": "object",
50 | "properties": {
51 | "url": {
52 | "type": "string"
53 | },
54 | "title": {
55 | "type": "string"
56 | },
57 | "author": {
58 | "type": "string"
59 | },
60 | "html": {
61 | "type": "string"
62 | },
63 | "length": {
64 | "type": "integer"
65 | },
66 | "description": {
67 | "type": "string"
68 | },
69 | "siteName": {
70 | "type": "string"
71 | },
72 | "topImage": {
73 | "type": "string"
74 | },
75 | "date": {
76 | "type": "string",
77 | "format": "date-time"
78 | },
79 | "keywords": {
80 | "type": "string"
81 | },
82 | "summary": {
83 | "type": "array",
84 | "items": {
85 | "type": "string"
86 | }
87 | },
88 | "sentiment": {
89 | "type": "object",
90 | "properties": {
91 | "score": {
92 | "type": "integer"
93 | },
94 | "comparative": {
95 | "type": "number"
96 | },
97 | "calculation": {
98 | "type": "array",
99 | "items": {
100 | "type": "object",
101 | "properties": {
102 | "expand": {
103 | "type": "integer"
104 | },
105 | "failure": {
106 | "type": "integer"
107 | },
108 | "wrong": {
109 | "type": "integer"
110 | }
111 | }
112 | }
113 | },
114 | "positive": {
115 | "type": "array",
116 | "items": {
117 | "type": "string"
118 | }
119 | },
120 | "negative": {
121 | "type": "array",
122 | "items": {
123 | "type": "string"
124 | }
125 | }
126 | }
127 | }
128 | }
129 | }
130 | }
131 | }
132 | }
133 | }
134 | },
135 | "parameters": [
136 | {
137 | "description": "API.market API Key",
138 | "in": "header",
139 | "name": "x-magicapi-key",
140 | "value": "clp7flnx6000j3pifm3pinw92",
141 | "required": true,
142 | "schema": {
143 | "type": "string"
144 | }
145 | }
146 | ]
147 | }
148 | },
149 | "security": {},
150 | "tags": []
151 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-coder.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.1.3",
6 | "description": "API for code generation using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/coder"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/coder/predictions/{request_id}": {
15 | "get": {
16 | "summary": "Get coder output URL",
17 | "description": "This endpoint retrieves the URL of the coding assistant's response for a given request ID.\n",
18 | "parameters": [
19 | {
20 | "name": "request_id",
21 | "in": "path",
22 | "required": true,
23 | "description": "Unique identifier for the request.",
24 | "schema": {
25 | "type": "string"
26 | }
27 | }
28 | ],
29 | "responses": {
30 | "200": {
31 | "description": "Successful response",
32 | "content": {
33 | "application/json": {
34 | "schema": {
35 | "type": "object",
36 | "properties": {
37 | "status": {
38 | "type": "string",
39 | "description": "Status of the prediction (e.g., \"succeeded\")."
40 | },
41 | "response_url": {
42 | "type": "string",
43 | "format": "uri",
44 | "description": "URL of the response."
45 | }
46 | }
47 | }
48 | }
49 | }
50 | },
51 | "400": {
52 | "description": "Bad Request",
53 | "content": {
54 | "application/json": {
55 | "schema": {
56 | "type": "object",
57 | "properties": {
58 | "error": {
59 | "type": "string",
60 | "description": "Description of the error."
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | },
68 | "security": [
69 | {
70 | "apiKey": []
71 | }
72 | ]
73 | },
74 | "parameters": [
75 | {
76 | "description": "API.market API Key",
77 | "in": "header",
78 | "name": "x-magicapi-key",
79 | "value": "clp7flnx6000j3pifm3pinw92",
80 | "required": true,
81 | "schema": {
82 | "type": "string"
83 | }
84 | }
85 | ]
86 | },
87 | "magicapi/coder/coder": {
88 | "post": {
89 | "summary": "Coding Assistant",
90 | "description": "Coding Assistant. \n Make sure you call get coder output URL MCP tool to get the URL for the request id received from this API ",
91 | "requestBody": {
92 | "required": true,
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "top_k": {
99 | "type": "integer",
100 | "default": 250
101 | },
102 | "top_p": {
103 | "type": "integer",
104 | "default": 0.95
105 | },
106 | "prompt": {
107 | "type": "string",
108 | "default": "Write a javascript function that calculates euclidean distance between two coordinates of any dimension"
109 | },
110 | "max_tokens": {
111 | "type": "integer",
112 | "default": 500
113 | },
114 | "temperature": {
115 | "type": "integer",
116 | "default": 0.95
117 | },
118 | "system_prompt": {
119 | "type": "string"
120 | },
121 | "repeat_penalty": {
122 | "type": "integer",
123 | "default": 1.1
124 | },
125 | "presence_penalty": {
126 | "type": "integer",
127 | "default": 0
128 | },
129 | "frequency_penalty": {
130 | "type": "integer",
131 | "default": 0
132 | }
133 | },
134 | "required": [
135 | "top_k",
136 | "top_p",
137 | "prompt",
138 | "max_tokens",
139 | "temperature",
140 | "system_prompt",
141 | "repeat_penalty",
142 | "presence_penalty",
143 | "frequency_penalty"
144 | ]
145 | }
146 | }
147 | }
148 | },
149 | "responses": {
150 | "200": {
151 | "description": "Successful response",
152 | "content": {
153 | "application/json": {
154 | "schema": {
155 | "type": "object",
156 | "properties": {
157 | "request_id": {
158 | "type": "string",
159 | "description": "Unique identifier for the request."
160 | }
161 | }
162 | }
163 | }
164 | }
165 | },
166 | "400": {
167 | "description": "Bad Request",
168 | "content": {
169 | "application/json": {
170 | "schema": {
171 | "type": "object",
172 | "properties": {
173 | "error": {
174 | "type": "string",
175 | "description": "Description of the error."
176 | }
177 | }
178 | }
179 | }
180 | }
181 | }
182 | },
183 | "security": [
184 | {
185 | "apiKey": []
186 | }
187 | ]
188 | },
189 | "parameters": [
190 | {
191 | "description": "API.market API Key",
192 | "in": "header",
193 | "name": "x-magicapi-key",
194 | "value": "clp7flnx6000j3pifm3pinw92",
195 | "required": true,
196 | "schema": {
197 | "type": "string"
198 | }
199 | }
200 | ]
201 | }
202 | },
203 | "security": {},
204 | "tags": []
205 | }
```
--------------------------------------------------------------------------------
/utils/LLM_summary_shortener.py:
--------------------------------------------------------------------------------
```python
1 | import os
2 | import glob
3 | import yaml
4 | import json
5 | import logging
6 | import requests
7 | import re
8 | import sys
9 | # Set up logging with time, level, and message
10 | logging.basicConfig(level=logging.INFO,
11 | format='%(levelname)s - %(message)s')
12 |
13 | def is_valid_string(s):
14 | pattern = r'^[a-zA-Z0-9 _-]+$'
15 | return bool(re.match(pattern, s))
16 |
17 |
18 | def update_summary(current_summary: str, depth: int = 0) -> str:
19 | """
20 | Sends a request to the Magic API using the current_summary and returns the new_summary from the response.
21 |
22 | Parameters:
23 | current_summary (str): The summary text to be sent as the user input.
24 |
25 | Returns:
26 | new_summary (str): The new summary generated by the API.
27 |
28 | Raises:
29 | ValueError: If the API key is not found in the environment.
30 | requests.HTTPError: For any HTTP errors that occur during the API call.
31 | """
32 |
33 |
34 | # Retrieve API key from environment variable
35 | logging.info(
36 | f"Initiating API call with the provided input: {current_summary}")
37 | api_key = os.environ.get("x_magicapi_key")
38 | if not api_key:
39 | raise ValueError(
40 | "API key not found. Please set the 'x_magicapi_key' environment variable.")
41 |
42 | # API endpoint and headers
43 | url = "https://api.magicapi.dev/api/v2/bridgeml/llm/llm/chat/completions"
44 | headers = {
45 | "accept": "application/json",
46 | "x-magicapi-key": api_key,
47 | "Content-Type": "application/json"
48 | }
49 | system_prompt = """
50 | You are a technical API documentation summarizer.
51 | Given an API endpoint summary, create a shorter version that:
52 | 1. Maintains the core functionality description
53 | 2. Is under 54 characters (including spaces)
54 | 3. Uses only alphanumeric characters, hyphens and underscores
55 | 4. Preserves technical meaning and clarity
56 |
57 | Bad example: 'iCanSee' for 'A fast text-to-image model that makes high-quality images in 4 steps'
58 | Good example: 'Create high-quality images from text in 4 steps'
59 | """
60 | # Prepare payload with current_summary as the user message
61 | payload = {
62 | "messages": [
63 | {
64 | "role": "system",
65 | "content": system_prompt
66 | },
67 | {
68 | "role": "user",
69 | "content": current_summary
70 | }
71 | ],
72 | "model": "llama-3.2-1b-preview",
73 | "temperature": 1,
74 | "max_tokens": 1024,
75 | "top_p": 1,
76 | "stream": False,
77 | "stop": "</Output>"
78 | }
79 |
80 | # Make the POST request and wait for the API response
81 | response = requests.post(url, headers=headers, json=payload)
82 | response.raise_for_status() # Raises an exception for HTTP error codes
83 |
84 | # Parse the API response and extract the new summary
85 | data = response.json()
86 | new_summary = data["choices"][0]["message"]["content"]
87 | if (len(new_summary) >= 55 or (not is_valid_string(new_summary))) :
88 | logging.info(f'New summary is {new_summary}')
89 | if(depth ==10):
90 | logging.error('Please use manual summary shortener, the llm is unable to provide an appropriate summary, even after 10 retries')
91 | sys.exit()
92 | return update_summary(new_summary, depth+1)
93 |
94 | return new_summary
95 |
96 |
97 | # Define the HTTP methods we are interested in.
98 | HTTP_METHODS = {"get", "post", "put", "delete",
99 | "patch", "head", "options", "trace"}
100 |
101 |
102 | def update_method_summaries(paths_dict, file_name):
103 | """
104 | Iterate over all path entries and update the summary field in method definitions.
105 | Logs the original summary and the updated summary.
106 | """
107 | for path, methods in paths_dict.items():
108 | if isinstance(methods, dict):
109 | for method, operation in methods.items():
110 | # Only target keys that represent HTTP methods (case-insensitive)
111 | if (method.lower() in HTTP_METHODS and
112 | isinstance(operation, dict) and
113 | "summary" in operation and
114 | isinstance(operation["summary"], str) and
115 | len(operation["summary"]) >= 55):
116 | original_summary = operation["summary"]
117 | logging.info(
118 | f"path '{path}', method '{method}': updating summary from '{original_summary}'")
119 |
120 | try:
121 | new_summary = update_summary(
122 | current_summary=original_summary)
123 | except Exception as e:
124 | logging.error(f"Error updating summary for '{path}', method '{method}': {e}")
125 | continue
126 |
127 | logging.info(
128 | f"path '{path}', method '{method}': updating summary to '{new_summary}'")
129 |
130 | operation["summary"] = new_summary
131 |
132 |
133 | # Gather all OpenAPI spec files with .yaml, .yml, or .json extensions from the current directory.
134 |
135 | file_patterns = ["*.yaml", "*.yml", "*.json"]
136 | files = []
137 | script_dir = os.path.dirname(os.path.abspath(__file__))
138 | directory = os.path.join(script_dir, "../src/lib")
139 | for pattern in file_patterns:
140 | search_pattern = os.path.join(directory, pattern)
141 | files.extend(glob.glob(search_pattern))
142 |
143 |
144 | for file in files:
145 | logging.info(f"Opening file: {file}")
146 | try:
147 | with open(file, 'r') as f:
148 | data = json.load(f) if file.endswith(".json") else yaml.safe_load(f)
149 | logging.info(f"Finished reading file: {file}")
150 | except Exception as e:
151 | logging.error(f"Error reading {file}: {e}")
152 | continue
153 |
154 | # Only process files that have a 'paths' section.
155 | if "paths" in data and isinstance(data["paths"], dict):
156 | update_method_summaries(data["paths"], file)
157 |
158 | try:
159 | with open(file, 'w') as f:
160 | if file.endswith(".json"):
161 | json.dump(data, f, indent=2)
162 | else:
163 | yaml.dump(data, f, sort_keys=False)
164 | logging.info(f"Finished writing (closed) file: {file}")
165 | except Exception as e:
166 | logging.error(f"Error writing {file}: {e}")
167 |
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-whisper.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "Image Processing API",
5 | "version": "1.1.3",
6 | "description": "API for sentece wise transcription and analysis of audio, using AI models."
7 | },
8 | "servers": [
9 | {
10 | "url": "http://api.magicapi.dev/api/v1/magicapi/whisper"
11 | }
12 | ],
13 | "paths": {
14 | "magicapi/whisper/predictions/{request_id}": {
15 | "get": {
16 | "summary": "Get audio analysis URL",
17 | "description": "This endpoint retrieves the URL of the transcription and analysis of the audio for the given request ID.\n",
18 | "parameters": [
19 | {
20 | "name": "request_id",
21 | "in": "path",
22 | "required": true,
23 | "description": "Unique identifier for the request.",
24 | "schema": {
25 | "type": "string"
26 | }
27 | }
28 | ],
29 | "responses": {
30 | "200": {
31 | "description": "Successful response",
32 | "content": {
33 | "application/json": {
34 | "schema": {
35 | "type": "object",
36 | "properties": {
37 | "status": {
38 | "type": "string",
39 | "description": "Status of the prediction (e.g., \"succeeded\")."
40 | },
41 | "response_url": {
42 | "type": "string",
43 | "format": "uri",
44 | "description": "URL of the audio's transcription and analysis."
45 | }
46 | }
47 | }
48 | }
49 | }
50 | },
51 | "400": {
52 | "description": "Bad Request",
53 | "content": {
54 | "application/json": {
55 | "schema": {
56 | "type": "object",
57 | "properties": {
58 | "error": {
59 | "type": "string",
60 | "description": "Description of the error."
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | },
68 | "security": [
69 | {
70 | "apiKey": []
71 | }
72 | ]
73 | },
74 | "parameters": [
75 | {
76 | "description": "API.market API Key",
77 | "in": "header",
78 | "name": "x-magicapi-key",
79 | "value": "clp7flnx6000j3pifm3pinw92",
80 | "required": true,
81 | "schema": {
82 | "type": "string"
83 | }
84 | }
85 | ]
86 | },
87 | "magicapi/whisper/whisper": {
88 | "post": {
89 | "summary": "Whisper Audio Processing",
90 | "description": "API for sentece wise transcription and analysis of audio, using AI models. Make sure to call get audio analysis URL with the request ID received from this API.",
91 | "requestBody": {
92 | "required": true,
93 | "content": {
94 | "application/json": {
95 | "schema": {
96 | "type": "object",
97 | "properties": {
98 | "audio": {
99 | "type": "string",
100 | "default": "https://replicate.delivery/mgxm/e5159b1b-508a-4be4-b892-e1eb47850bdc/OSR_uk_000_0050_8k.wav"
101 | },
102 | "model": {
103 | "type": "string",
104 | "default": "large-v3"
105 | },
106 | "translate": {
107 | "type": "boolean",
108 | "default": false
109 | },
110 | "temperature": {
111 | "type": "integer",
112 | "default": 0
113 | },
114 | "transcription": {
115 | "type": "string",
116 | "default": "plain text"
117 | },
118 | "suppress_tokens": {
119 | "type": "string",
120 | "default": -1
121 | },
122 | "logprob_threshold": {
123 | "type": "integer",
124 | "default": -1
125 | },
126 | "no_speech_threshold": {
127 | "type": "integer",
128 | "default": 0.6
129 | },
130 | "condition_on_previous_text": {
131 | "type": "boolean",
132 | "default": true
133 | },
134 | "compression_ratio_threshold": {
135 | "type": "integer",
136 | "default": 2.4
137 | },
138 | "temperature_increment_on_fallback": {
139 | "type": "integer",
140 | "default": 0.2
141 | }
142 | },
143 | "required": [
144 | "audio",
145 | "model",
146 | "translate",
147 | "temperature",
148 | "transcription",
149 | "suppress_tokens",
150 | "logprob_threshold",
151 | "no_speech_threshold",
152 | "condition_on_previous_text",
153 | "compression_ratio_threshold",
154 | "temperature_increment_on_fallback"
155 | ]
156 | }
157 | }
158 | }
159 | },
160 | "responses": {
161 | "200": {
162 | "description": "Successful response",
163 | "content": {
164 | "application/json": {
165 | "schema": {
166 | "type": "object",
167 | "properties": {
168 | "request_id": {
169 | "type": "string",
170 | "description": "Unique identifier for the request."
171 | }
172 | }
173 | }
174 | }
175 | }
176 | },
177 | "400": {
178 | "description": "Bad Request",
179 | "content": {
180 | "application/json": {
181 | "schema": {
182 | "type": "object",
183 | "properties": {
184 | "error": {
185 | "type": "string",
186 | "description": "Description of the error."
187 | }
188 | }
189 | }
190 | }
191 | }
192 | }
193 | },
194 | "security": [
195 | {
196 | "apiKey": []
197 | }
198 | ]
199 | },
200 | "parameters": [
201 | {
202 | "description": "API.market API Key",
203 | "in": "header",
204 | "name": "x-magicapi-key",
205 | "value": "clp7flnx6000j3pifm3pinw92",
206 | "required": true,
207 | "schema": {
208 | "type": "string"
209 | }
210 | }
211 | ]
212 | }
213 | },
214 | "security": {},
215 | "tags": []
216 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_trueway-matrix.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.1",
3 | "info": {
4 | "title": "TrueWay Matrix API V1",
5 | "description": "Calculate distances and driving durations between a set of origins and destinations on the real road network",
6 | "contact": {
7 | "name": "TrueWay Team",
8 | "url": "https://truewayapi.com/",
9 | "email": "[email protected]"
10 | },
11 | "version": "v1"
12 | },
13 | "servers": [
14 | {
15 | "url": "http://api.magicapi.dev/api/v1/trueway/matrix"
16 | }
17 | ],
18 | "paths": {
19 | "trueway/matrix/MatrixService/CalculateDrivingMatrix": {
20 | "get": {
21 | "tags": [
22 | "MatrixService"
23 | ],
24 | "summary": "distance and duration bw starts and stops",
25 | "description": "Calculate length and driving time of the optimal routes between origin and destination points on the real road network.",
26 | "parameters": [
27 | {
28 | "name": "origins",
29 | "in": "query",
30 | "description": "List of origins described as semicolon-delimited coordinate pairs with latitudes and longitudes. Maximum 25 pairs per request.",
31 | "required": true,
32 | "schema": {
33 | "type": "string"
34 | },
35 | "example": "40.629041,-74.025606;40.630099,-73.993521;40.644895,-74.013818;40.627177,-73.980853"
36 | },
37 | {
38 | "name": "destinations",
39 | "in": "query",
40 | "description": "List of destinations described as semicolon-delimited coordinate pairs with latitudes and longitudes. If not specified, an n x n matrix will be generated using the origins. Maximum 25 pairs per request.",
41 | "schema": {
42 | "type": "string"
43 | },
44 | "example": "40.629041,-74.025606;40.630099,-73.993521;40.644895,-74.013818;40.627177,-73.980853"
45 | },
46 | {
47 | "name": "avoid_tolls",
48 | "in": "query",
49 | "description": "Avoid tolls",
50 | "schema": {
51 | "type": "boolean",
52 | "default": false
53 | }
54 | },
55 | {
56 | "name": "avoid_highways",
57 | "in": "query",
58 | "description": "Avoid highways",
59 | "schema": {
60 | "type": "boolean",
61 | "default": false
62 | }
63 | },
64 | {
65 | "name": "avoid_ferries",
66 | "in": "query",
67 | "description": "Avoid ferries",
68 | "schema": {
69 | "type": "boolean",
70 | "default": false
71 | }
72 | },
73 | {
74 | "name": "start_time",
75 | "in": "query",
76 | "description": "Time when travel is expected to start. You can specify the time as an integer in seconds since midnight, January 1, 1970 UTC or you can use 'now' to specify the current time.",
77 | "schema": {
78 | "type": "string"
79 | }
80 | }
81 | ],
82 | "responses": {
83 | "200": {
84 | "description": "Success",
85 | "content": {
86 | "application/json": {
87 | "schema": {
88 | "required": [
89 | "distances",
90 | "durations"
91 | ],
92 | "type": "object",
93 | "properties": {
94 | "distances": {
95 | "type": "array",
96 | "items": {
97 | "type": "array",
98 | "items": {
99 | "type": "integer",
100 | "format": "int32"
101 | }
102 | },
103 | "description": "An array of distances(in meters) between origins and destinations locations"
104 | },
105 | "durations": {
106 | "type": "array",
107 | "items": {
108 | "type": "array",
109 | "items": {
110 | "type": "integer",
111 | "format": "int32"
112 | }
113 | },
114 | "description": "An array of durations(in seconds) between origins and destinations locations"
115 | }
116 | },
117 | "additionalProperties": false
118 | }
119 | }
120 | }
121 | },
122 | "400": {
123 | "description": "Bad Request",
124 | "content": {
125 | "application/json": {
126 | "schema": {
127 | "required": [
128 | "error"
129 | ],
130 | "type": "object",
131 | "properties": {
132 | "error": {
133 | "type": "string"
134 | },
135 | "message": {
136 | "type": "string",
137 | "nullable": true
138 | }
139 | },
140 | "additionalProperties": false
141 | }
142 | }
143 | }
144 | },
145 | "500": {
146 | "description": "Server Error",
147 | "content": {
148 | "application/json": {
149 | "schema": {
150 | "required": [
151 | "error"
152 | ],
153 | "type": "object",
154 | "properties": {
155 | "error": {
156 | "type": "string"
157 | },
158 | "message": {
159 | "type": "string",
160 | "nullable": true
161 | }
162 | },
163 | "additionalProperties": false
164 | }
165 | }
166 | }
167 | }
168 | }
169 | },
170 | "parameters": [
171 | {
172 | "description": "API.market API Key",
173 | "in": "header",
174 | "name": "x-magicapi-key",
175 | "value": "clp7flnx6000j3pifm3pinw92",
176 | "required": true,
177 | "schema": {
178 | "type": "string"
179 | }
180 | }
181 | ]
182 | }
183 | },
184 | "components": {
185 | "schemas": {
186 | "DistanceMatrixResponse": {
187 | "required": [
188 | "distances",
189 | "durations"
190 | ],
191 | "type": "object",
192 | "properties": {
193 | "distances": {
194 | "type": "array",
195 | "items": {
196 | "type": "array",
197 | "items": {
198 | "type": "integer",
199 | "format": "int32"
200 | }
201 | },
202 | "description": "An array of distances(in meters) between origins and destinations locations"
203 | },
204 | "durations": {
205 | "type": "array",
206 | "items": {
207 | "type": "array",
208 | "items": {
209 | "type": "integer",
210 | "format": "int32"
211 | }
212 | },
213 | "description": "An array of durations(in seconds) between origins and destinations locations"
214 | }
215 | },
216 | "additionalProperties": false
217 | },
218 | "FaultResponse": {
219 | "required": [
220 | "error"
221 | ],
222 | "type": "object",
223 | "properties": {
224 | "error": {
225 | "type": "string"
226 | },
227 | "message": {
228 | "type": "string",
229 | "nullable": true
230 | }
231 | },
232 | "additionalProperties": false
233 | }
234 | }
235 | },
236 | "security": {},
237 | "tags": []
238 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_magicapi-pdf-extract.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.0.0",
3 | "info": {
4 | "title": "PDF to Text/HTML API",
5 | "description": "Convert PDF to Text/HTML API",
6 | "version": "1.0.2"
7 | },
8 | "paths": {
9 | "magicapi/pdf!extract/pdf_to_html_url/": {
10 | "post": {
11 | "summary": "Convert PDF to HTML from URL",
12 | "requestBody": {
13 | "required": true,
14 | "content": {
15 | "application/json": {
16 | "schema": {
17 | "type": "object",
18 | "properties": {
19 | "pdf_url": {
20 | "type": "string",
21 | "format": "uri",
22 | "description": "URL of the PDF file to convert",
23 | "example": "https://www.sbs.ox.ac.uk/sites/default/files/2019-01/cv-template.pdf"
24 | }
25 | }
26 | }
27 | }
28 | }
29 | },
30 | "responses": {
31 | "200": {
32 | "description": "HTML content generated from the PDF",
33 | "content": {
34 | "text/html": {
35 | "schema": {
36 | "type": "string",
37 | "description": "HTML content generated from the PDF"
38 | }
39 | }
40 | }
41 | },
42 | "400": {
43 | "description": "Bad request"
44 | },
45 | "500": {
46 | "description": "Internal server error"
47 | }
48 | }
49 | },
50 | "parameters": [
51 | {
52 | "description": "API.market API Key",
53 | "in": "header",
54 | "name": "x-magicapi-key",
55 | "value": "clp7flnx6000j3pifm3pinw92",
56 | "required": true,
57 | "schema": {
58 | "type": "string"
59 | }
60 | }
61 | ]
62 | },
63 | "magicapi/pdf!extract/pdf_to_text_url/": {
64 | "post": {
65 | "summary": "Convert PDF to Text from URL",
66 | "description": "Converts a PDF file located at the provided URL to plain text.",
67 | "requestBody": {
68 | "required": true,
69 | "content": {
70 | "application/json": {
71 | "schema": {
72 | "type": "object",
73 | "properties": {
74 | "pdf_url": {
75 | "type": "string",
76 | "description": "URL of the PDF file to convert",
77 | "example": "https://www.sbs.ox.ac.uk/sites/default/files/2019-01/cv-template.pdf"
78 | }
79 | }
80 | }
81 | }
82 | }
83 | },
84 | "responses": {
85 | "200": {
86 | "description": "Successful response",
87 | "content": {
88 | "application/json": {
89 | "schema": {
90 | "type": "object",
91 | "properties": {
92 | "text": {
93 | "type": "string",
94 | "description": "Plain text extracted from the PDF file from given URL"
95 | }
96 | }
97 | }
98 | }
99 | }
100 | },
101 | "400": {
102 | "description": "Bad request",
103 | "content": {
104 | "application/json": {
105 | "schema": {
106 | "type": "object",
107 | "properties": {
108 | "error": {
109 | "type": "string",
110 | "description": "Description of the error"
111 | }
112 | }
113 | }
114 | }
115 | }
116 | },
117 | "500": {
118 | "description": "Internal server error",
119 | "content": {
120 | "application/json": {
121 | "schema": {
122 | "type": "object",
123 | "properties": {
124 | "error": {
125 | "type": "string",
126 | "description": "Description of the error"
127 | }
128 | }
129 | }
130 | }
131 | }
132 | }
133 | }
134 | },
135 | "parameters": [
136 | {
137 | "description": "API.market API Key",
138 | "in": "header",
139 | "name": "x-magicapi-key",
140 | "value": "clp7flnx6000j3pifm3pinw92",
141 | "required": true,
142 | "schema": {
143 | "type": "string"
144 | }
145 | }
146 | ]
147 | },
148 | "magicapi/pdf!extract/pdf_to_text_file/": {
149 | "post": {
150 | "summary": "Convert PDF to Text from File",
151 | "description": "Converts a PDF file uploaded as form data to plain text.",
152 | "requestBody": {
153 | "required": true,
154 | "content": {
155 | "multipart/form-data": {
156 | "schema": {
157 | "type": "object",
158 | "properties": {
159 | "pdf_file": {
160 | "type": "string",
161 | "format": "binary",
162 | "description": "PDF file to convert"
163 | }
164 | }
165 | }
166 | }
167 | }
168 | },
169 | "responses": {
170 | "200": {
171 | "description": "Successful response",
172 | "content": {
173 | "application/json": {
174 | "schema": {
175 | "type": "object",
176 | "properties": {
177 | "text": {
178 | "type": "string",
179 | "description": "Plain text extracted from the PDF file"
180 | }
181 | }
182 | }
183 | }
184 | }
185 | },
186 | "400": {
187 | "description": "Bad request",
188 | "content": {
189 | "application/json": {
190 | "schema": {
191 | "type": "object",
192 | "properties": {
193 | "error": {
194 | "type": "string",
195 | "description": "Description of the error"
196 | }
197 | }
198 | }
199 | }
200 | }
201 | },
202 | "500": {
203 | "description": "Internal server error",
204 | "content": {
205 | "application/json": {
206 | "schema": {
207 | "type": "object",
208 | "properties": {
209 | "error": {
210 | "type": "string",
211 | "description": "Description of the error"
212 | }
213 | }
214 | }
215 | }
216 | }
217 | }
218 | }
219 | },
220 | "parameters": [
221 | {
222 | "description": "API.market API Key",
223 | "in": "header",
224 | "name": "x-magicapi-key",
225 | "value": "clp7flnx6000j3pifm3pinw92",
226 | "required": true,
227 | "schema": {
228 | "type": "string"
229 | }
230 | }
231 | ]
232 | },
233 | "magicapi/pdf!extract/pdf_to_html_file/": {
234 | "post": {
235 | "summary": "Convert PDF to HTML from File",
236 | "description": "Converts a PDF file uploaded as form data to HTML.",
237 | "requestBody": {
238 | "required": true,
239 | "content": {
240 | "multipart/form-data": {
241 | "schema": {
242 | "type": "object",
243 | "properties": {
244 | "pdf_file": {
245 | "type": "string",
246 | "format": "binary",
247 | "description": "PDF file to convert"
248 | }
249 | }
250 | }
251 | }
252 | }
253 | },
254 | "responses": {
255 | "200": {
256 | "description": "Successful response",
257 | "content": {
258 | "application/json": {
259 | "schema": {
260 | "type": "object",
261 | "properties": {
262 | "html": {
263 | "type": "string",
264 | "description": "HTML content generated from the PDF file"
265 | }
266 | }
267 | }
268 | }
269 | }
270 | },
271 | "400": {
272 | "description": "Bad request",
273 | "content": {
274 | "application/json": {
275 | "schema": {
276 | "type": "object",
277 | "properties": {
278 | "error": {
279 | "type": "string",
280 | "description": "Description of the error"
281 | }
282 | }
283 | }
284 | }
285 | }
286 | },
287 | "500": {
288 | "description": "Internal server error",
289 | "content": {
290 | "application/json": {
291 | "schema": {
292 | "type": "object",
293 | "properties": {
294 | "error": {
295 | "type": "string",
296 | "description": "Description of the error"
297 | }
298 | }
299 | }
300 | }
301 | }
302 | }
303 | }
304 | },
305 | "parameters": [
306 | {
307 | "description": "API.market API Key",
308 | "in": "header",
309 | "name": "x-magicapi-key",
310 | "value": "clp7flnx6000j3pifm3pinw92",
311 | "required": true,
312 | "schema": {
313 | "type": "string"
314 | }
315 | }
316 | ]
317 | }
318 | },
319 | "servers": [
320 | {
321 | "url": "http://api.magicapi.dev/api/v1/magicapi/pdf-extract"
322 | }
323 | ],
324 | "security": {},
325 | "tags": []
326 | }
```
--------------------------------------------------------------------------------
/src/APIMarketMCPServer.ts:
--------------------------------------------------------------------------------
```typescript
1 | import axios from "axios";
2 | import fs from "fs";
3 | import readline from "readline";
4 | import path from "path";
5 | import { fileURLToPath } from "url";
6 | import { dirname } from "path";
7 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
8 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9 | import { OpenAPIV3 } from "openapi-types";
10 | import {
11 | ListToolsRequestSchema,
12 | CallToolRequestSchema,
13 | Tool,
14 | } from "@modelcontextprotocol/sdk/types.js";
15 | import { APIMarketMCPServerConfig } from "./utils.js";
16 | import { readFile } from "fs/promises";
17 |
18 | // Define __dirname for ESM compatibility
19 | const __dirname = dirname(fileURLToPath(import.meta.url));
20 |
21 | export class APIMarketMCPServer {
22 | private server: Server;
23 | private config: APIMarketMCPServerConfig;
24 |
25 | private tools: Map<string, Tool> = new Map();
26 | private headers: Map<string, string> = new Map();
27 |
28 | constructor(config: APIMarketMCPServerConfig) {
29 | this.config = config;
30 | this.server = new Server({
31 | name: config.name,
32 | version: config.version,
33 | });
34 |
35 | this.initializeHandlers();
36 | }
37 |
38 | private async loadOpenAPISpec(file_path: string): Promise<OpenAPIV3.Document> {
39 | if (typeof file_path === "string") {
40 | if (file_path.startsWith("http")) {
41 | // Load from URL
42 | const response = await axios.get(file_path);
43 | return response.data as OpenAPIV3.Document;
44 | } else {
45 | // Load from local file
46 | const content = await readFile(file_path, "utf-8");
47 | return JSON.parse(content) as OpenAPIV3.Document;
48 | }
49 | }
50 | if (typeof file_path === "object" && file_path !== null) {
51 | return file_path as OpenAPIV3.Document;
52 | }
53 | throw new Error("Invalid OpenAPI specification format");
54 | }
55 |
56 |
57 | private async listOfFilePaths(): Promise<string[]> {
58 | const lines = [];
59 | try {
60 | const fileStream = fs.createReadStream(this.config.openApiSpec);
61 |
62 | const rl = readline.createInterface({
63 | input: fileStream,
64 | crlfDelay: Infinity
65 | });
66 |
67 | for await (const line of rl) {
68 | lines.push(line);
69 | }
70 |
71 | return lines; // Return the array of lines
72 | } catch (error) {
73 | console.error(`Error reading file paths from ${this.config.openApiSpec}:`, error);
74 | throw new Error(`Failed to read API specifications list: ${error.message}`);
75 | }
76 |
77 | }
78 |
79 | private async parseOpenAPISpec(): Promise<void> {
80 | const paths = await this.listOfFilePaths()
81 | for (const cur_path of paths) {
82 |
83 | if (!cur_path || cur_path.trim() === '') {
84 | console.error('Skipping empty path');
85 | continue;
86 | }
87 |
88 | try {
89 | const spec = await this.loadOpenAPISpec(path.resolve(__dirname, cur_path));
90 |
91 | // Convert each OpenAPI path to an MCP tool
92 | for (const [path, pathItem] of Object.entries(spec.paths)) {
93 | if (!pathItem) continue;
94 |
95 | for (const [method, operation] of Object.entries(pathItem)) {
96 | if (method === "parameters" || !operation) continue;
97 |
98 | const op = operation as OpenAPIV3.OperationObject;
99 | // Create a clean tool ID by removing the leading slash and replacing special chars
100 |
101 | const cleanPath = path.replace(/^\//, "");
102 | const toolId = `${method.toUpperCase()}-${cleanPath}`.replace(
103 | /[^a-zA-Z0-9-_]/g,
104 | "-",
105 | );
106 | const tool: Tool = {
107 | name:
108 | (op.operationId || op.summary || `${method.toUpperCase()} ${path}`).replace(/\s+/g, "_"),
109 | description:
110 | op.description ||
111 | `Make a ${method.toUpperCase()} request to ${path}`,
112 | inputSchema: {
113 | type: "object",
114 | properties: {},
115 | // Add any additional properties from OpenAPI spec
116 | },
117 | };
118 |
119 | // Add parameters from operation
120 | if (op.parameters) {
121 | for (const param of op.parameters) {
122 | if ("name" in param && "in" in param) {
123 | const paramSchema = param.schema as OpenAPIV3.SchemaObject;
124 | tool.inputSchema.properties[param.name] = {
125 | type: paramSchema.type || "string",
126 | description: param.description || `${param.name} parameter`,
127 | };
128 | if (param.required) {
129 | tool.inputSchema.required = tool.inputSchema.required || [];
130 | tool.inputSchema.required.push(param.name);
131 | }
132 | }
133 | }
134 | }
135 |
136 | // Add request body if present (for POST, PUT, etc.)
137 | if (op.requestBody) {
138 | const requestBody = op.requestBody as OpenAPIV3.RequestBodyObject;
139 | const content = requestBody.content;
140 |
141 | // Usually we'd look for application/json content type
142 | if (content?.['application/json']) {
143 | this.headers.set(toolId, 'application/json');
144 | const jsonSchema = content['application/json'].schema as OpenAPIV3.SchemaObject;
145 |
146 | // If it's a reference, we'd need to resolve it
147 | // For simplicity, assuming it's an inline schema
148 | if (jsonSchema.properties) {
149 | // Add all properties from the request body schema
150 | for (const [propName, propSchema] of Object.entries(jsonSchema.properties)) {
151 | tool.inputSchema.properties[propName] = propSchema;
152 | }
153 |
154 | // Add required properties if defined
155 | if (jsonSchema.required) {
156 | tool.inputSchema.required = tool.inputSchema.required || [];
157 | tool.inputSchema.required.push(...jsonSchema.required);
158 | }
159 | }
160 | }
161 | else if (content?.['application/x-www-form-urlencoded']) {
162 | this.headers.set(toolId, 'application/x-www-form-urlencoded');
163 | const urlencodedSchema = content['application/x-www-form-urlencoded'].schema as OpenAPIV3.SchemaObject;
164 |
165 | if (urlencodedSchema.properties) {
166 | for (const [propName, propSchema] of Object.entries(urlencodedSchema.properties)) {
167 | tool.inputSchema.properties[propName] = propSchema;
168 | }
169 |
170 | if (urlencodedSchema.required) {
171 | tool.inputSchema.required = tool.inputSchema.required || [];
172 | tool.inputSchema.required.push(...urlencodedSchema.required);
173 | }
174 | }
175 | }
176 | }
177 |
178 | this.tools.set(toolId, tool);
179 | }
180 | }
181 | } catch (error) {
182 | console.error(`Error parsing OpenAPI spec from ${cur_path}:`, error);
183 | }
184 | }
185 | }
186 |
187 | private initializeHandlers(): void {
188 | // Handle tool listing
189 | this.server.setRequestHandler(ListToolsRequestSchema, async () => {
190 | return {
191 | tools: Array.from(this.tools.values()),
192 | };
193 | });
194 |
195 | // Handle tool execution
196 | this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
197 | const { id, name, arguments: params } = request.params;
198 |
199 | console.error("Received request:", request.params);
200 | console.error("Using parameters from arguments:", params);
201 |
202 | // Find tool by ID or name
203 | let tool: Tool | undefined;
204 | let toolId: string | undefined;
205 |
206 | if (id) {
207 | toolId = id.trim();
208 | tool = this.tools.get(toolId);
209 | } else if (name) {
210 | // Search for tool by name
211 | for (const [tid, t] of this.tools.entries()) {
212 | if (t.name === name) {
213 | tool = t;
214 | toolId = tid;
215 | break;
216 | }
217 | }
218 | }
219 |
220 | if (!tool || !toolId) {
221 | console.error(
222 | `Available tools: ${Array.from(this.tools.entries())
223 | .map(([id, t]) => `${id} (${t.name})`)
224 | .join(", ")}`,
225 | );
226 | throw new Error(`Tool not found: ${id || name}`);
227 | }
228 |
229 | console.error(`Executing tool: ${toolId} (${tool.name})`);
230 |
231 | try {
232 | // Extract method and path from tool ID
233 | const [method, ...pathParts] = toolId.split("-");
234 | let path = "/" + pathParts.join("/")
235 | .replace(/-/g, "/")
236 | .replaceAll('!', "-");
237 |
238 |
239 | // Ensure base URL ends with slash for proper joining
240 | const baseUrl = this.config.apiBaseUrl.endsWith("/")
241 | ? this.config.apiBaseUrl
242 | : `${this.config.apiBaseUrl}/`;
243 |
244 |
245 | // Remove leading slash from path to avoid double slashes
246 | const cleanPath = path.startsWith("/") ? path.slice(1) : path;
247 |
248 | let url;
249 | try {
250 | // Validate that the path results in a valid URL
251 | // Construct the full URL
252 | url = new URL(cleanPath, baseUrl).toString();
253 | } catch (error) {
254 | throw new Error(`Invalid path generated from tool ID ${toolId}: ${error.message}`);
255 | }
256 | // Prepare request configuration
257 | this.config.headers = this.config.headers || {};
258 | const contentType = this.headers.get(toolId);
259 | if (contentType) {
260 | this.config.headers['Content-Type'] = contentType;
261 | }
262 | const config: any = {
263 | method: method.toLowerCase(),
264 | url: url,
265 | headers: this.config.headers,
266 | };
267 |
268 | // Handle different parameter types based on HTTP method
269 | if (method.toLowerCase() === "get") {
270 | // For GET requests, ensure parameters are properly structured
271 | if (params && typeof params === "object") {
272 | // Handle array parameters properly
273 | const queryParams: Record<string, string> = {};
274 | for (const [key, value] of Object.entries(params)) {
275 | if (Array.isArray(value)) {
276 | // Join array values with commas for query params
277 | queryParams[key] = value.join(",");
278 | } else if (value !== undefined && value !== null) {
279 | // Convert other values to strings
280 | queryParams[key] = String(value);
281 | }
282 | }
283 | config.params = queryParams;
284 | }
285 | } else {
286 | // For POST, PUT, PATCH - send as body
287 | config.data = params;
288 | }
289 |
290 | console.error("Final request config:", config);
291 |
292 | try {
293 |
294 | const response = await axios(config);
295 | return {
296 | content: [{
297 | type: "text",
298 | text: JSON.stringify(response.data, null, 2)
299 | }]
300 | };
301 | } catch (error) {
302 | if (axios.isAxiosError(error)) {
303 | console.error("Request failed:", {
304 | status: error.response?.status,
305 | statusText: error.response?.statusText,
306 | data: error.response?.data,
307 | headers: error.response?.headers,
308 | });
309 | throw new Error(
310 | `API request failed: ${error.message} - ${JSON.stringify(error.response?.data)}`,
311 | );
312 | }
313 | throw error;
314 | }
315 |
316 | } catch (error) {
317 | if (axios.isAxiosError(error)) {
318 | throw new Error(`API request failed: ${error.message}`);
319 | }
320 | throw error;
321 | }
322 | });
323 | }
324 |
325 | async start(): Promise<void> {
326 | await this.parseOpenAPISpec();
327 | const transport = new StdioServerTransport();
328 | await this.server.connect(transport);
329 | console.error("OpenAPI MCP Server running on stdio");
330 | }
331 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_capix-free.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.1.0",
3 | "info": {
4 | "title": "Content Detector API",
5 | "version": "0.1.1"
6 | },
7 | "servers": [
8 | {
9 | "url": "http://api.magicapi.dev/api/v1/capix/free"
10 | }
11 | ],
12 | "paths": {
13 | "capix/free/detector/v1/": {
14 | "post": {
15 | "tags": [
16 | "ContentDetectorAI"
17 | ],
18 | "summary": "Content Detector Ai",
19 | "operationId": "ContentDetectorAI",
20 | "requestBody": {
21 | "content": {
22 | "application/x-www-form-urlencoded": {
23 | "schema": {
24 | "type": "object",
25 | "properties": {
26 | "content": {
27 | "type": "string",
28 | "title": "Content",
29 | "default": "ContentDetector.AI is an accurate and free AI Detector and AI Content Detector that can be used to detect any AI-generated content. It provides a probability score based on the likelihood that the text content was generated by AI tools or chatbots."
30 | }
31 | },
32 | "required": [
33 | "content"
34 | ],
35 | "title": "Body"
36 | }
37 | }
38 | }
39 | },
40 | "responses": {
41 | "200": {
42 | "description": "Successful Response",
43 | "content": {
44 | "application/json": {
45 | "schema": {}
46 | }
47 | }
48 | },
49 | "400": {
50 | "content": {
51 | "application/json": {
52 | "schema": {
53 | "properties": {
54 | "message": {
55 | "type": "string",
56 | "title": "Message"
57 | }
58 | },
59 | "type": "object",
60 | "required": [
61 | "message"
62 | ],
63 | "title": "ValueError"
64 | }
65 | }
66 | },
67 | "description": "Bad Request"
68 | },
69 | "422": {
70 | "content": {
71 | "application/json": {
72 | "schema": {
73 | "properties": {
74 | "message": {
75 | "type": "string",
76 | "title": "Message",
77 | "default": "Invalid request data"
78 | }
79 | },
80 | "type": "object",
81 | "title": "ValidationError"
82 | }
83 | }
84 | },
85 | "description": "Unprocessable Entity"
86 | },
87 | "500": {
88 | "content": {
89 | "application/json": {
90 | "schema": {
91 | "properties": {
92 | "message": {
93 | "type": "string",
94 | "title": "Message",
95 | "default": "Internal Server Error"
96 | }
97 | },
98 | "type": "object",
99 | "title": "ServerError"
100 | }
101 | }
102 | },
103 | "description": "Internal Server Error"
104 | }
105 | }
106 | },
107 | "parameters": [
108 | {
109 | "description": "API.market API Key",
110 | "in": "header",
111 | "name": "x-magicapi-key",
112 | "value": "clp7flnx6000j3pifm3pinw92",
113 | "required": true,
114 | "schema": {
115 | "type": "string"
116 | }
117 | }
118 | ]
119 | }
120 | },
121 | "components": {
122 | "schemas": {
123 | "Body_BookTitleGenerator": {
124 | "properties": {
125 | "description": {
126 | "type": "string",
127 | "title": "Description",
128 | "default": "let us dive"
129 | },
130 | "mode": {
131 | "type": "string",
132 | "title": "Mode",
133 | "description": "`Standard`, `Creative`, `Formal`, `Simple`",
134 | "default": "Formal"
135 | }
136 | },
137 | "required": [
138 | "description",
139 | "mode"
140 | ],
141 | "type": "object",
142 | "title": "Body_BookTitleGenerator"
143 | },
144 | "Body_ContentDetectorAI": {
145 | "properties": {
146 | "content": {
147 | "type": "string",
148 | "title": "Content",
149 | "default": "ContentDetector.AI is an accurate and free AI Detector and AI Content Detector that can be used to detect any AI-generated content. It provides a probability score based on the likelihood that the text content was generated by AI tools or chatbots."
150 | }
151 | },
152 | "required": [
153 | "content"
154 | ],
155 | "type": "object",
156 | "title": "Body_ContentDetectorAI"
157 | },
158 | "Body_EssayGenerator": {
159 | "properties": {
160 | "description": {
161 | "type": "string",
162 | "title": "Description",
163 | "default": "Essay Topic: The Impact of Social Media on Human Communication\n\n\nKey Details and Questions:\n\n\nIntroduction: Introduce the topic by highlighting the ubiquity of social media in modern life. Pose the central question: Has social media enhanced or hindered human communication?\n\n\nHistorical Perspective:\n\n\nHow did people communicate before the advent of social media?\nWhat were the key stages in the evolution of social media platforms?\nPositive Impacts of Social Media:\n\n\nHow has social media facilitated global connectivity and understanding?\nDiscuss the role of social media in democratizing content creation and information sharing.\nNegative Impacts of Social Media:\n\n\nAnalyze the potential for misinformation and echo chambers.\nExplore the effects of social media on mental health and interpersonal relationships.\nSocial Media and Business:\n\n\nHow has social media transformed business marketing and customer engagement?\nDiscuss the rise of influencer culture and its implications.\nThe Future of Social Media:\n\n\nSpeculate on the future trends in social media.\nWhat role might emerging technologies like AI and VR play in the evolution of social media?\nConclusion:\n\n\nSummarize the main points.\nReflect on the balance between the benefits and drawbacks of social media.\nProvide a personal perspective or a call to action on how to use social media responsibly.\nThemes to Explore:\n\n\nThe role of technology in shaping human interaction.\nThe balance between virtual and real-life communication.\nEthical considerations in the age of digital media."
164 | },
165 | "word_count": {
166 | "type": "integer",
167 | "title": "Word Count",
168 | "default": 1200
169 | },
170 | "mode": {
171 | "type": "string",
172 | "title": "Mode",
173 | "description": "`Standard`, `Academic`, `Professional`, `Creative`, `Journalistic`",
174 | "default": "Standard"
175 | }
176 | },
177 | "required": [
178 | "description",
179 | "word_count",
180 | "mode"
181 | ],
182 | "type": "object",
183 | "title": "Body_EssayGenerator"
184 | },
185 | "Body_SentenceExpander": {
186 | "properties": {
187 | "sentence": {
188 | "type": "string",
189 | "title": "Sentence",
190 | "default": "Struggling with wordy sentences? Want to make your writing crisp and clear? We've got you covered! Introducing Sentence Shortener, the perfect free tool to help you cut down on those extra words. No more headaches over long, complicated sentences. With our AI, you can make your writing easy to read and understand - in just a few clicks!\n\n\n\n"
191 | },
192 | "word_count": {
193 | "type": "integer",
194 | "title": "Word Count",
195 | "default": 80
196 | }
197 | },
198 | "required": [
199 | "sentence",
200 | "word_count"
201 | ],
202 | "type": "object",
203 | "title": "Body_SentenceExpander"
204 | },
205 | "Body_SentenceShortener": {
206 | "properties": {
207 | "sentence": {
208 | "type": "string",
209 | "title": "Sentence",
210 | "default": "Struggling with wordy sentences? Want to make your writing crisp and clear? We've got you covered! Introducing Sentence Shortener, the perfect free tool to help you cut down on those extra words. No more headaches over long, complicated sentences. With our AI, you can make your writing easy to read and understand - in just a few clicks!\n\n\n\n"
211 | },
212 | "word_count": {
213 | "type": "integer",
214 | "title": "Word Count",
215 | "default": 50
216 | }
217 | },
218 | "required": [
219 | "sentence",
220 | "word_count"
221 | ],
222 | "type": "object",
223 | "title": "Body_SentenceShortener"
224 | },
225 | "Body_StoryGenerator": {
226 | "properties": {
227 | "text": {
228 | "type": "string",
229 | "title": "Text",
230 | "default": "Story Topic: A Time-Travel Adventure\n\n\nSetting: The story is set in both the present day and the Victorian era. The present-day setting is a bustling modern city known for its technological advancements. The Victorian setting is characterized by cobblestone streets, gas-lit lamps, and the early stages of industrialization.\n\n\nMain Characters:\n\n\nAlex: A curious and adventurous software engineer from the present day who inadvertently discovers a time-travel device.\nEliza: A resourceful and intelligent Victorian-era inventor who dreams of changing the future.\nPlot Details:\n\n\nDiscovery of the Time Machine: Alex discovers an old, mysterious device in their attic, left behind by a forgotten ancestor. Experimenting with it, they accidentally activate it and are transported to the Victorian era.\nMeeting Eliza: Alex meets Eliza, who is fascinated by the time machine and Alex's futuristic knowledge. Together, they explore the possibilities of time travel.\nA Threat Emerges: A sinister figure from the Victorian era learns about the time machine and wants to use it for nefarious purposes, threatening both the past and the future.\nRace Against Time: Alex and Eliza must work together to safeguard the time machine and prevent the alteration of history. They face challenges in both eras, blending elements of Victorian society with futuristic technology.\nResolution: The story concludes with a thrilling confrontation, and a decision that affects both characters' destinies.\nThemes: The story explores themes of adventure, the ethics of time travel, the impact of technology on society, and the timeless nature of human curiosity and ambition."
231 | },
232 | "word_count": {
233 | "type": "integer",
234 | "title": "Word Count",
235 | "default": 1200
236 | },
237 | "mode": {
238 | "type": "string",
239 | "title": "Mode",
240 | "description": "`Standard`, `Creative`, `Complex`, `Simple`",
241 | "default": "Creative"
242 | }
243 | },
244 | "required": [
245 | "text",
246 | "word_count",
247 | "mode"
248 | ],
249 | "type": "object",
250 | "title": "Body_StoryGenerator"
251 | },
252 | "ServerError": {
253 | "properties": {
254 | "message": {
255 | "type": "string",
256 | "title": "Message",
257 | "default": "Internal Server Error"
258 | }
259 | },
260 | "type": "object",
261 | "title": "ServerError"
262 | },
263 | "ValidationError": {
264 | "properties": {
265 | "message": {
266 | "type": "string",
267 | "title": "Message",
268 | "default": "Invalid request data"
269 | }
270 | },
271 | "type": "object",
272 | "title": "ValidationError"
273 | },
274 | "ValueError": {
275 | "properties": {
276 | "message": {
277 | "type": "string",
278 | "title": "Message"
279 | }
280 | },
281 | "type": "object",
282 | "required": [
283 | "message"
284 | ],
285 | "title": "ValueError"
286 | }
287 | }
288 | },
289 | "security": {},
290 | "tags": []
291 | }
```
--------------------------------------------------------------------------------
/src/lib/modified_capix-shortener.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "openapi": "3.1.0",
3 | "info": {
4 | "title": "Content Detector API",
5 | "version": "0.1.1"
6 | },
7 | "servers": [
8 | {
9 | "url": "http://api.magicapi.dev/api/v1/capix/shortener"
10 | }
11 | ],
12 | "paths": {
13 | "capix/shortener/sentence/shortener/v1/": {
14 | "post": {
15 | "tags": [
16 | "SentenceShortener"
17 | ],
18 | "summary": "Sentence Shortener",
19 | "operationId": "SentenceShortener",
20 | "requestBody": {
21 | "content": {
22 | "application/x-www-form-urlencoded": {
23 | "schema": {
24 | "type": "object",
25 | "properties": {
26 | "sentence": {
27 | "type": "string",
28 | "title": "Sentence",
29 | "default": "Struggling with wordy sentences? Want to make your writing crisp and clear? We've got you covered! Introducing Sentence Shortener, the perfect free tool to help you cut down on those extra words. No more headaches over long, complicated sentences. With our AI, you can make your writing easy to read and understand - in just a few clicks!\n\n\n\n"
30 | },
31 | "word_count": {
32 | "type": "integer",
33 | "title": "Word Count",
34 | "default": 50
35 | }
36 | },
37 | "required": [
38 | "word_count",
39 | "sentence"
40 | ],
41 | "title": "Body"
42 | }
43 | }
44 | }
45 | },
46 | "responses": {
47 | "200": {
48 | "description": "Successful Response",
49 | "content": {
50 | "application/json": {
51 | "schema": {}
52 | }
53 | }
54 | },
55 | "400": {
56 | "content": {
57 | "application/json": {
58 | "schema": {
59 | "properties": {
60 | "message": {
61 | "type": "string",
62 | "title": "Message"
63 | }
64 | },
65 | "type": "object",
66 | "required": [
67 | "message"
68 | ],
69 | "title": "ValueError"
70 | }
71 | }
72 | },
73 | "description": "Bad Request"
74 | },
75 | "422": {
76 | "content": {
77 | "application/json": {
78 | "schema": {
79 | "properties": {
80 | "message": {
81 | "type": "string",
82 | "title": "Message",
83 | "default": "Invalid request data"
84 | }
85 | },
86 | "type": "object",
87 | "title": "ValidationError"
88 | }
89 | }
90 | },
91 | "description": "Unprocessable Entity"
92 | },
93 | "500": {
94 | "content": {
95 | "application/json": {
96 | "schema": {
97 | "properties": {
98 | "message": {
99 | "type": "string",
100 | "title": "Message",
101 | "default": "Internal Server Error"
102 | }
103 | },
104 | "type": "object",
105 | "title": "ServerError"
106 | }
107 | }
108 | },
109 | "description": "Internal Server Error"
110 | }
111 | }
112 | },
113 | "parameters": [
114 | {
115 | "description": "API.market API Key",
116 | "in": "header",
117 | "name": "x-magicapi-key",
118 | "value": "clp7flnx6000j3pifm3pinw92",
119 | "required": true,
120 | "schema": {
121 | "type": "string"
122 | }
123 | }
124 | ]
125 | }
126 | },
127 | "components": {
128 | "schemas": {
129 | "Body_BookTitleGenerator": {
130 | "properties": {
131 | "description": {
132 | "type": "string",
133 | "title": "Description",
134 | "default": "let us dive"
135 | },
136 | "mode": {
137 | "type": "string",
138 | "title": "Mode",
139 | "description": "`Standard`, `Creative`, `Formal`, `Simple`",
140 | "default": "Formal"
141 | }
142 | },
143 | "required": [
144 | "description",
145 | "mode"
146 | ],
147 | "type": "object",
148 | "title": "Body_BookTitleGenerator"
149 | },
150 | "Body_ContentDetectorAI": {
151 | "properties": {
152 | "content": {
153 | "type": "string",
154 | "title": "Content",
155 | "default": "ContentDetector.AI is an accurate and free AI Detector and AI Content Detector that can be used to detect any AI-generated content. It provides a probability score based on the likelihood that the text content was generated by AI tools or chatbots."
156 | }
157 | },
158 | "required": [
159 | "content"
160 | ],
161 | "type": "object",
162 | "title": "Body_ContentDetectorAI"
163 | },
164 | "Body_EssayGenerator": {
165 | "properties": {
166 | "description": {
167 | "type": "string",
168 | "title": "Description",
169 | "default": "Essay Topic: The Impact of Social Media on Human Communication\n\n\nKey Details and Questions:\n\n\nIntroduction: Introduce the topic by highlighting the ubiquity of social media in modern life. Pose the central question: Has social media enhanced or hindered human communication?\n\n\nHistorical Perspective:\n\n\nHow did people communicate before the advent of social media?\nWhat were the key stages in the evolution of social media platforms?\nPositive Impacts of Social Media:\n\n\nHow has social media facilitated global connectivity and understanding?\nDiscuss the role of social media in democratizing content creation and information sharing.\nNegative Impacts of Social Media:\n\n\nAnalyze the potential for misinformation and echo chambers.\nExplore the effects of social media on mental health and interpersonal relationships.\nSocial Media and Business:\n\n\nHow has social media transformed business marketing and customer engagement?\nDiscuss the rise of influencer culture and its implications.\nThe Future of Social Media:\n\n\nSpeculate on the future trends in social media.\nWhat role might emerging technologies like AI and VR play in the evolution of social media?\nConclusion:\n\n\nSummarize the main points.\nReflect on the balance between the benefits and drawbacks of social media.\nProvide a personal perspective or a call to action on how to use social media responsibly.\nThemes to Explore:\n\n\nThe role of technology in shaping human interaction.\nThe balance between virtual and real-life communication.\nEthical considerations in the age of digital media."
170 | },
171 | "word_count": {
172 | "type": "integer",
173 | "title": "Word Count",
174 | "default": 1200
175 | },
176 | "mode": {
177 | "type": "string",
178 | "title": "Mode",
179 | "description": "`Standard`, `Academic`, `Professional`, `Creative`, `Journalistic`",
180 | "default": "Standard"
181 | }
182 | },
183 | "required": [
184 | "description",
185 | "word_count",
186 | "mode"
187 | ],
188 | "type": "object",
189 | "title": "Body_EssayGenerator"
190 | },
191 | "Body_SentenceExpander": {
192 | "properties": {
193 | "sentence": {
194 | "type": "string",
195 | "title": "Sentence",
196 | "default": "Struggling with wordy sentences? Want to make your writing crisp and clear? We've got you covered! Introducing Sentence Shortener, the perfect free tool to help you cut down on those extra words. No more headaches over long, complicated sentences. With our AI, you can make your writing easy to read and understand - in just a few clicks!\n\n\n\n"
197 | },
198 | "word_count": {
199 | "type": "integer",
200 | "title": "Word Count",
201 | "default": 80
202 | }
203 | },
204 | "required": [
205 | "sentence",
206 | "word_count"
207 | ],
208 | "type": "object",
209 | "title": "Body_SentenceExpander"
210 | },
211 | "Body_SentenceShortener": {
212 | "properties": {
213 | "sentence": {
214 | "type": "string",
215 | "title": "Sentence",
216 | "default": "Struggling with wordy sentences? Want to make your writing crisp and clear? We've got you covered! Introducing Sentence Shortener, the perfect free tool to help you cut down on those extra words. No more headaches over long, complicated sentences. With our AI, you can make your writing easy to read and understand - in just a few clicks!\n\n\n\n"
217 | },
218 | "word_count": {
219 | "type": "integer",
220 | "title": "Word Count",
221 | "default": 50
222 | }
223 | },
224 | "required": [
225 | "sentence",
226 | "word_count"
227 | ],
228 | "type": "object",
229 | "title": "Body_SentenceShortener"
230 | },
231 | "Body_StoryGenerator": {
232 | "properties": {
233 | "text": {
234 | "type": "string",
235 | "title": "Text",
236 | "default": "Story Topic: A Time-Travel Adventure\n\n\nSetting: The story is set in both the present day and the Victorian era. The present-day setting is a bustling modern city known for its technological advancements. The Victorian setting is characterized by cobblestone streets, gas-lit lamps, and the early stages of industrialization.\n\n\nMain Characters:\n\n\nAlex: A curious and adventurous software engineer from the present day who inadvertently discovers a time-travel device.\nEliza: A resourceful and intelligent Victorian-era inventor who dreams of changing the future.\nPlot Details:\n\n\nDiscovery of the Time Machine: Alex discovers an old, mysterious device in their attic, left behind by a forgotten ancestor. Experimenting with it, they accidentally activate it and are transported to the Victorian era.\nMeeting Eliza: Alex meets Eliza, who is fascinated by the time machine and Alex's futuristic knowledge. Together, they explore the possibilities of time travel.\nA Threat Emerges: A sinister figure from the Victorian era learns about the time machine and wants to use it for nefarious purposes, threatening both the past and the future.\nRace Against Time: Alex and Eliza must work together to safeguard the time machine and prevent the alteration of history. They face challenges in both eras, blending elements of Victorian society with futuristic technology.\nResolution: The story concludes with a thrilling confrontation, and a decision that affects both characters' destinies.\nThemes: The story explores themes of adventure, the ethics of time travel, the impact of technology on society, and the timeless nature of human curiosity and ambition."
237 | },
238 | "word_count": {
239 | "type": "integer",
240 | "title": "Word Count",
241 | "default": 1200
242 | },
243 | "mode": {
244 | "type": "string",
245 | "title": "Mode",
246 | "description": "`Standard`, `Creative`, `Complex`, `Simple`",
247 | "default": "Creative"
248 | }
249 | },
250 | "required": [
251 | "text",
252 | "word_count",
253 | "mode"
254 | ],
255 | "type": "object",
256 | "title": "Body_StoryGenerator"
257 | },
258 | "ServerError": {
259 | "properties": {
260 | "message": {
261 | "type": "string",
262 | "title": "Message",
263 | "default": "Internal Server Error"
264 | }
265 | },
266 | "type": "object",
267 | "title": "ServerError"
268 | },
269 | "ValidationError": {
270 | "properties": {
271 | "message": {
272 | "type": "string",
273 | "title": "Message",
274 | "default": "Invalid request data"
275 | }
276 | },
277 | "type": "object",
278 | "title": "ValidationError"
279 | },
280 | "ValueError": {
281 | "properties": {
282 | "message": {
283 | "type": "string",
284 | "title": "Message"
285 | }
286 | },
287 | "type": "object",
288 | "required": [
289 | "message"
290 | ],
291 | "title": "ValueError"
292 | }
293 | }
294 | },
295 | "security": {},
296 | "tags": []
297 | }
```