Documentation
¶
Overview ¶
Package mcp hosts the Gothic dev session's MCP surface over Streamable HTTP.
The dev proxy process serves it at /_gothicframework/mcp (default-on; the hot-reload command mounts it and --no-mcp opts out). The surface is the machine port of the framework's own tooling: the managed browser (view, act, record), the build pipeline (build_*, sync, build_status), the request trace and the dev bus (trace, logs), and the bundled skill documents (skillsearch/skillinfo/skill, also reachable as gothic-skill:// resources).
Results stay small: heavy content (skill document bodies, page-view grids, take frame lists) is returned only on an explicit named request.
Concurrency: every tool serializes on the machinery's own locks (the browser Manager, the build Controller); the surface adds one mutex only for its own small per-session state (the diff baseline, the last take).
Index ¶
Constants ¶
const MCPEndpointPath = "/_gothicframework/mcp"
MCPEndpointPath is where the dev proxy mux serves the MCP endpoint.
Variables ¶
This section is empty.
Functions ¶
func Handler ¶
func Handler(factory func() *Capability) http.Handler
Handler builds the whole MCP surface as an http.Handler: one server, every contract tool, the skill resources, and Streamable HTTP with plain-JSON responses (the dev server's own traffic pattern: one request, one answer).
Types ¶
type BrowserPort ¶
type BrowserPort interface {
Open(url string) error
Act(ctx context.Context, steps []browser.Step) error
CaptureStill(ctx context.Context, opts browser.StillOptions) ([]browser.StillResult, error)
StartRecording(opts browser.RecordOptions) (TakePort, error)
ActiveTake() TakePort
SetHeadless(headless bool) error
// SetViewport pins a device-metrics override on the managed page until
// ClearViewport; height 0 keeps the page's current height.
SetViewport(width, height int, mobile bool) error
ClearViewport() error
// Console returns the page's retained console errors/warnings, newest
// first; last <= 0 returns the whole ring.
Console(last int) []browser.ConsoleEntry
Running() bool
// Eval runs one rod-style JS function expression ("() => …") in the page
// and returns its value serialized. Promise results are awaited.
Eval(js string) (string, error)
}
BrowserPort is the managed-browser surface the tools use. NewBrowserPort adapts cli/internal/browser.Manager (whose StartRecording returns the concrete *Take) to the interface.
func NewBrowserPort ¶
func NewBrowserPort(m *browser.Manager) BrowserPort
NewBrowserPort adapts a managed browser Manager to the BrowserPort.
type BuildPort ¶
type BuildPort interface {
BuildTempl(file string) buildctl.BuildResult
BuildRoutes() buildctl.BuildResult
BuildTopics() buildctl.BuildResult
BuildWasm(target string) buildctl.BuildResult
BuildGo() buildctl.BuildResult
BuildCSS(page string) buildctl.BuildResult
Sync() buildctl.BuildResult
BuildStatus() buildctl.StatusResult
}
BuildPort is the build-pipeline surface the tools use. cli/internal/buildctl.Controller implements it exactly.
type Capability ¶
type Capability struct {
// Browser is the managed browser (nil when the session has none).
Browser BrowserPort
// Build is the build controller (nil when the session has none).
Build BuildPort
// Timeline reads the observation timeline (server trace + dev bus).
Timeline TimelinePort
// Skills serves the bundled skill documents.
Skills SkillsPort
// MarkSink injects a named mark into the dev bus (nil disables record_mark).
MarkSink MarkSink
// Marks pulls the act marks out of the dev bus ring (newest first) — the
// closure the recording takes run on. Production binds it to
// browser.MarksFromRecords over the proxy's ring; nil falls back to the
// Timeline port's Bus read.
Marks func() []browser.TakeMark
// Engine is the managed browser's engine label reported in page-view
// payloads (e.g. "chromium 131"); empty when unknown.
Engine string
// Version is the CLI version reported as the MCP server's version
// (passed in — the cmd package owns the constant).
Version string
}
Capability is the machinery one dev session exposes to MCP clients. The hot-reload command builds it once over its real subsystems; tests build fakes. Nil members make the matching tools fail with a clean tool error instead of a panic.
type HTTPBaseTimeline ¶
type HTTPBaseTimeline struct {
// Base is the dev proxy's origin.
Base string
// Client is the HTTP client (zero value = a 5s-timeout default).
Client *http.Client
}
HTTPBaseTimeline reads the observation timeline over the dev proxy's own HTTP surface. Construct it with the proxy's base URL (e.g. "http://127.0.0.1:3000").
type MarkSink ¶
MarkSink injects one named mark into the dev bus (a kind:"mark" record), so the active take's marks poller and every record reader see it on the same timeline. Production posts to the proxy's bus ingest endpoint.
type SkillsPort ¶
type SkillsPort interface {
Search(query string) []skills.Ref
Info(names []string) []skills.SkillInfo
Load(names []string) []skills.Document
Names() []string
}
SkillsPort serves the bundled skill documents. cli/internal/skills.Set implements it exactly.
type TakePort ¶
type TakePort interface {
Stop(discard bool) (browser.TakeManifest, error)
Wait() (browser.TakeManifest, error)
Done() <-chan struct{}
}
TakePort is the recording handle the record tools drive. *browser.Take implements it exactly.
type TimelinePort ¶
type TimelinePort interface {
// Trace returns the newest N server-side trace records.
Trace(ctx context.Context, last int) ([]map[string]any, error)
// Bus returns the newest N dev-bus records, newest first.
Bus(last int) ([]map[string]any, error)
}
TimelinePort reads the session's observation timeline from both planes: the app's server-side request trace and the dev bus (topic/durable/control/mark traffic decoded by the injected observer). Production wires both planes to HTTP reads over the dev proxy; tests stub them in memory.