mcp

package
v0.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package mcp exposes devbay to coding agents.

This is the primary interface, not a wrapper around the CLI. An agent shelling out and parsing terminal output is lossy in both directions: it has to guess at formatting that changes between versions, and it loses the distinction between "the test failed" and "the command failed". Every tool here returns a typed object.

Written against the 2026-07-28 spec, which changed three things that shape this file:

  • The protocol core is stateless. There is no initialize handshake and no session id, so no bay state may be keyed on a connection. Every tool takes an explicit bay name.
  • Servers cannot initiate requests. Nothing here calls out to the client; logs are pulled through a tool rather than pushed.
  • Custom transports over a reliable byte stream should reuse the stdio framing, which is newline-delimited JSON-RPC. So a unix socket and stdio are the same code path, and the shim binary an agent spawns is a pipe.

The server is nevertheless dual-era, because "the spec removed the handshake" and "the clients removed the handshake" are not the same date. Every shipping client still opens with `initialize`, and a modern-only server is unreachable from all of them: the stdio fallback probe is `server/discover`, and answering it with "unknown method" is not a recognized modern error, so a dual-era client concludes the server is legacy, falls back to `initialize`, and fails there too. Both doors are therefore open. Which one the client used selects nothing and is not remembered -- there is no session state to key on either way, so serving both costs a version string rather than an architecture.

Index

Constants

View Source
const RulesBody = `## Running and testing this repository

This repository uses devbay. Every branch gets its own containers, database,
ports and browser origin, so several can run at once without colliding.

- If you do not know whether this repository is set up for devbay yet, ask
  ` + "`repo_status`" + `. It names the next step, and ` + "`repo_init`" + `
  proposes a devbay.yaml when there is none.
- Create a bay before running or verifying anything: ` + "`bay_create`" + `.
- Run tests with ` + "`bay_run_task`" + `, not by running the test command
  yourself. It starts only the services the task declares it needs, so a unit
  suite boots nothing, and failures come back with a file, a line and the
  assertion instead of output to parse.
- Do not run ` + "`docker compose up`" + `, ` + "`docker run`" + `, or the
  application's dev server directly. They bind the ports the bays own and
  undo the isolation.
- Open ` + "`public_url`" + ` in a browser and call ` + "`url`" + ` from code.
  They are different addresses on purpose.
- Use ` + "`bay_logs`" + ` when a failure needs more than the structured
  result, and ` + "`bay_destroy`" + ` when the work is merged or abandoned.`

RulesBody is what the agent is told. Imperative, short, and specific about the two mistakes an agent actually makes: running the test command itself, and starting the stack outside a bay.

Variables

View Source
var Clients = []Client{
	{
		Key:    "claude",
		Name:   "Claude Code",
		Format: FormatMCPJSON,

		Project: ".mcp.json",
		Global:  ".claude.json",
		Note:    "Claude Code asks you to approve a project-scoped server the first time it sees one.",
	},
	{
		Key:     "cursor",
		Name:    "Cursor",
		Format:  FormatMCPJSON,
		Project: ".cursor/mcp.json",
		Global:  ".cursor/mcp.json",
		Note:    "Cursor picks it up on the next reload; check Settings, MCP for a green dot.",
	},
	{
		Key:    "codex",
		Name:   "Codex CLI",
		Format: FormatCodexTOML,

		Global: ".codex/config.toml",
		Note:   "Codex reads this at startup, so restart it.",
	},
}

Clients is the supported set, in the order `devbay mcp install` lists them.

View Source
var RuleFiles = []RuleFile{
	{Path: "CLAUDE.md", Client: "Claude Code"},
	{Path: "AGENTS.md", Client: "Codex CLI"},
	{
		Path:        filepath.Join(".cursor", "rules", "devbay.mdc"),
		Client:      "Cursor",
		Frontmatter: "---\ndescription: How to run and test this repository\nalwaysApply: true\n---\n\n",
	},
}

RuleFiles are the conventional locations, one per client.

View Source
var Version = "dev"

Version is the devbay build, reported as serverInfo. Set by main; the protocol says serverInfo is for display and logging only, so a client that cannot read it loses nothing but a line in a log.

Functions

func SocketPath

func SocketPath() string

SocketPath is the default control socket.

func SortedKeys added in v0.5.0

func SortedKeys() []string

SortedKeys is the client list as keys, for messages.

func ToolNames added in v0.5.0

func ToolNames() []string

ToolNames lists the tools an agent gets, without needing a live server.

Kept beside the client list because it is shown at the end of an install: telling somebody the wiring worked is less useful than telling them what their agent can now do.

Types

type Client added in v0.5.0

type Client struct {
	// Key is what the developer types: `devbay mcp install --client cursor`.
	Key string
	// Name is what they call it.
	Name string
	// Format is how that client stores servers.
	Format Format
	// Project is the config path relative to a repository root. Empty when the
	// client has no project-scoped configuration.
	Project string
	// Global is the config path relative to the home directory.
	Global string
	// Note is what to say after writing, when the client needs a nudge.
	Note string
}

Client is an agent that can be told about an MCP server.

func ClientByKey added in v0.5.0

func ClientByKey(key string) (Client, error)

ClientByKey finds a client, and lists the alternatives when there is no such thing rather than saying only that there is not.

func (Client) Paths added in v0.5.0

func (c Client) Paths(repoRoot, home string) (project, global string)

Paths returns where an install would write, project scope first.

type Format added in v0.5.0

type Format int

Format is a config dialect. Two shapes cover all three clients, which is why they are enumerated rather than abstracted.

const (
	// FormatMCPJSON is `{"mcpServers": {"devbay": {"command": …}}}`, used by
	// Claude Code and Cursor.
	FormatMCPJSON Format = iota
	// FormatCodexTOML is `[mcp_servers.devbay]` in ~/.codex/config.toml.
	FormatCodexTOML
)

type Result added in v0.5.0

type Result struct {
	Path    string
	Changed bool
	Created bool
	// Before is the previous devbay entry, when there was one.
	Before string
}

Install writes the devbay server into a client's config.

Merging rather than overwriting, because these files belong to the developer: a config holding six servers must still hold six servers afterwards. The only entry devbay touches is its own, and it reports whether it added one, changed one, or found the right one already there.

func Install added in v0.5.0

func Install(c Client, path, binary string) (Result, error)

Install adds or updates the devbay entry in path, in the client's dialect.

func WriteRules added in v0.5.0

func WriteRules(f RuleFile, root string) (Result, error)

WriteRules puts the block into path, replacing an existing one.

Appended rather than merged into the prose, because these files belong to whoever wrote them: a CLAUDE.md with a team's conventions in it must still have them afterwards, in the order they chose.

type RuleFile added in v0.5.0

type RuleFile struct {
	// Path is relative to the repository root.
	Path string
	// Client names who reads it, for the install output.
	Client string
	// Frontmatter is prepended when the file is created, for clients that
	// need it. Cursor ignores a rule file without one.
	Frontmatter string
}

RuleFile is an instruction file a client reads.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server serves the devbay tool surface.

func NewServer

func NewServer(mgr *bay.Manager) *Server

NewServer builds a server over a bay manager.

func (*Server) ListenUnix

func (s *Server) ListenUnix(ctx context.Context, path string) error

ListenUnix serves on a unix socket until the context is cancelled.

One daemon owns the ports, containers and worktrees for a machine, and many agent sessions connect to it. A socket rather than a per-session process is what makes that possible.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, rw io.ReadWriter) error

Serve runs the JSON-RPC loop over one connection.

func (*Server) Tools

func (s *Server) Tools() []Tool

Tools returns the registered tools.

type ServerEntry added in v0.5.0

type ServerEntry struct {
	Command string   `json:"command"`
	Args    []string `json:"args,omitempty"`
}

ServerEntry is what gets written: the command that speaks MCP.

type Tool

type Tool struct {
	Name        string         `json:"name"`
	Title       string         `json:"title,omitempty"`
	Description string         `json:"description"`
	InputSchema map[string]any `json:"inputSchema"`
	// contains filtered or unexported fields
}

Tool is one callable capability.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL