You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The MCP server (pkg/mcp) currently exposes Functions to AI agents by shelling out to the func binary as a subprocess. This was an expedient — it let the MCP surface land quickly by piggy-backing on the existing CLI. It should be replaced with direct use of the core library at pkg/functions, in the same way the CLI itself does.
Architectural principle
The real logic of Functions lives in pkg/functions (and friends — pkg/k8s, pkg/docker, pkg/knative, etc.). The cmd/ package wraps that library as a CLI. The pkg/mcp package should wrap the same library as an MCP server.
Today's reality is the bottom-left arrow points sideways — pkg/mcp calls into cli, which calls into pkg/functions. That extra hop is a leaky abstraction.
Remove the executor interface, its mocks, and the func binary as a runtime dependency of the MCP server.
Open design questions
Long-running operations (func deploy, func logs): how do we surface progress events to the agent? MCP supports progress notifications via the protocol; the in-process API would need to emit these.
Interactive prompts: func has prompt flows; MCP context never has a TTY. Handlers must either resolve prompts via the request payload or fail cleanly.
Testing surface: the current executor mock made it easy to test handlers in isolation. The replacement is to inject the same pkg/functions client or its interfaces — most of which already exist as injectable points.
Concurrency: the CLI assumes one operation per process; direct library use means handlers may run concurrently. Review pkg/functions for thread safety where MCP would call into it from multiple goroutines.
feat(mcp): add check_prerequisites tool for environment validation #3752 (check_prerequisites tool): a current-day example of the friction this issue resolves — needed to add ExecuteRaw to the executor to shell out to docker/kubectl. Once the MCP server uses pkg/functions and pkg/k8s directly, the same checks become idiomatic Go.
Summary
The MCP server (
pkg/mcp) currently exposes Functions to AI agents by shelling out to thefuncbinary as a subprocess. This was an expedient — it let the MCP surface land quickly by piggy-backing on the existing CLI. It should be replaced with direct use of the core library atpkg/functions, in the same way the CLI itself does.Architectural principle
The real logic of Functions lives in
pkg/functions(and friends —pkg/k8s,pkg/docker,pkg/knative, etc.). Thecmd/package wraps that library as a CLI. Thepkg/mcppackage should wrap the same library as an MCP server.Today's reality is the bottom-left arrow points sideways —
pkg/mcpcalls intocli, which calls intopkg/functions. That extra hop is a leaky abstraction.Why this matters now
exec.Command("func", ...), captures stdout/stderr blobs, and either passes the text to the agent verbatim or tries to parse it. The parsing is brittle (see feat(mcp): add structured error categories for agentic error handling #3753 for a worked example), the structured-output story is thin, and adding any tool requires routing through anexecutorinterface that has been growing leaky over time (e.g., the recently-proposedExecuteRawin feat(mcp): add check_prerequisites tool for environment validation #3752).func).The TODO comment already in the tree at
pkg/mcp/mcp.go:154-155flags exactly this direction.Scope
pkg/mcp/tools_*.gowith direct calls intopkg/functions(andpkg/k8s,pkg/docker, etc. where appropriate).executorinterface and its mocks once all handlers are migrated.CallToolResult.StructuredContent.errors.As) rather than substring matching.Phased migration suggested
list,describe,healthcheck,check_prerequisitesif that lands first via MCP: Add check_prerequisites tool for environment validation #3749 / feat(mcp): add check_prerequisites tool for environment validation #3752) — lowest risk, easiest to validate.build,deploy,delete,config_*).executorinterface, its mocks, and thefuncbinary as a runtime dependency of the MCP server.Open design questions
func deploy,func logs): how do we surface progress events to the agent? MCP supports progress notifications via the protocol; the in-process API would need to emit these.funchas prompt flows; MCP context never has a TTY. Handlers must either resolve prompts via the request payload or fail cleanly.executormock made it easy to test handlers in isolation. The replacement is to inject the samepkg/functionsclient or its interfaces — most of which already exist as injectable points.pkg/functionsfor thread safety where MCP would call into it from multiple goroutines.Relationship to other work
--jsonoutput mode to everyfuncsubcommand, including errors #3769 (--jsonoutput for everyfuncsubcommand) remains valuable — for scripts, CI, third-party tools, and IDEs that drivefuncas a subprocess. It is not blocked by this issue and does not block this issue.func --jsonoutput and forward structured errors via CallToolResult.StructuredContent #3770 (MCP consumefunc --jsonand forward viaStructuredContent) is superseded by this issue. Ifpkg/mcpcallspkg/functionsdirectly, there is nofunc --jsonsubprocess output to consume.check_prerequisitestool): a current-day example of the friction this issue resolves — needed to addExecuteRawto the executor to shell out todocker/kubectl. Once the MCP server usespkg/functionsandpkg/k8sdirectly, the same checks become idiomatic Go.pkg/functionsreach MCP handlers directly; categorization is a pure mapping, not a parsing problem.Non-goals
funcCLI. The CLI is the primary human-facing surface and stays as-is.