Skip to content

refactor(api): migrate console mcp-server responses to BaseModel#35219

Open
ai-hpc wants to merge 4 commits intolanggenius:mainfrom
ai-hpc:refactor/migrate-console-mcp-server-response-28015
Open

refactor(api): migrate console mcp-server responses to BaseModel#35219
ai-hpc wants to merge 4 commits intolanggenius:mainfrom
ai-hpc:refactor/migrate-console-mcp-server-response-28015

Conversation

@ai-hpc
Copy link
Copy Markdown
Contributor

@ai-hpc ai-hpc commented Apr 14, 2026

Part of #28015

Summary

Migrate response marshalling in api/controllers/console/app/mcp_server.py from Flask-RESTX response models to Pydantic ResponseModel schemas registered with register_schema_models().

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran make lint and make type-check (backend) and cd web && pnpm exec vp staged (frontend) to appease the lint gods

@dosubot dosubot bot added size:XS This PR changes 0-9 lines, ignoring generated files. refactor labels Apr 14, 2026
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Apr 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-14 21:07:26.903769770 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-14 21:07:16.455774337 +0000
@@ -1926,6 +1926,8 @@
    --> tests/unit_tests/controllers/console/app/test_app_response_models.py:110:12
 ERROR Object of class `object` has no attribute `exec_module` [missing-attribute]
    --> tests/unit_tests/controllers/console/app/test_app_response_models.py:111:5
+ERROR Could not import `AppMCPServerResponse` from `controllers.console.app.mcp_server` [missing-module-attribute]
+ --> tests/unit_tests/controllers/console/app/test_mcp_server_response.py:3:48
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `controllers.console.app.workflow._parse_file` [bad-argument-type]
   --> tests/unit_tests/controllers/console/app/test_workflow.py:25:40
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `controllers.console.app.workflow._parse_file` [bad-argument-type]

@github-actions
Copy link
Copy Markdown
Contributor

Pyrefly Diff

No changes detected.

class MCPServerCreatePayload(BaseModel):
description: str | None = Field(default=None, description="Server description")
parameters: dict[str, Any] = Field(..., description="Server parameters configuration")
parameters: dict = Field(..., description="Server parameters configuration")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dosu is this change correct?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change looks incorrect. Changing parameters from dict[str, Any] to bare dict would be a regression — PR #35107 (merged just yesterday) specifically added the [str, Any] annotation to improve type safety [1].

The codebase convention strongly favors dict[str, Any] for flexible dictionary fields in Pydantic models (e.g., WorkflowRunPayload.inputs: dict[str, Any] [2], DatasetUpdatePayload.external_retrieval_model: dict[str, Any] | None [3]). Bare dict only appears in legacy code.

The parameters field should stay as dict[str, Any] to maintain explicit type information and consistency with the rest of the API layer.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
Chat with Dosu Open in Cursor  Share on X

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates the console MCP server controller to use Pydantic ResponseModel schemas (via register_schema_models()) instead of Flask-RESTX response models for response marshalling.

Changes:

  • Replaces MCP server request/response models with Pydantic schemas and validators for JSON normalization.
  • Updates Swagger/OpenAPI @console_ns.response(...) metadata/messages for MCP server endpoints.
  • Adjusts response field types (e.g., status as AppMCPServerStatus) and parameter normalization logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +74 to 80
)
@login_required
@account_initialization_required
@setup_required
@get_app_model
def get(self, app_model):
server = db.session.scalar(select(AppMCPServer).where(AppMCPServer.app_id == app_model.id).limit(1))
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get() no longer handles the case where no AppMCPServer row exists for the app. model_validate(None, from_attributes=True) will raise a validation error (likely resulting in a 500) instead of returning an empty config or a 404. Restore explicit handling (e.g., raise NotFound and document a 404 response, or keep the previous empty-object behavior and adjust the response schema accordingly).

Suggested change
)
@login_required
@account_initialization_required
@setup_required
@get_app_model
def get(self, app_model):
server = db.session.scalar(select(AppMCPServer).where(AppMCPServer.app_id == app_model.id).limit(1))
)
@console_ns.response(404, "MCP server configuration not found")
@login_required
@account_initialization_required
@setup_required
@get_app_model
def get(self, app_model):
server = db.session.scalar(select(AppMCPServer).where(AppMCPServer.app_id == app_model.id).limit(1))
if server is None:
raise NotFound("MCP server configuration not found")

Copilot uses AI. Check for mistakes.
Comment on lines 86 to +89
@console_ns.expect(console_ns.models[MCPServerCreatePayload.__name__])
@console_ns.response(200, "Server created", console_ns.models[AppMCPServerResponse.__name__])
@console_ns.response(
201, "MCP server configuration created successfully", console_ns.models[AppMCPServerResponse.__name__]
)
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This route is documented as returning HTTP 201, but post() currently returns only the body (which will default to 200). Return a (body, 201) tuple (or equivalent) so the runtime status code matches the declared response.

Copilot uses AI. Check for mistakes.
Comment on lines 20 to 29
class MCPServerCreatePayload(BaseModel):
description: str | None = Field(default=None, description="Server description")
parameters: dict[str, Any] = Field(..., description="Server parameters configuration")
parameters: dict = Field(..., description="Server parameters configuration")


class MCPServerUpdatePayload(BaseModel):
id: str = Field(..., description="Server ID")
description: str | None = Field(default=None, description="Server description")
parameters: dict[str, Any] = Field(..., description="Server parameters configuration")
parameters: dict = Field(..., description="Server parameters configuration")
status: str | None = Field(default=None, description="Server status")
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameters is now typed as plain dict, which loses the key/value typing used elsewhere in console payload schemas (e.g. api/controllers/console/workspace/tool_providers.py:118 and api/controllers/console/datasets/data_source.py:49 use dict[str, Any]). Consider switching back to dict[str, Any] (and re-adding the Any import) to keep typing and generated schemas consistent.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants