blob: f59b0a2184984e29f4365ad2855b1df5e5ff5b1c [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""Transport fixture for the official MCP 2026-07-28 conformance suite."""
from __future__ import annotations
import argparse
import asyncio
import json
import logging
import uvicorn
from mcp.server.stdio import stdio_server
from mcp.types import (
ClientCapabilities,
GetPromptResult,
Prompt,
Resource,
SamplingCapability,
Tool,
)
from doris_mcp_server import __version__
from doris_mcp_server.protocol import (
create_doris_mcp_server,
create_transport_security,
)
class EmptyResourcesManager:
async def list_resources(self) -> list[Resource]:
return []
async def read_resource(self, uri: str) -> str:
return json.dumps({"uri": uri})
class CapabilityToolsManager:
async def list_tools(self) -> list[Tool]:
return [
Tool(
name="test_missing_capability",
description="Exercise the required-client-capability boundary.",
input_schema={"type": "object", "properties": {}},
)
]
async def call_tool(self, name: str, arguments: dict) -> str:
del arguments
return json.dumps({"ok": True, "tool": name})
class EmptyPromptsManager:
async def list_prompts(self) -> list[Prompt]:
return []
async def get_prompt(self, name: str, arguments: dict) -> GetPromptResult:
raise ValueError(f"Unknown prompt: {name}")
def create_conformance_server():
return create_doris_mcp_server(
resources_manager=EmptyResourcesManager(),
tools_manager=CapabilityToolsManager(),
prompts_manager=EmptyPromptsManager(),
name="doris-mcp-conformance-test",
version=__version__,
logger=logging.getLogger(__name__),
required_tool_capabilities={
"test_missing_capability": ClientCapabilities(sampling=SamplingCapability())
},
)
async def run_stdio() -> None:
server = create_conformance_server()
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options(),
)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--transport", choices=("http", "stdio"), required=True)
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", default=39123, type=int)
args = parser.parse_args()
if args.transport == "stdio":
asyncio.run(run_stdio())
return
server = create_conformance_server()
app = server.streamable_http_app(
json_response=True,
stateless_http=True,
host=args.host,
transport_security=create_transport_security(args.host),
)
uvicorn.run(app, host=args.host, port=args.port, log_level="warning")
if __name__ == "__main__":
main()