90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
from collections.abc import Sequence
|
||
from typing import Any
|
||
|
||
from django.conf import settings
|
||
from mcp.server import MCPServer
|
||
from mcp.server.auth.middleware.auth_context import AuthContextMiddleware
|
||
from mcp.server.auth.middleware.bearer_auth import (
|
||
BearerAuthBackend,
|
||
)
|
||
from mcp.server.auth.provider import TokenVerifier
|
||
from mcp.server.transport_security import TransportSecuritySettings
|
||
from starlette.middleware.authentication import AuthenticationMiddleware
|
||
from starlette.types import ASGIApp
|
||
|
||
from mcp_server.auth import (
|
||
FactoryJWTVerifier,
|
||
RequireFactoryJWTMiddleware,
|
||
)
|
||
from mcp_server.context import authenticated_user_claims
|
||
from mcp_server.tools.batch_stats import register_batch_stat_tools
|
||
from mcp_server.tools.datasets import register_dataset_tools
|
||
from mcp_server.tools.wprs import register_wpr_tools
|
||
|
||
|
||
PROTOCOL_REVISION = "2026-07-28"
|
||
|
||
mcp = MCPServer(
|
||
name="factory",
|
||
title="Factory MCP",
|
||
description="Factory 面向 Agent 的受控业务能力入口。",
|
||
instructions="所有工具均使用当前请求携带的 Factory JWT 身份执行。",
|
||
version=settings.SYS_VERSION,
|
||
)
|
||
|
||
|
||
@mcp.tool()
|
||
def factory_server_info() -> dict[str, Any]:
|
||
"""返回 Factory MCP 服务版本及协议基础信息。"""
|
||
return {
|
||
"name": "factory",
|
||
"system_version": settings.SYS_VERSION,
|
||
"protocol_revision": PROTOCOL_REVISION,
|
||
"authentication": "factory_jwt",
|
||
"domain_tools_ready": True,
|
||
}
|
||
|
||
|
||
@mcp.tool()
|
||
def factory_whoami() -> dict[str, Any]:
|
||
"""返回当前 Factory JWT 对应的用户身份。"""
|
||
return authenticated_user_claims()
|
||
|
||
|
||
register_dataset_tools(mcp)
|
||
register_wpr_tools(mcp)
|
||
register_batch_stat_tools(mcp)
|
||
|
||
|
||
def create_app(
|
||
*,
|
||
allowed_hosts: Sequence[str] | None = None,
|
||
allowed_origins: Sequence[str] | None = None,
|
||
token_verifier: TokenVerifier | None = None,
|
||
) -> ASGIApp:
|
||
"""创建仅接受 Factory JWT 的 MCP v2 Streamable HTTP 应用。"""
|
||
transport_security = TransportSecuritySettings(
|
||
enable_dns_rebinding_protection=True,
|
||
allowed_hosts=list(settings.MCP_ALLOWED_HOSTS if allowed_hosts is None else allowed_hosts),
|
||
allowed_origins=list(settings.MCP_ALLOWED_ORIGINS if allowed_origins is None else allowed_origins),
|
||
)
|
||
app: ASGIApp = mcp.streamable_http_app(
|
||
streamable_http_path=settings.MCP_PATH,
|
||
json_response=True,
|
||
max_request_body_size=settings.MCP_MAX_REQUEST_BODY_SIZE,
|
||
transport_security=transport_security,
|
||
host=settings.MCP_HOST,
|
||
)
|
||
|
||
# 包装顺序保证先解析 Bearer JWT,再写入 MCP 请求上下文,最后强制认证。
|
||
app = RequireFactoryJWTMiddleware(app)
|
||
app = AuthContextMiddleware(app)
|
||
app = AuthenticationMiddleware(
|
||
app,
|
||
backend=BearerAuthBackend(token_verifier or FactoryJWTVerifier()),
|
||
)
|
||
return app
|
||
|
||
|
||
application = create_app()
|