goodbye modes 2 working on it
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
from .handlers import BrokerAdminHandlers, ProxyAdminRuntime, TransparentAdminHandlers
|
||||
from .tools import register_service_admin_tools
|
||||
|
||||
__all__ = ["BrokerAdminHandlers", "ProxyAdminRuntime", "TransparentAdminHandlers"]
|
||||
__all__ = [
|
||||
"BrokerAdminHandlers",
|
||||
"ProxyAdminRuntime",
|
||||
"TransparentAdminHandlers",
|
||||
"register_service_admin_tools",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from wf_mcp.broker.service import WfMcpService
|
||||
|
||||
from .handlers.broker import BrokerAdminHandlers
|
||||
|
||||
|
||||
def register_service_admin_tools(
|
||||
server: Any,
|
||||
service: WfMcpService,
|
||||
*,
|
||||
namespace: str | None = "wf.admin",
|
||||
legacy_names: bool = False,
|
||||
include_connection_tools: bool = True,
|
||||
) -> None:
|
||||
"""Register service-backed admin/control tools on an MCP server.
|
||||
|
||||
The public server uses dotted `wf.admin.*` names. The retired broker server
|
||||
constructor still asks for bare compatibility names, so the namespace stays
|
||||
configurable while the implementation remains single-sourced.
|
||||
"""
|
||||
handlers = BrokerAdminHandlers(service)
|
||||
|
||||
legacy_name_map = {
|
||||
"read_resource": "read_broker_resource",
|
||||
"render_prompt": "render_broker_prompt",
|
||||
"invoke_method": "invoke_broker_method",
|
||||
"call_tool": "call_broker_tool",
|
||||
"get_events": "get_broker_events",
|
||||
}
|
||||
|
||||
def name(local_name: str) -> str:
|
||||
visible_name = legacy_name_map.get(local_name, local_name) if legacy_names else local_name
|
||||
return visible_name if namespace is None else f"{namespace}.{visible_name}"
|
||||
|
||||
if include_connection_tools:
|
||||
|
||||
@server.tool(
|
||||
name=name("list_connections"),
|
||||
title="List Connections",
|
||||
description="List configured MCP connections known to this server.",
|
||||
)
|
||||
async def list_connections() -> list[dict[str, Any]]:
|
||||
return handlers.list_connections()
|
||||
|
||||
@server.tool(
|
||||
name=name("get_connection_statuses"),
|
||||
title="Get Connection Statuses",
|
||||
description="Show configured MCP connection status and catalog counts.",
|
||||
)
|
||||
async def get_connection_statuses() -> list[dict[str, Any]]:
|
||||
return handlers.get_connection_statuses()
|
||||
|
||||
@server.tool(
|
||||
name=name("refresh_connection_catalog"),
|
||||
title="Refresh Connection Catalog",
|
||||
description="Refresh one connection catalog snapshot from its upstream MCP server.",
|
||||
)
|
||||
async def refresh_connection_catalog(connection_id: str) -> dict[str, Any]:
|
||||
return await handlers.refresh_connection_catalog(connection_id)
|
||||
|
||||
@server.tool(
|
||||
name=name("get_catalog"),
|
||||
title="Get Catalog",
|
||||
description="Return the current upstream MCP capability catalog.",
|
||||
)
|
||||
async def get_catalog() -> dict[str, Any]:
|
||||
return handlers.get_catalog()
|
||||
|
||||
@server.tool(
|
||||
name=name("get_planner_catalog"),
|
||||
title="Get Planner Catalog",
|
||||
description="Return the planner catalog including local workflow sources.",
|
||||
)
|
||||
async def get_planner_catalog() -> dict[str, Any]:
|
||||
return handlers.get_planner_catalog()
|
||||
|
||||
@server.tool(
|
||||
name=name("list_spec_sources"),
|
||||
title="List Spec Sources",
|
||||
description="List planner-visible sources that currently provide node specs.",
|
||||
)
|
||||
async def list_spec_sources() -> list[dict[str, Any]]:
|
||||
return handlers.list_spec_sources()
|
||||
|
||||
@server.tool(
|
||||
name=name("list_sources"),
|
||||
title="List Sources",
|
||||
description="List configured capability sources and what each source owns.",
|
||||
)
|
||||
async def list_sources() -> list[dict[str, Any]]:
|
||||
return handlers.list_sources()
|
||||
|
||||
@server.tool(
|
||||
name=name("read_resource"),
|
||||
title="Read Resource",
|
||||
description="Read a broker-catalog resource by qualified name.",
|
||||
)
|
||||
async def read_resource(qualified_name: str) -> dict[str, Any]:
|
||||
return await handlers.read_broker_resource(qualified_name)
|
||||
|
||||
@server.tool(
|
||||
name=name("render_prompt"),
|
||||
title="Render Prompt",
|
||||
description="Render a broker-catalog prompt by qualified name.",
|
||||
)
|
||||
async def render_prompt(
|
||||
qualified_name: str,
|
||||
arguments: dict[str, str] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return await handlers.render_broker_prompt(
|
||||
qualified_name,
|
||||
arguments=arguments,
|
||||
)
|
||||
|
||||
@server.tool(
|
||||
name=name("invoke_method"),
|
||||
title="Invoke Method",
|
||||
description="Invoke a raw MCP method on one configured connection.",
|
||||
)
|
||||
async def invoke_method(
|
||||
connection_id: str,
|
||||
method: str,
|
||||
params: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return await handlers.invoke_broker_method(
|
||||
connection_id,
|
||||
method,
|
||||
params=params,
|
||||
)
|
||||
|
||||
@server.tool(
|
||||
name=name("call_tool"),
|
||||
title="Call Tool",
|
||||
description="Call one upstream MCP tool through the broker service layer.",
|
||||
)
|
||||
async def call_tool(
|
||||
connection_id: str,
|
||||
tool_name: str,
|
||||
arguments: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return await handlers.call_broker_tool(
|
||||
connection_id,
|
||||
tool_name,
|
||||
arguments=arguments,
|
||||
)
|
||||
|
||||
@server.tool(
|
||||
name=name("get_events"),
|
||||
title="Get Events",
|
||||
description="Return locally recorded broker/platform events.",
|
||||
)
|
||||
async def get_events() -> list[dict[str, Any]]:
|
||||
return handlers.get_broker_events()
|
||||
@@ -1,79 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
from ..admin_surface import BrokerAdminHandlers
|
||||
from ..admin_surface import register_service_admin_tools
|
||||
from .service import WfMcpService
|
||||
|
||||
|
||||
def register_broker_tools(server: FastMCP, service: WfMcpService) -> None:
|
||||
"""Register broker tool handlers on a FastMCP server."""
|
||||
handlers = BrokerAdminHandlers(service)
|
||||
|
||||
# These MCP tool names are compatibility exports. Their capability metadata
|
||||
# belongs to the wf.admin source; future admin-enabled servers can project
|
||||
# dotted wf.admin.* names from that source.
|
||||
@server.tool()
|
||||
async def list_connections() -> list[dict[str, Any]]:
|
||||
return handlers.list_connections()
|
||||
|
||||
@server.tool()
|
||||
async def get_connection_statuses() -> list[dict[str, Any]]:
|
||||
return handlers.get_connection_statuses()
|
||||
|
||||
@server.tool()
|
||||
async def refresh_connection_catalog(connection_id: str) -> dict[str, Any]:
|
||||
return await handlers.refresh_connection_catalog(connection_id)
|
||||
|
||||
@server.tool()
|
||||
async def get_catalog() -> dict[str, Any]:
|
||||
return handlers.get_catalog()
|
||||
|
||||
@server.tool()
|
||||
async def get_planner_catalog() -> dict[str, Any]:
|
||||
return handlers.get_planner_catalog()
|
||||
|
||||
@server.tool()
|
||||
async def list_spec_sources() -> list[dict[str, Any]]:
|
||||
return handlers.list_spec_sources()
|
||||
|
||||
@server.tool()
|
||||
async def list_sources() -> list[dict[str, Any]]:
|
||||
return handlers.list_sources()
|
||||
|
||||
@server.tool()
|
||||
async def read_broker_resource(qualified_name: str) -> dict[str, Any]:
|
||||
return await handlers.read_broker_resource(qualified_name)
|
||||
|
||||
@server.tool()
|
||||
async def render_broker_prompt(
|
||||
qualified_name: str,
|
||||
arguments: dict[str, str] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return await handlers.render_broker_prompt(qualified_name, arguments=arguments)
|
||||
|
||||
@server.tool()
|
||||
async def invoke_broker_method(
|
||||
connection_id: str,
|
||||
method: str,
|
||||
params: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return await handlers.invoke_broker_method(connection_id, method, params=params)
|
||||
|
||||
@server.tool()
|
||||
async def call_broker_tool(
|
||||
connection_id: str,
|
||||
tool_name: str,
|
||||
arguments: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return await handlers.call_broker_tool(
|
||||
connection_id,
|
||||
tool_name,
|
||||
arguments=arguments,
|
||||
)
|
||||
|
||||
@server.tool()
|
||||
async def get_broker_events() -> list[dict[str, Any]]:
|
||||
return handlers.get_broker_events()
|
||||
"""Register legacy bare-name broker tools from the shared admin registrar."""
|
||||
register_service_admin_tools(
|
||||
server,
|
||||
service,
|
||||
namespace=None,
|
||||
legacy_names=True,
|
||||
)
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ from .broker import (
|
||||
build_service_from_config,
|
||||
load_broker_config,
|
||||
)
|
||||
from .server import run_unified_proxy_server
|
||||
from .server import run_server
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
@@ -115,7 +115,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
|
||||
if args.command == "serve":
|
||||
config = load_broker_config(args.config)
|
||||
run_unified_proxy_server(
|
||||
run_server(
|
||||
config,
|
||||
args.transport,
|
||||
config_path=args.config,
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
from .unified import (
|
||||
create_unified_proxy_client,
|
||||
create_unified_proxy_server,
|
||||
run_unified_proxy_server,
|
||||
)
|
||||
from .core import create_server, create_server_client, run_server
|
||||
|
||||
__all__ = [
|
||||
"create_unified_proxy_client",
|
||||
"create_unified_proxy_server",
|
||||
"run_unified_proxy_server",
|
||||
"create_server",
|
||||
"create_server_client",
|
||||
"run_server",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.client import Client
|
||||
from fastmcp.client.transports.memory import FastMCPTransport
|
||||
|
||||
from ..admin_surface import register_service_admin_tools
|
||||
from ..broker.config import build_service_from_config
|
||||
from ..broker.transport import normalize_transport
|
||||
from ..models import BrokerConfig
|
||||
from ..transparent_proxy.runtime import ProxyRuntime
|
||||
from ..workflow_surface import register_workflow_tools
|
||||
|
||||
|
||||
def create_server(
|
||||
config: BrokerConfig,
|
||||
*,
|
||||
config_path: str | Path | None = None,
|
||||
resources_as_tools: bool = False,
|
||||
prompts_as_tools: bool = False,
|
||||
search_tools: bool = False,
|
||||
admin_tools: bool = True,
|
||||
) -> FastMCP[Any]:
|
||||
"""Create the public MCP server with proxy, admin, and workflow tools."""
|
||||
service = build_service_from_config(config)
|
||||
runtime = ProxyRuntime(
|
||||
config,
|
||||
config_path=config_path,
|
||||
resources_as_tools=resources_as_tools,
|
||||
prompts_as_tools=prompts_as_tools,
|
||||
search_tools=search_tools,
|
||||
admin_tools=admin_tools,
|
||||
event_bus=service.event_bus,
|
||||
)
|
||||
if admin_tools:
|
||||
register_service_admin_tools(
|
||||
runtime.server,
|
||||
service,
|
||||
include_connection_tools=False,
|
||||
)
|
||||
register_workflow_tools(runtime.server, service)
|
||||
return runtime.server
|
||||
|
||||
|
||||
def run_server(
|
||||
config: BrokerConfig,
|
||||
transport: str = "stdio",
|
||||
*,
|
||||
config_path: str | Path | None = None,
|
||||
resources_as_tools: bool = False,
|
||||
prompts_as_tools: bool = False,
|
||||
search_tools: bool = False,
|
||||
admin_tools: bool = True,
|
||||
) -> None:
|
||||
server = create_server(
|
||||
config,
|
||||
config_path=config_path,
|
||||
resources_as_tools=resources_as_tools,
|
||||
prompts_as_tools=prompts_as_tools,
|
||||
search_tools=search_tools,
|
||||
admin_tools=admin_tools,
|
||||
)
|
||||
server.run(transport=normalize_transport(transport), show_banner=False)
|
||||
|
||||
|
||||
def create_server_client(
|
||||
config: BrokerConfig,
|
||||
*,
|
||||
config_path: str | Path | None = None,
|
||||
resources_as_tools: bool = False,
|
||||
prompts_as_tools: bool = False,
|
||||
search_tools: bool = False,
|
||||
admin_tools: bool = True,
|
||||
) -> Client[FastMCPTransport]:
|
||||
return Client(
|
||||
FastMCPTransport(
|
||||
create_server(
|
||||
config,
|
||||
config_path=config_path,
|
||||
resources_as_tools=resources_as_tools,
|
||||
prompts_as_tools=prompts_as_tools,
|
||||
search_tools=search_tools,
|
||||
admin_tools=admin_tools,
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -1,3 +1,4 @@
|
||||
from .handlers import WorkflowSurfaceHandlers
|
||||
from .tools import register_workflow_tools
|
||||
|
||||
__all__ = ["WorkflowSurfaceHandlers"]
|
||||
__all__ = ["WorkflowSurfaceHandlers", "register_workflow_tools"]
|
||||
|
||||
@@ -1,92 +1,17 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.client import Client
|
||||
from fastmcp.client.transports.memory import FastMCPTransport
|
||||
|
||||
from ..broker.config import build_service_from_config
|
||||
from ..broker.transport import normalize_transport
|
||||
from ..models import BrokerConfig
|
||||
from ..transparent_proxy.runtime import ProxyRuntime
|
||||
from ..workflow_surface import WorkflowSurfaceHandlers
|
||||
from wf_mcp.broker.service import WfMcpService
|
||||
|
||||
from .handlers import WorkflowSurfaceHandlers
|
||||
|
||||
|
||||
def create_unified_proxy_server(
|
||||
config: BrokerConfig,
|
||||
*,
|
||||
config_path: str | Path | None = None,
|
||||
resources_as_tools: bool = False,
|
||||
prompts_as_tools: bool = False,
|
||||
search_tools: bool = False,
|
||||
admin_tools: bool = True,
|
||||
) -> FastMCP[Any]:
|
||||
"""Create one MCP server with upstream proxy, admin, and workflow tools."""
|
||||
service = build_service_from_config(config)
|
||||
runtime = ProxyRuntime(
|
||||
config,
|
||||
config_path=config_path,
|
||||
resources_as_tools=resources_as_tools,
|
||||
prompts_as_tools=prompts_as_tools,
|
||||
search_tools=search_tools,
|
||||
admin_tools=admin_tools,
|
||||
event_bus=service.event_bus,
|
||||
)
|
||||
_register_workflow_tools(runtime.server, WorkflowSurfaceHandlers(service))
|
||||
return runtime.server
|
||||
|
||||
|
||||
def run_unified_proxy_server(
|
||||
config: BrokerConfig,
|
||||
transport: str = "stdio",
|
||||
*,
|
||||
config_path: str | Path | None = None,
|
||||
resources_as_tools: bool = False,
|
||||
prompts_as_tools: bool = False,
|
||||
search_tools: bool = False,
|
||||
admin_tools: bool = True,
|
||||
) -> None:
|
||||
server = create_unified_proxy_server(
|
||||
config,
|
||||
config_path=config_path,
|
||||
resources_as_tools=resources_as_tools,
|
||||
prompts_as_tools=prompts_as_tools,
|
||||
search_tools=search_tools,
|
||||
admin_tools=admin_tools,
|
||||
)
|
||||
server.run(transport=normalize_transport(transport), show_banner=False)
|
||||
|
||||
|
||||
def create_unified_proxy_client(
|
||||
config: BrokerConfig,
|
||||
*,
|
||||
config_path: str | Path | None = None,
|
||||
resources_as_tools: bool = False,
|
||||
prompts_as_tools: bool = False,
|
||||
search_tools: bool = False,
|
||||
admin_tools: bool = True,
|
||||
) -> Client[FastMCPTransport]:
|
||||
return Client(
|
||||
FastMCPTransport(
|
||||
create_unified_proxy_server(
|
||||
config,
|
||||
config_path=config_path,
|
||||
resources_as_tools=resources_as_tools,
|
||||
prompts_as_tools=prompts_as_tools,
|
||||
search_tools=search_tools,
|
||||
admin_tools=admin_tools,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _register_workflow_tools(
|
||||
server: FastMCP[Any],
|
||||
handlers: WorkflowSurfaceHandlers,
|
||||
) -> None:
|
||||
"""Register stable workflow tools on the unified MCP surface."""
|
||||
def register_workflow_tools(server: FastMCP[Any], service: WfMcpService) -> None:
|
||||
"""Register stable workflow tools on the public MCP server surface."""
|
||||
handlers = WorkflowSurfaceHandlers(service)
|
||||
|
||||
@server.tool(
|
||||
name="wf.workflow.list_artifacts",
|
||||
@@ -107,9 +32,7 @@ def _register_workflow_tools(
|
||||
@server.tool(
|
||||
name="wf.workflow.create_artifact_from_plan",
|
||||
title="Create Workflow Artifact From Plan",
|
||||
description=(
|
||||
"Validate a raw workflow plan and save it as a versioned artifact."
|
||||
),
|
||||
description="Validate a raw workflow plan and save it as a versioned artifact.",
|
||||
)
|
||||
async def create_artifact_from_plan(
|
||||
artifact_id: str,
|
||||
@@ -137,10 +60,7 @@ def _register_workflow_tools(
|
||||
title="Inspect Workflow Artifact",
|
||||
description="Return the full saved artifact for artifact_id and version.",
|
||||
)
|
||||
async def inspect_artifact(
|
||||
artifact_id: str,
|
||||
version: int,
|
||||
) -> dict[str, Any]:
|
||||
async def inspect_artifact(artifact_id: str, version: int) -> dict[str, Any]:
|
||||
return await handlers.inspect_artifact(
|
||||
artifact_id=artifact_id,
|
||||
version=version,
|
||||
@@ -165,9 +85,7 @@ def _register_workflow_tools(
|
||||
@server.tool(
|
||||
name="wf.workflow.validate_deployment",
|
||||
title="Validate Workflow Deployment",
|
||||
description=(
|
||||
"Check whether a deployment_id can run with currently enabled sources."
|
||||
),
|
||||
description="Check whether a deployment_id can run with currently enabled sources.",
|
||||
)
|
||||
async def validate_deployment(deployment_id: str) -> dict[str, Any]:
|
||||
return await handlers.validate_deployment(deployment_id=deployment_id)
|
||||
Reference in New Issue
Block a user