[Bug] MCP provider detail endpoint returns 500 "invalid input syntax for type uuid" — server_identifier passed where a provider UUID is expected
- Dominant language
- TypeScript
- Stars
- 156k
- Forks
- 24.6k
- Avg merge
- 22h 9m
- Merged PRs (30d)
- 610
Description
### Self Checks
- [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
- [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
- [x] I confirm that I am using English to submit this report, otherwise it will be closed.
- [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
- [x] Please do not modify this template :) and fill in all the required fields.
### Dify version
1.17.0
### Cloud or Self Hosted
Self Hosted (Kubernetes)
### Steps to reproduce
1. Register an MCP tool provider (Tools → MCP → add a streamable-http server). In `tool_mcp_providers` the row gets a UUID `id` plus a human-readable `server_identifier` (e.g. `my-mcp-tools`).
2. Open the provider's detail page in the console (the view that lists its tools). The front-end calls:
```
GET /console/api/workspaces/current/tool-provider/mcp/tools/my-mcp-tools
```
i.e. the **server_identifier** is passed in the path (`web/service/use-tools.ts` → `useMCPTools(providerID)`).
3. The API returns HTTP 500.
Root cause chain (verified against the `1.17.0` tag and today's `main`):
- `api/controllers/console/workspace/tool_providers.py:1589` (`ToolMCPDetailApi.get`) calls `service.get_provider(provider_id=provider_id, tenant_id=...)` — the path segment is treated as the UUID `id`; `server_identifier` is never passed.
- `api/services/tools/mcp_tools_manage_service.py::get_provider` therefore builds `WHERE tool_mcp_providers.id = 'my-mcp-tools'::UUID`, and PostgreSQL rejects it.
- The identifier confusion originates in `api/services/tools/tools_transform_service.py:277`:
```python
response["id"] = db_provider.server_identifier if not for_list else db_provider.id
```
so non-list responses (create/update) expose the **server_identifier** as the entity `id`, which the front-end then round-trips into subsequent detail calls.
- `get_provider_entity(by_server_id=...)` in the same service already implements the intended dual-form dispatch, but `ToolMCPDetailApi` misses it.
- Sibling routes follow the same pattern (`/tool-provider/mcp/update/` via `list_provider_tools`, `/tool-provider/mcp/auth`, provider delete): all pass the path segment as `provider_id=`, so they hit the same failure once a non-UUID identifier is round-tripped.
### ✔️ Expected Behavior
`GET /console/api/workspaces/current/tool-provider/mcp/tools/{server_identifier}` returns the provider entity with its tools (as it does when a UUID `id` happens to be passed).
### ❌ Actual Behavior
HTTP 500 with:
```
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type uuid: "my-mcp-tools"
[SQL: SELECT ... FROM tool_mcp_providers
WHERE tool_mcp_providers.tenant_id = %(tenant_id_1)s::UUID AND tool_mcp_providers.id = %(id_1)s::UUID]
File "/app/api/services/tools/mcp_tools_manage_service.py", line 112, in get_provider
```
Suggested fix: dual-form dispatch in `get_provider` — when `provider_id` is not a valid UUID, fall back to the `server_identifier` branch (a single change covers detail/update/auth/delete), or apply `by_server_id=True` semantics at `ToolMCPDetailApi`.
Contributor guide
Research direction
Start with api/controllers/console/workspace/tool_providers.py, api/services/tools/mcp_tools_manage_service.py, and api/services/tools/tools_transform_service.py; trace ToolMCPDetailApi.get, get_provider, get_provider_entity, and the frontend useMCPTools(providerID) call. Reproduce the detail request with a server_identifier, then verify that detail, update, auth, and delete routes resolve it without a UUID error and preserve UUID behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, python, typescript
- Domain
- api, backend, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100