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