goodbye modes 1
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# MCP Protocol Proxy Inventory
|
||||
|
||||
This document records observed behavior of `wf-mcp` unified mode against real
|
||||
This document records observed behavior of the `wf-mcp` server against real
|
||||
upstream MCP servers. It is not a design spec. It is a fact log for deciding
|
||||
which proxy features need explicit implementation.
|
||||
|
||||
@@ -23,7 +23,7 @@ everything.default
|
||||
Proxy mode:
|
||||
|
||||
```text
|
||||
wf-mcp serve --mode unified
|
||||
wf-mcp serve
|
||||
```
|
||||
|
||||
### Working
|
||||
|
||||
@@ -49,7 +49,7 @@ Remove the public `serve --mode broker` and `serve --mode proxy` choices.
|
||||
|
||||
After this pass:
|
||||
|
||||
- `wf-mcp serve` runs the unified surface
|
||||
- `wf-mcp serve` runs the server surface
|
||||
- users no longer choose among three product modes
|
||||
- docs should describe one server behavior, not a mode matrix
|
||||
|
||||
@@ -76,7 +76,7 @@ These packages still represent useful implementation boundaries:
|
||||
- `wf_mcp.server`
|
||||
|
||||
`transparent_proxy` is already partly a legacy package name, but the code inside
|
||||
it still owns real proxy-mounting mechanics used by unified mode. Rename or
|
||||
it still owns real proxy-mounting mechanics used by the server. Rename or
|
||||
re-home that code only as a later cleanup if the package name becomes a real
|
||||
source of confusion.
|
||||
|
||||
|
||||
@@ -101,11 +101,12 @@ The current practical proxy roadmap, including which FastMCP gaps are worth
|
||||
working around locally and which should stay upstream-dependent for now, lives
|
||||
in [`wf_mcp_proxy_reality_and_roadmap.md`](wf_mcp_proxy_reality_and_roadmap.md).
|
||||
|
||||
The public MCP mode split is now being retired. The current execution plan is
|
||||
The public MCP mode split has been retired. The execution plan is
|
||||
[`superpowers/plans/2026-05-16-retire-legacy-mcp-modes.md`](superpowers/plans/2026-05-16-retire-legacy-mcp-modes.md):
|
||||
`broker` and `proxy` are legacy public launch surfaces, while unified behavior
|
||||
is the intended product surface. Internal concern packages remain useful even
|
||||
after the public mode choices disappear.
|
||||
`broker` and `proxy` were legacy public launch surfaces, while the ordinary
|
||||
server now exposes both local capabilities and proxied upstream capabilities.
|
||||
Internal concern packages remain useful even though the public mode choices are
|
||||
gone.
|
||||
|
||||
## Future Extraction
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
`wf_mcp` should model capabilities before it models MCP server tool lists.
|
||||
Tools, workflow node specs, prompts, resources, and admin controls all belong to
|
||||
a source. Broker mode, transparent proxy mode, workflow planning, and future UI
|
||||
surfaces are projections of those sources.
|
||||
a source. The MCP server, workflow planning, and future UI surfaces are
|
||||
projections of those sources.
|
||||
|
||||
This avoids the current trap where broker admin tools, transparent proxy admin
|
||||
tools, workflow node specs, and upstream MCP tools all look like unrelated
|
||||
@@ -237,15 +237,15 @@ names.
|
||||
|
||||
## Migration Path
|
||||
|
||||
1. Add explicit admin MCP exposure controls for broker mode.
|
||||
2. Project broker admin tools from `wf.admin` only when admin MCP exposure is
|
||||
1. Keep explicit admin MCP exposure controls on the server surface.
|
||||
2. Project admin tools from `wf.admin` only when admin MCP exposure is
|
||||
enabled.
|
||||
3. Add source-level enable/disable operations backed by `wf.admin`.
|
||||
4. Add persisted source policy so source visibility survives process restart.
|
||||
5. Add system prompts/resources for `wf.std` and `wf.mcp` manuals.
|
||||
|
||||
The implementation should avoid having broker mode and transparent proxy mode
|
||||
define separate copies of the same admin/control capabilities.
|
||||
The implementation should avoid having separate backend layers define copies of
|
||||
the same admin/control capabilities.
|
||||
|
||||
## Current Inventory Surfaces
|
||||
|
||||
|
||||
@@ -51,16 +51,15 @@ new workflow artifacts are saved. A stable `run_deployment` tool lets an LLM
|
||||
test saved workflows immediately without requiring dynamic tool registration or
|
||||
tool-list notifications to work perfectly.
|
||||
|
||||
This control surface should not fork between broker mode and transparent proxy
|
||||
mode. The project currently has two MCP exposure styles:
|
||||
This control surface should not fork between backend service layers. The public
|
||||
server now has one exposure style, but internally it still combines:
|
||||
|
||||
- compatibility broker tools such as list/call wrappers
|
||||
- transparent proxy projection through MCP `tools/list` and `tools/call`
|
||||
- service-backed local workflow/admin tools
|
||||
- upstream proxy projection through MCP `tools/list` and `tools/call`
|
||||
|
||||
Workflow artifact operations should be defined once and projected through the
|
||||
chosen MCP server surface. If broker and transparent modes remain as launch
|
||||
options, they should share the same platform service instead of owning separate
|
||||
workflow registries or separate run semantics.
|
||||
server surface instead of owning separate workflow registries or separate run
|
||||
semantics.
|
||||
|
||||
Dynamic projection of saved workflows as individual MCP tools can exist later,
|
||||
but it should be optional. The stable run tool is the reliable base layer.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from .broker import (
|
||||
load_broker_config,
|
||||
run_broker_server,
|
||||
run_transparent_proxy_server,
|
||||
WfMcpService,
|
||||
)
|
||||
from .capabilities import (
|
||||
@@ -39,7 +37,5 @@ __all__ = [
|
||||
"create_transparent_proxy_client",
|
||||
"create_transparent_proxy_server",
|
||||
"load_broker_config",
|
||||
"run_broker_server",
|
||||
"run_transparent_proxy_server",
|
||||
"validate_transparent_proxy_config",
|
||||
]
|
||||
|
||||
@@ -5,11 +5,7 @@ from .discovery import (
|
||||
specs_from_discovered_tools,
|
||||
)
|
||||
from .events import McpEvent, make_event
|
||||
from .server import (
|
||||
create_broker_server,
|
||||
run_broker_server,
|
||||
run_transparent_proxy_server,
|
||||
)
|
||||
from .server import create_broker_server
|
||||
from .config import build_service_from_config, load_broker_config
|
||||
from .transport import normalize_transport
|
||||
from .service import WfMcpService
|
||||
@@ -24,8 +20,6 @@ __all__ = [
|
||||
"discover_connection_capabilities",
|
||||
"load_broker_config",
|
||||
"make_event",
|
||||
"run_broker_server",
|
||||
"run_transparent_proxy_server",
|
||||
"snapshot_from_specs",
|
||||
"specs_from_discovered_tools",
|
||||
"normalize_transport",
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
from ..transparent_proxy import create_transparent_proxy_server
|
||||
from .artifact_tools import register_artifact_tools
|
||||
from .config import build_service_from_config, load_broker_config
|
||||
from .prompts import register_broker_prompts
|
||||
from .resources import register_broker_resources
|
||||
from .service import WfMcpService
|
||||
from .tools import register_broker_tools
|
||||
from .transport import normalize_transport
|
||||
|
||||
|
||||
def create_broker_server(service: WfMcpService) -> FastMCP:
|
||||
@@ -31,38 +25,3 @@ def create_broker_server(service: WfMcpService) -> FastMCP:
|
||||
register_broker_prompts(server, service)
|
||||
return server
|
||||
|
||||
|
||||
def main() -> None:
|
||||
config_path = os.environ.get("WF_MCP_CONFIG", "wf_mcp.config.json")
|
||||
transport_env = os.environ.get("WF_MCP_TRANSPORT", "stdio")
|
||||
run_broker_server(config_path, transport_env)
|
||||
|
||||
|
||||
def run_broker_server(config_path: str | Path, transport: str = "stdio") -> None:
|
||||
config = load_broker_config(config_path)
|
||||
service = build_service_from_config(config)
|
||||
server = create_broker_server(service)
|
||||
server.run(transport=normalize_transport(transport))
|
||||
|
||||
|
||||
def run_transparent_proxy_server(
|
||||
config_path: str | Path,
|
||||
transport: str = "stdio",
|
||||
*,
|
||||
resources_as_tools: bool = False,
|
||||
prompts_as_tools: bool = False,
|
||||
search_tools: bool = False,
|
||||
) -> None:
|
||||
config = load_broker_config(config_path)
|
||||
server = create_transparent_proxy_server(
|
||||
config,
|
||||
config_path=config_path,
|
||||
resources_as_tools=resources_as_tools,
|
||||
prompts_as_tools=prompts_as_tools,
|
||||
search_tools=search_tools,
|
||||
)
|
||||
server.run(transport=normalize_transport(transport), show_banner=False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
+3
-22
@@ -9,8 +9,6 @@ from typing import Any
|
||||
from .broker import (
|
||||
build_service_from_config,
|
||||
load_broker_config,
|
||||
run_broker_server,
|
||||
run_transparent_proxy_server,
|
||||
)
|
||||
from .server import run_unified_proxy_server
|
||||
|
||||
@@ -25,18 +23,12 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
serve = subparsers.add_parser("serve", help="Run the broker MCP server.")
|
||||
serve = subparsers.add_parser("serve", help="Run the MCP server.")
|
||||
serve.add_argument(
|
||||
"--transport",
|
||||
default="stdio",
|
||||
choices=["stdio", "sse", "streamable-http", "streamable_http"],
|
||||
help="Transport to run the broker server with.",
|
||||
)
|
||||
serve.add_argument(
|
||||
"--mode",
|
||||
default="proxy",
|
||||
choices=["broker", "proxy", "unified"],
|
||||
help="Run broker mode, transparent proxy mode, or unified mode.",
|
||||
help="Transport to run the MCP server with.",
|
||||
)
|
||||
serve.add_argument(
|
||||
"--resources-as-tools",
|
||||
@@ -57,7 +49,7 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
"--no-admin-tools",
|
||||
dest="admin_tools",
|
||||
action="store_false",
|
||||
help="Hide wf.admin.* tools in unified mode.",
|
||||
help="Hide wf.admin.* tools.",
|
||||
)
|
||||
serve.set_defaults(admin_tools=True)
|
||||
|
||||
@@ -122,17 +114,6 @@ def main(argv: list[str] | None = None) -> int:
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if args.command == "serve":
|
||||
if args.mode == "proxy":
|
||||
run_transparent_proxy_server(
|
||||
args.config,
|
||||
args.transport,
|
||||
resources_as_tools=args.resources_as_tools,
|
||||
prompts_as_tools=args.prompts_as_tools,
|
||||
search_tools=args.search_tools,
|
||||
)
|
||||
elif args.mode == "broker":
|
||||
run_broker_server(args.config, args.transport)
|
||||
else:
|
||||
config = load_broker_config(args.config)
|
||||
run_unified_proxy_server(
|
||||
config,
|
||||
|
||||
@@ -43,7 +43,7 @@ class ProxyRuntime:
|
||||
"""Mount configured upstream MCP connections into one FastMCP server.
|
||||
|
||||
The `transparent_proxy` package name is compatibility history. This runtime
|
||||
is now the shared proxy mounting engine used by unified mode too.
|
||||
is now the shared proxy mounting engine used by the public server surface.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
||||
@@ -38,7 +38,6 @@ def test_build_parser_accepts_serve_transport() -> None:
|
||||
|
||||
assert args.command == "serve"
|
||||
assert args.transport == "streamable_http"
|
||||
assert args.mode == "proxy"
|
||||
assert args.resources_as_tools is False
|
||||
assert args.prompts_as_tools is False
|
||||
assert args.search_tools is False
|
||||
@@ -58,15 +57,16 @@ def test_build_parser_accepts_proxy_compatibility_flags() -> None:
|
||||
)
|
||||
|
||||
assert args.command == "serve"
|
||||
assert args.mode == "proxy"
|
||||
assert args.resources_as_tools is True
|
||||
assert args.prompts_as_tools is True
|
||||
assert args.search_tools is True
|
||||
|
||||
|
||||
def test_build_parser_accepts_unified_mode() -> None:
|
||||
def test_build_parser_rejects_legacy_mode_flag() -> None:
|
||||
parser = build_parser()
|
||||
args = parser.parse_args(
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
parser.parse_args(
|
||||
[
|
||||
"--config",
|
||||
"wf_mcp.config.json",
|
||||
@@ -76,10 +76,6 @@ def test_build_parser_accepts_unified_mode() -> None:
|
||||
]
|
||||
)
|
||||
|
||||
assert args.command == "serve"
|
||||
assert args.mode == "unified"
|
||||
assert args.admin_tools is True
|
||||
|
||||
|
||||
def test_build_parser_accepts_no_admin_tools_flag() -> None:
|
||||
parser = build_parser()
|
||||
@@ -88,14 +84,11 @@ def test_build_parser_accepts_no_admin_tools_flag() -> None:
|
||||
"--config",
|
||||
"wf_mcp.config.json",
|
||||
"serve",
|
||||
"--mode",
|
||||
"unified",
|
||||
"--no-admin-tools",
|
||||
]
|
||||
)
|
||||
|
||||
assert args.command == "serve"
|
||||
assert args.mode == "unified"
|
||||
assert args.admin_tools is False
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user