Skip to content

Commit df217a1

Browse files
rakduttarakdutta1crivetimihaiimolloymadhav165
authored
Fix Tool Edit Screen: Field Mapping Consistency and Custom Tool Naming Implementation (#786)
* db.py update Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * doc test Signed-off-by: RAKHI DUTTA <[email protected]> * pytest Signed-off-by: RAKHI DUTTA <[email protected]> * pytest Signed-off-by: RAKHI DUTTA <[email protected]> * revert alembic with main version Signed-off-by: RAKHI DUTTA <[email protected]> * 138 view realtime logs in UI and export logs (CSV, JSON) (#747) * Add logging UI Signed-off-by: Mihai Criveti <[email protected]> * Add logging UI Signed-off-by: Mihai Criveti <[email protected]> * Add logging UI Signed-off-by: Mihai Criveti <[email protected]> * Add logging UI readme Signed-off-by: Mihai Criveti <[email protected]> * Update logging flake8 Signed-off-by: Mihai Criveti <[email protected]> * Update logging flake8 Signed-off-by: Mihai Criveti <[email protected]> * test coverage Signed-off-by: Mihai Criveti <[email protected]> * test coverage Signed-off-by: Mihai Criveti <[email protected]> * Fix download Signed-off-by: Mihai Criveti <[email protected]> * Fix test Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * 749 reverse proxy (#750) * Fix download Signed-off-by: Mihai Criveti <[email protected]> * Reverse proxy Signed-off-by: Mihai Criveti <[email protected]> * Reverse proxy Signed-off-by: Mihai Criveti <[email protected]> * Reverse proxy Signed-off-by: Mihai Criveti <[email protected]> * doctest improvements Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * (fix) Added missing prompts/get (#748) Signed-off-by: Ian Molloy <[email protected]> * Adds RPC endpoints and updates RPC response and error handling (#746) * Fix rpc endpoints Signed-off-by: Madhav Kandukuri <[email protected]> * Remove commented code Signed-off-by: Madhav Kandukuri <[email protected]> * remove duplicate code in session registry Signed-off-by: Madhav Kandukuri <[email protected]> * Linting fixes Signed-off-by: Madhav Kandukuri <[email protected]> * Fix tests Signed-off-by: Madhav Kandukuri <[email protected]> --------- Signed-off-by: Madhav Kandukuri <[email protected]> * 753 fix tool invocation invalid method (#754) * Fix tool invocation 'Invalid method' error with backward compatibility (#753) - Add backward compatibility for direct tool invocation (pre-PR #746 format) - Support both old format (method=tool_name) and new format (method=tools/call) - Add comprehensive test coverage for RPC tool invocation scenarios - Ensure graceful fallback to gateway forwarding when method is not a tool The RPC endpoint now handles tool invocations in both formats: 1. New format: method='tools/call' with name and arguments in params 2. Old format: method='tool_name' with params as arguments (backward compat) This maintains compatibility with existing clients while supporting the new standardized RPC method structure introduced in PR #746. Signed-off-by: Mihai Criveti <[email protected]> * Fix flake8 E722: Replace bare except with Exception Signed-off-by: Mihai Criveti <[email protected]> * lint Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * fix: suppress bandit security warnings with appropriate nosec comments (#755) - Added nosec B105 for ENV_TOKEN as it's an environment variable name, not a hardcoded secret - Added nosec B110 for intentional exception swallowing in cleanup/error handling paths - Both cases are legitimate uses where errors should be silently ignored to prevent cascading failures Signed-off-by: Mihai Criveti <[email protected]> * Add agents file Signed-off-by: Mihai Criveti <[email protected]> * pylint (#759) Signed-off-by: Mihai Criveti <[email protected]> * Remove redundant title in readme. (#757) Signed-off-by: Vinod Muthusamy <[email protected]> Co-authored-by: Vinod Muthusamy <[email protected]> * Update documentation with fixed image tag Signed-off-by: Mihai Criveti <[email protected]> * 256 fuzz testing (#760) * Implement comprehensive fuzz testing automation (#256) - Add property-based testing with Hypothesis for JSON-RPC, JSONPath, and schema validation - Add coverage-guided fuzzing with Atheris for deep code path exploration - Add API endpoint fuzzing with Schemathesis for contract validation - Add security-focused testing for vulnerability discovery (SQL injection, XSS, etc.) - Add complete Makefile automation with fuzz-all, fuzz-quick, fuzz-extended targets - Add optional [fuzz] dependency group in pyproject.toml for clean installation - Add comprehensive reporting with JSON/Markdown outputs and executive summaries - Add complete developer documentation with examples and troubleshooting guides - Exclude fuzz tests from main test suite to prevent auth failures - Found multiple real bugs in JSON-RPC validation during development Signed-off-by: Mihai Criveti <[email protected]> * Update fuzz testing Signed-off-by: Mihai Criveti <[email protected]> * Update fuzz testing Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * 344 cors security headers (#761) * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS ADRs Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Fix compose Signed-off-by: Mihai Criveti <[email protected]> * Update helm chart Signed-off-by: Mihai Criveti <[email protected]> * Update CORS docs Signed-off-by: Mihai Criveti <[email protected]> * Update test Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * feat: Bulk Import Tools modal wiring #737 (#739) * feat: Bulk Import Tools modal wiring and backend implementation - Add modal UI in admin.html with bulk import button and dialog - Implement modal open/close/ESC functionality in admin.js - Add POST /admin/tools/import endpoint with rate limiting - Support both JSON textarea and file upload inputs - Validate JSON structure and enforce 200 tool limit - Return detailed success/failure information per tool - Include loading states and comprehensive error handling Refs #737 Signed-off-by: Mihai Criveti <[email protected]> * fix: Remove duplicate admin_import_tools function and fix HTML formatting - Remove duplicate admin_import_tools function definition - Fix HTML placeholder attribute to use double quotes - Add missing closing div tag - Fix flake8 blank line issues Signed-off-by: Mihai Criveti <[email protected]> * feat: Complete bulk import backend with file upload support and enhanced docs - Add file upload support to admin_import_tools endpoint - Fix response format to match frontend expectations - Add UI usage documentation with modal instructions - Update API docs to show all three input methods - Enhance bulk import guide with UI and API examples Backend improvements: - Support tools_file form field for JSON file uploads - Proper file content parsing with error handling - Response includes imported/failed counts and details - Frontend-compatible response format for UI display Signed-off-by: Mihai Criveti <[email protected]> * Bulk import Signed-off-by: Mihai Criveti <[email protected]> * fix: Remove conflicting inline script and fix bulk import functionality - Remove conflicting inline JavaScript that was preventing form submission - Fix indentation in setupBulkImportModal function - Ensure bulk import modal uses proper admin.js implementation - Restore proper form submission handling for bulk import This fixes the issue where bulk import appeared to do nothing. Signed-off-by: Mihai Criveti <[email protected]> * fix: Integrate bulk import setup with main initialization - Add setupBulkImportModal() to main initialization sequence - Remove duplicate DOMContentLoaded listener - Ensure bulk import doesn't interfere with other tab functionality Signed-off-by: Mihai Criveti <[email protected]> * fix: JavaScript formatting issues in bulk import modal - Fix multiline querySelector formatting - Fix multiline Error constructor formatting - Ensure prettier compliance for web linting Signed-off-by: Mihai Criveti <[email protected]> * debug: Temporarily disable bulk import setup to test tabs Signed-off-by: Mihai Criveti <[email protected]> * fix: Remove duplicate setupFormValidation call and delay bulk import setup - Remove duplicate setupFormValidation() call that could cause conflicts - Use setTimeout to delay bulk import modal setup after other initialization - Add better null safety to form element queries - This should fix tab switching issues Signed-off-by: Mihai Criveti <[email protected]> * fix: Restore proper initialization sequence for tab functionality - Remove setTimeout delay for bulk import setup - Keep bulk import setup in main initialization but with error handling - Ensure tab navigation isn't affected by bulk import modal setup Signed-off-by: Mihai Criveti <[email protected]> * fix: Correct HTML structure and restore tab navigation - Move bulk import modal to correct location after tools panel - Remove extra closing div that was breaking HTML structure - Ensure proper page-level modal placement - Restore tab navigation functionality for all tabs This fixes the broken Global Resources, Prompts, Gateways, Roots, and Metrics tabs. Signed-off-by: Mihai Criveti <[email protected]> * feat: Add configurable bulk import settings Configuration additions: - MCPGATEWAY_BULK_IMPORT_MAX_TOOLS (default: 200) - MCPGATEWAY_BULK_IMPORT_RATE_LIMIT (default: 10) Implementation: - config.py: Add new settings with defaults - admin.py: Use configurable rate limit and batch size - .env.example: Document all bulk import environment variables - admin.html: Use dynamic max tools value in UI text - CLAUDE.md: Document configuration options for developers - docs: Update bulk import guide with configuration details This makes bulk import fully configurable for different deployment scenarios. Signed-off-by: Mihai Criveti <[email protected]> * Update docs Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Mihai Criveti <[email protected]> * Implemented configuration export (#764) Signed-off-by: Mihai Criveti <[email protected]> * 185 186 import export (#769) * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export Signed-off-by: Mihai Criveti <[email protected]> * Import export testing Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * fix: local network address translation in discovery module (#767) Signed-off-by: Frederico Araujo <[email protected]> * Well known (#770) Signed-off-by: Mihai Criveti <[email protected]> * Update docs with jsonrpc tutorial (#772) Signed-off-by: Mihai Criveti <[email protected]> * 137 metadata timestamps (#776) * Metadata / creation dates Signed-off-by: Mihai Criveti <[email protected]> * Metadata / creation dates Signed-off-by: Mihai Criveti <[email protected]> * Metadata / creation dates Signed-off-by: Mihai Criveti <[email protected]> * Security headers CSP Signed-off-by: Mihai Criveti <[email protected]> * Display metadata for resources Signed-off-by: Madhav Kandukuri <[email protected]> * eslint fix Signed-off-by: Madhav Kandukuri <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Madhav Kandukuri <[email protected]> * feat #262: MCP Langchain Agent (#781) * feat: Add bulk import UI modal for tools Signed-off-by: Vicky <[email protected]> * feat: Add Langchain agent with OpenAI & A2A endpoints (refs #262) Signed-off-by: Vicky <[email protected]> * lint: prettier fix at ~L8090 (insert newline) Signed-off-by: Vicky <[email protected]> --------- Signed-off-by: Vicky <[email protected]> Co-authored-by: Vicky <[email protected]> * Cleanup pr Signed-off-by: Mihai Criveti <[email protected]> * Cleanup pr Signed-off-by: Mihai Criveti <[email protected]> * Issue 587/rest tool error (#778) * added params extraction from url logic Signed-off-by: Veeresh K <[email protected]> * added params extraction from url logic Signed-off-by: Veeresh K <[email protected]> * Rebase and lint / test Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Veeresh K <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Mihai Criveti <[email protected]> * edit column header (#777) Signed-off-by: Shoumi <[email protected]> * Test case update (#775) * session_registry test case updates Signed-off-by: Mohan Lakshmaiah <[email protected]> * test case update for routers/reverse_proxy Signed-off-by: Mohan Lakshmaiah <[email protected]> * test case update to mcpgateway/reverse_proxy.py Signed-off-by: Mohan Lakshmaiah <[email protected]> * Fix formatting issues from pre-commit hooks Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mohan Lakshmaiah <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Mohan Lakshmaiah <[email protected]> Co-authored-by: Mihai Criveti <[email protected]> * feat: add plugins cli, external plugin support, plugin template (#722) * feat: add support for external plugins Signed-off-by: Teryl Taylor <[email protected]> * feat(plugins): add external mcp server and associated test cases. Signed-off-by: Teryl Taylor <[email protected]> * fix(lint): fixed yamllint issues Signed-off-by: Teryl Taylor <[email protected]> * fix(lint): fixed flake8 issue. Signed-off-by: Teryl Taylor <[email protected]> * feat: define plugins cli and implement bootstrap command Signed-off-by: Frederico Araujo <[email protected]> * fix: implement install and package CLI commands Signed-off-by: Frederico Araujo <[email protected]> * fix: remote avoid insecure shell=True in subprocess invocation Signed-off-by: Frederico Araujo <[email protected]> * feat: add external plugin template Signed-off-by: Frederico Araujo <[email protected]> * feat: move copier config to repository root Signed-off-by: Frederico Araujo <[email protected]> * feat: update copier template Signed-off-by: Frederico Araujo <[email protected]> * feat: get default author from git config Signed-off-by: Frederico Araujo <[email protected]> * feat: update copier settings Signed-off-by: Frederico Araujo <[email protected]> * fix: copier config syntax Signed-off-by: Frederico Araujo <[email protected]> * feat: add external plugin template modules Signed-off-by: Frederico Araujo <[email protected]> * fix: template syntax Signed-off-by: Frederico Araujo <[email protected]> * fix: template syntax Signed-off-by: Frederico Araujo <[email protected]> * fix: make template Signed-off-by: Frederico Araujo <[email protected]> * feat: fix template issue Signed-off-by: Frederico Araujo <[email protected]> * fix: toml template Signed-off-by: Frederico Araujo <[email protected]> * fix: plugin mcp server initialization Signed-off-by: Frederico Araujo <[email protected]> * feat: init module for plugin framework Signed-off-by: Frederico Araujo <[email protected]> * feat: add chuck runtime and container wrapping Signed-off-by: Frederico Araujo <[email protected]> * fix: makefile template Signed-off-by: Frederico Araujo <[email protected]> * fix: plugins config path Signed-off-by: Frederico Araujo <[email protected]> * feat: add .env.template Signed-off-by: Frederico Araujo <[email protected]> * feat: add tools and resources support Signed-off-by: Frederico Araujo <[email protected]> * fix: lint yaml Signed-off-by: Frederico Araujo <[email protected]> * chore: cleanups Signed-off-by: Frederico Araujo <[email protected]> * feat: update manifest.in Signed-off-by: Frederico Araujo <[email protected]> * chore: linting Signed-off-by: Frederico Araujo <[email protected]> * fix: plugin config variable Signed-off-by: Frederico Araujo <[email protected]> * fix(tests): fixed doctests for plugins. Signed-off-by: Teryl Taylor <[email protected]> * refactor: external plugin server and plugin external API Signed-off-by: Frederico Araujo <[email protected]> * docs(plugins): removed subpackages from examples Signed-off-by: Teryl Taylor <[email protected]> * docs: update plugin docs to use public framework API Signed-off-by: Frederico Araujo <[email protected]> * fix(plugin): added resource payloads to base plugin. Signed-off-by: Teryl Taylor <[email protected]> * feat: udpate test templates Signed-off-by: Frederico Araujo <[email protected]> * feat: update test templates Signed-off-by: Frederico Araujo <[email protected]> * feat: update plugin template Signed-off-by: Frederico Araujo <[email protected]> * feat: update plugin template Signed-off-by: Frederico Araujo <[email protected]> * feat: update tempalte makefile Signed-off-by: Frederico Araujo <[email protected]> * feat: add template for native plugin Signed-off-by: Frederico Araujo <[email protected]> * feat: add readme for native template Signed-off-by: Frederico Araujo <[email protected]> * feat: force boostrap to be a subcommnand Signed-off-by: Frederico Araujo <[email protected]> * tests(plugin): added http streamable and error tests. Signed-off-by: Teryl Taylor <[email protected]> * tests: add tests for plugins CLI Signed-off-by: Frederico Araujo <[email protected]> * fix: deprecation warning Signed-off-by: Frederico Araujo <[email protected]> * tests: add CLI tests Signed-off-by: Frederico Araujo <[email protected]> * tests: update plugin cli Signed-off-by: Frederico Araujo <[email protected]> * tests(plugins): added client hook tests for external plugins. Signed-off-by: Teryl Taylor <[email protected]> * chore: update template readmes Signed-off-by: Frederico Araujo <[email protected]> * fix: lint docstrings in cli Signed-off-by: Frederico Araujo <[email protected]> * chore: fix lint errors in docstrings Signed-off-by: Frederico Araujo <[email protected]> * chore: fix lint errors Signed-off-by: Frederico Araujo <[email protected]> * tests: add external plugin server tests Signed-off-by: Frederico Araujo <[email protected]> * chore: cleanup Signed-off-by: Frederico Araujo <[email protected]> * chore: add missing docstrings Signed-off-by: Frederico Araujo <[email protected]> * chore: add missing docstrings Signed-off-by: Frederico Araujo <[email protected]> * tests: fix cli dryrun test Signed-off-by: Frederico Araujo <[email protected]> * chore: fix lint issues Signed-off-by: Frederico Araujo <[email protected]> * tests: fix teardown of client http tests Signed-off-by: Frederico Araujo <[email protected]> * tests: skipping flaky tests Signed-off-by: Frederico Araujo <[email protected]> * docs: plugin lifecycle tools Signed-off-by: Frederico Araujo <[email protected]> * docs: add missing plugin lifecycle doc Signed-off-by: Frederico Araujo <[email protected]> * Review, rebase and lint Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Teryl Taylor <[email protected]> Signed-off-by: Frederico Araujo <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Teryl Taylor <[email protected]> Co-authored-by: Mihai Criveti <[email protected]> * feat: Experimental Oauth 2.0 support in gateway (#768) * Oauth 2.1 design Signed-off-by: Shamsul Arefin <[email protected]> * oauth 2.0 design Signed-off-by: Shamsul Arefin <[email protected]> * Support for oauth auth type in gateway Signed-off-by: Shamsul Arefin <[email protected]> * Decrypt client secret Signed-off-by: Shamsul Arefin <[email protected]> * authorization code flow, token storage, tool fetching, tool calling with Oauth2.0 Signed-off-by: Shamsul Arefin <[email protected]> * test fixes Signed-off-by: Shamsul Arefin <[email protected]> * 256 fuzz testing (#760) * Implement comprehensive fuzz testing automation (#256) - Add property-based testing with Hypothesis for JSON-RPC, JSONPath, and schema validation - Add coverage-guided fuzzing with Atheris for deep code path exploration - Add API endpoint fuzzing with Schemathesis for contract validation - Add security-focused testing for vulnerability discovery (SQL injection, XSS, etc.) - Add complete Makefile automation with fuzz-all, fuzz-quick, fuzz-extended targets - Add optional [fuzz] dependency group in pyproject.toml for clean installation - Add comprehensive reporting with JSON/Markdown outputs and executive summaries - Add complete developer documentation with examples and troubleshooting guides - Exclude fuzz tests from main test suite to prevent auth failures - Found multiple real bugs in JSON-RPC validation during development Signed-off-by: Mihai Criveti <[email protected]> * Update fuzz testing Signed-off-by: Mihai Criveti <[email protected]> * Update fuzz testing Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * 344 cors security headers (#761) * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS ADRs Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Fix compose Signed-off-by: Mihai Criveti <[email protected]> * Update helm chart Signed-off-by: Mihai Criveti <[email protected]> * Update CORS docs Signed-off-by: Mihai Criveti <[email protected]> * Update test Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> Signed-off-by: Shamsul Arefin <[email protected]> * feat: Bulk Import Tools modal wiring #737 (#739) * feat: Bulk Import Tools modal wiring and backend implementation - Add modal UI in admin.html with bulk import button and dialog - Implement modal open/close/ESC functionality in admin.js - Add POST /admin/tools/import endpoint with rate limiting - Support both JSON textarea and file upload inputs - Validate JSON structure and enforce 200 tool limit - Return detailed success/failure information per tool - Include loading states and comprehensive error handling Refs #737 Signed-off-by: Mihai Criveti <[email protected]> * fix: Remove duplicate admin_import_tools function and fix HTML formatting - Remove duplicate admin_import_tools function definition - Fix HTML placeholder attribute to use double quotes - Add missing closing div tag - Fix flake8 blank line issues Signed-off-by: Mihai Criveti <[email protected]> * feat: Complete bulk import backend with file upload support and enhanced docs - Add file upload support to admin_import_tools endpoint - Fix response format to match frontend expectations - Add UI usage documentation with modal instructions - Update API docs to show all three input methods - Enhance bulk import guide with UI and API examples Backend improvements: - Support tools_file form field for JSON file uploads - Proper file content parsing with error handling - Response includes imported/failed counts and details - Frontend-compatible response format for UI display Signed-off-by: Mihai Criveti <[email protected]> * Bulk import Signed-off-by: Mihai Criveti <[email protected]> * fix: Remove conflicting inline script and fix bulk import functionality - Remove conflicting inline JavaScript that was preventing form submission - Fix indentation in setupBulkImportModal function - Ensure bulk import modal uses proper admin.js implementation - Restore proper form submission handling for bulk import This fixes the issue where bulk import appeared to do nothing. Signed-off-by: Mihai Criveti <[email protected]> * fix: Integrate bulk import setup with main initialization - Add setupBulkImportModal() to main initialization sequence - Remove duplicate DOMContentLoaded listener - Ensure bulk import doesn't interfere with other tab functionality Signed-off-by: Mihai Criveti <[email protected]> * fix: JavaScript formatting issues in bulk import modal - Fix multiline querySelector formatting - Fix multiline Error constructor formatting - Ensure prettier compliance for web linting Signed-off-by: Mihai Criveti <[email protected]> * debug: Temporarily disable bulk import setup to test tabs Signed-off-by: Mihai Criveti <[email protected]> * fix: Remove duplicate setupFormValidation call and delay bulk import setup - Remove duplicate setupFormValidation() call that could cause conflicts - Use setTimeout to delay bulk import modal setup after other initialization - Add better null safety to form element queries - This should fix tab switching issues Signed-off-by: Mihai Criveti <[email protected]> * fix: Restore proper initialization sequence for tab functionality - Remove setTimeout delay for bulk import setup - Keep bulk import setup in main initialization but with error handling - Ensure tab navigation isn't affected by bulk import modal setup Signed-off-by: Mihai Criveti <[email protected]> * fix: Correct HTML structure and restore tab navigation - Move bulk import modal to correct location after tools panel - Remove extra closing div that was breaking HTML structure - Ensure proper page-level modal placement - Restore tab navigation functionality for all tabs This fixes the broken Global Resources, Prompts, Gateways, Roots, and Metrics tabs. Signed-off-by: Mihai Criveti <[email protected]> * feat: Add configurable bulk import settings Configuration additions: - MCPGATEWAY_BULK_IMPORT_MAX_TOOLS (default: 200) - MCPGATEWAY_BULK_IMPORT_RATE_LIMIT (default: 10) Implementation: - config.py: Add new settings with defaults - admin.py: Use configurable rate limit and batch size - .env.example: Document all bulk import environment variables - admin.html: Use dynamic max tools value in UI text - CLAUDE.md: Document configuration options for developers - docs: Update bulk import guide with configuration details This makes bulk import fully configurable for different deployment scenarios. Signed-off-by: Mihai Criveti <[email protected]> * Update docs Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Mihai Criveti <[email protected]> Signed-off-by: Shamsul Arefin <[email protected]> * Implemented configuration export (#764) Signed-off-by: Mihai Criveti <[email protected]> Signed-off-by: Shamsul Arefin <[email protected]> * cleanup Signed-off-by: Shamsul Arefin <[email protected]> * cleanup Signed-off-by: Shamsul Arefin <[email protected]> * fixes Signed-off-by: Shamsul Arefin <[email protected]> * ruff fixes Signed-off-by: Shamsul Arefin <[email protected]> * fix flake8 errors Signed-off-by: Shamsul Arefin <[email protected]> * fix eslint errors Signed-off-by: Shamsul Arefin <[email protected]> * aiohttp added in the main dependencies section of pyproject.toml Signed-off-by: Shamsul Arefin <[email protected]> * Review, rebase and lint Signed-off-by: Mihai Criveti <[email protected]> * Fix Alembic multiple heads issue Create merge migration to resolve parallel migration chains: - Main branch migrations (34492f99a0c4) - OAuth branch migrations (add_oauth_tokens_table) This resolves CI/CD test failures caused by Alembic not knowing which migration head to follow during 'alembic upgrade head'. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> * Fix Alembic migration chain - remove merge migration hack - Remove unnecessary merge migration file (813b45a70b53) - Fix OAuth config migration to follow proper chain (f8c9d3e2a1b4 → 34492f99a0c4) - OAuth tokens migration already correctly follows (add_oauth_tokens_table → f8c9d3e2a1b4) - Now single migration head without parallel branches This eliminates the 'Multiple heads are present' error in CI/CD tests by ensuring migrations follow a linear chain instead of creating parallel migration branches that need artificial merge migrations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> * Review, rebase and lint Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Shamsul Arefin <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Shamsul Arefin <[email protected]> Co-authored-by: Mihai Criveti <[email protected]> Co-authored-by: VK <[email protected]> Co-authored-by: Claude <[email protected]> * Fix pre-commit hooks Signed-off-by: Mihai Criveti <[email protected]> * 744 annotations (#784) * Fix annotations edit Signed-off-by: Mihai Criveti <[email protected]> * Fix annotations edit Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> * fix: plugins template (#783) * feat: update context forge target in template's project dependencies Signed-off-by: Frederico Araujo <[email protected]> * fix: exclude jinja files from reformatting tabs Signed-off-by: Frederico Araujo <[email protected]> * fix: plugins cli defaults Signed-off-by: Frederico Araujo <[email protected]> * fix: revert formatted Makefile template Signed-off-by: Frederico Araujo <[email protected]> * feat: add optional packages Signed-off-by: Frederico Araujo <[email protected]> * docs: update plugin template docs Signed-off-by: Frederico Araujo <[email protected]> * docs: update template readme Signed-off-by: Frederico Araujo <[email protected]> --------- Signed-off-by: Frederico Araujo <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * doc test Signed-off-by: RAKHI DUTTA <[email protected]> * edit-tool Signed-off-by: RAKHI DUTTA <[email protected]> * web lint Signed-off-by: RAKHI DUTTA <[email protected]> * flake8 fix Signed-off-by: RAKHI DUTTA <[email protected]> * pytest fix Signed-off-by: RAKHI DUTTA <[email protected]> * revert with main Signed-off-by: RAKHI DUTTA <[email protected]> * flake fix Signed-off-by: RAKHI DUTTA <[email protected]> * revert with main Signed-off-by: RAKHI DUTTA <[email protected]> * alembic Signed-off-by: RAKHI DUTTA <[email protected]> * alembic change Signed-off-by: RAKHI DUTTA <[email protected]> * flake8 fix Signed-off-by: RAKHI DUTTA <[email protected]> * remove addtional line Signed-off-by: RAKHI DUTTA <[email protected]> * alembic Signed-off-by: RAKHI DUTTA <[email protected]> * Rebase and fix Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: RAKHI DUTTA <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> Signed-off-by: Ian Molloy <[email protected]> Signed-off-by: Madhav Kandukuri <[email protected]> Signed-off-by: Vinod Muthusamy <[email protected]> Signed-off-by: Frederico Araujo <[email protected]> Signed-off-by: Vicky <[email protected]> Signed-off-by: Veeresh K <[email protected]> Signed-off-by: Shoumi <[email protected]> Signed-off-by: Mohan Lakshmaiah <[email protected]> Signed-off-by: Teryl Taylor <[email protected]> Signed-off-by: Shamsul Arefin <[email protected]> Co-authored-by: RAKHI DUTTA <[email protected]> Co-authored-by: Mihai Criveti <[email protected]> Co-authored-by: Ian Molloy <[email protected]> Co-authored-by: Madhav Kandukuri <[email protected]> Co-authored-by: Vinod Muthusamy <[email protected]> Co-authored-by: Vinod Muthusamy <[email protected]> Co-authored-by: VK <[email protected]> Co-authored-by: Frederico Araujo <[email protected]> Co-authored-by: Madhav Kandukuri <[email protected]> Co-authored-by: Vicky <[email protected]> Co-authored-by: Veeresh K <[email protected]> Co-authored-by: Shoumi M <[email protected]> Co-authored-by: Mohan Lakshmaiah <[email protected]> Co-authored-by: Mohan Lakshmaiah <[email protected]> Co-authored-by: Teryl Taylor <[email protected]> Co-authored-by: Shamsul Arefin <[email protected]> Co-authored-by: Shamsul Arefin <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent 80bbf9d commit df217a1

15 files changed

+352
-86
lines changed

mcpgateway/admin.py

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,7 +1512,7 @@ async def admin_ui(
15121512
>>> mock_tool = ToolRead(
15131513
... id="t1", name="T1", original_name="T1", url="http://t1.com", description="d",
15141514
... created_at=datetime.now(timezone.utc), updated_at=datetime.now(timezone.utc),
1515-
... enabled=True, reachable=True, gateway_slug="default", original_name_slug="t1",
1515+
... enabled=True, reachable=True, gateway_slug="default", custom_name_slug="t1",
15161516
... request_type="GET", integration_type="MCP", headers={}, input_schema={},
15171517
... annotations={}, jsonpath_filter=None, auth=None, execution_count=0,
15181518
... metrics=ToolMetrics(
@@ -1521,6 +1521,7 @@ async def admin_ui(
15211521
... avg_response_time=0.0, last_execution_time=None
15221522
... ),
15231523
... gateway_id=None,
1524+
... customName="T1",
15241525
... tags=[]
15251526
... )
15261527
>>> server_service.list_servers = AsyncMock(return_value=[mock_server])
@@ -1633,34 +1634,35 @@ async def admin_list_tools(
16331634
>>> mock_user = "test_user"
16341635
>>>
16351636
>>> # Mock tool data
1636-
>>> mock_tool = ToolRead(
1637-
... id="tool-1",
1638-
... name="Test Tool",
1639-
... original_name="TestTool",
1640-
... url="http://test.com/tool",
1641-
... description="A test tool",
1642-
... request_type="HTTP",
1643-
... integration_type="MCP",
1644-
... headers={},
1645-
... input_schema={},
1646-
... annotations={},
1647-
... jsonpath_filter=None,
1648-
... auth=None,
1649-
... created_at=datetime.now(timezone.utc),
1650-
... updated_at=datetime.now(timezone.utc),
1651-
... enabled=True,
1652-
... reachable=True,
1653-
... gateway_id=None,
1654-
... execution_count=0,
1655-
... metrics=ToolMetrics(
1656-
... total_executions=5, successful_executions=5, failed_executions=0,
1657-
... failure_rate=0.0, min_response_time=0.1, max_response_time=0.5,
1658-
... avg_response_time=0.3, last_execution_time=datetime.now(timezone.utc)
1659-
... ),
1660-
... gateway_slug="default",
1661-
... original_name_slug="test-tool",
1662-
... tags=[]
1663-
... ) # Added gateway_id=None
1637+
>>> mock_tool = ToolRead(
1638+
... id="tool-1",
1639+
... name="Test Tool",
1640+
... original_name="TestTool",
1641+
... url="http://test.com/tool",
1642+
... description="A test tool",
1643+
... request_type="HTTP",
1644+
... integration_type="MCP",
1645+
... headers={},
1646+
... input_schema={},
1647+
... annotations={},
1648+
... jsonpath_filter=None,
1649+
... auth=None,
1650+
... created_at=datetime.now(timezone.utc),
1651+
... updated_at=datetime.now(timezone.utc),
1652+
... enabled=True,
1653+
... reachable=True,
1654+
... gateway_id=None,
1655+
... execution_count=0,
1656+
... metrics=ToolMetrics(
1657+
... total_executions=5, successful_executions=5, failed_executions=0,
1658+
... failure_rate=0.0, min_response_time=0.1, max_response_time=0.5,
1659+
... avg_response_time=0.3, last_execution_time=datetime.now(timezone.utc)
1660+
... ),
1661+
... gateway_slug="default",
1662+
... custom_name_slug="test-tool",
1663+
... customName="Test Tool",
1664+
... tags=[]
1665+
... ) # Added gateway_id=None
16641666
>>>
16651667
>>> # Mock the tool_service.list_tools method
16661668
>>> original_list_tools = tool_service.list_tools
@@ -1686,7 +1688,8 @@ async def admin_list_tools(
16861688
... failure_rate=0.0, min_response_time=0.0, max_response_time=0.0,
16871689
... avg_response_time=0.0, last_execution_time=None
16881690
... ),
1689-
... gateway_slug="default", original_name_slug="inactive-tool",
1691+
... gateway_slug="default", custom_name_slug="inactive-tool",
1692+
... customName="Inactive Tool",
16901693
... tags=[]
16911694
... )
16921695
>>> tool_service.list_tools = AsyncMock(return_value=[mock_tool, mock_inactive_tool])
@@ -1772,7 +1775,8 @@ async def admin_get_tool(tool_id: str, db: Session = Depends(get_db), user: str
17721775
... failure_rate=0.0, min_response_time=0.0, max_response_time=0.0, avg_response_time=0.0,
17731776
... last_execution_time=None
17741777
... ),
1775-
... gateway_slug="default", original_name_slug="get-tool",
1778+
... gateway_slug="default", custom_name_slug="get-tool",
1779+
... customName="Get Tool",
17761780
... tags=[]
17771781
... )
17781782
>>>
@@ -2088,6 +2092,7 @@ async def admin_edit_tool(
20882092
>>> # Happy path: Edit tool successfully
20892093
>>> form_data_success = FormData([
20902094
... ("name", "Updated_Tool"),
2095+
... ("customName", "ValidToolName"),
20912096
... ("url", "http://updated.com"),
20922097
... ("requestType", "GET"),
20932098
... ("integrationType", "REST"),
@@ -2110,6 +2115,7 @@ async def admin_edit_tool(
21102115
>>> # Edge case: Edit tool with inactive checkbox checked
21112116
>>> form_data_inactive = FormData([
21122117
... ("name", "Inactive_Edit"),
2118+
... ("customName", "ValidToolName"),
21132119
... ("url", "http://inactive.com"),
21142120
... ("is_inactive_checked", "true"),
21152121
... ("requestType", "GET"),
@@ -2128,6 +2134,7 @@ async def admin_edit_tool(
21282134
>>> # Error path: Tool name conflict (simulated with IntegrityError)
21292135
>>> form_data_conflict = FormData([
21302136
... ("name", "Conflicting_Name"),
2137+
... ("customName", "Conflicting_Name"),
21312138
... ("url", "http://conflict.com"),
21322139
... ("requestType", "GET"),
21332140
... ("integrationType", "REST")
@@ -2146,6 +2153,7 @@ async def admin_edit_tool(
21462153
>>> # Error path: ToolError raised
21472154
>>> form_data_tool_error = FormData([
21482155
... ("name", "Tool_Error"),
2156+
... ("customName", "Tool_Error"),
21492157
... ("url", "http://toolerror.com"),
21502158
... ("requestType", "GET"),
21512159
... ("integrationType", "REST")
@@ -2164,6 +2172,7 @@ async def admin_edit_tool(
21642172
>>> # Error path: Pydantic Validation Error
21652173
>>> form_data_validation_error = FormData([
21662174
... ("name", "Bad_URL"),
2175+
... ("customName","Bad_Custom_Name"),
21672176
... ("url", "not-a-valid-url"),
21682177
... ("requestType", "GET"),
21692178
... ("integrationType", "REST")
@@ -2181,6 +2190,7 @@ async def admin_edit_tool(
21812190
>>> # Error path: Unexpected exception
21822191
>>> form_data_unexpected = FormData([
21832192
... ("name", "Crash_Tool"),
2193+
... ("customName", "Crash_Tool"),
21842194
... ("url", "http://crash.com"),
21852195
... ("requestType", "GET"),
21862196
... ("integrationType", "REST")
@@ -2202,13 +2212,13 @@ async def admin_edit_tool(
22022212
"""
22032213
LOGGER.debug(f"User {user} is editing tool ID {tool_id}")
22042214
form = await request.form()
2205-
22062215
# Parse tags from comma-separated string
22072216
tags_str = str(form.get("tags", ""))
22082217
tags: list[str] = [tag.strip() for tag in tags_str.split(",") if tag.strip()] if tags_str else []
22092218

22102219
tool_data: dict[str, Any] = {
22112220
"name": form.get("name"),
2221+
"custom_name": form.get("customName"),
22122222
"url": form.get("url"),
22132223
"description": form.get("description"),
22142224
"headers": json.loads(form.get("headers") or "{}"),
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""merge_a2a_and_custom_name_changes
2+
3+
Revision ID: 1fc1795f6983
4+
Revises: add_a2a_agents_and_metrics, c9dd86c0aac9
5+
Create Date: 2025-08-20 19:04:40.589538
6+
7+
"""
8+
9+
# Standard
10+
from typing import Sequence, Union
11+
12+
# revision identifiers, used by Alembic.
13+
revision: str = "1fc1795f6983"
14+
down_revision: Union[str, Sequence[str], None] = ("add_a2a_agents_and_metrics", "c9dd86c0aac9")
15+
branch_labels: Union[str, Sequence[str], None] = None
16+
depends_on: Union[str, Sequence[str], None] = None
17+
18+
19+
def upgrade() -> None:
20+
"""Upgrade schema."""
21+
22+
23+
def downgrade() -> None:
24+
"""Downgrade schema."""
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# -*- coding: utf-8 -*-
2+
"""remove original_name_slug and added custom_name
3+
4+
Revision ID: c9dd86c0aac9
5+
Revises: add_oauth_tokens_table
6+
Create Date: 2025-08-19 15:15:26.509036
7+
8+
"""
9+
10+
# Standard
11+
from typing import Sequence, Union
12+
13+
# Third-Party
14+
from alembic import op
15+
import sqlalchemy as sa
16+
17+
# revision identifiers, used by Alembic.
18+
revision: str = "c9dd86c0aac9"
19+
down_revision: Union[str, Sequence[str], None] = "add_oauth_tokens_table"
20+
branch_labels: Union[str, Sequence[str], None] = None
21+
depends_on: Union[str, Sequence[str], None] = None
22+
23+
24+
def upgrade() -> None:
25+
"""Upgrade schema."""
26+
# Remove original_name_slug column
27+
op.alter_column("tools", "original_name_slug", new_column_name="custom_name_slug")
28+
29+
# Add custom_name column
30+
op.add_column("tools", sa.Column("custom_name", sa.String(), nullable=True))
31+
op.execute("UPDATE tools SET custom_name = original_name")
32+
# ### end Alembic commands ###
33+
34+
35+
def downgrade() -> None:
36+
"""Downgrade schema."""
37+
# Remove custom_name column
38+
op.drop_column("tools", "custom_name")
39+
40+
# Add original_name_slug column back
41+
op.alter_column("tools", "custom_name_slug", new_column_name="original_name_slug")
42+
# ### end Alembic commands ###

mcpgateway/db.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,6 @@ class Tool(Base):
369369

370370
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: uuid.uuid4().hex)
371371
original_name: Mapped[str] = mapped_column(String, nullable=False)
372-
original_name_slug: Mapped[str] = mapped_column(String, nullable=False)
373372
url: Mapped[str] = mapped_column(String, nullable=True)
374373
description: Mapped[Optional[str]]
375374
integration_type: Mapped[str] = mapped_column(default="MCP")
@@ -403,6 +402,10 @@ class Tool(Base):
403402
auth_type: Mapped[Optional[str]] = mapped_column(default=None) # "basic", "bearer", or None
404403
auth_value: Mapped[Optional[str]] = mapped_column(default=None)
405404

405+
# custom_name,custom_name_slug
406+
custom_name: Mapped[Optional[str]] = mapped_column(String, nullable=False)
407+
custom_name_slug: Mapped[Optional[str]] = mapped_column(String, nullable=False)
408+
406409
# Federation relationship with a local gateway
407410
gateway_id: Mapped[Optional[str]] = mapped_column(ForeignKey("gateways.id"))
408411
# gateway_slug: Mapped[Optional[str]] = mapped_column(ForeignKey("gateways.slug"))
@@ -431,15 +434,15 @@ def name(self):
431434
if self._computed_name: # pylint: disable=no-member
432435
return self._computed_name # orm column, resolved at runtime
433436

434-
original_slug = slugify(self.original_name) # pylint: disable=no-member
437+
custom_name_slug = slugify(self.custom_name_slug) # pylint: disable=no-member
435438

436439
# Gateway present → prepend its slug and the configured separator
437440
if self.gateway_id: # pylint: disable=no-member
438441
gateway_slug = slugify(self.gateway.name) # pylint: disable=no-member
439-
return f"{gateway_slug}{settings.gateway_tool_name_separator}{original_slug}"
442+
return f"{gateway_slug}{settings.gateway_tool_name_separator}{custom_name_slug}"
440443

441444
# No gateway → only the original name slug
442-
return original_slug
445+
return custom_name_slug
443446

444447
@name.setter
445448
def name(self, value):
@@ -1123,7 +1126,7 @@ def failure_rate(self) -> float:
11231126
float: The failure rate as a value between 0 and 1.
11241127
11251128
Examples:
1126-
>>> tool = Tool(original_name="test_tool", original_name_slug="test-tool", input_schema={})
1129+
>>> tool = Tool(custom_name="test_tool", custom_name_slug="test-tool", input_schema={})
11271130
>>> tool.failure_rate # No metrics yet
11281131
0.0
11291132
>>> tool.metrics = [
@@ -1285,7 +1288,7 @@ def update_tool_names_on_gateway_update(_mapper, connection, target):
12851288
stmt = (
12861289
tools_table.update()
12871290
.where(tools_table.c.gateway_id == target.id)
1288-
.values(name=new_gateway_slug + separator + tools_table.c.original_name_slug)
1291+
.values(name=new_gateway_slug + separator + tools_table.c.custom_name_slug)
12891292
.execution_options(synchronize_session=False) # Important for bulk updates
12901293
)
12911294

@@ -1617,18 +1620,29 @@ def set_a2a_agent_slug(_mapper, _conn, target):
16171620

16181621

16191622
@event.listens_for(Tool, "before_insert")
1620-
def set_tool_name(_mapper, _conn, target):
1621-
"""Set the computed name for a Tool before insert.
1623+
@event.listens_for(Tool, "before_update")
1624+
def set_custom_name_and_slug(mapper, connection, target):
1625+
"""
1626+
Event listener to set custom_name, custom_name_slug, and name for Tool before insert/update.
1627+
1628+
- Sets custom_name to original_name if not provided.
1629+
- Calculates custom_name_slug from custom_name using slugify.
1630+
- Updates name to gateway_slug + separator + custom_name_slug.
16221631
16231632
Args:
1624-
_mapper: Mapper
1625-
_conn: Connection
1626-
target: Target Tool instance
1633+
mapper: SQLAlchemy mapper for the Tool model.
1634+
connection: Database connection.
1635+
target: The Tool instance being inserted or updated.
16271636
"""
1628-
1629-
sep = settings.gateway_tool_name_separator
1630-
gateway_slug = target.gateway.slug if target.gateway_id else ""
1637+
# Set custom_name to original_name if not provided
1638+
if not target.custom_name:
1639+
target.custom_name = target.original_name
1640+
# Always update custom_name_slug from custom_name
1641+
target.custom_name_slug = slugify(target.custom_name)
1642+
# Update name field
1643+
gateway_slug = slugify(target.gateway.name) if target.gateway else ""
16311644
if gateway_slug:
1632-
target.name = f"{gateway_slug}{sep}{slugify(target.original_name)}"
1645+
sep = settings.gateway_tool_name_separator
1646+
target.name = f"{gateway_slug}{sep}{target.custom_name_slug}"
16331647
else:
1634-
target.name = slugify(target.original_name)
1648+
target.name = target.custom_name_slug

mcpgateway/schemas.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ class ToolUpdate(BaseModelWithConfigDict):
628628
"""
629629

630630
name: Optional[str] = Field(None, description="Unique name for the tool")
631+
custom_name: Optional[str] = Field(None, description="Custom name for the tool")
631632
url: Optional[Union[str, AnyHttpUrl]] = Field(None, description="Tool endpoint URL")
632633
description: Optional[str] = Field(None, description="Tool description")
633634
integration_type: Optional[Literal["REST", "MCP", "A2A"]] = Field(None, description="Tool integration type")
@@ -668,6 +669,19 @@ def validate_name(cls, v: str) -> str:
668669
"""
669670
return SecurityValidator.validate_tool_name(v)
670671

672+
@field_validator("custom_name")
673+
@classmethod
674+
def validate_custom_name(cls, v: str) -> str:
675+
"""Ensure custom tool names follow MCP naming conventions
676+
677+
Args:
678+
v (str): Value to validate
679+
680+
Returns:
681+
str: Value if validated as safe
682+
"""
683+
return SecurityValidator.validate_tool_name(v)
684+
671685
@field_validator("url")
672686
@classmethod
673687
def validate_url(cls, v: str) -> str:
@@ -864,7 +878,8 @@ class ToolRead(BaseModelWithConfigDict):
864878
metrics: ToolMetrics
865879
name: str
866880
gateway_slug: str
867-
original_name_slug: str
881+
custom_name: str
882+
custom_name_slug: str
868883
tags: List[str] = Field(default_factory=list, description="Tags for categorizing the tool")
869884

870885
# Comprehensive metadata for audit tracking

0 commit comments

Comments
 (0)