Skip to content

Conversation

@madhav165
Copy link
Collaborator

@madhav165 madhav165 commented Jun 22, 2025

✨ Feature / Enhancement PR

πŸ”— Epic / Issue

Closes #116
Makes progress on #135


πŸš€ Summary (1–2 sentences)

  • Allow tools with same names coming from different gateways to be added separately
  • Refresh tool list from gateway after Activate/Deactivate cycle or Edit Gateway action
  • Use drop downs to select tools in server creation and editing screens

Updated tool names

Tool selection screen


πŸ§ͺ Checks

  • make ruff passes
  • make bandit passes
  • make lint passes
  • make test passes
  • CHANGELOG updated (if user-facing)

πŸ““ ADRs

Refer to the ADRs for detailed changes.

  • Tool federation - docs/docs/architecture/adr/011-tool-federation.md
  • Drop down for tool selection in servers - docs/docs/architecture/adr/012-dropdown-ui-tool-selection.md

Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
@madhav165 madhav165 self-assigned this Jun 22, 2025
@madhav165 madhav165 requested a review from crivetimihai as a code owner June 22, 2025 17:55
@madhav165 madhav165 added enhancement New feature or request frontend Frontend development (HTML, CSS, JavaScript) python Python / backend development (FastAPI) labels Jun 22, 2025
@madhav165 madhav165 linked an issue Jun 22, 2025 that may be closed by this pull request
3 tasks
@crivetimihai
Copy link
Member

crivetimihai commented Jun 23, 2025

Awesome PR, but needs a bit more testing / fixes to merge. See:

Linting and smoketest: pass

βœ”οΈ make jsonlint yamllint tomllint ruff flake8
βœ”οΈ make smoketest

Running in docker with SSL on host

βœ”οΈ make docker-prod docker-run-ssl-host

curl -k https://localhost:4444/health` # {"status":"healthy"}
export MCPGATEWAY_BEARER_TOKEN=$(python3 -m mcpgateway.utils.create_jwt_token --username admin --exp 0 --secret my-test-key)
curl -sk -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" https://localhost:4444/version | jq '.uptime_seconds' # 211

βœ”οΈ https://localhost:4444/admin/ - all tabs work
βœ”οΈhttps://localhost:4444/version - works and shows correct data, correctly requires auth when not going through front page
βœ”οΈhttps://localhost:4444/redoc https://localhost:4444/docs API docs pages load AFTER auth
βœ”οΈmake docker-logs # shows no errors

❌ Adding a server according to README.md

npx -y supergateway --stdio "uvenv run mcp_server_time -- --local-timezone=Europe/Dublin" --port 8003 &
❌ curl -s -X POST -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"name":"local_time","url":"http://localhost:8003/sse"}' \
     https://localhost:4444/gateways

❌ Error in logs:

INFO:httpx:HTTP Request: POST http://localhost:8003/message?sessionId=0934e914-e707-4260-8493-fc76b97fbff9 "HTTP/1.1 202 Accepted"
ERROR:mcpgateway.services.gateway_service:Other grouped errors: (NameError("name 'unicode' is not defined"),)
127.0.0.1:50766 - "POST /admin/gateways HTTP/1.1" 500

Running in docker compose with Postgres and Redis

❌ make compose-up # after I changed gateway image to: mcpgateway/mcpgateway:latest (from previous make docker-prod) - database migration (alembic) does not exist so my old database won't work.

curl -sk -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" http://localhost:4444/version  | jq -c '.database, .redis'
# {"dialect":"postgresql","url":"postgresql://postgres@postgres:5432/mcp","reachable":true,"server_version":"17.5 (Debian 17.5-1.pgdg120+1)"}
# {"available":true,"url":"redis://redis:6379/0","reachable":true,"server_version":"8.0.1"}

❌ http://localhost:4444/
βœ— make compose-logs 
gateway-1     | sqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedColumn) column tools.original_name does not exist
gateway-1     | LINE 1: SELECT tools.id, tools.original_name, tools.url, tools.descr...

❌ This seems to require cleanup of previous db but is still incompatible with postgresql:

make compose-down compose-rm; docker volume rm mcp-context-forge_pgdata

gateway-1     |   File "/app/.venv/lib64/python3.11/site-packages/sqlalchemy/engine/base.py", line 1963, in _exec_single_context                                                                                  gateway-1     |     self.dialect.do_execute(                                                                                                                                                                      gateway-1     |   File "/app/.venv/lib64/python3.11/site-packages/sqlalchemy/engine/default.py", line 943, in do_execute                                                                                          gateway-1     |     cursor.execute(statement, parameters)                                                                                                                                                         gateway-1     | psycopg2.errors.DatatypeMismatch: foreign key constraint "server_metrics_server_id_fkey" cannot be implemented                                                                                    gateway-1     | DETAIL:  Key columns "server_id" and "id" are of incompatible types: integer and character varying.        

Key columns "server_id" and "id" are of incompatible types: integer and character varying

This suggests that the constraints only work with sqlite (or perhaps sqlite doesn't try to enforce them)

❌ make test fails - unit testing for test_gateway_service.py, test_server_service.py, test_tool_service.py, test_admin.py, test_main.py, test_schemas.py, test_ui_version.py:

FAILED tests/unit/mcpgateway/services/test_gateway_service.py::TestGatewayService::test_update_gateway_name_conflict - assert 'Gateway already exists with name' in "Failed to update gateway: Class 'unittest.mock.MagicMock' is not mapped"
FAILED tests/unit/mcpgateway/services/test_server_service.py::TestServerService::test_register_server - pydantic_core._pydantic_core.ValidationError: 2 validation errors for ServerRead
FAILED tests/unit/mcpgateway/services/test_server_service.py::TestServerService::test_list_servers - pydantic_core._pydantic_core.ValidationError: 2 validation errors for ServerRead
FAILED tests/unit/mcpgateway/services/test_server_service.py::TestServerService::test_get_server - pydantic_core._pydantic_core.ValidationError: 2 validation errors for ServerRead
FAILED tests/unit/mcpgateway/services/test_server_service.py::TestServerService::test_update_server - pydantic_core._pydantic_core.ValidationError: 2 validation errors for ServerRead
FAILED tests/unit/mcpgateway/services/test_server_service.py::TestServerService::test_toggle_server_status - pydantic_core._pydantic_core.ValidationError: 2 validation errors for ServerRead
FAILED tests/unit/mcpgateway/services/test_tool_service.py::TestToolService::test_register_tool - pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolRead
FAILED tests/unit/mcpgateway/services/test_tool_service.py::TestToolService::test_list_tools - pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolRead
FAILED tests/unit/mcpgateway/services/test_tool_service.py::TestToolService::test_get_tool - pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolRead
FAILED tests/unit/mcpgateway/services/test_tool_service.py::TestToolService::test_toggle_tool_status - pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolRead
FAILED tests/unit/mcpgateway/services/test_tool_service.py::TestToolService::test_update_tool - pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolRead
FAILED tests/unit/mcpgateway/test_admin.py::TestAdminServerRoutes::test_admin_get_server - AssertionError: assert <MagicMock na...601517212064'> == {'id': 1, 'name': 'Server 1'}
FAILED tests/unit/mcpgateway/test_admin.py::TestAdminServerRoutes::test_admin_add_server - AssertionError: Expected 'register_server' to have been called once. Called 0 times.
FAILED tests/unit/mcpgateway/test_admin.py::TestAdminServerRoutes::test_admin_edit_server - AssertionError: Expected 'update_server' to have been called once. Called 0 times.
FAILED tests/unit/mcpgateway/test_admin.py::TestAdminToolRoutes::test_admin_get_tool - AssertionError: assert <MagicMock na...601518376672'> == {'id': 1, 'name': 'Tool 1'}
FAILED tests/unit/mcpgateway/test_main.py::TestAPIEndpoints::test_list_servers_endpoint - pydantic_core._pydantic_core.ValidationError: 2 validation errors for ServerRead
FAILED tests/unit/mcpgateway/test_main.py::TestAPIEndpoints::test_rpc_tool_invocation - AssertionError: expected call not found.
FAILED tests/unit/mcpgateway/test_schemas.py::TestServerSchemas::test_server_read - pydantic_core._pydantic_core.ValidationError: 4 validation errors for ServerRead
FAILED tests/unit/mcpgateway/test_ui_version.py::test_admin_ui_contains_version_tab - sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: tools.original_name

I think the code change significantly enough to require updates to the unit tests as well.

Thanks!

@madhav165
Copy link
Collaborator Author

@crivetimihai Thanks for the detailed notes. Working on them.

Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
@madhav165 madhav165 marked this pull request as draft June 23, 2025 08:55
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
@madhav165
Copy link
Collaborator Author

@crivetimihai Code has been fixed. Will update the test cases to match the current datatypes and make the PR ready for review.

madhav165 and others added 4 commits June 24, 2025 14:56
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
madhav165 added 12 commits June 26, 2025 11:33
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
@crivetimihai
Copy link
Member

crivetimihai commented Jun 26, 2025

@madhav165 drafted but not tested #184 - we should probably merge that one FIRST, then this after rebase / db migration?

Note: As we start to get closer to a 'stable release' and lift the 'Development Status :: 4 - Beta' tag - we'll include changelog notes and documentation on Alembic schema migrations, etc. for breaking changes. We may also consider releasing the configuration Export feature prior (perhaps 0.2.1 - 2025-07-01) to give folks a way to export configs before breaking DB changes - drafted #185.

Let's talk tomorrow.

crivetimihai and others added 5 commits June 27, 2025 07:51
Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
@crivetimihai
Copy link
Member

I think we're in good enough shape to merge:

PR Test Matrix

Automated Checks

  • All checks pass

CLI / Make

  • make test β€” 333/333 pass with a old SQLite db
  • make test β€” 333/333 pass with a new SQLite db
  • make smoketest # fixed by changing test to include gateway slug
  • make docker-prod docker-run-ssl-host # or podman-.. then run some manual tests..
curl -sk https://localhost:4444/health
curl -sk https://localhost:4444/ready
export MCPGATEWAY_BEARER_TOKEN=$(python3 -m mcpgateway.utils.create_jwt_token --username admin --exp 0 --secret my-test-key)
curl -sk -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" https://localhost:4444/version
  • make dist verify
  • make devpi-install devpi-init devpi-start devpi-setup-user devpi-upload devpi-test

Admin UI & API

  • Visit:
  • /admin/, /redoc/, /docs, /version
  • Add time MCP Server to Registry :
docker run -p 8080:8080 --rm -it ghcr.io/ibm/fast-time-server:0.2.0
# or cd mcp-servers/go/fast-time-server; make build ...
  • Tools: Global Tools > get_current_time
  • Virtual Server: tooltip/checkbox for multiple tool select
  • Click all tabs
  • Gateway toggle (deactivate/reactivate)
  • Tool call: get_current_time
curl -sk -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" https://localhost:4444/version
curl -sk -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" https://localhost:4444/tools

Docker Compose (test with Postgres and Redis) with OLD database (migration)

  • Change to image: mcpgateway/mcpgateway:latest in docker-compose.yml && make compose-up

Keep your old PostgreSQL volume to test the migration

make compose-stop compose-rm
make compose-up compose-logs

[X] Docker Compose (test with Postgres and Redis) with NEW database

docker volume rm mcp-context-forge_pgdata
make compose-stop compose-rm
make compose-up compose-logs

πŸ§ͺ Other tests

  • mcpgateway.translate works (only did basic start test)
  • mcpgateway.wrapper stdio works
  • prompt/resource templates work
  • root-level SSE / subscriptions work
  • SSE Connection from Copilot
  • Streamable HTTP connection test from Copilot or Claude
  • mcpgateway.translate
  • prompt/resource templates (advanced)
  • root-level SSE / subscriptions

- [X] Helm Chart

  • Helm rollout works with PostgreSQL migration (new db)

Not tested: upgrade

Issues to solve after PR merge

image

@crivetimihai crivetimihai merged commit 86804bb into main Jun 27, 2025
22 of 23 checks passed
@crivetimihai crivetimihai deleted the tool-federation branch June 27, 2025 14:20
vk-playground pushed a commit to vk-playground/mcp-context-forge that referenced this pull request Sep 14, 2025
Fix tool federation, tool refresh and provide dropdown for tools

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
vk-playground pushed a commit to vk-playground/mcp-context-forge that referenced this pull request Sep 14, 2025
Fix tool federation, tool refresh and provide dropdown for tools
vk-playground pushed a commit to vk-playground/mcp-context-forge that referenced this pull request Sep 16, 2025
Fix tool federation, tool refresh and provide dropdown for tools
Signed-off-by: Vicky Kuo <vicky.kuo@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request frontend Frontend development (HTML, CSS, JavaScript) python Python / backend development (FastAPI)

Projects

None yet

3 participants